aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/fs_enet/mii-fec.c
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/fs_enet/mii-fec.c
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/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