aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorScott Wood <scottwood@freescale.com>2007-10-02 11:55:58 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-10 19:54:03 -0400
commit976de6a8c304dcc43e38efcb8a0bace7866b6242 (patch)
treebae132693bbcfa65c03cf44c7db924fdebf13158 /drivers/net
parent0d0d9c150c046cbd3e507adcfa2d78db82f1f452 (diff)
fs_enet: Be an of_platform device when CONFIG_PPC_CPM_NEW_BINDING is set.
The existing OF glue code was crufty and broken. Rather than fix it, it will be removed, and the ethernet driver now talks to the device tree directly. The old, non-CONFIG_PPC_CPM_NEW_BINDING code can go away once CPM platforms are dropped from arch/ppc (which will hopefully be soon), and existing arch/powerpc boards that I wasn't able to test on for this patchset get converted (which should be even sooner). Signed-off-by: Scott Wood <scottwood@freescale.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net')
-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