Commit c3a07134e6aa5b93a37f72ffa3d11fadf72bf757

Authored by Florian Fainelli
Committed by David S. Miller
1 parent 2ec9852138

mv643xx_eth: convert to use the Marvell Orion MDIO driver

This patch converts the Marvell MV643XX ethernet driver to use the
Marvell Orion MDIO driver. As a result, PowerPC and ARM platforms
registering the Marvell MV643XX ethernet driver are also updated to
register a Marvell Orion MDIO driver. This driver voluntarily overlaps
with the Marvell Ethernet shared registers because it will use a subset
of this shared register (shared_base + 0x4 to shared_base + 0x84). The
Ethernet driver is also updated to look up for a PHY device using the
Orion MDIO bus driver.

For ARM and PowerPC we register a single instance of the "mvmdio" driver
in the system like it used to be done with the use of the "shared_smi"
platform_data cookie on ARM.

Note that it is safe to register the mvmdio driver only for the "ge00"
instance of the driver because this "ge00" interface is guaranteed to
always be explicitely registered by consumers of
arch/arm/plat-orion/common.c and other instances (ge01, ge10 and ge11)
were all pointing their shared_smi to ge00. For PowerPC the in-tree
Device Tree Source files mention only one MV643XX ethernet MAC instance
so the MDIO bus driver is registered only when id == 0.

Signed-off-by: Florian Fainelli <florian@openwrt.org>
Signed-off-by: David S. Miller <davem@davemloft.net>

Showing 7 changed files with 84 additions and 209 deletions Side-by-side Diff

arch/arm/plat-orion/common.c
... ... @@ -238,6 +238,7 @@
238 238 struct mv643xx_eth_shared_platform_data *orion_ge_shared_data,
239 239 struct resource *orion_ge_resource, unsigned long irq,
240 240 struct platform_device *orion_ge_shared,
  241 + struct platform_device *orion_ge_mvmdio,
241 242 struct mv643xx_eth_platform_data *eth_data,
242 243 struct platform_device *orion_ge)
243 244 {
... ... @@ -247,6 +248,8 @@
247 248 orion_ge->dev.platform_data = eth_data;
248 249  
249 250 platform_device_register(orion_ge_shared);
  251 + if (orion_ge_mvmdio)
  252 + platform_device_register(orion_ge_mvmdio);
250 253 platform_device_register(orion_ge);
251 254 }
252 255  
... ... @@ -258,8 +261,6 @@
258 261 static struct resource orion_ge00_shared_resources[] = {
259 262 {
260 263 .name = "ge00 base",
261   - }, {
262   - .name = "ge00 err irq",
263 264 },
264 265 };
265 266  
... ... @@ -271,6 +272,19 @@
271 272 },
272 273 };
273 274  
  275 +static struct resource orion_ge_mvmdio_resources[] = {
  276 + {
  277 + .name = "ge00 mvmdio base",
  278 + }, {
  279 + .name = "ge00 mvmdio err irq",
  280 + },
  281 +};
  282 +
  283 +static struct platform_device orion_ge_mvmdio = {
  284 + .name = "orion-mdio",
  285 + .id = -1,
  286 +};
  287 +
274 288 static struct resource orion_ge00_resources[] = {
275 289 {
276 290 .name = "ge00 irq",
277 291  
278 292  
279 293  
... ... @@ -295,26 +309,25 @@
295 309 unsigned int tx_csum_limit)
296 310 {
297 311 fill_resources(&orion_ge00_shared, orion_ge00_shared_resources,
298   - mapbase + 0x2000, SZ_16K - 1, irq_err);
  312 + mapbase + 0x2000, SZ_16K - 1, NO_IRQ);
  313 + fill_resources(&orion_ge_mvmdio, orion_ge_mvmdio_resources,
  314 + mapbase + 0x2004, 0x84 - 1, irq_err);
299 315 orion_ge00_shared_data.tx_csum_limit = tx_csum_limit;
300 316 ge_complete(&orion_ge00_shared_data,
301 317 orion_ge00_resources, irq, &orion_ge00_shared,
  318 + &orion_ge_mvmdio,
302 319 eth_data, &orion_ge00);
303 320 }
304 321  
305 322 /*****************************************************************************
306 323 * GE01
307 324 ****************************************************************************/
308   -struct mv643xx_eth_shared_platform_data orion_ge01_shared_data = {
309   - .shared_smi = &orion_ge00_shared,
310   -};
  325 +struct mv643xx_eth_shared_platform_data orion_ge01_shared_data;
311 326  
312 327 static struct resource orion_ge01_shared_resources[] = {
313 328 {
314 329 .name = "ge01 base",
315   - }, {
316   - .name = "ge01 err irq",
317   - },
  330 + }
318 331 };
319 332  
320 333 static struct platform_device orion_ge01_shared = {
321 334  
322 335  
323 336  
... ... @@ -349,26 +362,23 @@
349 362 unsigned int tx_csum_limit)
350 363 {
351 364 fill_resources(&orion_ge01_shared, orion_ge01_shared_resources,
352   - mapbase + 0x2000, SZ_16K - 1, irq_err);
  365 + mapbase + 0x2000, SZ_16K - 1, NO_IRQ);
353 366 orion_ge01_shared_data.tx_csum_limit = tx_csum_limit;
354 367 ge_complete(&orion_ge01_shared_data,
355 368 orion_ge01_resources, irq, &orion_ge01_shared,
  369 + NULL,
356 370 eth_data, &orion_ge01);
357 371 }
358 372  
359 373 /*****************************************************************************
360 374 * GE10
361 375 ****************************************************************************/
362   -struct mv643xx_eth_shared_platform_data orion_ge10_shared_data = {
363   - .shared_smi = &orion_ge00_shared,
364   -};
  376 +struct mv643xx_eth_shared_platform_data orion_ge10_shared_data;
365 377  
366 378 static struct resource orion_ge10_shared_resources[] = {
367 379 {
368 380 .name = "ge10 base",
369   - }, {
370   - .name = "ge10 err irq",
371   - },
  381 + }
372 382 };
373 383  
374 384 static struct platform_device orion_ge10_shared = {
375 385  
376 386  
377 387  
... ... @@ -402,24 +412,21 @@
402 412 unsigned long irq_err)
403 413 {
404 414 fill_resources(&orion_ge10_shared, orion_ge10_shared_resources,
405   - mapbase + 0x2000, SZ_16K - 1, irq_err);
  415 + mapbase + 0x2000, SZ_16K - 1, NO_IRQ);
406 416 ge_complete(&orion_ge10_shared_data,
407 417 orion_ge10_resources, irq, &orion_ge10_shared,
  418 + NULL,
408 419 eth_data, &orion_ge10);
409 420 }
410 421  
411 422 /*****************************************************************************
412 423 * GE11
413 424 ****************************************************************************/
414   -struct mv643xx_eth_shared_platform_data orion_ge11_shared_data = {
415   - .shared_smi = &orion_ge00_shared,
416   -};
  425 +struct mv643xx_eth_shared_platform_data orion_ge11_shared_data;
417 426  
418 427 static struct resource orion_ge11_shared_resources[] = {
419 428 {
420 429 .name = "ge11 base",
421   - }, {
422   - .name = "ge11 err irq",
423 430 },
424 431 };
425 432  
426 433  
... ... @@ -454,9 +461,10 @@
454 461 unsigned long irq_err)
455 462 {
456 463 fill_resources(&orion_ge11_shared, orion_ge11_shared_resources,
457   - mapbase + 0x2000, SZ_16K - 1, irq_err);
  464 + mapbase + 0x2000, SZ_16K - 1, NO_IRQ);
458 465 ge_complete(&orion_ge11_shared_data,
459 466 orion_ge11_resources, irq, &orion_ge11_shared,
  467 + NULL,
460 468 eth_data, &orion_ge11);
461 469 }
462 470  
arch/powerpc/platforms/chrp/pegasos_eth.c
... ... @@ -47,6 +47,25 @@
47 47 .resource = mv643xx_eth_shared_resources,
48 48 };
49 49  
  50 +/*
  51 + * The orion mdio driver only covers shared + 0x4 up to shared + 0x84 - 1
  52 + */
  53 +static struct resource mv643xx_eth_mvmdio_resources[] = {
  54 + [0] = {
  55 + .name = "ethernet mdio base",
  56 + .start = 0xf1000000 + MV643XX_ETH_SHARED_REGS + 0x4,
  57 + .end = 0xf1000000 + MV643XX_ETH_SHARED_REGS + 0x83,
  58 + .flags = IORESOURCE_MEM,
  59 + },
  60 +};
  61 +
  62 +static struct platform_device mv643xx_eth_mvmdio_device = {
  63 + .name = "orion-mdio",
  64 + .id = -1,
  65 + .num_resources = ARRAY_SIZE(mv643xx_eth_mvmdio_resources),
  66 + .resource = mv643xx_eth_shared_resources,
  67 +};
  68 +
50 69 static struct resource mv643xx_eth_port1_resources[] = {
51 70 [0] = {
52 71 .name = "eth port1 irq",
... ... @@ -82,6 +101,7 @@
82 101  
83 102 static struct platform_device *mv643xx_eth_pd_devs[] __initdata = {
84 103 &mv643xx_eth_shared_device,
  104 + &mv643xx_eth_mvmdio_device,
85 105 &eth_port1_device,
86 106 };
87 107  
arch/powerpc/sysdev/mv64x60_dev.c
... ... @@ -214,15 +214,27 @@
214 214 struct device_node *np, int id)
215 215 {
216 216 struct platform_device *pdev;
217   - struct resource r[1];
  217 + struct resource r[2];
218 218 int err;
219 219  
220 220 err = of_address_to_resource(np, 0, &r[0]);
221 221 if (err)
222 222 return ERR_PTR(err);
223 223  
  224 + /* register an orion mdio bus driver */
  225 + r[1].start = r[0].start + 0x4;
  226 + r[1].end = r[0].start + 0x84 - 1;
  227 + r[1].flags = IORESOURCE_MEM;
  228 +
  229 + if (id == 0) {
  230 + pdev = platform_device_register_simple("orion-mdio", -1, &r[1], 1);
  231 + if (!pdev)
  232 + return pdev;
  233 + }
  234 +
224 235 pdev = platform_device_register_simple(MV643XX_ETH_SHARED_NAME, id,
225   - r, 1);
  236 + &r[0], 1);
  237 +
226 238 return pdev;
227 239 }
228 240  
drivers/net/ethernet/marvell/Kconfig
... ... @@ -23,6 +23,7 @@
23 23 depends on (MV64X60 || PPC32 || PLAT_ORION) && INET
24 24 select INET_LRO
25 25 select PHYLIB
  26 + select MVMDIO
26 27 ---help---
27 28 This driver supports the gigabit ethernet MACs in the
28 29 Marvell Discovery PPC/MIPS chipset family (MV643XX) and
... ... @@ -38,9 +39,7 @@
38 39 interface units of the Marvell EBU SoCs (Kirkwood, Orion5x,
39 40 Dove, Armada 370 and Armada XP).
40 41  
41   - For now, this driver is only needed for the MVNETA driver
42   - (used on Armada 370 and XP), but it could be used in the
43   - future by the MV643XX_ETH driver.
  42 + This driver is used by the MV643XX_ETH and MVNETA drivers.
44 43  
45 44 config MVNETA
46 45 tristate "Marvell Armada 370/XP network interface support"
drivers/net/ethernet/marvell/Makefile
... ... @@ -2,8 +2,8 @@
2 2 # Makefile for the Marvell device drivers.
3 3 #
4 4  
5   -obj-$(CONFIG_MV643XX_ETH) += mv643xx_eth.o
6 5 obj-$(CONFIG_MVMDIO) += mvmdio.o
  6 +obj-$(CONFIG_MV643XX_ETH) += mv643xx_eth.o
7 7 obj-$(CONFIG_MVNETA) += mvneta.o
8 8 obj-$(CONFIG_PXA168_ETH) += pxa168_eth.o
9 9 obj-$(CONFIG_SKGE) += skge.o
drivers/net/ethernet/marvell/mv643xx_eth.c
... ... @@ -69,14 +69,6 @@
69 69 * Registers shared between all ports.
70 70 */
71 71 #define PHY_ADDR 0x0000
72   -#define SMI_REG 0x0004
73   -#define SMI_BUSY 0x10000000
74   -#define SMI_READ_VALID 0x08000000
75   -#define SMI_OPCODE_READ 0x04000000
76   -#define SMI_OPCODE_WRITE 0x00000000
77   -#define ERR_INT_CAUSE 0x0080
78   -#define ERR_INT_SMI_DONE 0x00000010
79   -#define ERR_INT_MASK 0x0084
80 72 #define WINDOW_BASE(w) (0x0200 + ((w) << 3))
81 73 #define WINDOW_SIZE(w) (0x0204 + ((w) << 3))
82 74 #define WINDOW_REMAP_HIGH(w) (0x0280 + ((w) << 2))
... ... @@ -266,25 +258,6 @@
266 258 void __iomem *base;
267 259  
268 260 /*
269   - * Points at the right SMI instance to use.
270   - */
271   - struct mv643xx_eth_shared_private *smi;
272   -
273   - /*
274   - * Provides access to local SMI interface.
275   - */
276   - struct mii_bus *smi_bus;
277   -
278   - /*
279   - * If we have access to the error interrupt pin (which is
280   - * somewhat misnamed as it not only reflects internal errors
281   - * but also reflects SMI completion), use that to wait for
282   - * SMI access completion instead of polling the SMI busy bit.
283   - */
284   - int err_interrupt;
285   - wait_queue_head_t smi_busy_wait;
286   -
287   - /*
288 261 * Per-port MBUS window access register value.
289 262 */
290 263 u32 win_protect;
... ... @@ -1122,97 +1095,6 @@
1122 1095 wrlp(mp, PORT_SERIAL_CONTROL, pscr);
1123 1096 }
1124 1097  
1125   -static irqreturn_t mv643xx_eth_err_irq(int irq, void *dev_id)
1126   -{
1127   - struct mv643xx_eth_shared_private *msp = dev_id;
1128   -
1129   - if (readl(msp->base + ERR_INT_CAUSE) & ERR_INT_SMI_DONE) {
1130   - writel(~ERR_INT_SMI_DONE, msp->base + ERR_INT_CAUSE);
1131   - wake_up(&msp->smi_busy_wait);
1132   - return IRQ_HANDLED;
1133   - }
1134   -
1135   - return IRQ_NONE;
1136   -}
1137   -
1138   -static int smi_is_done(struct mv643xx_eth_shared_private *msp)
1139   -{
1140   - return !(readl(msp->base + SMI_REG) & SMI_BUSY);
1141   -}
1142   -
1143   -static int smi_wait_ready(struct mv643xx_eth_shared_private *msp)
1144   -{
1145   - if (msp->err_interrupt == NO_IRQ) {
1146   - int i;
1147   -
1148   - for (i = 0; !smi_is_done(msp); i++) {
1149   - if (i == 10)
1150   - return -ETIMEDOUT;
1151   - msleep(10);
1152   - }
1153   -
1154   - return 0;
1155   - }
1156   -
1157   - if (!smi_is_done(msp)) {
1158   - wait_event_timeout(msp->smi_busy_wait, smi_is_done(msp),
1159   - msecs_to_jiffies(100));
1160   - if (!smi_is_done(msp))
1161   - return -ETIMEDOUT;
1162   - }
1163   -
1164   - return 0;
1165   -}
1166   -
1167   -static int smi_bus_read(struct mii_bus *bus, int addr, int reg)
1168   -{
1169   - struct mv643xx_eth_shared_private *msp = bus->priv;
1170   - void __iomem *smi_reg = msp->base + SMI_REG;
1171   - int ret;
1172   -
1173   - if (smi_wait_ready(msp)) {
1174   - pr_warn("SMI bus busy timeout\n");
1175   - return -ETIMEDOUT;
1176   - }
1177   -
1178   - writel(SMI_OPCODE_READ | (reg << 21) | (addr << 16), smi_reg);
1179   -
1180   - if (smi_wait_ready(msp)) {
1181   - pr_warn("SMI bus busy timeout\n");
1182   - return -ETIMEDOUT;
1183   - }
1184   -
1185   - ret = readl(smi_reg);
1186   - if (!(ret & SMI_READ_VALID)) {
1187   - pr_warn("SMI bus read not valid\n");
1188   - return -ENODEV;
1189   - }
1190   -
1191   - return ret & 0xffff;
1192   -}
1193   -
1194   -static int smi_bus_write(struct mii_bus *bus, int addr, int reg, u16 val)
1195   -{
1196   - struct mv643xx_eth_shared_private *msp = bus->priv;
1197   - void __iomem *smi_reg = msp->base + SMI_REG;
1198   -
1199   - if (smi_wait_ready(msp)) {
1200   - pr_warn("SMI bus busy timeout\n");
1201   - return -ETIMEDOUT;
1202   - }
1203   -
1204   - writel(SMI_OPCODE_WRITE | (reg << 21) |
1205   - (addr << 16) | (val & 0xffff), smi_reg);
1206   -
1207   - if (smi_wait_ready(msp)) {
1208   - pr_warn("SMI bus busy timeout\n");
1209   - return -ETIMEDOUT;
1210   - }
1211   -
1212   - return 0;
1213   -}
1214   -
1215   -
1216 1098 /* statistics ***************************************************************/
1217 1099 static struct net_device_stats *mv643xx_eth_get_stats(struct net_device *dev)
1218 1100 {
... ... @@ -2688,47 +2570,6 @@
2688 2570 goto out_free;
2689 2571  
2690 2572 /*
2691   - * Set up and register SMI bus.
2692   - */
2693   - if (pd == NULL || pd->shared_smi == NULL) {
2694   - msp->smi_bus = mdiobus_alloc();
2695   - if (msp->smi_bus == NULL)
2696   - goto out_unmap;
2697   -
2698   - msp->smi_bus->priv = msp;
2699   - msp->smi_bus->name = "mv643xx_eth smi";
2700   - msp->smi_bus->read = smi_bus_read;
2701   - msp->smi_bus->write = smi_bus_write,
2702   - snprintf(msp->smi_bus->id, MII_BUS_ID_SIZE, "%s-%d",
2703   - pdev->name, pdev->id);
2704   - msp->smi_bus->parent = &pdev->dev;
2705   - msp->smi_bus->phy_mask = 0xffffffff;
2706   - if (mdiobus_register(msp->smi_bus) < 0)
2707   - goto out_free_mii_bus;
2708   - msp->smi = msp;
2709   - } else {
2710   - msp->smi = platform_get_drvdata(pd->shared_smi);
2711   - }
2712   -
2713   - msp->err_interrupt = NO_IRQ;
2714   - init_waitqueue_head(&msp->smi_busy_wait);
2715   -
2716   - /*
2717   - * Check whether the error interrupt is hooked up.
2718   - */
2719   - res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
2720   - if (res != NULL) {
2721   - int err;
2722   -
2723   - err = request_irq(res->start, mv643xx_eth_err_irq,
2724   - IRQF_SHARED, "mv643xx_eth", msp);
2725   - if (!err) {
2726   - writel(ERR_INT_SMI_DONE, msp->base + ERR_INT_MASK);
2727   - msp->err_interrupt = res->start;
2728   - }
2729   - }
2730   -
2731   - /*
2732 2573 * (Re-)program MBUS remapping windows if we are asked to.
2733 2574 */
2734 2575 dram = mv_mbus_dram_info();
... ... @@ -2743,10 +2584,6 @@
2743 2584  
2744 2585 return 0;
2745 2586  
2746   -out_free_mii_bus:
2747   - mdiobus_free(msp->smi_bus);
2748   -out_unmap:
2749   - iounmap(msp->base);
2750 2587 out_free:
2751 2588 kfree(msp);
2752 2589 out:
2753 2590  
... ... @@ -2756,14 +2593,7 @@
2756 2593 static int mv643xx_eth_shared_remove(struct platform_device *pdev)
2757 2594 {
2758 2595 struct mv643xx_eth_shared_private *msp = platform_get_drvdata(pdev);
2759   - struct mv643xx_eth_shared_platform_data *pd = pdev->dev.platform_data;
2760 2596  
2761   - if (pd == NULL || pd->shared_smi == NULL) {
2762   - mdiobus_unregister(msp->smi_bus);
2763   - mdiobus_free(msp->smi_bus);
2764   - }
2765   - if (msp->err_interrupt != NO_IRQ)
2766   - free_irq(msp->err_interrupt, msp);
2767 2597 iounmap(msp->base);
2768 2598 kfree(msp);
2769 2599  
2770 2600  
2771 2601  
... ... @@ -2826,14 +2656,21 @@
2826 2656 mp->txq_count = pd->tx_queue_count ? : 1;
2827 2657 }
2828 2658  
  2659 +static void mv643xx_eth_adjust_link(struct net_device *dev)
  2660 +{
  2661 + struct mv643xx_eth_private *mp = netdev_priv(dev);
  2662 +
  2663 + mv643xx_adjust_pscr(mp);
  2664 +}
  2665 +
2829 2666 static struct phy_device *phy_scan(struct mv643xx_eth_private *mp,
2830 2667 int phy_addr)
2831 2668 {
2832   - struct mii_bus *bus = mp->shared->smi->smi_bus;
2833 2669 struct phy_device *phydev;
2834 2670 int start;
2835 2671 int num;
2836 2672 int i;
  2673 + char phy_id[MII_BUS_ID_SIZE + 3];
2837 2674  
2838 2675 if (phy_addr == MV643XX_ETH_PHY_ADDR_DEFAULT) {
2839 2676 start = phy_addr_get(mp) & 0x1f;
2840 2677  
2841 2678  
... ... @@ -2843,17 +2680,19 @@
2843 2680 num = 1;
2844 2681 }
2845 2682  
  2683 + /* Attempt to connect to the PHY using orion-mdio */
2846 2684 phydev = NULL;
2847 2685 for (i = 0; i < num; i++) {
2848 2686 int addr = (start + i) & 0x1f;
2849 2687  
2850   - if (bus->phy_map[addr] == NULL)
2851   - mdiobus_scan(bus, addr);
  2688 + snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT,
  2689 + "orion-mdio-mii", addr);
2852 2690  
2853   - if (phydev == NULL) {
2854   - phydev = bus->phy_map[addr];
2855   - if (phydev != NULL)
2856   - phy_addr_set(mp, addr);
  2691 + phydev = phy_connect(mp->dev, phy_id, mv643xx_eth_adjust_link,
  2692 + PHY_INTERFACE_MODE_GMII);
  2693 + if (!IS_ERR(phydev)) {
  2694 + phy_addr_set(mp, addr);
  2695 + break;
2857 2696 }
2858 2697 }
2859 2698  
... ... @@ -2865,8 +2704,6 @@
2865 2704 struct phy_device *phy = mp->phy;
2866 2705  
2867 2706 phy_reset(mp);
2868   -
2869   - phy_attach(mp->dev, dev_name(&phy->dev), PHY_INTERFACE_MODE_GMII);
2870 2707  
2871 2708 if (speed == 0) {
2872 2709 phy->autoneg = AUTONEG_ENABLE;
include/linux/mv643xx_eth.h
... ... @@ -19,7 +19,6 @@
19 19  
20 20 struct mv643xx_eth_shared_platform_data {
21 21 struct mbus_dram_target_info *dram;
22   - struct platform_device *shared_smi;
23 22 /*
24 23 * Max packet size for Tx IP/Layer 4 checksum, when set to 0, default
25 24 * limit of 9KiB will be used.