diff options
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/gianfar.c | 321 | ||||
-rw-r--r-- | drivers/net/gianfar.h | 21 | ||||
-rw-r--r-- | drivers/net/gianfar_ethtool.c | 22 | ||||
-rw-r--r-- | drivers/net/gianfar_mii.c | 212 | ||||
-rw-r--r-- | drivers/net/gianfar_mii.h | 2 |
5 files changed, 386 insertions, 192 deletions
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 55e319fa7fe6..7398704c4b55 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c | |||
@@ -25,11 +25,8 @@ | |||
25 | * | 25 | * |
26 | * Theory of operation | 26 | * Theory of operation |
27 | * | 27 | * |
28 | * The driver is initialized through platform_device. Structures which | 28 | * The driver is initialized through of_device. Configuration information |
29 | * define the configuration needed by the board are defined in a | 29 | * is therefore conveyed through an OF-style device tree. |
30 | * board structure in arch/ppc/platforms (though I do not | ||
31 | * discount the possibility that other architectures could one | ||
32 | * day be supported. | ||
33 | * | 30 | * |
34 | * The Gianfar Ethernet Controller uses a ring of buffer | 31 | * The Gianfar Ethernet Controller uses a ring of buffer |
35 | * descriptors. The beginning is indicated by a register | 32 | * descriptors. The beginning is indicated by a register |
@@ -78,7 +75,7 @@ | |||
78 | #include <linux/if_vlan.h> | 75 | #include <linux/if_vlan.h> |
79 | #include <linux/spinlock.h> | 76 | #include <linux/spinlock.h> |
80 | #include <linux/mm.h> | 77 | #include <linux/mm.h> |
81 | #include <linux/platform_device.h> | 78 | #include <linux/of_platform.h> |
82 | #include <linux/ip.h> | 79 | #include <linux/ip.h> |
83 | #include <linux/tcp.h> | 80 | #include <linux/tcp.h> |
84 | #include <linux/udp.h> | 81 | #include <linux/udp.h> |
@@ -92,6 +89,8 @@ | |||
92 | #include <linux/crc32.h> | 89 | #include <linux/crc32.h> |
93 | #include <linux/mii.h> | 90 | #include <linux/mii.h> |
94 | #include <linux/phy.h> | 91 | #include <linux/phy.h> |
92 | #include <linux/phy_fixed.h> | ||
93 | #include <linux/of.h> | ||
95 | 94 | ||
96 | #include "gianfar.h" | 95 | #include "gianfar.h" |
97 | #include "gianfar_mii.h" | 96 | #include "gianfar_mii.h" |
@@ -119,8 +118,9 @@ static irqreturn_t gfar_interrupt(int irq, void *dev_id); | |||
119 | static void adjust_link(struct net_device *dev); | 118 | static void adjust_link(struct net_device *dev); |
120 | static void init_registers(struct net_device *dev); | 119 | static void init_registers(struct net_device *dev); |
121 | static int init_phy(struct net_device *dev); | 120 | static int init_phy(struct net_device *dev); |
122 | static int gfar_probe(struct platform_device *pdev); | 121 | static int gfar_probe(struct of_device *ofdev, |
123 | static int gfar_remove(struct platform_device *pdev); | 122 | const struct of_device_id *match); |
123 | static int gfar_remove(struct of_device *ofdev); | ||
124 | static void free_skb_resources(struct gfar_private *priv); | 124 | static void free_skb_resources(struct gfar_private *priv); |
125 | static void gfar_set_multi(struct net_device *dev); | 125 | static void gfar_set_multi(struct net_device *dev); |
126 | static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr); | 126 | static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr); |
@@ -152,25 +152,158 @@ static inline int gfar_uses_fcb(struct gfar_private *priv) | |||
152 | return (priv->vlan_enable || priv->rx_csum_enable); | 152 | return (priv->vlan_enable || priv->rx_csum_enable); |
153 | } | 153 | } |
154 | 154 | ||
155 | static int gfar_of_init(struct net_device *dev) | ||
156 | { | ||
157 | struct device_node *phy, *mdio; | ||
158 | const unsigned int *id; | ||
159 | const char *model; | ||
160 | const char *ctype; | ||
161 | const void *mac_addr; | ||
162 | const phandle *ph; | ||
163 | u64 addr, size; | ||
164 | int err = 0; | ||
165 | struct gfar_private *priv = netdev_priv(dev); | ||
166 | struct device_node *np = priv->node; | ||
167 | char bus_name[MII_BUS_ID_SIZE]; | ||
168 | |||
169 | if (!np || !of_device_is_available(np)) | ||
170 | return -ENODEV; | ||
171 | |||
172 | /* get a pointer to the register memory */ | ||
173 | addr = of_translate_address(np, of_get_address(np, 0, &size, NULL)); | ||
174 | priv->regs = ioremap(addr, size); | ||
175 | |||
176 | if (priv->regs == NULL) | ||
177 | return -ENOMEM; | ||
178 | |||
179 | priv->interruptTransmit = irq_of_parse_and_map(np, 0); | ||
180 | |||
181 | model = of_get_property(np, "model", NULL); | ||
182 | |||
183 | /* If we aren't the FEC we have multiple interrupts */ | ||
184 | if (model && strcasecmp(model, "FEC")) { | ||
185 | priv->interruptReceive = irq_of_parse_and_map(np, 1); | ||
186 | |||
187 | priv->interruptError = irq_of_parse_and_map(np, 2); | ||
188 | |||
189 | if (priv->interruptTransmit < 0 || | ||
190 | priv->interruptReceive < 0 || | ||
191 | priv->interruptError < 0) { | ||
192 | err = -EINVAL; | ||
193 | goto err_out; | ||
194 | } | ||
195 | } | ||
196 | |||
197 | mac_addr = of_get_mac_address(np); | ||
198 | if (mac_addr) | ||
199 | memcpy(dev->dev_addr, mac_addr, MAC_ADDR_LEN); | ||
200 | |||
201 | if (model && !strcasecmp(model, "TSEC")) | ||
202 | priv->device_flags = | ||
203 | FSL_GIANFAR_DEV_HAS_GIGABIT | | ||
204 | FSL_GIANFAR_DEV_HAS_COALESCE | | ||
205 | FSL_GIANFAR_DEV_HAS_RMON | | ||
206 | FSL_GIANFAR_DEV_HAS_MULTI_INTR; | ||
207 | if (model && !strcasecmp(model, "eTSEC")) | ||
208 | priv->device_flags = | ||
209 | FSL_GIANFAR_DEV_HAS_GIGABIT | | ||
210 | FSL_GIANFAR_DEV_HAS_COALESCE | | ||
211 | FSL_GIANFAR_DEV_HAS_RMON | | ||
212 | FSL_GIANFAR_DEV_HAS_MULTI_INTR | | ||
213 | FSL_GIANFAR_DEV_HAS_CSUM | | ||
214 | FSL_GIANFAR_DEV_HAS_VLAN | | ||
215 | FSL_GIANFAR_DEV_HAS_MAGIC_PACKET | | ||
216 | FSL_GIANFAR_DEV_HAS_EXTENDED_HASH; | ||
217 | |||
218 | ctype = of_get_property(np, "phy-connection-type", NULL); | ||
219 | |||
220 | /* We only care about rgmii-id. The rest are autodetected */ | ||
221 | if (ctype && !strcmp(ctype, "rgmii-id")) | ||
222 | priv->interface = PHY_INTERFACE_MODE_RGMII_ID; | ||
223 | else | ||
224 | priv->interface = PHY_INTERFACE_MODE_MII; | ||
225 | |||
226 | if (of_get_property(np, "fsl,magic-packet", NULL)) | ||
227 | priv->device_flags |= FSL_GIANFAR_DEV_HAS_MAGIC_PACKET; | ||
228 | |||
229 | ph = of_get_property(np, "phy-handle", NULL); | ||
230 | if (ph == NULL) { | ||
231 | u32 *fixed_link; | ||
232 | |||
233 | fixed_link = (u32 *)of_get_property(np, "fixed-link", NULL); | ||
234 | if (!fixed_link) { | ||
235 | err = -ENODEV; | ||
236 | goto err_out; | ||
237 | } | ||
238 | |||
239 | snprintf(priv->phy_bus_id, BUS_ID_SIZE, PHY_ID_FMT, "0", | ||
240 | fixed_link[0]); | ||
241 | } else { | ||
242 | phy = of_find_node_by_phandle(*ph); | ||
243 | |||
244 | if (phy == NULL) { | ||
245 | err = -ENODEV; | ||
246 | goto err_out; | ||
247 | } | ||
248 | |||
249 | mdio = of_get_parent(phy); | ||
250 | |||
251 | id = of_get_property(phy, "reg", NULL); | ||
252 | |||
253 | of_node_put(phy); | ||
254 | of_node_put(mdio); | ||
255 | |||
256 | gfar_mdio_bus_name(bus_name, mdio); | ||
257 | snprintf(priv->phy_bus_id, BUS_ID_SIZE, "%s:%02x", | ||
258 | bus_name, *id); | ||
259 | } | ||
260 | |||
261 | /* Find the TBI PHY. If it's not there, we don't support SGMII */ | ||
262 | ph = of_get_property(np, "tbi-handle", NULL); | ||
263 | if (ph) { | ||
264 | struct device_node *tbi = of_find_node_by_phandle(*ph); | ||
265 | struct of_device *ofdev; | ||
266 | struct mii_bus *bus; | ||
267 | |||
268 | if (!tbi) | ||
269 | return 0; | ||
270 | |||
271 | mdio = of_get_parent(tbi); | ||
272 | if (!mdio) | ||
273 | return 0; | ||
274 | |||
275 | ofdev = of_find_device_by_node(mdio); | ||
276 | |||
277 | of_node_put(mdio); | ||
278 | |||
279 | id = of_get_property(tbi, "reg", NULL); | ||
280 | if (!id) | ||
281 | return 0; | ||
282 | |||
283 | of_node_put(tbi); | ||
284 | |||
285 | bus = dev_get_drvdata(&ofdev->dev); | ||
286 | |||
287 | priv->tbiphy = bus->phy_map[*id]; | ||
288 | } | ||
289 | |||
290 | return 0; | ||
291 | |||
292 | err_out: | ||
293 | iounmap(priv->regs); | ||
294 | return err; | ||
295 | } | ||
296 | |||
155 | /* Set up the ethernet device structure, private data, | 297 | /* Set up the ethernet device structure, private data, |
156 | * and anything else we need before we start */ | 298 | * and anything else we need before we start */ |
157 | static int gfar_probe(struct platform_device *pdev) | 299 | static int gfar_probe(struct of_device *ofdev, |
300 | const struct of_device_id *match) | ||
158 | { | 301 | { |
159 | u32 tempval; | 302 | u32 tempval; |
160 | struct net_device *dev = NULL; | 303 | struct net_device *dev = NULL; |
161 | struct gfar_private *priv = NULL; | 304 | struct gfar_private *priv = NULL; |
162 | struct gianfar_platform_data *einfo; | 305 | int err = 0; |
163 | struct resource *r; | 306 | DECLARE_MAC_BUF(mac); |
164 | int err = 0, irq; | ||
165 | |||
166 | einfo = (struct gianfar_platform_data *) pdev->dev.platform_data; | ||
167 | |||
168 | if (NULL == einfo) { | ||
169 | printk(KERN_ERR "gfar %d: Missing additional data!\n", | ||
170 | pdev->id); | ||
171 | |||
172 | return -ENODEV; | ||
173 | } | ||
174 | 307 | ||
175 | /* Create an ethernet device instance */ | 308 | /* Create an ethernet device instance */ |
176 | dev = alloc_etherdev(sizeof (*priv)); | 309 | dev = alloc_etherdev(sizeof (*priv)); |
@@ -180,48 +313,19 @@ static int gfar_probe(struct platform_device *pdev) | |||
180 | 313 | ||
181 | priv = netdev_priv(dev); | 314 | priv = netdev_priv(dev); |
182 | priv->dev = dev; | 315 | priv->dev = dev; |
316 | priv->node = ofdev->node; | ||
183 | 317 | ||
184 | /* Set the info in the priv to the current info */ | 318 | err = gfar_of_init(dev); |
185 | priv->einfo = einfo; | ||
186 | |||
187 | /* fill out IRQ fields */ | ||
188 | if (einfo->device_flags & FSL_GIANFAR_DEV_HAS_MULTI_INTR) { | ||
189 | irq = platform_get_irq_byname(pdev, "tx"); | ||
190 | if (irq < 0) | ||
191 | goto regs_fail; | ||
192 | priv->interruptTransmit = irq; | ||
193 | |||
194 | irq = platform_get_irq_byname(pdev, "rx"); | ||
195 | if (irq < 0) | ||
196 | goto regs_fail; | ||
197 | priv->interruptReceive = irq; | ||
198 | |||
199 | irq = platform_get_irq_byname(pdev, "error"); | ||
200 | if (irq < 0) | ||
201 | goto regs_fail; | ||
202 | priv->interruptError = irq; | ||
203 | } else { | ||
204 | irq = platform_get_irq(pdev, 0); | ||
205 | if (irq < 0) | ||
206 | goto regs_fail; | ||
207 | priv->interruptTransmit = irq; | ||
208 | } | ||
209 | |||
210 | /* get a pointer to the register memory */ | ||
211 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
212 | priv->regs = ioremap(r->start, sizeof (struct gfar)); | ||
213 | 319 | ||
214 | if (NULL == priv->regs) { | 320 | if (err) |
215 | err = -ENOMEM; | ||
216 | goto regs_fail; | 321 | goto regs_fail; |
217 | } | ||
218 | 322 | ||
219 | spin_lock_init(&priv->txlock); | 323 | spin_lock_init(&priv->txlock); |
220 | spin_lock_init(&priv->rxlock); | 324 | spin_lock_init(&priv->rxlock); |
221 | spin_lock_init(&priv->bflock); | 325 | spin_lock_init(&priv->bflock); |
222 | INIT_WORK(&priv->reset_task, gfar_reset_task); | 326 | INIT_WORK(&priv->reset_task, gfar_reset_task); |
223 | 327 | ||
224 | platform_set_drvdata(pdev, dev); | 328 | dev_set_drvdata(&ofdev->dev, priv); |
225 | 329 | ||
226 | /* Stop the DMA engine now, in case it was running before */ | 330 | /* Stop the DMA engine now, in case it was running before */ |
227 | /* (The firmware could have used it, and left it running). */ | 331 | /* (The firmware could have used it, and left it running). */ |
@@ -239,13 +343,10 @@ static int gfar_probe(struct platform_device *pdev) | |||
239 | /* Initialize ECNTRL */ | 343 | /* Initialize ECNTRL */ |
240 | gfar_write(&priv->regs->ecntrl, ECNTRL_INIT_SETTINGS); | 344 | gfar_write(&priv->regs->ecntrl, ECNTRL_INIT_SETTINGS); |
241 | 345 | ||
242 | /* Copy the station address into the dev structure, */ | ||
243 | memcpy(dev->dev_addr, einfo->mac_addr, MAC_ADDR_LEN); | ||
244 | |||
245 | /* Set the dev->base_addr to the gfar reg region */ | 346 | /* Set the dev->base_addr to the gfar reg region */ |
246 | dev->base_addr = (unsigned long) (priv->regs); | 347 | dev->base_addr = (unsigned long) (priv->regs); |
247 | 348 | ||
248 | SET_NETDEV_DEV(dev, &pdev->dev); | 349 | SET_NETDEV_DEV(dev, &ofdev->dev); |
249 | 350 | ||
250 | /* Fill in the dev structure */ | 351 | /* Fill in the dev structure */ |
251 | dev->open = gfar_enet_open; | 352 | dev->open = gfar_enet_open; |
@@ -263,7 +364,7 @@ static int gfar_probe(struct platform_device *pdev) | |||
263 | 364 | ||
264 | dev->ethtool_ops = &gfar_ethtool_ops; | 365 | dev->ethtool_ops = &gfar_ethtool_ops; |
265 | 366 | ||
266 | if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_CSUM) { | 367 | if (priv->device_flags & FSL_GIANFAR_DEV_HAS_CSUM) { |
267 | priv->rx_csum_enable = 1; | 368 | priv->rx_csum_enable = 1; |
268 | dev->features |= NETIF_F_IP_CSUM; | 369 | dev->features |= NETIF_F_IP_CSUM; |
269 | } else | 370 | } else |
@@ -271,7 +372,7 @@ static int gfar_probe(struct platform_device *pdev) | |||
271 | 372 | ||
272 | priv->vlgrp = NULL; | 373 | priv->vlgrp = NULL; |
273 | 374 | ||
274 | if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_VLAN) { | 375 | if (priv->device_flags & FSL_GIANFAR_DEV_HAS_VLAN) { |
275 | dev->vlan_rx_register = gfar_vlan_rx_register; | 376 | dev->vlan_rx_register = gfar_vlan_rx_register; |
276 | 377 | ||
277 | dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; | 378 | dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; |
@@ -279,7 +380,7 @@ static int gfar_probe(struct platform_device *pdev) | |||
279 | priv->vlan_enable = 1; | 380 | priv->vlan_enable = 1; |
280 | } | 381 | } |
281 | 382 | ||
282 | if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_EXTENDED_HASH) { | 383 | if (priv->device_flags & FSL_GIANFAR_DEV_HAS_EXTENDED_HASH) { |
283 | priv->extended_hash = 1; | 384 | priv->extended_hash = 1; |
284 | priv->hash_width = 9; | 385 | priv->hash_width = 9; |
285 | 386 | ||
@@ -314,7 +415,7 @@ static int gfar_probe(struct platform_device *pdev) | |||
314 | priv->hash_regs[7] = &priv->regs->gaddr7; | 415 | priv->hash_regs[7] = &priv->regs->gaddr7; |
315 | } | 416 | } |
316 | 417 | ||
317 | if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_PADDING) | 418 | if (priv->device_flags & FSL_GIANFAR_DEV_HAS_PADDING) |
318 | priv->padding = DEFAULT_PADDING; | 419 | priv->padding = DEFAULT_PADDING; |
319 | else | 420 | else |
320 | priv->padding = 0; | 421 | priv->padding = 0; |
@@ -368,29 +469,28 @@ regs_fail: | |||
368 | return err; | 469 | return err; |
369 | } | 470 | } |
370 | 471 | ||
371 | static int gfar_remove(struct platform_device *pdev) | 472 | static int gfar_remove(struct of_device *ofdev) |
372 | { | 473 | { |
373 | struct net_device *dev = platform_get_drvdata(pdev); | 474 | struct gfar_private *priv = dev_get_drvdata(&ofdev->dev); |
374 | struct gfar_private *priv = netdev_priv(dev); | ||
375 | 475 | ||
376 | platform_set_drvdata(pdev, NULL); | 476 | dev_set_drvdata(&ofdev->dev, NULL); |
377 | 477 | ||
378 | iounmap(priv->regs); | 478 | iounmap(priv->regs); |
379 | free_netdev(dev); | 479 | free_netdev(priv->dev); |
380 | 480 | ||
381 | return 0; | 481 | return 0; |
382 | } | 482 | } |
383 | 483 | ||
384 | #ifdef CONFIG_PM | 484 | #ifdef CONFIG_PM |
385 | static int gfar_suspend(struct platform_device *pdev, pm_message_t state) | 485 | static int gfar_suspend(struct of_device *ofdev, pm_message_t state) |
386 | { | 486 | { |
387 | struct net_device *dev = platform_get_drvdata(pdev); | 487 | struct gfar_private *priv = dev_get_drvdata(&ofdev->dev); |
388 | struct gfar_private *priv = netdev_priv(dev); | 488 | struct net_device *dev = priv->dev; |
389 | unsigned long flags; | 489 | unsigned long flags; |
390 | u32 tempval; | 490 | u32 tempval; |
391 | 491 | ||
392 | int magic_packet = priv->wol_en && | 492 | int magic_packet = priv->wol_en && |
393 | (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET); | 493 | (priv->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET); |
394 | 494 | ||
395 | netif_device_detach(dev); | 495 | netif_device_detach(dev); |
396 | 496 | ||
@@ -431,14 +531,14 @@ static int gfar_suspend(struct platform_device *pdev, pm_message_t state) | |||
431 | return 0; | 531 | return 0; |
432 | } | 532 | } |
433 | 533 | ||
434 | static int gfar_resume(struct platform_device *pdev) | 534 | static int gfar_resume(struct of_device *ofdev) |
435 | { | 535 | { |
436 | struct net_device *dev = platform_get_drvdata(pdev); | 536 | struct gfar_private *priv = dev_get_drvdata(&ofdev->dev); |
437 | struct gfar_private *priv = netdev_priv(dev); | 537 | struct net_device *dev = priv->dev; |
438 | unsigned long flags; | 538 | unsigned long flags; |
439 | u32 tempval; | 539 | u32 tempval; |
440 | int magic_packet = priv->wol_en && | 540 | int magic_packet = priv->wol_en && |
441 | (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET); | 541 | (priv->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET); |
442 | 542 | ||
443 | if (!netif_running(dev)) { | 543 | if (!netif_running(dev)) { |
444 | netif_device_attach(dev); | 544 | netif_device_attach(dev); |
@@ -497,7 +597,7 @@ static phy_interface_t gfar_get_interface(struct net_device *dev) | |||
497 | if (ecntrl & ECNTRL_REDUCED_MII_MODE) | 597 | if (ecntrl & ECNTRL_REDUCED_MII_MODE) |
498 | return PHY_INTERFACE_MODE_RMII; | 598 | return PHY_INTERFACE_MODE_RMII; |
499 | else { | 599 | else { |
500 | phy_interface_t interface = priv->einfo->interface; | 600 | phy_interface_t interface = priv->interface; |
501 | 601 | ||
502 | /* | 602 | /* |
503 | * This isn't autodetected right now, so it must | 603 | * This isn't autodetected right now, so it must |
@@ -510,7 +610,7 @@ static phy_interface_t gfar_get_interface(struct net_device *dev) | |||
510 | } | 610 | } |
511 | } | 611 | } |
512 | 612 | ||
513 | if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_GIGABIT) | 613 | if (priv->device_flags & FSL_GIANFAR_DEV_HAS_GIGABIT) |
514 | return PHY_INTERFACE_MODE_GMII; | 614 | return PHY_INTERFACE_MODE_GMII; |
515 | 615 | ||
516 | return PHY_INTERFACE_MODE_MII; | 616 | return PHY_INTERFACE_MODE_MII; |
@@ -524,21 +624,18 @@ static int init_phy(struct net_device *dev) | |||
524 | { | 624 | { |
525 | struct gfar_private *priv = netdev_priv(dev); | 625 | struct gfar_private *priv = netdev_priv(dev); |
526 | uint gigabit_support = | 626 | uint gigabit_support = |
527 | priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_GIGABIT ? | 627 | priv->device_flags & FSL_GIANFAR_DEV_HAS_GIGABIT ? |
528 | SUPPORTED_1000baseT_Full : 0; | 628 | SUPPORTED_1000baseT_Full : 0; |
529 | struct phy_device *phydev; | 629 | struct phy_device *phydev; |
530 | char phy_id[BUS_ID_SIZE]; | ||
531 | phy_interface_t interface; | 630 | phy_interface_t interface; |
532 | 631 | ||
533 | priv->oldlink = 0; | 632 | priv->oldlink = 0; |
534 | priv->oldspeed = 0; | 633 | priv->oldspeed = 0; |
535 | priv->oldduplex = -1; | 634 | priv->oldduplex = -1; |
536 | 635 | ||
537 | snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT, priv->einfo->bus_id, priv->einfo->phy_id); | ||
538 | |||
539 | interface = gfar_get_interface(dev); | 636 | interface = gfar_get_interface(dev); |
540 | 637 | ||
541 | phydev = phy_connect(dev, phy_id, &adjust_link, 0, interface); | 638 | phydev = phy_connect(dev, priv->phy_bus_id, &adjust_link, 0, interface); |
542 | 639 | ||
543 | if (interface == PHY_INTERFACE_MODE_SGMII) | 640 | if (interface == PHY_INTERFACE_MODE_SGMII) |
544 | gfar_configure_serdes(dev); | 641 | gfar_configure_serdes(dev); |
@@ -569,35 +666,31 @@ static int init_phy(struct net_device *dev) | |||
569 | static void gfar_configure_serdes(struct net_device *dev) | 666 | static void gfar_configure_serdes(struct net_device *dev) |
570 | { | 667 | { |
571 | struct gfar_private *priv = netdev_priv(dev); | 668 | struct gfar_private *priv = netdev_priv(dev); |
572 | struct gfar_mii __iomem *regs = | ||
573 | (void __iomem *)&priv->regs->gfar_mii_regs; | ||
574 | int tbipa = gfar_read(&priv->regs->tbipa); | ||
575 | struct mii_bus *bus = gfar_get_miibus(priv); | ||
576 | 669 | ||
577 | if (bus) | 670 | if (!priv->tbiphy) { |
578 | mutex_lock(&bus->mdio_lock); | 671 | printk(KERN_WARNING "SGMII mode requires that the device " |
672 | "tree specify a tbi-handle\n"); | ||
673 | return; | ||
674 | } | ||
579 | 675 | ||
580 | /* If the link is already up, we must already be ok, and don't need to | 676 | /* |
677 | * If the link is already up, we must already be ok, and don't need to | ||
581 | * configure and reset the TBI<->SerDes link. Maybe U-Boot configured | 678 | * configure and reset the TBI<->SerDes link. Maybe U-Boot configured |
582 | * everything for us? Resetting it takes the link down and requires | 679 | * everything for us? Resetting it takes the link down and requires |
583 | * several seconds for it to come back. | 680 | * several seconds for it to come back. |
584 | */ | 681 | */ |
585 | if (gfar_local_mdio_read(regs, tbipa, MII_BMSR) & BMSR_LSTATUS) | 682 | if (phy_read(priv->tbiphy, MII_BMSR) & BMSR_LSTATUS) |
586 | goto done; | 683 | return; |
587 | 684 | ||
588 | /* Single clk mode, mii mode off(for serdes communication) */ | 685 | /* Single clk mode, mii mode off(for serdes communication) */ |
589 | gfar_local_mdio_write(regs, tbipa, MII_TBICON, TBICON_CLK_SELECT); | 686 | phy_write(priv->tbiphy, MII_TBICON, TBICON_CLK_SELECT); |
590 | 687 | ||
591 | gfar_local_mdio_write(regs, tbipa, MII_ADVERTISE, | 688 | phy_write(priv->tbiphy, MII_ADVERTISE, |
592 | ADVERTISE_1000XFULL | ADVERTISE_1000XPAUSE | | 689 | ADVERTISE_1000XFULL | ADVERTISE_1000XPAUSE | |
593 | ADVERTISE_1000XPSE_ASYM); | 690 | ADVERTISE_1000XPSE_ASYM); |
594 | 691 | ||
595 | gfar_local_mdio_write(regs, tbipa, MII_BMCR, BMCR_ANENABLE | | 692 | phy_write(priv->tbiphy, MII_BMCR, BMCR_ANENABLE | |
596 | BMCR_ANRESTART | BMCR_FULLDPLX | BMCR_SPEED1000); | 693 | BMCR_ANRESTART | BMCR_FULLDPLX | BMCR_SPEED1000); |
597 | |||
598 | done: | ||
599 | if (bus) | ||
600 | mutex_unlock(&bus->mdio_lock); | ||
601 | } | 694 | } |
602 | 695 | ||
603 | static void init_registers(struct net_device *dev) | 696 | static void init_registers(struct net_device *dev) |
@@ -630,7 +723,7 @@ static void init_registers(struct net_device *dev) | |||
630 | gfar_write(&priv->regs->gaddr7, 0); | 723 | gfar_write(&priv->regs->gaddr7, 0); |
631 | 724 | ||
632 | /* Zero out the rmon mib registers if it has them */ | 725 | /* Zero out the rmon mib registers if it has them */ |
633 | if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_RMON) { | 726 | if (priv->device_flags & FSL_GIANFAR_DEV_HAS_RMON) { |
634 | memset_io(&(priv->regs->rmon), 0, sizeof (struct rmon_mib)); | 727 | memset_io(&(priv->regs->rmon), 0, sizeof (struct rmon_mib)); |
635 | 728 | ||
636 | /* Mask off the CAM interrupts */ | 729 | /* Mask off the CAM interrupts */ |
@@ -705,7 +798,7 @@ void stop_gfar(struct net_device *dev) | |||
705 | spin_unlock_irqrestore(&priv->txlock, flags); | 798 | spin_unlock_irqrestore(&priv->txlock, flags); |
706 | 799 | ||
707 | /* Free the IRQs */ | 800 | /* Free the IRQs */ |
708 | if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MULTI_INTR) { | 801 | if (priv->device_flags & FSL_GIANFAR_DEV_HAS_MULTI_INTR) { |
709 | free_irq(priv->interruptError, dev); | 802 | free_irq(priv->interruptError, dev); |
710 | free_irq(priv->interruptTransmit, dev); | 803 | free_irq(priv->interruptTransmit, dev); |
711 | free_irq(priv->interruptReceive, dev); | 804 | free_irq(priv->interruptReceive, dev); |
@@ -919,7 +1012,7 @@ int startup_gfar(struct net_device *dev) | |||
919 | 1012 | ||
920 | /* If the device has multiple interrupts, register for | 1013 | /* If the device has multiple interrupts, register for |
921 | * them. Otherwise, only register for the one */ | 1014 | * them. Otherwise, only register for the one */ |
922 | if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MULTI_INTR) { | 1015 | if (priv->device_flags & FSL_GIANFAR_DEV_HAS_MULTI_INTR) { |
923 | /* Install our interrupt handlers for Error, | 1016 | /* Install our interrupt handlers for Error, |
924 | * Transmit, and Receive */ | 1017 | * Transmit, and Receive */ |
925 | if (request_irq(priv->interruptError, gfar_error, | 1018 | if (request_irq(priv->interruptError, gfar_error, |
@@ -1751,7 +1844,7 @@ static void gfar_netpoll(struct net_device *dev) | |||
1751 | struct gfar_private *priv = netdev_priv(dev); | 1844 | struct gfar_private *priv = netdev_priv(dev); |
1752 | 1845 | ||
1753 | /* If the device has multiple interrupts, run tx/rx */ | 1846 | /* If the device has multiple interrupts, run tx/rx */ |
1754 | if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MULTI_INTR) { | 1847 | if (priv->device_flags & FSL_GIANFAR_DEV_HAS_MULTI_INTR) { |
1755 | disable_irq(priv->interruptTransmit); | 1848 | disable_irq(priv->interruptTransmit); |
1756 | disable_irq(priv->interruptReceive); | 1849 | disable_irq(priv->interruptReceive); |
1757 | disable_irq(priv->interruptError); | 1850 | disable_irq(priv->interruptError); |
@@ -2045,7 +2138,7 @@ static irqreturn_t gfar_error(int irq, void *dev_id) | |||
2045 | gfar_write(&priv->regs->ievent, events & IEVENT_ERR_MASK); | 2138 | gfar_write(&priv->regs->ievent, events & IEVENT_ERR_MASK); |
2046 | 2139 | ||
2047 | /* Magic Packet is not an error. */ | 2140 | /* Magic Packet is not an error. */ |
2048 | if ((priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET) && | 2141 | if ((priv->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET) && |
2049 | (events & IEVENT_MAG)) | 2142 | (events & IEVENT_MAG)) |
2050 | events &= ~IEVENT_MAG; | 2143 | events &= ~IEVENT_MAG; |
2051 | 2144 | ||
@@ -2111,16 +2204,24 @@ static irqreturn_t gfar_error(int irq, void *dev_id) | |||
2111 | /* work with hotplug and coldplug */ | 2204 | /* work with hotplug and coldplug */ |
2112 | MODULE_ALIAS("platform:fsl-gianfar"); | 2205 | MODULE_ALIAS("platform:fsl-gianfar"); |
2113 | 2206 | ||
2207 | static struct of_device_id gfar_match[] = | ||
2208 | { | ||
2209 | { | ||
2210 | .type = "network", | ||
2211 | .compatible = "gianfar", | ||
2212 | }, | ||
2213 | {}, | ||
2214 | }; | ||
2215 | |||
2114 | /* Structure for a device driver */ | 2216 | /* Structure for a device driver */ |
2115 | static struct platform_driver gfar_driver = { | 2217 | static struct of_platform_driver gfar_driver = { |
2218 | .name = "fsl-gianfar", | ||
2219 | .match_table = gfar_match, | ||
2220 | |||
2116 | .probe = gfar_probe, | 2221 | .probe = gfar_probe, |
2117 | .remove = gfar_remove, | 2222 | .remove = gfar_remove, |
2118 | .suspend = gfar_suspend, | 2223 | .suspend = gfar_suspend, |
2119 | .resume = gfar_resume, | 2224 | .resume = gfar_resume, |
2120 | .driver = { | ||
2121 | .name = "fsl-gianfar", | ||
2122 | .owner = THIS_MODULE, | ||
2123 | }, | ||
2124 | }; | 2225 | }; |
2125 | 2226 | ||
2126 | static int __init gfar_init(void) | 2227 | static int __init gfar_init(void) |
@@ -2130,7 +2231,7 @@ static int __init gfar_init(void) | |||
2130 | if (err) | 2231 | if (err) |
2131 | return err; | 2232 | return err; |
2132 | 2233 | ||
2133 | err = platform_driver_register(&gfar_driver); | 2234 | err = of_register_platform_driver(&gfar_driver); |
2134 | 2235 | ||
2135 | if (err) | 2236 | if (err) |
2136 | gfar_mdio_exit(); | 2237 | gfar_mdio_exit(); |
@@ -2140,7 +2241,7 @@ static int __init gfar_init(void) | |||
2140 | 2241 | ||
2141 | static void __exit gfar_exit(void) | 2242 | static void __exit gfar_exit(void) |
2142 | { | 2243 | { |
2143 | platform_driver_unregister(&gfar_driver); | 2244 | of_unregister_platform_driver(&gfar_driver); |
2144 | gfar_mdio_exit(); | 2245 | gfar_mdio_exit(); |
2145 | } | 2246 | } |
2146 | 2247 | ||
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h index f46e9b63af13..ca7f0a6a68c5 100644 --- a/drivers/net/gianfar.h +++ b/drivers/net/gianfar.h | |||
@@ -657,6 +657,19 @@ struct gfar { | |||
657 | 657 | ||
658 | }; | 658 | }; |
659 | 659 | ||
660 | /* Flags related to gianfar device features */ | ||
661 | #define FSL_GIANFAR_DEV_HAS_GIGABIT 0x00000001 | ||
662 | #define FSL_GIANFAR_DEV_HAS_COALESCE 0x00000002 | ||
663 | #define FSL_GIANFAR_DEV_HAS_RMON 0x00000004 | ||
664 | #define FSL_GIANFAR_DEV_HAS_MULTI_INTR 0x00000008 | ||
665 | #define FSL_GIANFAR_DEV_HAS_CSUM 0x00000010 | ||
666 | #define FSL_GIANFAR_DEV_HAS_VLAN 0x00000020 | ||
667 | #define FSL_GIANFAR_DEV_HAS_EXTENDED_HASH 0x00000040 | ||
668 | #define FSL_GIANFAR_DEV_HAS_PADDING 0x00000080 | ||
669 | #define FSL_GIANFAR_DEV_HAS_MAGIC_PACKET 0x00000100 | ||
670 | #define FSL_GIANFAR_DEV_HAS_BD_STASHING 0x00000200 | ||
671 | #define FSL_GIANFAR_DEV_HAS_BUF_STASHING 0x00000400 | ||
672 | |||
660 | /* Struct stolen almost completely (and shamelessly) from the FCC enet source | 673 | /* Struct stolen almost completely (and shamelessly) from the FCC enet source |
661 | * (Ok, that's not so true anymore, but there is a family resemblence) | 674 | * (Ok, that's not so true anymore, but there is a family resemblence) |
662 | * The GFAR buffer descriptors track the ring buffers. The rx_bd_base | 675 | * The GFAR buffer descriptors track the ring buffers. The rx_bd_base |
@@ -694,6 +707,7 @@ struct gfar_private { | |||
694 | /* RX Locked fields */ | 707 | /* RX Locked fields */ |
695 | spinlock_t rxlock; | 708 | spinlock_t rxlock; |
696 | 709 | ||
710 | struct device_node *node; | ||
697 | struct net_device *dev; | 711 | struct net_device *dev; |
698 | struct napi_struct napi; | 712 | struct napi_struct napi; |
699 | 713 | ||
@@ -733,6 +747,9 @@ struct gfar_private { | |||
733 | /* Bitfield update lock */ | 747 | /* Bitfield update lock */ |
734 | spinlock_t bflock; | 748 | spinlock_t bflock; |
735 | 749 | ||
750 | phy_interface_t interface; | ||
751 | char phy_bus_id[BUS_ID_SIZE]; | ||
752 | u32 device_flags; | ||
736 | unsigned char vlan_enable:1, | 753 | unsigned char vlan_enable:1, |
737 | rx_csum_enable:1, | 754 | rx_csum_enable:1, |
738 | extended_hash:1, | 755 | extended_hash:1, |
@@ -744,11 +761,9 @@ struct gfar_private { | |||
744 | unsigned int interruptReceive; | 761 | unsigned int interruptReceive; |
745 | unsigned int interruptError; | 762 | unsigned int interruptError; |
746 | 763 | ||
747 | /* info structure initialized by platform code */ | ||
748 | struct gianfar_platform_data *einfo; | ||
749 | |||
750 | /* PHY stuff */ | 764 | /* PHY stuff */ |
751 | struct phy_device *phydev; | 765 | struct phy_device *phydev; |
766 | struct phy_device *tbiphy; | ||
752 | struct mii_bus *mii_bus; | 767 | struct mii_bus *mii_bus; |
753 | int oldspeed; | 768 | int oldspeed; |
754 | int oldduplex; | 769 | int oldduplex; |
diff --git a/drivers/net/gianfar_ethtool.c b/drivers/net/gianfar_ethtool.c index fb7d3ccc0fdc..53944b120a3d 100644 --- a/drivers/net/gianfar_ethtool.c +++ b/drivers/net/gianfar_ethtool.c | |||
@@ -121,7 +121,7 @@ static void gfar_gstrings(struct net_device *dev, u32 stringset, u8 * buf) | |||
121 | { | 121 | { |
122 | struct gfar_private *priv = netdev_priv(dev); | 122 | struct gfar_private *priv = netdev_priv(dev); |
123 | 123 | ||
124 | if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_RMON) | 124 | if (priv->device_flags & FSL_GIANFAR_DEV_HAS_RMON) |
125 | memcpy(buf, stat_gstrings, GFAR_STATS_LEN * ETH_GSTRING_LEN); | 125 | memcpy(buf, stat_gstrings, GFAR_STATS_LEN * ETH_GSTRING_LEN); |
126 | else | 126 | else |
127 | memcpy(buf, stat_gstrings, | 127 | memcpy(buf, stat_gstrings, |
@@ -138,7 +138,7 @@ static void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy, | |||
138 | struct gfar_private *priv = netdev_priv(dev); | 138 | struct gfar_private *priv = netdev_priv(dev); |
139 | u64 *extra = (u64 *) & priv->extra_stats; | 139 | u64 *extra = (u64 *) & priv->extra_stats; |
140 | 140 | ||
141 | if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_RMON) { | 141 | if (priv->device_flags & FSL_GIANFAR_DEV_HAS_RMON) { |
142 | u32 __iomem *rmon = (u32 __iomem *) & priv->regs->rmon; | 142 | u32 __iomem *rmon = (u32 __iomem *) & priv->regs->rmon; |
143 | struct gfar_stats *stats = (struct gfar_stats *) buf; | 143 | struct gfar_stats *stats = (struct gfar_stats *) buf; |
144 | 144 | ||
@@ -158,7 +158,7 @@ static int gfar_sset_count(struct net_device *dev, int sset) | |||
158 | 158 | ||
159 | switch (sset) { | 159 | switch (sset) { |
160 | case ETH_SS_STATS: | 160 | case ETH_SS_STATS: |
161 | if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_RMON) | 161 | if (priv->device_flags & FSL_GIANFAR_DEV_HAS_RMON) |
162 | return GFAR_STATS_LEN; | 162 | return GFAR_STATS_LEN; |
163 | else | 163 | else |
164 | return GFAR_EXTRA_STATS_LEN; | 164 | return GFAR_EXTRA_STATS_LEN; |
@@ -280,7 +280,7 @@ static int gfar_gcoalesce(struct net_device *dev, struct ethtool_coalesce *cvals | |||
280 | { | 280 | { |
281 | struct gfar_private *priv = netdev_priv(dev); | 281 | struct gfar_private *priv = netdev_priv(dev); |
282 | 282 | ||
283 | if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_COALESCE)) | 283 | if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_COALESCE)) |
284 | return -EOPNOTSUPP; | 284 | return -EOPNOTSUPP; |
285 | 285 | ||
286 | if (NULL == priv->phydev) | 286 | if (NULL == priv->phydev) |
@@ -332,7 +332,7 @@ static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals | |||
332 | { | 332 | { |
333 | struct gfar_private *priv = netdev_priv(dev); | 333 | struct gfar_private *priv = netdev_priv(dev); |
334 | 334 | ||
335 | if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_COALESCE)) | 335 | if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_COALESCE)) |
336 | return -EOPNOTSUPP; | 336 | return -EOPNOTSUPP; |
337 | 337 | ||
338 | /* Set up rx coalescing */ | 338 | /* Set up rx coalescing */ |
@@ -482,7 +482,7 @@ static int gfar_set_rx_csum(struct net_device *dev, uint32_t data) | |||
482 | unsigned long flags; | 482 | unsigned long flags; |
483 | int err = 0; | 483 | int err = 0; |
484 | 484 | ||
485 | if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_CSUM)) | 485 | if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_CSUM)) |
486 | return -EOPNOTSUPP; | 486 | return -EOPNOTSUPP; |
487 | 487 | ||
488 | if (dev->flags & IFF_UP) { | 488 | if (dev->flags & IFF_UP) { |
@@ -515,7 +515,7 @@ static uint32_t gfar_get_rx_csum(struct net_device *dev) | |||
515 | { | 515 | { |
516 | struct gfar_private *priv = netdev_priv(dev); | 516 | struct gfar_private *priv = netdev_priv(dev); |
517 | 517 | ||
518 | if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_CSUM)) | 518 | if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_CSUM)) |
519 | return 0; | 519 | return 0; |
520 | 520 | ||
521 | return priv->rx_csum_enable; | 521 | return priv->rx_csum_enable; |
@@ -526,7 +526,7 @@ static int gfar_set_tx_csum(struct net_device *dev, uint32_t data) | |||
526 | unsigned long flags; | 526 | unsigned long flags; |
527 | struct gfar_private *priv = netdev_priv(dev); | 527 | struct gfar_private *priv = netdev_priv(dev); |
528 | 528 | ||
529 | if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_CSUM)) | 529 | if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_CSUM)) |
530 | return -EOPNOTSUPP; | 530 | return -EOPNOTSUPP; |
531 | 531 | ||
532 | spin_lock_irqsave(&priv->txlock, flags); | 532 | spin_lock_irqsave(&priv->txlock, flags); |
@@ -547,7 +547,7 @@ static uint32_t gfar_get_tx_csum(struct net_device *dev) | |||
547 | { | 547 | { |
548 | struct gfar_private *priv = netdev_priv(dev); | 548 | struct gfar_private *priv = netdev_priv(dev); |
549 | 549 | ||
550 | if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_CSUM)) | 550 | if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_CSUM)) |
551 | return 0; | 551 | return 0; |
552 | 552 | ||
553 | return (dev->features & NETIF_F_IP_CSUM) != 0; | 553 | return (dev->features & NETIF_F_IP_CSUM) != 0; |
@@ -570,7 +570,7 @@ static void gfar_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) | |||
570 | { | 570 | { |
571 | struct gfar_private *priv = netdev_priv(dev); | 571 | struct gfar_private *priv = netdev_priv(dev); |
572 | 572 | ||
573 | if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET) { | 573 | if (priv->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET) { |
574 | wol->supported = WAKE_MAGIC; | 574 | wol->supported = WAKE_MAGIC; |
575 | wol->wolopts = priv->wol_en ? WAKE_MAGIC : 0; | 575 | wol->wolopts = priv->wol_en ? WAKE_MAGIC : 0; |
576 | } else { | 576 | } else { |
@@ -583,7 +583,7 @@ static int gfar_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) | |||
583 | struct gfar_private *priv = netdev_priv(dev); | 583 | struct gfar_private *priv = netdev_priv(dev); |
584 | unsigned long flags; | 584 | unsigned long flags; |
585 | 585 | ||
586 | if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET) && | 586 | if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET) && |
587 | wol->wolopts != 0) | 587 | wol->wolopts != 0) |
588 | return -EINVAL; | 588 | return -EINVAL; |
589 | 589 | ||
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 */ | ||
156 | static 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 | |||
194 | void 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 | ||
154 | static 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 */ | ||
204 | static 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 | |||
221 | static 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 | ||
241 | bus_register_fail: | 319 | err_free_irqs: |
320 | kfree(new_bus->irq); | ||
321 | err_unmap_regs: | ||
242 | iounmap(regs); | 322 | iounmap(regs); |
243 | reg_map_fail: | 323 | err_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 | ||
250 | static int gfar_mdio_remove(struct device *dev) | 330 | static 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 | ||
265 | static struct device_driver gianfar_mdio_driver = { | 346 | static 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 | |||
361 | static 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 | ||
272 | static 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. */ | ||
284 | struct 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 | |||
293 | int __init gfar_mdio_init(void) | 369 | int __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 | ||
298 | void gfar_mdio_exit(void) | 374 | void gfar_mdio_exit(void) |
299 | { | 375 | { |
300 | driver_unregister(&gianfar_mdio_driver); | 376 | of_unregister_platform_driver(&gianfar_mdio_driver); |
301 | } | 377 | } |
diff --git a/drivers/net/gianfar_mii.h b/drivers/net/gianfar_mii.h index 02dc970ca1ff..65c242cd468a 100644 --- a/drivers/net/gianfar_mii.h +++ b/drivers/net/gianfar_mii.h | |||
@@ -49,4 +49,6 @@ int gfar_local_mdio_read(struct gfar_mii __iomem *regs, int mii_id, int regnum); | |||
49 | struct mii_bus *gfar_get_miibus(const struct gfar_private *priv); | 49 | struct mii_bus *gfar_get_miibus(const struct gfar_private *priv); |
50 | int __init gfar_mdio_init(void); | 50 | int __init gfar_mdio_init(void); |
51 | void gfar_mdio_exit(void); | 51 | void gfar_mdio_exit(void); |
52 | |||
53 | void gfar_mdio_bus_name(char *name, struct device_node *np); | ||
52 | #endif /* GIANFAR_PHY_H */ | 54 | #endif /* GIANFAR_PHY_H */ |