diff options
author | Victor Gallardo <vgallardo@amcc.com> | 2008-10-02 02:37:57 -0400 |
---|---|---|
committer | Josh Boyer <jwboyer@linux.vnet.ibm.com> | 2008-10-02 13:06:42 -0400 |
commit | 9e3cb29497561c846d0e7efc445731764d93c749 (patch) | |
tree | fec0caf2a561850074bfcb29013603d2fde9b056 /drivers/net/ibm_newemac/core.c | |
parent | 5a013fc7bb48acefe94011f4b83fef95b381f875 (diff) |
ibm_newemac: Add support for GPCS, SGMII and M88E1112 PHY
Add support for the phy types found on the Arches and other
PowerPC 460 based boards.
Signed-off-by: Victor Gallardo <vgallardo@amcc.com>
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Acked-by: Jeff Garzik <jeff@garzik.org>
Signed-off-by: Josh Boyer <jwboyer@linux.vnet.ibm.com>
Diffstat (limited to 'drivers/net/ibm_newemac/core.c')
-rw-r--r-- | drivers/net/ibm_newemac/core.c | 58 |
1 files changed, 49 insertions, 9 deletions
diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c index 4e633870e6e..efcf21c9f5c 100644 --- a/drivers/net/ibm_newemac/core.c +++ b/drivers/net/ibm_newemac/core.c | |||
@@ -130,6 +130,7 @@ static inline void emac_report_timeout_error(struct emac_instance *dev, | |||
130 | const char *error) | 130 | const char *error) |
131 | { | 131 | { |
132 | if (emac_has_feature(dev, EMAC_FTR_440GX_PHY_CLK_FIX | | 132 | if (emac_has_feature(dev, EMAC_FTR_440GX_PHY_CLK_FIX | |
133 | EMAC_FTR_460EX_PHY_CLK_FIX | | ||
133 | EMAC_FTR_440EP_PHY_CLK_FIX)) | 134 | EMAC_FTR_440EP_PHY_CLK_FIX)) |
134 | DBG(dev, "%s" NL, error); | 135 | DBG(dev, "%s" NL, error); |
135 | else if (net_ratelimit()) | 136 | else if (net_ratelimit()) |
@@ -201,13 +202,15 @@ static inline int emac_phy_supports_gige(int phy_mode) | |||
201 | { | 202 | { |
202 | return phy_mode == PHY_MODE_GMII || | 203 | return phy_mode == PHY_MODE_GMII || |
203 | phy_mode == PHY_MODE_RGMII || | 204 | phy_mode == PHY_MODE_RGMII || |
205 | phy_mode == PHY_MODE_SGMII || | ||
204 | phy_mode == PHY_MODE_TBI || | 206 | phy_mode == PHY_MODE_TBI || |
205 | phy_mode == PHY_MODE_RTBI; | 207 | phy_mode == PHY_MODE_RTBI; |
206 | } | 208 | } |
207 | 209 | ||
208 | static inline int emac_phy_gpcs(int phy_mode) | 210 | static inline int emac_phy_gpcs(int phy_mode) |
209 | { | 211 | { |
210 | return phy_mode == PHY_MODE_TBI || | 212 | return phy_mode == PHY_MODE_SGMII || |
213 | phy_mode == PHY_MODE_TBI || | ||
211 | phy_mode == PHY_MODE_RTBI; | 214 | phy_mode == PHY_MODE_RTBI; |
212 | } | 215 | } |
213 | 216 | ||
@@ -351,10 +354,24 @@ static int emac_reset(struct emac_instance *dev) | |||
351 | emac_tx_disable(dev); | 354 | emac_tx_disable(dev); |
352 | } | 355 | } |
353 | 356 | ||
357 | #ifdef CONFIG_PPC_DCR_NATIVE | ||
358 | /* Enable internal clock source */ | ||
359 | if (emac_has_feature(dev, EMAC_FTR_460EX_PHY_CLK_FIX)) | ||
360 | dcri_clrset(SDR0, SDR0_ETH_CFG, | ||
361 | 0, SDR0_ETH_CFG_ECS << dev->cell_index); | ||
362 | #endif | ||
363 | |||
354 | out_be32(&p->mr0, EMAC_MR0_SRST); | 364 | out_be32(&p->mr0, EMAC_MR0_SRST); |
355 | while ((in_be32(&p->mr0) & EMAC_MR0_SRST) && n) | 365 | while ((in_be32(&p->mr0) & EMAC_MR0_SRST) && n) |
356 | --n; | 366 | --n; |
357 | 367 | ||
368 | #ifdef CONFIG_PPC_DCR_NATIVE | ||
369 | /* Enable external clock source */ | ||
370 | if (emac_has_feature(dev, EMAC_FTR_460EX_PHY_CLK_FIX)) | ||
371 | dcri_clrset(SDR0, SDR0_ETH_CFG, | ||
372 | SDR0_ETH_CFG_ECS << dev->cell_index, 0); | ||
373 | #endif | ||
374 | |||
358 | if (n) { | 375 | if (n) { |
359 | dev->reset_failed = 0; | 376 | dev->reset_failed = 0; |
360 | return 0; | 377 | return 0; |
@@ -547,8 +564,9 @@ static int emac_configure(struct emac_instance *dev) | |||
547 | switch (dev->phy.speed) { | 564 | switch (dev->phy.speed) { |
548 | case SPEED_1000: | 565 | case SPEED_1000: |
549 | if (emac_phy_gpcs(dev->phy.mode)) { | 566 | if (emac_phy_gpcs(dev->phy.mode)) { |
550 | mr1 |= EMAC_MR1_MF_1000GPCS | | 567 | mr1 |= EMAC_MR1_MF_1000GPCS | EMAC_MR1_MF_IPPA( |
551 | EMAC_MR1_MF_IPPA(dev->phy.address); | 568 | (dev->phy.gpcs_address != 0xffffffff) ? |
569 | dev->phy.gpcs_address : dev->phy.address); | ||
552 | 570 | ||
553 | /* Put some arbitrary OUI, Manuf & Rev IDs so we can | 571 | /* Put some arbitrary OUI, Manuf & Rev IDs so we can |
554 | * identify this GPCS PHY later. | 572 | * identify this GPCS PHY later. |
@@ -660,8 +678,12 @@ static int emac_configure(struct emac_instance *dev) | |||
660 | out_be32(&p->iser, r); | 678 | out_be32(&p->iser, r); |
661 | 679 | ||
662 | /* We need to take GPCS PHY out of isolate mode after EMAC reset */ | 680 | /* We need to take GPCS PHY out of isolate mode after EMAC reset */ |
663 | if (emac_phy_gpcs(dev->phy.mode)) | 681 | if (emac_phy_gpcs(dev->phy.mode)) { |
664 | emac_mii_reset_phy(&dev->phy); | 682 | if (dev->phy.gpcs_address != 0xffffffff) |
683 | emac_mii_reset_gpcs(&dev->phy); | ||
684 | else | ||
685 | emac_mii_reset_phy(&dev->phy); | ||
686 | } | ||
665 | 687 | ||
666 | return 0; | 688 | return 0; |
667 | } | 689 | } |
@@ -866,7 +888,9 @@ static int emac_mdio_read(struct net_device *ndev, int id, int reg) | |||
866 | struct emac_instance *dev = netdev_priv(ndev); | 888 | struct emac_instance *dev = netdev_priv(ndev); |
867 | int res; | 889 | int res; |
868 | 890 | ||
869 | res = __emac_mdio_read(dev->mdio_instance ? dev->mdio_instance : dev, | 891 | res = __emac_mdio_read((dev->mdio_instance && |
892 | dev->phy.gpcs_address != id) ? | ||
893 | dev->mdio_instance : dev, | ||
870 | (u8) id, (u8) reg); | 894 | (u8) id, (u8) reg); |
871 | return res; | 895 | return res; |
872 | } | 896 | } |
@@ -875,7 +899,9 @@ static void emac_mdio_write(struct net_device *ndev, int id, int reg, int val) | |||
875 | { | 899 | { |
876 | struct emac_instance *dev = netdev_priv(ndev); | 900 | struct emac_instance *dev = netdev_priv(ndev); |
877 | 901 | ||
878 | __emac_mdio_write(dev->mdio_instance ? dev->mdio_instance : dev, | 902 | __emac_mdio_write((dev->mdio_instance && |
903 | dev->phy.gpcs_address != id) ? | ||
904 | dev->mdio_instance : dev, | ||
879 | (u8) id, (u8) reg, (u16) val); | 905 | (u8) id, (u8) reg, (u16) val); |
880 | } | 906 | } |
881 | 907 | ||
@@ -2367,7 +2393,11 @@ static int __devinit emac_init_phy(struct emac_instance *dev) | |||
2367 | * XXX I probably should move these settings to the dev tree | 2393 | * XXX I probably should move these settings to the dev tree |
2368 | */ | 2394 | */ |
2369 | dev->phy.address = -1; | 2395 | dev->phy.address = -1; |
2370 | dev->phy.features = SUPPORTED_100baseT_Full | SUPPORTED_MII; | 2396 | dev->phy.features = SUPPORTED_MII; |
2397 | if (emac_phy_supports_gige(dev->phy_mode)) | ||
2398 | dev->phy.features |= SUPPORTED_1000baseT_Full; | ||
2399 | else | ||
2400 | dev->phy.features |= SUPPORTED_100baseT_Full; | ||
2371 | dev->phy.pause = 1; | 2401 | dev->phy.pause = 1; |
2372 | 2402 | ||
2373 | return 0; | 2403 | return 0; |
@@ -2406,7 +2436,9 @@ static int __devinit emac_init_phy(struct emac_instance *dev) | |||
2406 | * Note that the busy_phy_map is currently global | 2436 | * Note that the busy_phy_map is currently global |
2407 | * while it should probably be per-ASIC... | 2437 | * while it should probably be per-ASIC... |
2408 | */ | 2438 | */ |
2409 | dev->phy.address = dev->cell_index; | 2439 | dev->phy.gpcs_address = dev->gpcs_address; |
2440 | if (dev->phy.gpcs_address == 0xffffffff) | ||
2441 | dev->phy.address = dev->cell_index; | ||
2410 | } | 2442 | } |
2411 | 2443 | ||
2412 | emac_configure(dev); | 2444 | emac_configure(dev); |
@@ -2516,6 +2548,8 @@ static int __devinit emac_init_config(struct emac_instance *dev) | |||
2516 | dev->phy_address = 0xffffffff; | 2548 | dev->phy_address = 0xffffffff; |
2517 | if (emac_read_uint_prop(np, "phy-map", &dev->phy_map, 0)) | 2549 | if (emac_read_uint_prop(np, "phy-map", &dev->phy_map, 0)) |
2518 | dev->phy_map = 0xffffffff; | 2550 | dev->phy_map = 0xffffffff; |
2551 | if (emac_read_uint_prop(np, "gpcs-address", &dev->gpcs_address, 0)) | ||
2552 | dev->gpcs_address = 0xffffffff; | ||
2519 | if (emac_read_uint_prop(np->parent, "clock-frequency", &dev->opb_bus_freq, 1)) | 2553 | if (emac_read_uint_prop(np->parent, "clock-frequency", &dev->opb_bus_freq, 1)) |
2520 | return -ENXIO; | 2554 | return -ENXIO; |
2521 | if (emac_read_uint_prop(np, "tah-device", &dev->tah_ph, 0)) | 2555 | if (emac_read_uint_prop(np, "tah-device", &dev->tah_ph, 0)) |
@@ -2559,6 +2593,9 @@ static int __devinit emac_init_config(struct emac_instance *dev) | |||
2559 | /* Check EMAC version */ | 2593 | /* Check EMAC version */ |
2560 | if (of_device_is_compatible(np, "ibm,emac4sync")) { | 2594 | if (of_device_is_compatible(np, "ibm,emac4sync")) { |
2561 | dev->features |= (EMAC_FTR_EMAC4 | EMAC_FTR_EMAC4SYNC); | 2595 | dev->features |= (EMAC_FTR_EMAC4 | EMAC_FTR_EMAC4SYNC); |
2596 | if (of_device_is_compatible(np, "ibm,emac-460ex") || | ||
2597 | of_device_is_compatible(np, "ibm,emac-460gt")) | ||
2598 | dev->features |= EMAC_FTR_460EX_PHY_CLK_FIX; | ||
2562 | } else if (of_device_is_compatible(np, "ibm,emac4")) { | 2599 | } else if (of_device_is_compatible(np, "ibm,emac4")) { |
2563 | dev->features |= EMAC_FTR_EMAC4; | 2600 | dev->features |= EMAC_FTR_EMAC4; |
2564 | if (of_device_is_compatible(np, "ibm,emac-440gx")) | 2601 | if (of_device_is_compatible(np, "ibm,emac-440gx")) |
@@ -2826,6 +2863,9 @@ static int __devinit emac_probe(struct of_device *ofdev, | |||
2826 | ndev->dev_addr[0], ndev->dev_addr[1], ndev->dev_addr[2], | 2863 | ndev->dev_addr[0], ndev->dev_addr[1], ndev->dev_addr[2], |
2827 | ndev->dev_addr[3], ndev->dev_addr[4], ndev->dev_addr[5]); | 2864 | ndev->dev_addr[3], ndev->dev_addr[4], ndev->dev_addr[5]); |
2828 | 2865 | ||
2866 | if (dev->phy_mode == PHY_MODE_SGMII) | ||
2867 | printk(KERN_NOTICE "%s: in SGMII mode\n", ndev->name); | ||
2868 | |||
2829 | if (dev->phy.address >= 0) | 2869 | if (dev->phy.address >= 0) |
2830 | printk("%s: found %s PHY (0x%02x)\n", ndev->name, | 2870 | printk("%s: found %s PHY (0x%02x)\n", ndev->name, |
2831 | dev->phy.def->name, dev->phy.address); | 2871 | dev->phy.def->name, dev->phy.address); |