aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/fs_enet/fs_enet-main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/fs_enet/fs_enet-main.c')
-rw-r--r--drivers/net/fs_enet/fs_enet-main.c258
1 files changed, 241 insertions, 17 deletions
diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c
index 7a0298687875..fc4fda805d44 100644
--- a/drivers/net/fs_enet/fs_enet-main.c
+++ b/drivers/net/fs_enet/fs_enet-main.c
@@ -42,12 +42,18 @@
42#include <asm/irq.h> 42#include <asm/irq.h>
43#include <asm/uaccess.h> 43#include <asm/uaccess.h>
44 44
45#ifdef CONFIG_PPC_CPM_NEW_BINDING
46#include <asm/of_platform.h>
47#endif
48
45#include "fs_enet.h" 49#include "fs_enet.h"
46 50
47/*************************************************/ 51/*************************************************/
48 52
53#ifndef CONFIG_PPC_CPM_NEW_BINDING
49static char version[] __devinitdata = 54static char version[] __devinitdata =
50 DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")" "\n"; 55 DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")" "\n";
56#endif
51 57
52MODULE_AUTHOR("Pantelis Antoniou <panto@intracom.gr>"); 58MODULE_AUTHOR("Pantelis Antoniou <panto@intracom.gr>");
53MODULE_DESCRIPTION("Freescale Ethernet Driver"); 59MODULE_DESCRIPTION("Freescale Ethernet Driver");
@@ -948,6 +954,7 @@ static int fs_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
948extern int fs_mii_connect(struct net_device *dev); 954extern int fs_mii_connect(struct net_device *dev);
949extern void fs_mii_disconnect(struct net_device *dev); 955extern void fs_mii_disconnect(struct net_device *dev);
950 956
957#ifndef CONFIG_PPC_CPM_NEW_BINDING
951static struct net_device *fs_init_instance(struct device *dev, 958static struct net_device *fs_init_instance(struct device *dev,
952 struct fs_platform_info *fpi) 959 struct fs_platform_info *fpi)
953{ 960{
@@ -1129,6 +1136,7 @@ static int fs_cleanup_instance(struct net_device *ndev)
1129 1136
1130 return 0; 1137 return 0;
1131} 1138}
1139#endif
1132 1140
1133/**************************************************************************************/ 1141/**************************************************************************************/
1134 1142
@@ -1137,35 +1145,250 @@ void *fs_enet_immap = NULL;
1137 1145
1138static int setup_immap(void) 1146static int setup_immap(void)
1139{ 1147{
1140 phys_addr_t paddr = 0;
1141 unsigned long size = 0;
1142
1143#ifdef CONFIG_CPM1 1148#ifdef CONFIG_CPM1
1144 paddr = IMAP_ADDR; 1149 fs_enet_immap = ioremap(IMAP_ADDR, 0x4000);
1145 size = 0x10000; /* map 64K */ 1150 WARN_ON(!fs_enet_immap);
1146#endif 1151#elif defined(CONFIG_CPM2)
1147 1152 fs_enet_immap = cpm2_immr;
1148#ifdef CONFIG_CPM2
1149 paddr = CPM_MAP_ADDR;
1150 size = 0x40000; /* map 256 K */
1151#endif 1153#endif
1152 fs_enet_immap = ioremap(paddr, size);
1153 if (fs_enet_immap == NULL)
1154 return -EBADF; /* XXX ahem; maybe just BUG_ON? */
1155 1154
1156 return 0; 1155 return 0;
1157} 1156}
1158 1157
1159static void cleanup_immap(void) 1158static void cleanup_immap(void)
1160{ 1159{
1161 if (fs_enet_immap != NULL) { 1160#if defined(CONFIG_CPM1)
1162 iounmap(fs_enet_immap); 1161 iounmap(fs_enet_immap);
1163 fs_enet_immap = NULL; 1162#endif
1164 }
1165} 1163}
1166 1164
1167/**************************************************************************************/ 1165/**************************************************************************************/
1168 1166
1167#ifdef CONFIG_PPC_CPM_NEW_BINDING
1168static int __devinit find_phy(struct device_node *np,
1169 struct fs_platform_info *fpi)
1170{
1171 struct device_node *phynode, *mdionode;
1172 struct resource res;
1173 int ret = 0, len;
1174
1175 const u32 *data = of_get_property(np, "phy-handle", &len);
1176 if (!data || len != 4)
1177 return -EINVAL;
1178
1179 phynode = of_find_node_by_phandle(*data);
1180 if (!phynode)
1181 return -EINVAL;
1182
1183 mdionode = of_get_parent(phynode);
1184 if (!mdionode)
1185 goto out_put_phy;
1186
1187 ret = of_address_to_resource(mdionode, 0, &res);
1188 if (ret)
1189 goto out_put_mdio;
1190
1191 data = of_get_property(phynode, "reg", &len);
1192 if (!data || len != 4)
1193 goto out_put_mdio;
1194
1195 snprintf(fpi->bus_id, 16, PHY_ID_FMT, res.start, *data);
1196
1197out_put_mdio:
1198 of_node_put(mdionode);
1199out_put_phy:
1200 of_node_put(phynode);
1201 return ret;
1202}
1203
1204#ifdef CONFIG_FS_ENET_HAS_FEC
1205#define IS_FEC(match) ((match)->data == &fs_fec_ops)
1206#else
1207#define IS_FEC(match) 0
1208#endif
1209
1210static int __devinit fs_enet_probe(struct of_device *ofdev,
1211 const struct of_device_id *match)
1212{
1213 struct net_device *ndev;
1214 struct fs_enet_private *fep;
1215 struct fs_platform_info *fpi;
1216 const u32 *data;
1217 const u8 *mac_addr;
1218 int privsize, len, ret = -ENODEV;
1219
1220 fpi = kzalloc(sizeof(*fpi), GFP_KERNEL);
1221 if (!fpi)
1222 return -ENOMEM;
1223
1224 if (!IS_FEC(match)) {
1225 data = of_get_property(ofdev->node, "fsl,cpm-command", &len);
1226 if (!data || len != 4)
1227 goto out_free_fpi;
1228
1229 fpi->cp_command = *data;
1230 }
1231
1232 fpi->rx_ring = 32;
1233 fpi->tx_ring = 32;
1234 fpi->rx_copybreak = 240;
1235 fpi->use_napi = 0;
1236 fpi->napi_weight = 17;
1237
1238 ret = find_phy(ofdev->node, fpi);
1239 if (ret)
1240 goto out_free_fpi;
1241
1242 privsize = sizeof(*fep) +
1243 sizeof(struct sk_buff **) *
1244 (fpi->rx_ring + fpi->tx_ring);
1245
1246 ndev = alloc_etherdev(privsize);
1247 if (!ndev) {
1248 ret = -ENOMEM;
1249 goto out_free_fpi;
1250 }
1251
1252 SET_MODULE_OWNER(ndev);
1253 dev_set_drvdata(&ofdev->dev, ndev);
1254
1255 fep = netdev_priv(ndev);
1256 fep->dev = &ofdev->dev;
1257 fep->fpi = fpi;
1258 fep->ops = match->data;
1259
1260 ret = fep->ops->setup_data(ndev);
1261 if (ret)
1262 goto out_free_dev;
1263
1264 fep->rx_skbuff = (struct sk_buff **)&fep[1];
1265 fep->tx_skbuff = fep->rx_skbuff + fpi->rx_ring;
1266
1267 spin_lock_init(&fep->lock);
1268 spin_lock_init(&fep->tx_lock);
1269
1270 mac_addr = of_get_mac_address(ofdev->node);
1271 if (mac_addr)
1272 memcpy(ndev->dev_addr, mac_addr, 6);
1273
1274 ret = fep->ops->allocate_bd(ndev);
1275 if (ret)
1276 goto out_cleanup_data;
1277
1278 fep->rx_bd_base = fep->ring_base;
1279 fep->tx_bd_base = fep->rx_bd_base + fpi->rx_ring;
1280
1281 fep->tx_ring = fpi->tx_ring;
1282 fep->rx_ring = fpi->rx_ring;
1283
1284 ndev->open = fs_enet_open;
1285 ndev->hard_start_xmit = fs_enet_start_xmit;
1286 ndev->tx_timeout = fs_timeout;
1287 ndev->watchdog_timeo = 2 * HZ;
1288 ndev->stop = fs_enet_close;
1289 ndev->get_stats = fs_enet_get_stats;
1290 ndev->set_multicast_list = fs_set_multicast_list;
1291 if (fpi->use_napi) {
1292 ndev->poll = fs_enet_rx_napi;
1293 ndev->weight = fpi->napi_weight;
1294 }
1295 ndev->ethtool_ops = &fs_ethtool_ops;
1296 ndev->do_ioctl = fs_ioctl;
1297
1298 init_timer(&fep->phy_timer_list);
1299
1300 netif_carrier_off(ndev);
1301
1302 ret = register_netdev(ndev);
1303 if (ret)
1304 goto out_free_bd;
1305
1306 printk(KERN_INFO "%s: fs_enet: %02x:%02x:%02x:%02x:%02x:%02x\n",
1307 ndev->name,
1308 ndev->dev_addr[0], ndev->dev_addr[1], ndev->dev_addr[2],
1309 ndev->dev_addr[3], ndev->dev_addr[4], ndev->dev_addr[5]);
1310
1311 return 0;
1312
1313out_free_bd:
1314 fep->ops->free_bd(ndev);
1315out_cleanup_data:
1316 fep->ops->cleanup_data(ndev);
1317out_free_dev:
1318 free_netdev(ndev);
1319 dev_set_drvdata(&ofdev->dev, NULL);
1320out_free_fpi:
1321 kfree(fpi);
1322 return ret;
1323}
1324
1325static int fs_enet_remove(struct of_device *ofdev)
1326{
1327 struct net_device *ndev = dev_get_drvdata(&ofdev->dev);
1328 struct fs_enet_private *fep = netdev_priv(ndev);
1329
1330 unregister_netdev(ndev);
1331
1332 fep->ops->free_bd(ndev);
1333 fep->ops->cleanup_data(ndev);
1334 dev_set_drvdata(fep->dev, NULL);
1335
1336 free_netdev(ndev);
1337 return 0;
1338}
1339
1340static struct of_device_id fs_enet_match[] = {
1341#ifdef CONFIG_FS_ENET_HAS_SCC
1342 {
1343 .compatible = "fsl,cpm1-scc-enet",
1344 .data = (void *)&fs_scc_ops,
1345 },
1346#endif
1347#ifdef CONFIG_FS_ENET_HAS_FCC
1348 {
1349 .compatible = "fsl,cpm2-fcc-enet",
1350 .data = (void *)&fs_fcc_ops,
1351 },
1352#endif
1353#ifdef CONFIG_FS_ENET_HAS_FEC
1354 {
1355 .compatible = "fsl,pq1-fec-enet",
1356 .data = (void *)&fs_fec_ops,
1357 },
1358#endif
1359 {}
1360};
1361
1362static struct of_platform_driver fs_enet_driver = {
1363 .name = "fs_enet",
1364 .match_table = fs_enet_match,
1365 .probe = fs_enet_probe,
1366 .remove = fs_enet_remove,
1367};
1368
1369static int __init fs_init(void)
1370{
1371 int r = setup_immap();
1372 if (r != 0)
1373 return r;
1374
1375 r = of_register_platform_driver(&fs_enet_driver);
1376 if (r != 0)
1377 goto out;
1378
1379 return 0;
1380
1381out:
1382 cleanup_immap();
1383 return r;
1384}
1385
1386static void __exit fs_cleanup(void)
1387{
1388 of_unregister_platform_driver(&fs_enet_driver);
1389 cleanup_immap();
1390}
1391#else
1169static int __devinit fs_enet_probe(struct device *dev) 1392static int __devinit fs_enet_probe(struct device *dev)
1170{ 1393{
1171 struct net_device *ndev; 1394 struct net_device *ndev;
@@ -1279,6 +1502,7 @@ static void __exit fs_cleanup(void)
1279 driver_unregister(&fs_enet_scc_driver); 1502 driver_unregister(&fs_enet_scc_driver);
1280 cleanup_immap(); 1503 cleanup_immap();
1281} 1504}
1505#endif
1282 1506
1283#ifdef CONFIG_NET_POLL_CONTROLLER 1507#ifdef CONFIG_NET_POLL_CONTROLLER
1284static void fs_enet_netpoll(struct net_device *dev) 1508static void fs_enet_netpoll(struct net_device *dev)