aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/fsl_pq_mdio.c
diff options
context:
space:
mode:
authorAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
committerAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
commitada47b5fe13d89735805b566185f4885f5a3f750 (patch)
tree644b88f8a71896307d71438e9b3af49126ffb22b /drivers/net/fsl_pq_mdio.c
parent43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff)
parent3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff)
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/net/fsl_pq_mdio.c')
-rw-r--r--drivers/net/fsl_pq_mdio.c99
1 files changed, 79 insertions, 20 deletions
diff --git a/drivers/net/fsl_pq_mdio.c b/drivers/net/fsl_pq_mdio.c
index efbf67689eca..3acac5f930c8 100644
--- a/drivers/net/fsl_pq_mdio.c
+++ b/drivers/net/fsl_pq_mdio.c
@@ -3,8 +3,9 @@
3 * Provides Bus interface for MIIM regs 3 * Provides Bus interface for MIIM regs
4 * 4 *
5 * Author: Andy Fleming <afleming@freescale.com> 5 * Author: Andy Fleming <afleming@freescale.com>
6 * Modifier: Sandeep Gopalpet <sandeep.kumar@freescale.com>
6 * 7 *
7 * Copyright (c) 2002-2004,2008 Freescale Semiconductor, Inc. 8 * Copyright 2002-2004, 2008-2009 Freescale Semiconductor, Inc.
8 * 9 *
9 * Based on gianfar_mii.c and ucc_geth_mii.c (Li Yang, Kim Phillips) 10 * Based on gianfar_mii.c and ucc_geth_mii.c (Li Yang, Kim Phillips)
10 * 11 *
@@ -45,6 +46,11 @@
45#include "gianfar.h" 46#include "gianfar.h"
46#include "fsl_pq_mdio.h" 47#include "fsl_pq_mdio.h"
47 48
49struct fsl_pq_mdio_priv {
50 void __iomem *map;
51 struct fsl_pq_mdio __iomem *regs;
52};
53
48/* 54/*
49 * Write value to the PHY at mii_id at register regnum, 55 * Write value to the PHY at mii_id at register regnum,
50 * on the bus attached to the local interface, which may be different from the 56 * on the bus attached to the local interface, which may be different from the
@@ -102,13 +108,20 @@ int fsl_pq_local_mdio_read(struct fsl_pq_mdio __iomem *regs,
102 return value; 108 return value;
103} 109}
104 110
111static struct fsl_pq_mdio __iomem *fsl_pq_mdio_get_regs(struct mii_bus *bus)
112{
113 struct fsl_pq_mdio_priv *priv = bus->priv;
114
115 return priv->regs;
116}
117
105/* 118/*
106 * Write value to the PHY at mii_id at register regnum, 119 * Write value to the PHY at mii_id at register regnum,
107 * on the bus, waiting until the write is done before returning. 120 * on the bus, waiting until the write is done before returning.
108 */ 121 */
109int fsl_pq_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value) 122int fsl_pq_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value)
110{ 123{
111 struct fsl_pq_mdio __iomem *regs = (void __iomem *)bus->priv; 124 struct fsl_pq_mdio __iomem *regs = fsl_pq_mdio_get_regs(bus);
112 125
113 /* Write to the local MII regs */ 126 /* Write to the local MII regs */
114 return(fsl_pq_local_mdio_write(regs, mii_id, regnum, value)); 127 return(fsl_pq_local_mdio_write(regs, mii_id, regnum, value));
@@ -120,7 +133,7 @@ int fsl_pq_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value)
120 */ 133 */
121int fsl_pq_mdio_read(struct mii_bus *bus, int mii_id, int regnum) 134int fsl_pq_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
122{ 135{
123 struct fsl_pq_mdio __iomem *regs = (void __iomem *)bus->priv; 136 struct fsl_pq_mdio __iomem *regs = fsl_pq_mdio_get_regs(bus);
124 137
125 /* Read the local MII regs */ 138 /* Read the local MII regs */
126 return(fsl_pq_local_mdio_read(regs, mii_id, regnum)); 139 return(fsl_pq_local_mdio_read(regs, mii_id, regnum));
@@ -129,7 +142,7 @@ int fsl_pq_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
129/* Reset the MIIM registers, and wait for the bus to free */ 142/* Reset the MIIM registers, and wait for the bus to free */
130static int fsl_pq_mdio_reset(struct mii_bus *bus) 143static int fsl_pq_mdio_reset(struct mii_bus *bus)
131{ 144{
132 struct fsl_pq_mdio __iomem *regs = (void __iomem *)bus->priv; 145 struct fsl_pq_mdio __iomem *regs = fsl_pq_mdio_get_regs(bus);
133 int timeout = PHY_INIT_TIMEOUT; 146 int timeout = PHY_INIT_TIMEOUT;
134 147
135 mutex_lock(&bus->mdio_lock); 148 mutex_lock(&bus->mdio_lock);
@@ -189,7 +202,7 @@ static int fsl_pq_mdio_find_free(struct mii_bus *new_bus)
189 202
190 203
191#if defined(CONFIG_GIANFAR) || defined(CONFIG_GIANFAR_MODULE) 204#if defined(CONFIG_GIANFAR) || defined(CONFIG_GIANFAR_MODULE)
192static u32 __iomem *get_gfar_tbipa(struct fsl_pq_mdio __iomem *regs) 205static u32 __iomem *get_gfar_tbipa(struct fsl_pq_mdio __iomem *regs, struct device_node *np)
193{ 206{
194 struct gfar __iomem *enet_regs; 207 struct gfar __iomem *enet_regs;
195 208
@@ -198,10 +211,16 @@ static u32 __iomem *get_gfar_tbipa(struct fsl_pq_mdio __iomem *regs)
198 * Also, we have to cast back to struct gfar because of 211 * Also, we have to cast back to struct gfar because of
199 * definition weirdness done in gianfar.h. 212 * definition weirdness done in gianfar.h.
200 */ 213 */
201 enet_regs = (struct gfar __iomem *) 214 if(of_device_is_compatible(np, "fsl,gianfar-mdio") ||
202 ((char __iomem *)regs - offsetof(struct gfar, gfar_mii_regs)); 215 of_device_is_compatible(np, "fsl,gianfar-tbi") ||
203 216 of_device_is_compatible(np, "gianfar")) {
204 return &enet_regs->tbipa; 217 enet_regs = (struct gfar __iomem *)regs;
218 return &enet_regs->tbipa;
219 } else if (of_device_is_compatible(np, "fsl,etsec2-mdio") ||
220 of_device_is_compatible(np, "fsl,etsec2-tbi")) {
221 return of_iomap(np, 1);
222 } else
223 return NULL;
205} 224}
206#endif 225#endif
207 226
@@ -250,33 +269,58 @@ static int fsl_pq_mdio_probe(struct of_device *ofdev,
250{ 269{
251 struct device_node *np = ofdev->node; 270 struct device_node *np = ofdev->node;
252 struct device_node *tbi; 271 struct device_node *tbi;
253 struct fsl_pq_mdio __iomem *regs; 272 struct fsl_pq_mdio_priv *priv;
273 struct fsl_pq_mdio __iomem *regs = NULL;
274 void __iomem *map;
254 u32 __iomem *tbipa; 275 u32 __iomem *tbipa;
255 struct mii_bus *new_bus; 276 struct mii_bus *new_bus;
256 int tbiaddr = -1; 277 int tbiaddr = -1;
257 u64 addr, size; 278 const u32 *addrp;
279 u64 addr = 0, size = 0;
258 int err = 0; 280 int err = 0;
259 281
282 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
283 if (!priv)
284 return -ENOMEM;
285
260 new_bus = mdiobus_alloc(); 286 new_bus = mdiobus_alloc();
261 if (NULL == new_bus) 287 if (NULL == new_bus)
262 return -ENOMEM; 288 goto err_free_priv;
263 289
264 new_bus->name = "Freescale PowerQUICC MII Bus", 290 new_bus->name = "Freescale PowerQUICC MII Bus",
265 new_bus->read = &fsl_pq_mdio_read, 291 new_bus->read = &fsl_pq_mdio_read,
266 new_bus->write = &fsl_pq_mdio_write, 292 new_bus->write = &fsl_pq_mdio_write,
267 new_bus->reset = &fsl_pq_mdio_reset, 293 new_bus->reset = &fsl_pq_mdio_reset,
294 new_bus->priv = priv;
268 fsl_pq_mdio_bus_name(new_bus->id, np); 295 fsl_pq_mdio_bus_name(new_bus->id, np);
269 296
297 addrp = of_get_address(np, 0, &size, NULL);
298 if (!addrp) {
299 err = -EINVAL;
300 goto err_free_bus;
301 }
302
270 /* Set the PHY base address */ 303 /* Set the PHY base address */
271 addr = of_translate_address(np, of_get_address(np, 0, &size, NULL)); 304 addr = of_translate_address(np, addrp);
272 regs = ioremap(addr, size); 305 if (addr == OF_BAD_ADDR) {
306 err = -EINVAL;
307 goto err_free_bus;
308 }
273 309
274 if (NULL == regs) { 310 map = ioremap(addr, size);
311 if (!map) {
275 err = -ENOMEM; 312 err = -ENOMEM;
276 goto err_free_bus; 313 goto err_free_bus;
277 } 314 }
315 priv->map = map;
278 316
279 new_bus->priv = (void __force *)regs; 317 if (of_device_is_compatible(np, "fsl,gianfar-mdio") ||
318 of_device_is_compatible(np, "fsl,gianfar-tbi") ||
319 of_device_is_compatible(np, "fsl,ucc-mdio") ||
320 of_device_is_compatible(np, "ucc_geth_phy"))
321 map -= offsetof(struct fsl_pq_mdio, miimcfg);
322 regs = map;
323 priv->regs = regs;
280 324
281 new_bus->irq = kcalloc(PHY_MAX_ADDR, sizeof(int), GFP_KERNEL); 325 new_bus->irq = kcalloc(PHY_MAX_ADDR, sizeof(int), GFP_KERNEL);
282 326
@@ -290,9 +334,15 @@ static int fsl_pq_mdio_probe(struct of_device *ofdev,
290 334
291 if (of_device_is_compatible(np, "fsl,gianfar-mdio") || 335 if (of_device_is_compatible(np, "fsl,gianfar-mdio") ||
292 of_device_is_compatible(np, "fsl,gianfar-tbi") || 336 of_device_is_compatible(np, "fsl,gianfar-tbi") ||
337 of_device_is_compatible(np, "fsl,etsec2-mdio") ||
338 of_device_is_compatible(np, "fsl,etsec2-tbi") ||
293 of_device_is_compatible(np, "gianfar")) { 339 of_device_is_compatible(np, "gianfar")) {
294#if defined(CONFIG_GIANFAR) || defined(CONFIG_GIANFAR_MODULE) 340#if defined(CONFIG_GIANFAR) || defined(CONFIG_GIANFAR_MODULE)
295 tbipa = get_gfar_tbipa(regs); 341 tbipa = get_gfar_tbipa(regs, np);
342 if (!tbipa) {
343 err = -EINVAL;
344 goto err_free_irqs;
345 }
296#else 346#else
297 err = -ENODEV; 347 err = -ENODEV;
298 goto err_free_irqs; 348 goto err_free_irqs;
@@ -363,10 +413,11 @@ static int fsl_pq_mdio_probe(struct of_device *ofdev,
363err_free_irqs: 413err_free_irqs:
364 kfree(new_bus->irq); 414 kfree(new_bus->irq);
365err_unmap_regs: 415err_unmap_regs:
366 iounmap(regs); 416 iounmap(priv->map);
367err_free_bus: 417err_free_bus:
368 kfree(new_bus); 418 kfree(new_bus);
369 419err_free_priv:
420 kfree(priv);
370 return err; 421 return err;
371} 422}
372 423
@@ -375,14 +426,16 @@ static int fsl_pq_mdio_remove(struct of_device *ofdev)
375{ 426{
376 struct device *device = &ofdev->dev; 427 struct device *device = &ofdev->dev;
377 struct mii_bus *bus = dev_get_drvdata(device); 428 struct mii_bus *bus = dev_get_drvdata(device);
429 struct fsl_pq_mdio_priv *priv = bus->priv;
378 430
379 mdiobus_unregister(bus); 431 mdiobus_unregister(bus);
380 432
381 dev_set_drvdata(device, NULL); 433 dev_set_drvdata(device, NULL);
382 434
383 iounmap((void __iomem *)bus->priv); 435 iounmap(priv->map);
384 bus->priv = NULL; 436 bus->priv = NULL;
385 mdiobus_free(bus); 437 mdiobus_free(bus);
438 kfree(priv);
386 439
387 return 0; 440 return 0;
388} 441}
@@ -405,6 +458,12 @@ static struct of_device_id fsl_pq_mdio_match[] = {
405 { 458 {
406 .compatible = "fsl,gianfar-mdio", 459 .compatible = "fsl,gianfar-mdio",
407 }, 460 },
461 {
462 .compatible = "fsl,etsec2-tbi",
463 },
464 {
465 .compatible = "fsl,etsec2-mdio",
466 },
408 {}, 467 {},
409}; 468};
410MODULE_DEVICE_TABLE(of, fsl_pq_mdio_match); 469MODULE_DEVICE_TABLE(of, fsl_pq_mdio_match);