aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/gianfar_mii.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/gianfar_mii.c')
-rw-r--r--drivers/net/gianfar_mii.c212
1 files changed, 144 insertions, 68 deletions
diff --git a/drivers/net/gianfar_mii.c b/drivers/net/gianfar_mii.c
index 0e2595d24933..f3706e415b45 100644
--- a/drivers/net/gianfar_mii.c
+++ b/drivers/net/gianfar_mii.c
@@ -34,6 +34,8 @@
34#include <linux/crc32.h> 34#include <linux/crc32.h>
35#include <linux/mii.h> 35#include <linux/mii.h>
36#include <linux/phy.h> 36#include <linux/phy.h>
37#include <linux/of.h>
38#include <linux/of_platform.h>
37 39
38#include <asm/io.h> 40#include <asm/io.h>
39#include <asm/irq.h> 41#include <asm/irq.h>
@@ -150,19 +152,83 @@ static int gfar_mdio_reset(struct mii_bus *bus)
150 return 0; 152 return 0;
151} 153}
152 154
155/* Allocate an array which provides irq #s for each PHY on the given bus */
156static int *create_irq_map(struct device_node *np)
157{
158 int *irqs;
159 int i;
160 struct device_node *child = NULL;
161
162 irqs = kcalloc(PHY_MAX_ADDR, sizeof(int), GFP_KERNEL);
163
164 if (!irqs)
165 return NULL;
166
167 for (i = 0; i < PHY_MAX_ADDR; i++)
168 irqs[i] = PHY_POLL;
169
170 while ((child = of_get_next_child(np, child)) != NULL) {
171 int irq = irq_of_parse_and_map(child, 0);
172 const u32 *id;
173
174 if (irq == NO_IRQ)
175 continue;
176
177 id = of_get_property(child, "reg", NULL);
178
179 if (!id)
180 continue;
181
182 if (*id < PHY_MAX_ADDR && *id >= 0)
183 irqs[*id] = irq;
184 else
185 printk(KERN_WARNING "%s: "
186 "%d is not a valid PHY address\n",
187 np->full_name, *id);
188 }
189
190 return irqs;
191}
192
193
194void gfar_mdio_bus_name(char *name, struct device_node *np)
195{
196 const u32 *reg;
197
198 reg = of_get_property(np, "reg", NULL);
153 199
154static int gfar_mdio_probe(struct device *dev) 200 snprintf(name, MII_BUS_ID_SIZE, "%s@%x", np->name, reg ? *reg : 0);
201}
202
203/* Scan the bus in reverse, looking for an empty spot */
204static int gfar_mdio_find_free(struct mii_bus *new_bus)
205{
206 int i;
207
208 for (i = PHY_MAX_ADDR; i > 0; i--) {
209 u32 phy_id;
210
211 if (get_phy_id(new_bus, i, &phy_id))
212 return -1;
213
214 if (phy_id == 0xffffffff)
215 break;
216 }
217
218 return i;
219}
220
221static int gfar_mdio_probe(struct of_device *ofdev,
222 const struct of_device_id *match)
155{ 223{
156 struct platform_device *pdev = to_platform_device(dev);
157 struct gianfar_mdio_data *pdata;
158 struct gfar_mii __iomem *regs; 224 struct gfar_mii __iomem *regs;
159 struct gfar __iomem *enet_regs; 225 struct gfar __iomem *enet_regs;
160 struct mii_bus *new_bus; 226 struct mii_bus *new_bus;
161 struct resource *r; 227 int err = 0;
162 int i, err = 0; 228 u64 addr, size;
163 229 struct device_node *np = ofdev->node;
164 if (NULL == dev) 230 struct device_node *tbi;
165 return -EINVAL; 231 int tbiaddr = -1;
166 232
167 new_bus = mdiobus_alloc(); 233 new_bus = mdiobus_alloc();
168 if (NULL == new_bus) 234 if (NULL == new_bus)
@@ -172,31 +238,28 @@ static int gfar_mdio_probe(struct device *dev)
172 new_bus->read = &gfar_mdio_read, 238 new_bus->read = &gfar_mdio_read,
173 new_bus->write = &gfar_mdio_write, 239 new_bus->write = &gfar_mdio_write,
174 new_bus->reset = &gfar_mdio_reset, 240 new_bus->reset = &gfar_mdio_reset,
175 snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", pdev->id); 241 gfar_mdio_bus_name(new_bus->id, np);
176
177 pdata = (struct gianfar_mdio_data *)pdev->dev.platform_data;
178
179 if (NULL == pdata) {
180 printk(KERN_ERR "gfar mdio %d: Missing platform data!\n", pdev->id);
181 return -ENODEV;
182 }
183
184 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
185 242
186 /* Set the PHY base address */ 243 /* Set the PHY base address */
187 regs = ioremap(r->start, sizeof (struct gfar_mii)); 244 addr = of_translate_address(np, of_get_address(np, 0, &size, NULL));
245 regs = ioremap(addr, size);
188 246
189 if (NULL == regs) { 247 if (NULL == regs) {
190 err = -ENOMEM; 248 err = -ENOMEM;
191 goto reg_map_fail; 249 goto err_free_bus;
192 } 250 }
193 251
194 new_bus->priv = (void __force *)regs; 252 new_bus->priv = (void __force *)regs;
195 253
196 new_bus->irq = pdata->irq; 254 new_bus->irq = create_irq_map(np);
255
256 if (new_bus->irq == NULL) {
257 err = -ENOMEM;
258 goto err_unmap_regs;
259 }
197 260
198 new_bus->parent = dev; 261 new_bus->parent = &ofdev->dev;
199 dev_set_drvdata(dev, new_bus); 262 dev_set_drvdata(&ofdev->dev, new_bus);
200 263
201 /* 264 /*
202 * This is mildly evil, but so is our hardware for doing this. 265 * This is mildly evil, but so is our hardware for doing this.
@@ -206,96 +269,109 @@ static int gfar_mdio_probe(struct device *dev)
206 enet_regs = (struct gfar __iomem *) 269 enet_regs = (struct gfar __iomem *)
207 ((char *)regs - offsetof(struct gfar, gfar_mii_regs)); 270 ((char *)regs - offsetof(struct gfar, gfar_mii_regs));
208 271
209 /* Scan the bus, looking for an empty spot for TBIPA */ 272 for_each_child_of_node(np, tbi) {
210 gfar_write(&enet_regs->tbipa, 0); 273 if (!strncmp(tbi->type, "tbi-phy", 8))
211 for (i = PHY_MAX_ADDR; i > 0; i--) { 274 break;
212 u32 phy_id; 275 }
213 276
214 err = get_phy_id(new_bus, i, &phy_id); 277 if (tbi) {
215 if (err) 278 const u32 *prop = of_get_property(tbi, "reg", NULL);
216 goto bus_register_fail;
217 279
218 if (phy_id == 0xffffffff) 280 if (prop)
219 break; 281 tbiaddr = *prop;
220 } 282 }
221 283
222 /* The bus is full. We don't support using 31 PHYs, sorry */ 284 if (tbiaddr == -1) {
223 if (i == 0) { 285 gfar_write(&enet_regs->tbipa, 0);
286
287 tbiaddr = gfar_mdio_find_free(new_bus);
288 }
289
290 /*
291 * We define TBIPA at 0 to be illegal, opting to fail for boards that
292 * have PHYs at 1-31, rather than change tbipa and rescan.
293 */
294 if (tbiaddr == 0) {
224 err = -EBUSY; 295 err = -EBUSY;
225 296
226 goto bus_register_fail; 297 goto err_free_irqs;
227 } 298 }
228 299
229 gfar_write(&enet_regs->tbipa, i); 300 gfar_write(&enet_regs->tbipa, tbiaddr);
301
302 /*
303 * The TBIPHY-only buses will find PHYs at every address,
304 * so we mask them all but the TBI
305 */
306 if (!of_device_is_compatible(np, "fsl,gianfar-mdio"))
307 new_bus->phy_mask = ~(1 << tbiaddr);
230 308
231 err = mdiobus_register(new_bus); 309 err = mdiobus_register(new_bus);
232 310
233 if (0 != err) { 311 if (err != 0) {
234 printk (KERN_ERR "%s: Cannot register as MDIO bus\n", 312 printk (KERN_ERR "%s: Cannot register as MDIO bus\n",
235 new_bus->name); 313 new_bus->name);
236 goto bus_register_fail; 314 goto err_free_irqs;
237 } 315 }
238 316
239 return 0; 317 return 0;
240 318
241bus_register_fail: 319err_free_irqs:
320 kfree(new_bus->irq);
321err_unmap_regs:
242 iounmap(regs); 322 iounmap(regs);
243reg_map_fail: 323err_free_bus:
244 mdiobus_free(new_bus); 324 mdiobus_free(new_bus);
245 325
246 return err; 326 return err;
247} 327}
248 328
249 329
250static int gfar_mdio_remove(struct device *dev) 330static int gfar_mdio_remove(struct of_device *ofdev)
251{ 331{
252 struct mii_bus *bus = dev_get_drvdata(dev); 332 struct mii_bus *bus = dev_get_drvdata(&ofdev->dev);
253 333
254 mdiobus_unregister(bus); 334 mdiobus_unregister(bus);
255 335
256 dev_set_drvdata(dev, NULL); 336 dev_set_drvdata(&ofdev->dev, NULL);
257 337
258 iounmap((void __iomem *)bus->priv); 338 iounmap((void __iomem *)bus->priv);
259 bus->priv = NULL; 339 bus->priv = NULL;
340 kfree(bus->irq);
260 mdiobus_free(bus); 341 mdiobus_free(bus);
261 342
262 return 0; 343 return 0;
263} 344}
264 345
265static struct device_driver gianfar_mdio_driver = { 346static struct of_device_id gfar_mdio_match[] =
347{
348 {
349 .compatible = "fsl,gianfar-mdio",
350 },
351 {
352 .compatible = "fsl,gianfar-tbi",
353 },
354 {
355 .type = "mdio",
356 .compatible = "gianfar",
357 },
358 {},
359};
360
361static struct of_platform_driver gianfar_mdio_driver = {
266 .name = "fsl-gianfar_mdio", 362 .name = "fsl-gianfar_mdio",
267 .bus = &platform_bus_type, 363 .match_table = gfar_mdio_match,
364
268 .probe = gfar_mdio_probe, 365 .probe = gfar_mdio_probe,
269 .remove = gfar_mdio_remove, 366 .remove = gfar_mdio_remove,
270}; 367};
271 368
272static int match_mdio_bus(struct device *dev, void *data)
273{
274 const struct gfar_private *priv = data;
275 const struct platform_device *pdev = to_platform_device(dev);
276
277 return !strcmp(pdev->name, gianfar_mdio_driver.name) &&
278 pdev->id == priv->einfo->mdio_bus;
279}
280
281/* Given a gfar_priv structure, find the mii_bus controlled by this device (not
282 * necessarily the same as the bus the gfar's PHY is on), if one exists.
283 * Normally only the first gianfar controls a mii_bus. */
284struct mii_bus *gfar_get_miibus(const struct gfar_private *priv)
285{
286 /*const*/ struct device *d;
287
288 d = bus_find_device(gianfar_mdio_driver.bus, NULL, (void *)priv,
289 match_mdio_bus);
290 return d ? dev_get_drvdata(d) : NULL;
291}
292
293int __init gfar_mdio_init(void) 369int __init gfar_mdio_init(void)
294{ 370{
295 return driver_register(&gianfar_mdio_driver); 371 return of_register_platform_driver(&gianfar_mdio_driver);
296} 372}
297 373
298void gfar_mdio_exit(void) 374void gfar_mdio_exit(void)
299{ 375{
300 driver_unregister(&gianfar_mdio_driver); 376 of_unregister_platform_driver(&gianfar_mdio_driver);
301} 377}