aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/fs_enet/Kconfig1
-rw-r--r--drivers/net/fs_enet/fs_enet-main.c258
-rw-r--r--drivers/net/fs_enet/fs_enet.h55
-rw-r--r--drivers/net/fs_enet/mac-fcc.c89
-rw-r--r--drivers/net/fs_enet/mac-fec.c19
-rw-r--r--drivers/net/fs_enet/mac-scc.c53
-rw-r--r--drivers/net/fs_enet/mii-bitbang.c269
-rw-r--r--drivers/net/fs_enet/mii-fec.c143
8 files changed, 709 insertions, 178 deletions
diff --git a/drivers/net/fs_enet/Kconfig b/drivers/net/fs_enet/Kconfig
index e27ee210b605..2765e49e07df 100644
--- a/drivers/net/fs_enet/Kconfig
+++ b/drivers/net/fs_enet/Kconfig
@@ -11,6 +11,7 @@ config FS_ENET_HAS_SCC
11config FS_ENET_HAS_FCC 11config FS_ENET_HAS_FCC
12 bool "Chip has an FCC usable for ethernet" 12 bool "Chip has an FCC usable for ethernet"
13 depends on FS_ENET && CPM2 13 depends on FS_ENET && CPM2
14 select MDIO_BITBANG
14 default y 15 default y
15 16
16config FS_ENET_HAS_FEC 17config FS_ENET_HAS_FEC
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)
diff --git a/drivers/net/fs_enet/fs_enet.h b/drivers/net/fs_enet/fs_enet.h
index 85571e49ec72..5a5c9d18df2e 100644
--- a/drivers/net/fs_enet/fs_enet.h
+++ b/drivers/net/fs_enet/fs_enet.h
@@ -24,19 +24,6 @@ struct fec_info {
24#include <asm/cpm2.h> 24#include <asm/cpm2.h>
25#endif 25#endif
26 26
27/* This is used to operate with pins.
28 Note that the actual port size may
29 be different; cpm(s) handle it OK */
30struct bb_info {
31 u8 mdio_dat_msk;
32 u8 mdio_dir_msk;
33 u8 *mdio_dir;
34 u8 *mdio_dat;
35 u8 mdc_msk;
36 u8 *mdc_dat;
37 int delay;
38};
39
40/* hw driver ops */ 27/* hw driver ops */
41struct fs_ops { 28struct fs_ops {
42 int (*setup_data)(struct net_device *dev); 29 int (*setup_data)(struct net_device *dev);
@@ -85,48 +72,12 @@ struct phy_info {
85#define ENET_RX_ALIGN 16 72#define ENET_RX_ALIGN 16
86#define ENET_RX_FRSIZE L1_CACHE_ALIGN(PKT_MAXBUF_SIZE + ENET_RX_ALIGN - 1) 73#define ENET_RX_FRSIZE L1_CACHE_ALIGN(PKT_MAXBUF_SIZE + ENET_RX_ALIGN - 1)
87 74
88struct fs_enet_mii_bus {
89 struct list_head list;
90 spinlock_t mii_lock;
91 const struct fs_mii_bus_info *bus_info;
92 int refs;
93 u32 usage_map;
94
95 int (*mii_read)(struct fs_enet_mii_bus *bus,
96 int phy_id, int location);
97
98 void (*mii_write)(struct fs_enet_mii_bus *bus,
99 int phy_id, int location, int value);
100
101 union {
102 struct {
103 unsigned int mii_speed;
104 void *fecp;
105 } fec;
106
107 struct {
108 /* note that the actual port size may */
109 /* be different; cpm(s) handle it OK */
110 u8 mdio_msk;
111 u8 *mdio_dir;
112 u8 *mdio_dat;
113 u8 mdc_msk;
114 u8 *mdc_dir;
115 u8 *mdc_dat;
116 } bitbang;
117
118 struct {
119 u16 lpa;
120 } fixed;
121 };
122};
123
124struct fs_enet_private { 75struct fs_enet_private {
125 struct napi_struct napi; 76 struct napi_struct napi;
126 struct device *dev; /* pointer back to the device (must be initialized first) */ 77 struct device *dev; /* pointer back to the device (must be initialized first) */
127 spinlock_t lock; /* during all ops except TX pckt processing */ 78 spinlock_t lock; /* during all ops except TX pckt processing */
128 spinlock_t tx_lock; /* during fs_start_xmit and fs_tx */ 79 spinlock_t tx_lock; /* during fs_start_xmit and fs_tx */
129 const struct fs_platform_info *fpi; 80 struct fs_platform_info *fpi;
130 const struct fs_ops *ops; 81 const struct fs_ops *ops;
131 int rx_ring, tx_ring; 82 int rx_ring, tx_ring;
132 dma_addr_t ring_mem_addr; 83 dma_addr_t ring_mem_addr;
@@ -145,7 +96,6 @@ struct fs_enet_private {
145 u32 msg_enable; 96 u32 msg_enable;
146 struct mii_if_info mii_if; 97 struct mii_if_info mii_if;
147 unsigned int last_mii_status; 98 unsigned int last_mii_status;
148 struct fs_enet_mii_bus *mii_bus;
149 int interrupt; 99 int interrupt;
150 100
151 struct phy_device *phydev; 101 struct phy_device *phydev;
@@ -187,9 +137,10 @@ struct fs_enet_private {
187}; 137};
188 138
189/***************************************************************************/ 139/***************************************************************************/
140#ifndef CONFIG_PPC_CPM_NEW_BINDING
190int fs_enet_mdio_bb_init(void); 141int fs_enet_mdio_bb_init(void);
191int fs_mii_fixed_init(struct fs_enet_mii_bus *bus);
192int fs_enet_mdio_fec_init(void); 142int fs_enet_mdio_fec_init(void);
143#endif
193 144
194void fs_init_bds(struct net_device *dev); 145void fs_init_bds(struct net_device *dev);
195void fs_cleanup_bds(struct net_device *dev); 146void fs_cleanup_bds(struct net_device *dev);
diff --git a/drivers/net/fs_enet/mac-fcc.c b/drivers/net/fs_enet/mac-fcc.c
index e990f728d51b..6094cbf542a2 100644
--- a/drivers/net/fs_enet/mac-fcc.c
+++ b/drivers/net/fs_enet/mac-fcc.c
@@ -42,6 +42,10 @@
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_device.h>
47#endif
48
45#include "fs_enet.h" 49#include "fs_enet.h"
46 50
47/*************************************************/ 51/*************************************************/
@@ -74,33 +78,64 @@
74 78
75#define MAX_CR_CMD_LOOPS 10000 79#define MAX_CR_CMD_LOOPS 10000
76 80
77static inline int fcc_cr_cmd(struct fs_enet_private *fep, u32 mcn, u32 op) 81static inline int fcc_cr_cmd(struct fs_enet_private *fep, u32 op)
78{ 82{
79 const struct fs_platform_info *fpi = fep->fpi; 83 const struct fs_platform_info *fpi = fep->fpi;
80 cpm2_map_t *immap = fs_enet_immap; 84 cpm2_map_t *immap = fs_enet_immap;
81 cpm_cpm2_t *cpmp = &immap->im_cpm; 85 cpm_cpm2_t *cpmp = &immap->im_cpm;
82 u32 v;
83 int i; 86 int i;
84 87
85 /* Currently I don't know what feature call will look like. But 88 W32(cpmp, cp_cpcr, fpi->cp_command | op | CPM_CR_FLG);
86 I guess there'd be something like do_cpm_cmd() which will require page & sblock */
87 v = mk_cr_cmd(fpi->cp_page, fpi->cp_block, mcn, op);
88 W32(cpmp, cp_cpcr, v | CPM_CR_FLG);
89 for (i = 0; i < MAX_CR_CMD_LOOPS; i++) 89 for (i = 0; i < MAX_CR_CMD_LOOPS; i++)
90 if ((R32(cpmp, cp_cpcr) & CPM_CR_FLG) == 0) 90 if ((R32(cpmp, cp_cpcr) & CPM_CR_FLG) == 0)
91 break; 91 return 0;
92
93 if (i >= MAX_CR_CMD_LOOPS) {
94 printk(KERN_ERR "%s(): Not able to issue CPM command\n",
95 __FUNCTION__);
96 return 1;
97 }
98 92
99 return 0; 93 printk(KERN_ERR "%s(): Not able to issue CPM command\n",
94 __FUNCTION__);
95 return 1;
100} 96}
101 97
102static int do_pd_setup(struct fs_enet_private *fep) 98static int do_pd_setup(struct fs_enet_private *fep)
103{ 99{
100#ifdef CONFIG_PPC_CPM_NEW_BINDING
101 struct of_device *ofdev = to_of_device(fep->dev);
102 struct fs_platform_info *fpi = fep->fpi;
103 int ret = -EINVAL;
104
105 fep->interrupt = of_irq_to_resource(ofdev->node, 0, NULL);
106 if (fep->interrupt == NO_IRQ)
107 goto out;
108
109 fep->fcc.fccp = of_iomap(ofdev->node, 0);
110 if (!fep->fcc.fccp)
111 goto out;
112
113 fep->fcc.ep = of_iomap(ofdev->node, 1);
114 if (!fep->fcc.ep)
115 goto out_fccp;
116
117 fep->fcc.fcccp = of_iomap(ofdev->node, 2);
118 if (!fep->fcc.fcccp)
119 goto out_ep;
120
121 fep->fcc.mem = (void *)cpm_dpalloc(128, 8);
122 fpi->dpram_offset = (u32)cpm2_immr;
123 if (IS_ERR_VALUE(fpi->dpram_offset)) {
124 ret = fpi->dpram_offset;
125 goto out_fcccp;
126 }
127
128 return 0;
129
130out_fcccp:
131 iounmap(fep->fcc.fcccp);
132out_ep:
133 iounmap(fep->fcc.ep);
134out_fccp:
135 iounmap(fep->fcc.fccp);
136out:
137 return ret;
138#else
104 struct platform_device *pdev = to_platform_device(fep->dev); 139 struct platform_device *pdev = to_platform_device(fep->dev);
105 struct resource *r; 140 struct resource *r;
106 141
@@ -138,6 +173,7 @@ static int do_pd_setup(struct fs_enet_private *fep)
138 return -EINVAL; 173 return -EINVAL;
139 174
140 return 0; 175 return 0;
176#endif
141} 177}
142 178
143#define FCC_NAPI_RX_EVENT_MSK (FCC_ENET_RXF | FCC_ENET_RXB) 179#define FCC_NAPI_RX_EVENT_MSK (FCC_ENET_RXF | FCC_ENET_RXB)
@@ -148,11 +184,17 @@ static int do_pd_setup(struct fs_enet_private *fep)
148static int setup_data(struct net_device *dev) 184static int setup_data(struct net_device *dev)
149{ 185{
150 struct fs_enet_private *fep = netdev_priv(dev); 186 struct fs_enet_private *fep = netdev_priv(dev);
151 const struct fs_platform_info *fpi = fep->fpi; 187#ifndef CONFIG_PPC_CPM_NEW_BINDING
188 struct fs_platform_info *fpi = fep->fpi;
189
190 fpi->cp_command = (fpi->cp_page << 26) |
191 (fpi->cp_block << 21) |
192 (12 << 6);
152 193
153 fep->fcc.idx = fs_get_fcc_index(fpi->fs_no); 194 fep->fcc.idx = fs_get_fcc_index(fpi->fs_no);
154 if ((unsigned int)fep->fcc.idx >= 3) /* max 3 FCCs */ 195 if ((unsigned int)fep->fcc.idx >= 3) /* max 3 FCCs */
155 return -EINVAL; 196 return -EINVAL;
197#endif
156 198
157 if (do_pd_setup(fep) != 0) 199 if (do_pd_setup(fep) != 0)
158 return -EINVAL; 200 return -EINVAL;
@@ -226,7 +268,7 @@ static void set_multicast_one(struct net_device *dev, const u8 *mac)
226 W16(ep, fen_taddrh, taddrh); 268 W16(ep, fen_taddrh, taddrh);
227 W16(ep, fen_taddrm, taddrm); 269 W16(ep, fen_taddrm, taddrm);
228 W16(ep, fen_taddrl, taddrl); 270 W16(ep, fen_taddrl, taddrl);
229 fcc_cr_cmd(fep, 0x0C, CPM_CR_SET_GADDR); 271 fcc_cr_cmd(fep, CPM_CR_SET_GADDR);
230} 272}
231 273
232static void set_multicast_finish(struct net_device *dev) 274static void set_multicast_finish(struct net_device *dev)
@@ -281,7 +323,7 @@ static void restart(struct net_device *dev)
281 323
282 /* clear everything (slow & steady does it) */ 324 /* clear everything (slow & steady does it) */
283 for (i = 0; i < sizeof(*ep); i++) 325 for (i = 0; i < sizeof(*ep); i++)
284 out_8((char *)ep + i, 0); 326 out_8((u8 __iomem *)ep + i, 0);
285 327
286 /* get physical address */ 328 /* get physical address */
287 rx_bd_base_phys = fep->ring_mem_addr; 329 rx_bd_base_phys = fep->ring_mem_addr;
@@ -397,7 +439,7 @@ static void restart(struct net_device *dev)
397 S8(fcccp, fcc_gfemr, 0x20); 439 S8(fcccp, fcc_gfemr, 0x20);
398 } 440 }
399 441
400 fcc_cr_cmd(fep, 0x0c, CPM_CR_INIT_TRX); 442 fcc_cr_cmd(fep, CPM_CR_INIT_TRX);
401 443
402 /* clear events */ 444 /* clear events */
403 W16(fccp, fcc_fcce, 0xffff); 445 W16(fccp, fcc_fcce, 0xffff);
@@ -515,23 +557,22 @@ int get_regs(struct net_device *dev, void *p, int *sizep)
515{ 557{
516 struct fs_enet_private *fep = netdev_priv(dev); 558 struct fs_enet_private *fep = netdev_priv(dev);
517 559
518 if (*sizep < sizeof(fcc_t) + sizeof(fcc_c_t) + sizeof(fcc_enet_t)) 560 if (*sizep < sizeof(fcc_t) + sizeof(fcc_enet_t) + 1)
519 return -EINVAL; 561 return -EINVAL;
520 562
521 memcpy_fromio(p, fep->fcc.fccp, sizeof(fcc_t)); 563 memcpy_fromio(p, fep->fcc.fccp, sizeof(fcc_t));
522 p = (char *)p + sizeof(fcc_t); 564 p = (char *)p + sizeof(fcc_t);
523 565
524 memcpy_fromio(p, fep->fcc.fcccp, sizeof(fcc_c_t));
525 p = (char *)p + sizeof(fcc_c_t);
526
527 memcpy_fromio(p, fep->fcc.ep, sizeof(fcc_enet_t)); 566 memcpy_fromio(p, fep->fcc.ep, sizeof(fcc_enet_t));
567 p = (char *)p + sizeof(fcc_enet_t);
528 568
569 memcpy_fromio(p, fep->fcc.fcccp, 1);
529 return 0; 570 return 0;
530} 571}
531 572
532int get_regs_len(struct net_device *dev) 573int get_regs_len(struct net_device *dev)
533{ 574{
534 return sizeof(fcc_t) + sizeof(fcc_c_t) + sizeof(fcc_enet_t); 575 return sizeof(fcc_t) + sizeof(fcc_enet_t) + 1;
535} 576}
536 577
537/* Some transmit errors cause the transmitter to shut 578/* Some transmit errors cause the transmitter to shut
@@ -551,7 +592,7 @@ void tx_restart(struct net_device *dev)
551 udelay(10); 592 udelay(10);
552 S32(fccp, fcc_gfmr, FCC_GFMR_ENT); 593 S32(fccp, fcc_gfmr, FCC_GFMR_ENT);
553 594
554 fcc_cr_cmd(fep, 0x0C, CPM_CR_RESTART_TX); 595 fcc_cr_cmd(fep, CPM_CR_RESTART_TX);
555} 596}
556 597
557/*************************************************************************/ 598/*************************************************************************/
diff --git a/drivers/net/fs_enet/mac-fec.c b/drivers/net/fs_enet/mac-fec.c
index cbdc17b743db..924d6617cd30 100644
--- a/drivers/net/fs_enet/mac-fec.c
+++ b/drivers/net/fs_enet/mac-fec.c
@@ -43,6 +43,10 @@
43#include <asm/commproc.h> 43#include <asm/commproc.h>
44#endif 44#endif
45 45
46#ifdef CONFIG_PPC_CPM_NEW_BINDING
47#include <asm/of_device.h>
48#endif
49
46#include "fs_enet.h" 50#include "fs_enet.h"
47#include "fec.h" 51#include "fec.h"
48 52
@@ -95,6 +99,19 @@ static int whack_reset(fec_t * fecp)
95 99
96static int do_pd_setup(struct fs_enet_private *fep) 100static int do_pd_setup(struct fs_enet_private *fep)
97{ 101{
102#ifdef CONFIG_PPC_CPM_NEW_BINDING
103 struct of_device *ofdev = to_of_device(fep->dev);
104
105 fep->interrupt = of_irq_to_resource(ofdev->node, 0, NULL);
106 if (fep->interrupt == NO_IRQ)
107 return -EINVAL;
108
109 fep->fec.fecp = of_iomap(ofdev->node, 0);
110 if (!fep->fcc.fccp)
111 return -EINVAL;
112
113 return 0;
114#else
98 struct platform_device *pdev = to_platform_device(fep->dev); 115 struct platform_device *pdev = to_platform_device(fep->dev);
99 struct resource *r; 116 struct resource *r;
100 117
@@ -110,7 +127,7 @@ static int do_pd_setup(struct fs_enet_private *fep)
110 return -EINVAL; 127 return -EINVAL;
111 128
112 return 0; 129 return 0;
113 130#endif
114} 131}
115 132
116#define FEC_NAPI_RX_EVENT_MSK (FEC_ENET_RXF | FEC_ENET_RXB) 133#define FEC_NAPI_RX_EVENT_MSK (FEC_ENET_RXF | FEC_ENET_RXB)
diff --git a/drivers/net/fs_enet/mac-scc.c b/drivers/net/fs_enet/mac-scc.c
index 6f32674a78e9..add9e32d4f47 100644
--- a/drivers/net/fs_enet/mac-scc.c
+++ b/drivers/net/fs_enet/mac-scc.c
@@ -43,6 +43,10 @@
43#include <asm/commproc.h> 43#include <asm/commproc.h>
44#endif 44#endif
45 45
46#ifdef CONFIG_PPC_CPM_NEW_BINDING
47#include <asm/of_platform.h>
48#endif
49
46#include "fs_enet.h" 50#include "fs_enet.h"
47 51
48/*************************************************/ 52/*************************************************/
@@ -89,27 +93,38 @@
89 93
90static inline int scc_cr_cmd(struct fs_enet_private *fep, u32 op) 94static inline int scc_cr_cmd(struct fs_enet_private *fep, u32 op)
91{ 95{
92 cpm8xx_t *cpmp = &((immap_t *)fs_enet_immap)->im_cpm; 96 const struct fs_platform_info *fpi = fep->fpi;
93 u32 v, ch; 97 int i;
94 int i = 0;
95 98
96 ch = fep->scc.idx << 2; 99 W16(cpmp, cp_cpcr, fpi->cp_command | CPM_CR_FLG | (op << 8));
97 v = mk_cr_cmd(ch, op);
98 W16(cpmp, cp_cpcr, v | CPM_CR_FLG);
99 for (i = 0; i < MAX_CR_CMD_LOOPS; i++) 100 for (i = 0; i < MAX_CR_CMD_LOOPS; i++)
100 if ((R16(cpmp, cp_cpcr) & CPM_CR_FLG) == 0) 101 if ((R16(cpmp, cp_cpcr) & CPM_CR_FLG) == 0)
101 break; 102 return 0;
102 103
103 if (i >= MAX_CR_CMD_LOOPS) { 104 printk(KERN_ERR "%s(): Not able to issue CPM command\n",
104 printk(KERN_ERR "%s(): Not able to issue CPM command\n", 105 __FUNCTION__);
105 __FUNCTION__); 106 return 1;
106 return 1;
107 }
108 return 0;
109} 107}
110 108
111static int do_pd_setup(struct fs_enet_private *fep) 109static int do_pd_setup(struct fs_enet_private *fep)
112{ 110{
111#ifdef CONFIG_PPC_CPM_NEW_BINDING
112 struct of_device *ofdev = to_of_device(fep->dev);
113
114 fep->interrupt = of_irq_to_resource(ofdev->node, 0, NULL);
115 if (fep->interrupt == NO_IRQ)
116 return -EINVAL;
117
118 fep->scc.sccp = of_iomap(ofdev->node, 0);
119 if (!fep->scc.sccp)
120 return -EINVAL;
121
122 fep->scc.ep = of_iomap(ofdev->node, 1);
123 if (!fep->scc.ep) {
124 iounmap(fep->scc.sccp);
125 return -EINVAL;
126 }
127#else
113 struct platform_device *pdev = to_platform_device(fep->dev); 128 struct platform_device *pdev = to_platform_device(fep->dev);
114 struct resource *r; 129 struct resource *r;
115 130
@@ -129,6 +144,7 @@ static int do_pd_setup(struct fs_enet_private *fep)
129 144
130 if (fep->scc.ep == NULL) 145 if (fep->scc.ep == NULL)
131 return -EINVAL; 146 return -EINVAL;
147#endif
132 148
133 return 0; 149 return 0;
134} 150}
@@ -141,12 +157,17 @@ static int do_pd_setup(struct fs_enet_private *fep)
141static int setup_data(struct net_device *dev) 157static int setup_data(struct net_device *dev)
142{ 158{
143 struct fs_enet_private *fep = netdev_priv(dev); 159 struct fs_enet_private *fep = netdev_priv(dev);
144 const struct fs_platform_info *fpi = fep->fpi; 160
161#ifdef CONFIG_PPC_CPM_NEW_BINDING
162 struct fs_platform_info *fpi = fep->fpi;
145 163
146 fep->scc.idx = fs_get_scc_index(fpi->fs_no); 164 fep->scc.idx = fs_get_scc_index(fpi->fs_no);
147 if ((unsigned int)fep->fcc.idx > 4) /* max 4 SCCs */ 165 if ((unsigned int)fep->fcc.idx >= 4) /* max 4 SCCs */
148 return -EINVAL; 166 return -EINVAL;
149 167
168 fpi->cp_command = fep->fcc.idx << 6;
169#endif
170
150 do_pd_setup(fep); 171 do_pd_setup(fep);
151 172
152 fep->scc.hthi = 0; 173 fep->scc.hthi = 0;
@@ -154,7 +175,7 @@ static int setup_data(struct net_device *dev)
154 175
155 fep->ev_napi_rx = SCC_NAPI_RX_EVENT_MSK; 176 fep->ev_napi_rx = SCC_NAPI_RX_EVENT_MSK;
156 fep->ev_rx = SCC_RX_EVENT; 177 fep->ev_rx = SCC_RX_EVENT;
157 fep->ev_tx = SCC_TX_EVENT; 178 fep->ev_tx = SCC_TX_EVENT | SCCE_ENET_TXE;
158 fep->ev_err = SCC_ERR_EVENT_MSK; 179 fep->ev_err = SCC_ERR_EVENT_MSK;
159 180
160 return 0; 181 return 0;
diff --git a/drivers/net/fs_enet/mii-bitbang.c b/drivers/net/fs_enet/mii-bitbang.c
index 422f82877873..7cf132f0f952 100644
--- a/drivers/net/fs_enet/mii-bitbang.c
+++ b/drivers/net/fs_enet/mii-bitbang.c
@@ -13,11 +13,6 @@
13 */ 13 */
14 14
15#include <linux/module.h> 15#include <linux/module.h>
16#include <linux/types.h>
17#include <linux/kernel.h>
18#include <linux/string.h>
19#include <linux/ptrace.h>
20#include <linux/errno.h>
21#include <linux/ioport.h> 16#include <linux/ioport.h>
22#include <linux/slab.h> 17#include <linux/slab.h>
23#include <linux/interrupt.h> 18#include <linux/interrupt.h>
@@ -25,86 +20,77 @@
25#include <linux/delay.h> 20#include <linux/delay.h>
26#include <linux/netdevice.h> 21#include <linux/netdevice.h>
27#include <linux/etherdevice.h> 22#include <linux/etherdevice.h>
28#include <linux/skbuff.h>
29#include <linux/spinlock.h>
30#include <linux/mii.h> 23#include <linux/mii.h>
31#include <linux/ethtool.h> 24#include <linux/ethtool.h>
32#include <linux/bitops.h> 25#include <linux/bitops.h>
33#include <linux/platform_device.h> 26#include <linux/platform_device.h>
34 27
35#include <asm/pgtable.h> 28#ifdef CONFIG_PPC_CPM_NEW_BINDING
36#include <asm/irq.h> 29#include <linux/of_platform.h>
37#include <asm/uaccess.h> 30#endif
38 31
39#include "fs_enet.h" 32#include "fs_enet.h"
40 33
41static int bitbang_prep_bit(u8 **datp, u8 *mskp, 34struct bb_info {
42 struct fs_mii_bit *mii_bit) 35 __be32 __iomem *dir;
43{ 36 __be32 __iomem *dat;
44 void *dat; 37 u32 mdio_msk;
45 int adv; 38 u32 mdc_msk;
46 u8 msk; 39 int delay;
47 40};
48 dat = (void*) mii_bit->offset;
49
50 adv = mii_bit->bit >> 3;
51 dat = (char *)dat + adv;
52
53 msk = 1 << (7 - (mii_bit->bit & 7));
54
55 *datp = dat;
56 *mskp = msk;
57
58 return 0;
59}
60 41
61static inline void bb_set(u8 *p, u8 m) 42/* FIXME: If any other users of GPIO crop up, then these will have to
43 * have some sort of global synchronization to avoid races with other
44 * pins on the same port. The ideal solution would probably be to
45 * bind the ports to a GPIO driver, and have this be a client of it.
46 */
47static inline void bb_set(u32 __iomem *p, u32 m)
62{ 48{
63 out_8(p, in_8(p) | m); 49 out_be32(p, in_be32(p) | m);
64} 50}
65 51
66static inline void bb_clr(u8 *p, u8 m) 52static inline void bb_clr(u32 __iomem *p, u32 m)
67{ 53{
68 out_8(p, in_8(p) & ~m); 54 out_be32(p, in_be32(p) & ~m);
69} 55}
70 56
71static inline int bb_read(u8 *p, u8 m) 57static inline int bb_read(u32 __iomem *p, u32 m)
72{ 58{
73 return (in_8(p) & m) != 0; 59 return (in_be32(p) & m) != 0;
74} 60}
75 61
76static inline void mdio_active(struct bb_info *bitbang) 62static inline void mdio_active(struct bb_info *bitbang)
77{ 63{
78 bb_set(bitbang->mdio_dir, bitbang->mdio_dir_msk); 64 bb_set(bitbang->dir, bitbang->mdio_msk);
79} 65}
80 66
81static inline void mdio_tristate(struct bb_info *bitbang ) 67static inline void mdio_tristate(struct bb_info *bitbang)
82{ 68{
83 bb_clr(bitbang->mdio_dir, bitbang->mdio_dir_msk); 69 bb_clr(bitbang->dir, bitbang->mdio_msk);
84} 70}
85 71
86static inline int mdio_read(struct bb_info *bitbang ) 72static inline int mdio_read(struct bb_info *bitbang)
87{ 73{
88 return bb_read(bitbang->mdio_dat, bitbang->mdio_dat_msk); 74 return bb_read(bitbang->dat, bitbang->mdio_msk);
89} 75}
90 76
91static inline void mdio(struct bb_info *bitbang , int what) 77static inline void mdio(struct bb_info *bitbang, int what)
92{ 78{
93 if (what) 79 if (what)
94 bb_set(bitbang->mdio_dat, bitbang->mdio_dat_msk); 80 bb_set(bitbang->dat, bitbang->mdio_msk);
95 else 81 else
96 bb_clr(bitbang->mdio_dat, bitbang->mdio_dat_msk); 82 bb_clr(bitbang->dat, bitbang->mdio_msk);
97} 83}
98 84
99static inline void mdc(struct bb_info *bitbang , int what) 85static inline void mdc(struct bb_info *bitbang, int what)
100{ 86{
101 if (what) 87 if (what)
102 bb_set(bitbang->mdc_dat, bitbang->mdc_msk); 88 bb_set(bitbang->dat, bitbang->mdc_msk);
103 else 89 else
104 bb_clr(bitbang->mdc_dat, bitbang->mdc_msk); 90 bb_clr(bitbang->dat, bitbang->mdc_msk);
105} 91}
106 92
107static inline void mii_delay(struct bb_info *bitbang ) 93static inline void mii_delay(struct bb_info *bitbang)
108{ 94{
109 udelay(bitbang->delay); 95 udelay(bitbang->delay);
110} 96}
@@ -280,29 +266,178 @@ static int fs_enet_mii_bb_reset(struct mii_bus *bus)
280 return 0; 266 return 0;
281} 267}
282 268
283static int fs_mii_bitbang_init(struct bb_info *bitbang, struct fs_mii_bb_platform_info* fmpi) 269#ifdef CONFIG_PPC_CPM_NEW_BINDING
270static int __devinit fs_mii_bitbang_init(struct mii_bus *bus,
271 struct device_node *np)
284{ 272{
285 int r; 273 struct resource res;
274 const u32 *data;
275 int mdio_pin, mdc_pin, len;
276 struct bb_info *bitbang = bus->priv;
286 277
287 bitbang->delay = fmpi->delay; 278 int ret = of_address_to_resource(np, 0, &res);
279 if (ret)
280 return ret;
281
282 if (res.end - res.start < 13)
283 return -ENODEV;
284
285 /* This should really encode the pin number as well, but all
286 * we get is an int, and the odds of multiple bitbang mdio buses
287 * is low enough that it's not worth going too crazy.
288 */
289 bus->id = res.start;
290
291 data = of_get_property(np, "fsl,mdio-pin", &len);
292 if (!data || len != 4)
293 return -ENODEV;
294 mdio_pin = *data;
295
296 data = of_get_property(np, "fsl,mdc-pin", &len);
297 if (!data || len != 4)
298 return -ENODEV;
299 mdc_pin = *data;
300
301 bitbang->dir = ioremap(res.start, res.end - res.start + 1);
302 if (!bitbang->dir)
303 return -ENOMEM;
304
305 bitbang->dat = bitbang->dir + 4;
306 bitbang->mdio_msk = 1 << (31 - mdio_pin);
307 bitbang->mdc_msk = 1 << (31 - mdc_pin);
308 bitbang->delay = 1; /* 1 us between operations */
288 309
289 r = bitbang_prep_bit(&bitbang->mdio_dir, 310 return 0;
290 &bitbang->mdio_dir_msk, 311}
291 &fmpi->mdio_dir); 312
292 if (r != 0) 313static void __devinit add_phy(struct mii_bus *bus, struct device_node *np)
293 return r; 314{
294 315 const u32 *data;
295 r = bitbang_prep_bit(&bitbang->mdio_dat, 316 int len, id, irq;
296 &bitbang->mdio_dat_msk, 317
297 &fmpi->mdio_dat); 318 data = of_get_property(np, "reg", &len);
298 if (r != 0) 319 if (!data || len != 4)
299 return r; 320 return;
300 321
301 r = bitbang_prep_bit(&bitbang->mdc_dat, 322 id = *data;
302 &bitbang->mdc_msk, 323 bus->phy_mask &= ~(1 << id);
303 &fmpi->mdc_dat); 324
304 if (r != 0) 325 irq = of_irq_to_resource(np, 0, NULL);
305 return r; 326 if (irq != NO_IRQ)
327 bus->irq[id] = irq;
328}
329
330static int __devinit fs_enet_mdio_probe(struct of_device *ofdev,
331 const struct of_device_id *match)
332{
333 struct device_node *np = NULL;
334 struct mii_bus *new_bus;
335 struct bb_info *bitbang;
336 int ret = -ENOMEM;
337 int i;
338
339 new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL);
340 if (!new_bus)
341 goto out;
342
343 bitbang = kzalloc(sizeof(struct bb_info), GFP_KERNEL);
344 if (!bitbang)
345 goto out_free_bus;
346
347 new_bus->priv = bitbang;
348 new_bus->name = "CPM2 Bitbanged MII",
349 new_bus->read = &fs_enet_mii_bb_read,
350 new_bus->write = &fs_enet_mii_bb_write,
351 new_bus->reset = &fs_enet_mii_bb_reset,
352
353 ret = fs_mii_bitbang_init(new_bus, ofdev->node);
354 if (ret)
355 goto out_free_bitbang;
356
357 new_bus->phy_mask = ~0;
358 new_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
359 if (!new_bus->irq)
360 goto out_unmap_regs;
361
362 for (i = 0; i < PHY_MAX_ADDR; i++)
363 new_bus->irq[i] = -1;
364
365 while ((np = of_get_next_child(ofdev->node, np)))
366 if (!strcmp(np->type, "ethernet-phy"))
367 add_phy(new_bus, np);
368
369 new_bus->dev = &ofdev->dev;
370 dev_set_drvdata(&ofdev->dev, new_bus);
371
372 ret = mdiobus_register(new_bus);
373 if (ret)
374 goto out_free_irqs;
375
376 return 0;
377
378out_free_irqs:
379 dev_set_drvdata(&ofdev->dev, NULL);
380 kfree(new_bus->irq);
381out_unmap_regs:
382 iounmap(bitbang->dir);
383out_free_bitbang:
384 kfree(bitbang);
385out_free_bus:
386 kfree(new_bus);
387out:
388 return ret;
389}
390
391static int fs_enet_mdio_remove(struct of_device *ofdev)
392{
393 struct mii_bus *bus = dev_get_drvdata(&ofdev->dev);
394 struct bb_info *bitbang = bus->priv;
395
396 mdiobus_unregister(bus);
397 dev_set_drvdata(&ofdev->dev, NULL);
398 kfree(bus->irq);
399 iounmap(bitbang->dir);
400 kfree(bitbang);
401 kfree(bus);
402
403 return 0;
404}
405
406static struct of_device_id fs_enet_mdio_bb_match[] = {
407 {
408 .compatible = "fsl,cpm2-mdio-bitbang",
409 },
410 {},
411};
412
413static struct of_platform_driver fs_enet_bb_mdio_driver = {
414 .name = "fsl-bb-mdio",
415 .match_table = fs_enet_mdio_bb_match,
416 .probe = fs_enet_mdio_probe,
417 .remove = fs_enet_mdio_remove,
418};
419
420int fs_enet_mdio_bb_init(void)
421{
422 return of_register_platform_driver(&fs_enet_bb_mdio_driver);
423}
424
425void fs_enet_mdio_bb_exit(void)
426{
427 of_unregister_platform_driver(&fs_enet_bb_mdio_driver);
428}
429
430module_init(fs_enet_mdio_bb_init);
431module_exit(fs_enet_mdio_bb_exit);
432#else
433static int __devinit fs_mii_bitbang_init(struct bb_info *bitbang,
434 struct fs_mii_bb_platform_info *fmpi)
435{
436 bitbang->dir = (u32 __iomem *)fmpi->mdio_dir.offset;
437 bitbang->dat = (u32 __iomem *)fmpi->mdio_dat.offset;
438 bitbang->mdio_msk = 1U << (31 - fmpi->mdio_dat.bit);
439 bitbang->mdc_msk = 1U << (31 - fmpi->mdc_dat.bit);
440 bitbang->delay = fmpi->delay;
306 441
307 return 0; 442 return 0;
308} 443}
diff --git a/drivers/net/fs_enet/mii-fec.c b/drivers/net/fs_enet/mii-fec.c
index 53db696b948f..f91c38d0b57b 100644
--- a/drivers/net/fs_enet/mii-fec.c
+++ b/drivers/net/fs_enet/mii-fec.c
@@ -36,6 +36,10 @@
36#include <asm/irq.h> 36#include <asm/irq.h>
37#include <asm/uaccess.h> 37#include <asm/uaccess.h>
38 38
39#ifdef CONFIG_PPC_CPM_NEW_BINDING
40#include <asm/of_platform.h>
41#endif
42
39#include "fs_enet.h" 43#include "fs_enet.h"
40#include "fec.h" 44#include "fec.h"
41 45
@@ -47,6 +51,7 @@
47 51
48#define FEC_MII_LOOPS 10000 52#define FEC_MII_LOOPS 10000
49 53
54#ifndef CONFIG_PPC_CPM_NEW_BINDING
50static int match_has_phy (struct device *dev, void* data) 55static int match_has_phy (struct device *dev, void* data)
51{ 56{
52 struct platform_device* pdev = container_of(dev, struct platform_device, dev); 57 struct platform_device* pdev = container_of(dev, struct platform_device, dev);
@@ -90,6 +95,7 @@ static int fs_mii_fec_init(struct fec_info* fec, struct fs_mii_fec_platform_info
90 95
91 return 0; 96 return 0;
92} 97}
98#endif
93 99
94static int fs_enet_fec_mii_read(struct mii_bus *bus , int phy_id, int location) 100static int fs_enet_fec_mii_read(struct mii_bus *bus , int phy_id, int location)
95{ 101{
@@ -145,6 +151,141 @@ static int fs_enet_fec_mii_reset(struct mii_bus *bus)
145 return 0; 151 return 0;
146} 152}
147 153
154#ifdef CONFIG_PPC_CPM_NEW_BINDING
155static void __devinit add_phy(struct mii_bus *bus, struct device_node *np)
156{
157 const u32 *data;
158 int len, id, irq;
159
160 data = of_get_property(np, "reg", &len);
161 if (!data || len != 4)
162 return;
163
164 id = *data;
165 bus->phy_mask &= ~(1 << id);
166
167 irq = of_irq_to_resource(np, 0, NULL);
168 if (irq != NO_IRQ)
169 bus->irq[id] = irq;
170}
171
172static int __devinit fs_enet_mdio_probe(struct of_device *ofdev,
173 const struct of_device_id *match)
174{
175 struct device_node *np = NULL;
176 struct resource res;
177 struct mii_bus *new_bus;
178 struct fec_info *fec;
179 int ret = -ENOMEM, i;
180
181 new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL);
182 if (!new_bus)
183 goto out;
184
185 fec = kzalloc(sizeof(struct fec_info), GFP_KERNEL);
186 if (!fec)
187 goto out_mii;
188
189 new_bus->priv = fec;
190 new_bus->name = "FEC MII Bus";
191 new_bus->read = &fs_enet_fec_mii_read;
192 new_bus->write = &fs_enet_fec_mii_write;
193 new_bus->reset = &fs_enet_fec_mii_reset;
194
195 ret = of_address_to_resource(ofdev->node, 0, &res);
196 if (ret)
197 return ret;
198
199 new_bus->id = res.start;
200
201 fec->fecp = ioremap(res.start, res.end - res.start + 1);
202 if (!fec->fecp)
203 goto out_fec;
204
205 fec->mii_speed = ((ppc_proc_freq + 4999999) / 5000000) << 1;
206
207 setbits32(&fec->fecp->fec_r_cntrl, FEC_RCNTRL_MII_MODE);
208 setbits32(&fec->fecp->fec_ecntrl, FEC_ECNTRL_PINMUX |
209 FEC_ECNTRL_ETHER_EN);
210 out_be32(&fec->fecp->fec_ievent, FEC_ENET_MII);
211 out_be32(&fec->fecp->fec_mii_speed, fec->mii_speed);
212
213 new_bus->phy_mask = ~0;
214 new_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
215 if (!new_bus->irq)
216 goto out_unmap_regs;
217
218 for (i = 0; i < PHY_MAX_ADDR; i++)
219 new_bus->irq[i] = -1;
220
221 while ((np = of_get_next_child(ofdev->node, np)))
222 if (!strcmp(np->type, "ethernet-phy"))
223 add_phy(new_bus, np);
224
225 new_bus->dev = &ofdev->dev;
226 dev_set_drvdata(&ofdev->dev, new_bus);
227
228 ret = mdiobus_register(new_bus);
229 if (ret)
230 goto out_free_irqs;
231
232 return 0;
233
234out_free_irqs:
235 dev_set_drvdata(&ofdev->dev, NULL);
236 kfree(new_bus->irq);
237out_unmap_regs:
238 iounmap(fec->fecp);
239out_fec:
240 kfree(fec);
241out_mii:
242 kfree(new_bus);
243out:
244 return ret;
245}
246
247static int fs_enet_mdio_remove(struct of_device *ofdev)
248{
249 struct mii_bus *bus = dev_get_drvdata(&ofdev->dev);
250 struct fec_info *fec = bus->priv;
251
252 mdiobus_unregister(bus);
253 dev_set_drvdata(&ofdev->dev, NULL);
254 kfree(bus->irq);
255 iounmap(fec->fecp);
256 kfree(fec);
257 kfree(bus);
258
259 return 0;
260}
261
262static struct of_device_id fs_enet_mdio_fec_match[] = {
263 {
264 .compatible = "fsl,pq1-fec-mdio",
265 },
266 {},
267};
268
269static struct of_platform_driver fs_enet_fec_mdio_driver = {
270 .name = "fsl-fec-mdio",
271 .match_table = fs_enet_mdio_fec_match,
272 .probe = fs_enet_mdio_probe,
273 .remove = fs_enet_mdio_remove,
274};
275
276static int fs_enet_mdio_fec_init(void)
277{
278 return of_register_platform_driver(&fs_enet_fec_mdio_driver);
279}
280
281static void fs_enet_mdio_fec_exit(void)
282{
283 of_unregister_platform_driver(&fs_enet_fec_mdio_driver);
284}
285
286module_init(fs_enet_mdio_fec_init);
287module_exit(fs_enet_mdio_fec_exit);
288#else
148static int __devinit fs_enet_fec_mdio_probe(struct device *dev) 289static int __devinit fs_enet_fec_mdio_probe(struct device *dev)
149{ 290{
150 struct platform_device *pdev = to_platform_device(dev); 291 struct platform_device *pdev = to_platform_device(dev);
@@ -235,4 +376,4 @@ void fs_enet_mdio_fec_exit(void)
235{ 376{
236 driver_unregister(&fs_enet_fec_mdio_driver); 377 driver_unregister(&fs_enet_fec_mdio_driver);
237} 378}
238 379#endif