aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/fs_enet/mii-fec.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/fs_enet/mii-fec.c')
-rw-r--r--drivers/net/fs_enet/mii-fec.c143
1 files changed, 142 insertions, 1 deletions
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