diff options
Diffstat (limited to 'drivers/net/phy')
-rw-r--r-- | drivers/net/phy/Kconfig | 10 | ||||
-rw-r--r-- | drivers/net/phy/Makefile | 1 | ||||
-rw-r--r-- | drivers/net/phy/amd-xgbe-phy.c | 168 | ||||
-rw-r--r-- | drivers/net/phy/bcm7xxx.c | 116 | ||||
-rw-r--r-- | drivers/net/phy/broadcom.c | 122 | ||||
-rw-r--r-- | drivers/net/phy/dp83640.c | 29 | ||||
-rw-r--r-- | drivers/net/phy/fixed.c | 11 | ||||
-rw-r--r-- | drivers/net/phy/mdio-bcm-unimac.c | 213 | ||||
-rw-r--r-- | drivers/net/phy/mdio_bus.c | 8 | ||||
-rw-r--r-- | drivers/net/phy/phy.c | 12 | ||||
-rw-r--r-- | drivers/net/phy/phy_device.c | 4 |
11 files changed, 447 insertions, 247 deletions
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 65de0cab8d07..14afa4f24424 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig | |||
@@ -159,8 +159,6 @@ config MDIO_OCTEON | |||
159 | config MDIO_SUN4I | 159 | config MDIO_SUN4I |
160 | tristate "Allwinner sun4i MDIO interface support" | 160 | tristate "Allwinner sun4i MDIO interface support" |
161 | depends on ARCH_SUNXI | 161 | depends on ARCH_SUNXI |
162 | select REGULATOR | ||
163 | select REGULATOR_FIXED_VOLTAGE | ||
164 | help | 162 | help |
165 | This driver supports the MDIO interface found in the network | 163 | This driver supports the MDIO interface found in the network |
166 | interface units of the Allwinner SoC that have an EMAC (A10, | 164 | interface units of the Allwinner SoC that have an EMAC (A10, |
@@ -205,6 +203,14 @@ config MDIO_BUS_MUX_MMIOREG | |||
205 | 203 | ||
206 | Currently, only 8-bit registers are supported. | 204 | Currently, only 8-bit registers are supported. |
207 | 205 | ||
206 | config MDIO_BCM_UNIMAC | ||
207 | tristate "Broadcom UniMAC MDIO bus controller" | ||
208 | help | ||
209 | This module provides a driver for the Broadcom UniMAC MDIO busses. | ||
210 | This hardware can be found in the Broadcom GENET Ethernet MAC | ||
211 | controllers as well as some Broadcom Ethernet switches such as the | ||
212 | Starfighter 2 switches. | ||
213 | |||
208 | endif # PHYLIB | 214 | endif # PHYLIB |
209 | 215 | ||
210 | config MICREL_KS8995MA | 216 | config MICREL_KS8995MA |
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index 7dc3d5b304cf..eb3b18b5978b 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile | |||
@@ -34,3 +34,4 @@ obj-$(CONFIG_MDIO_BUS_MUX_MMIOREG) += mdio-mux-mmioreg.o | |||
34 | obj-$(CONFIG_MDIO_SUN4I) += mdio-sun4i.o | 34 | obj-$(CONFIG_MDIO_SUN4I) += mdio-sun4i.o |
35 | obj-$(CONFIG_MDIO_MOXART) += mdio-moxart.o | 35 | obj-$(CONFIG_MDIO_MOXART) += mdio-moxart.o |
36 | obj-$(CONFIG_AMD_XGBE_PHY) += amd-xgbe-phy.o | 36 | obj-$(CONFIG_AMD_XGBE_PHY) += amd-xgbe-phy.o |
37 | obj-$(CONFIG_MDIO_BCM_UNIMAC) += mdio-bcm-unimac.o | ||
diff --git a/drivers/net/phy/amd-xgbe-phy.c b/drivers/net/phy/amd-xgbe-phy.c index f3230eef41fd..c456559f6e7f 100644 --- a/drivers/net/phy/amd-xgbe-phy.c +++ b/drivers/net/phy/amd-xgbe-phy.c | |||
@@ -75,7 +75,6 @@ | |||
75 | #include <linux/of_device.h> | 75 | #include <linux/of_device.h> |
76 | #include <linux/uaccess.h> | 76 | #include <linux/uaccess.h> |
77 | 77 | ||
78 | |||
79 | MODULE_AUTHOR("Tom Lendacky <thomas.lendacky@amd.com>"); | 78 | MODULE_AUTHOR("Tom Lendacky <thomas.lendacky@amd.com>"); |
80 | MODULE_LICENSE("Dual BSD/GPL"); | 79 | MODULE_LICENSE("Dual BSD/GPL"); |
81 | MODULE_VERSION("1.0.0-a"); | 80 | MODULE_VERSION("1.0.0-a"); |
@@ -100,9 +99,11 @@ MODULE_DESCRIPTION("AMD 10GbE (amd-xgbe) PHY driver"); | |||
100 | #ifndef MDIO_PMA_10GBR_PMD_CTRL | 99 | #ifndef MDIO_PMA_10GBR_PMD_CTRL |
101 | #define MDIO_PMA_10GBR_PMD_CTRL 0x0096 | 100 | #define MDIO_PMA_10GBR_PMD_CTRL 0x0096 |
102 | #endif | 101 | #endif |
102 | |||
103 | #ifndef MDIO_PMA_10GBR_FEC_CTRL | 103 | #ifndef MDIO_PMA_10GBR_FEC_CTRL |
104 | #define MDIO_PMA_10GBR_FEC_CTRL 0x00ab | 104 | #define MDIO_PMA_10GBR_FEC_CTRL 0x00ab |
105 | #endif | 105 | #endif |
106 | |||
106 | #ifndef MDIO_AN_XNP | 107 | #ifndef MDIO_AN_XNP |
107 | #define MDIO_AN_XNP 0x0016 | 108 | #define MDIO_AN_XNP 0x0016 |
108 | #endif | 109 | #endif |
@@ -110,14 +111,23 @@ MODULE_DESCRIPTION("AMD 10GbE (amd-xgbe) PHY driver"); | |||
110 | #ifndef MDIO_AN_INTMASK | 111 | #ifndef MDIO_AN_INTMASK |
111 | #define MDIO_AN_INTMASK 0x8001 | 112 | #define MDIO_AN_INTMASK 0x8001 |
112 | #endif | 113 | #endif |
114 | |||
113 | #ifndef MDIO_AN_INT | 115 | #ifndef MDIO_AN_INT |
114 | #define MDIO_AN_INT 0x8002 | 116 | #define MDIO_AN_INT 0x8002 |
115 | #endif | 117 | #endif |
116 | 118 | ||
119 | #ifndef MDIO_AN_KR_CTRL | ||
120 | #define MDIO_AN_KR_CTRL 0x8003 | ||
121 | #endif | ||
122 | |||
117 | #ifndef MDIO_CTRL1_SPEED1G | 123 | #ifndef MDIO_CTRL1_SPEED1G |
118 | #define MDIO_CTRL1_SPEED1G (MDIO_CTRL1_SPEED10G & ~BMCR_SPEED100) | 124 | #define MDIO_CTRL1_SPEED1G (MDIO_CTRL1_SPEED10G & ~BMCR_SPEED100) |
119 | #endif | 125 | #endif |
120 | 126 | ||
127 | #ifndef MDIO_KR_CTRL_PDETECT | ||
128 | #define MDIO_KR_CTRL_PDETECT 0x01 | ||
129 | #endif | ||
130 | |||
121 | /* SerDes integration register offsets */ | 131 | /* SerDes integration register offsets */ |
122 | #define SIR0_KR_RT_1 0x002c | 132 | #define SIR0_KR_RT_1 0x002c |
123 | #define SIR0_STATUS 0x0040 | 133 | #define SIR0_STATUS 0x0040 |
@@ -161,7 +171,6 @@ MODULE_DESCRIPTION("AMD 10GbE (amd-xgbe) PHY driver"); | |||
161 | #define SPEED_1000_TXAMP 0xf | 171 | #define SPEED_1000_TXAMP 0xf |
162 | #define SPEED_1000_WORD 0x1 | 172 | #define SPEED_1000_WORD 0x1 |
163 | 173 | ||
164 | |||
165 | /* SerDes RxTx register offsets */ | 174 | /* SerDes RxTx register offsets */ |
166 | #define RXTX_REG20 0x0050 | 175 | #define RXTX_REG20 0x0050 |
167 | #define RXTX_REG114 0x01c8 | 176 | #define RXTX_REG114 0x01c8 |
@@ -255,7 +264,6 @@ do { \ | |||
255 | XSIR1_IOWRITE((_priv), _reg, reg_val); \ | 264 | XSIR1_IOWRITE((_priv), _reg, reg_val); \ |
256 | } while (0) | 265 | } while (0) |
257 | 266 | ||
258 | |||
259 | /* Macros for reading or writing SerDes RxTx registers | 267 | /* Macros for reading or writing SerDes RxTx registers |
260 | * The ioread macros will get bit fields or full values using the | 268 | * The ioread macros will get bit fields or full values using the |
261 | * register definitions formed using the input names | 269 | * register definitions formed using the input names |
@@ -283,7 +291,6 @@ do { \ | |||
283 | XRXTX_IOWRITE((_priv), _reg, reg_val); \ | 291 | XRXTX_IOWRITE((_priv), _reg, reg_val); \ |
284 | } while (0) | 292 | } while (0) |
285 | 293 | ||
286 | |||
287 | enum amd_xgbe_phy_an { | 294 | enum amd_xgbe_phy_an { |
288 | AMD_XGBE_AN_READY = 0, | 295 | AMD_XGBE_AN_READY = 0, |
289 | AMD_XGBE_AN_START, | 296 | AMD_XGBE_AN_START, |
@@ -331,7 +338,6 @@ struct amd_xgbe_phy_priv { | |||
331 | 338 | ||
332 | /* Maintain link status for re-starting auto-negotiation */ | 339 | /* Maintain link status for re-starting auto-negotiation */ |
333 | unsigned int link; | 340 | unsigned int link; |
334 | enum amd_xgbe_phy_mode mode; | ||
335 | unsigned int speed_set; | 341 | unsigned int speed_set; |
336 | 342 | ||
337 | /* Auto-negotiation state machine support */ | 343 | /* Auto-negotiation state machine support */ |
@@ -342,6 +348,7 @@ struct amd_xgbe_phy_priv { | |||
342 | enum amd_xgbe_phy_rx kx_state; | 348 | enum amd_xgbe_phy_rx kx_state; |
343 | struct work_struct an_work; | 349 | struct work_struct an_work; |
344 | struct workqueue_struct *an_workqueue; | 350 | struct workqueue_struct *an_workqueue; |
351 | unsigned int parallel_detect; | ||
345 | }; | 352 | }; |
346 | 353 | ||
347 | static int amd_xgbe_an_enable_kr_training(struct phy_device *phydev) | 354 | static int amd_xgbe_an_enable_kr_training(struct phy_device *phydev) |
@@ -468,8 +475,6 @@ static int amd_xgbe_phy_xgmii_mode(struct phy_device *phydev) | |||
468 | 475 | ||
469 | amd_xgbe_phy_serdes_complete_ratechange(phydev); | 476 | amd_xgbe_phy_serdes_complete_ratechange(phydev); |
470 | 477 | ||
471 | priv->mode = AMD_XGBE_MODE_KR; | ||
472 | |||
473 | return 0; | 478 | return 0; |
474 | } | 479 | } |
475 | 480 | ||
@@ -518,8 +523,6 @@ static int amd_xgbe_phy_gmii_2500_mode(struct phy_device *phydev) | |||
518 | 523 | ||
519 | amd_xgbe_phy_serdes_complete_ratechange(phydev); | 524 | amd_xgbe_phy_serdes_complete_ratechange(phydev); |
520 | 525 | ||
521 | priv->mode = AMD_XGBE_MODE_KX; | ||
522 | |||
523 | return 0; | 526 | return 0; |
524 | } | 527 | } |
525 | 528 | ||
@@ -568,18 +571,43 @@ static int amd_xgbe_phy_gmii_mode(struct phy_device *phydev) | |||
568 | 571 | ||
569 | amd_xgbe_phy_serdes_complete_ratechange(phydev); | 572 | amd_xgbe_phy_serdes_complete_ratechange(phydev); |
570 | 573 | ||
571 | priv->mode = AMD_XGBE_MODE_KX; | 574 | return 0; |
575 | } | ||
576 | |||
577 | static int amd_xgbe_phy_cur_mode(struct phy_device *phydev, | ||
578 | enum amd_xgbe_phy_mode *mode) | ||
579 | { | ||
580 | int ret; | ||
581 | |||
582 | ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL2); | ||
583 | if (ret < 0) | ||
584 | return ret; | ||
585 | |||
586 | if ((ret & MDIO_PCS_CTRL2_TYPE) == MDIO_PCS_CTRL2_10GBR) | ||
587 | *mode = AMD_XGBE_MODE_KR; | ||
588 | else | ||
589 | *mode = AMD_XGBE_MODE_KX; | ||
572 | 590 | ||
573 | return 0; | 591 | return 0; |
574 | } | 592 | } |
575 | 593 | ||
594 | static bool amd_xgbe_phy_in_kr_mode(struct phy_device *phydev) | ||
595 | { | ||
596 | enum amd_xgbe_phy_mode mode; | ||
597 | |||
598 | if (amd_xgbe_phy_cur_mode(phydev, &mode)) | ||
599 | return false; | ||
600 | |||
601 | return (mode == AMD_XGBE_MODE_KR); | ||
602 | } | ||
603 | |||
576 | static int amd_xgbe_phy_switch_mode(struct phy_device *phydev) | 604 | static int amd_xgbe_phy_switch_mode(struct phy_device *phydev) |
577 | { | 605 | { |
578 | struct amd_xgbe_phy_priv *priv = phydev->priv; | 606 | struct amd_xgbe_phy_priv *priv = phydev->priv; |
579 | int ret; | 607 | int ret; |
580 | 608 | ||
581 | /* If we are in KR switch to KX, and vice-versa */ | 609 | /* If we are in KR switch to KX, and vice-versa */ |
582 | if (priv->mode == AMD_XGBE_MODE_KR) { | 610 | if (amd_xgbe_phy_in_kr_mode(phydev)) { |
583 | if (priv->speed_set == AMD_XGBE_PHY_SPEEDSET_1000_10000) | 611 | if (priv->speed_set == AMD_XGBE_PHY_SPEEDSET_1000_10000) |
584 | ret = amd_xgbe_phy_gmii_mode(phydev); | 612 | ret = amd_xgbe_phy_gmii_mode(phydev); |
585 | else | 613 | else |
@@ -591,15 +619,20 @@ static int amd_xgbe_phy_switch_mode(struct phy_device *phydev) | |||
591 | return ret; | 619 | return ret; |
592 | } | 620 | } |
593 | 621 | ||
594 | static enum amd_xgbe_phy_an amd_xgbe_an_switch_mode(struct phy_device *phydev) | 622 | static int amd_xgbe_phy_set_mode(struct phy_device *phydev, |
623 | enum amd_xgbe_phy_mode mode) | ||
595 | { | 624 | { |
625 | enum amd_xgbe_phy_mode cur_mode; | ||
596 | int ret; | 626 | int ret; |
597 | 627 | ||
598 | ret = amd_xgbe_phy_switch_mode(phydev); | 628 | ret = amd_xgbe_phy_cur_mode(phydev, &cur_mode); |
599 | if (ret < 0) | 629 | if (ret) |
600 | return AMD_XGBE_AN_ERROR; | 630 | return ret; |
601 | 631 | ||
602 | return AMD_XGBE_AN_START; | 632 | if (mode != cur_mode) |
633 | ret = amd_xgbe_phy_switch_mode(phydev); | ||
634 | |||
635 | return ret; | ||
603 | } | 636 | } |
604 | 637 | ||
605 | static enum amd_xgbe_phy_an amd_xgbe_an_tx_training(struct phy_device *phydev, | 638 | static enum amd_xgbe_phy_an amd_xgbe_an_tx_training(struct phy_device *phydev, |
@@ -610,8 +643,8 @@ static enum amd_xgbe_phy_an amd_xgbe_an_tx_training(struct phy_device *phydev, | |||
610 | 643 | ||
611 | *state = AMD_XGBE_RX_COMPLETE; | 644 | *state = AMD_XGBE_RX_COMPLETE; |
612 | 645 | ||
613 | /* If we're in KX mode then we're done */ | 646 | /* If we're not in KR mode then we're done */ |
614 | if (priv->mode == AMD_XGBE_MODE_KX) | 647 | if (!amd_xgbe_phy_in_kr_mode(phydev)) |
615 | return AMD_XGBE_AN_EVENT; | 648 | return AMD_XGBE_AN_EVENT; |
616 | 649 | ||
617 | /* Enable/Disable FEC */ | 650 | /* Enable/Disable FEC */ |
@@ -669,7 +702,6 @@ static enum amd_xgbe_phy_an amd_xgbe_an_tx_xnp(struct phy_device *phydev, | |||
669 | static enum amd_xgbe_phy_an amd_xgbe_an_rx_bpa(struct phy_device *phydev, | 702 | static enum amd_xgbe_phy_an amd_xgbe_an_rx_bpa(struct phy_device *phydev, |
670 | enum amd_xgbe_phy_rx *state) | 703 | enum amd_xgbe_phy_rx *state) |
671 | { | 704 | { |
672 | struct amd_xgbe_phy_priv *priv = phydev->priv; | ||
673 | unsigned int link_support; | 705 | unsigned int link_support; |
674 | int ret, ad_reg, lp_reg; | 706 | int ret, ad_reg, lp_reg; |
675 | 707 | ||
@@ -679,9 +711,9 @@ static enum amd_xgbe_phy_an amd_xgbe_an_rx_bpa(struct phy_device *phydev, | |||
679 | return AMD_XGBE_AN_ERROR; | 711 | return AMD_XGBE_AN_ERROR; |
680 | 712 | ||
681 | /* Check for a supported mode, otherwise restart in a different one */ | 713 | /* Check for a supported mode, otherwise restart in a different one */ |
682 | link_support = (priv->mode == AMD_XGBE_MODE_KR) ? 0x80 : 0x20; | 714 | link_support = amd_xgbe_phy_in_kr_mode(phydev) ? 0x80 : 0x20; |
683 | if (!(ret & link_support)) | 715 | if (!(ret & link_support)) |
684 | return amd_xgbe_an_switch_mode(phydev); | 716 | return AMD_XGBE_AN_INCOMPAT_LINK; |
685 | 717 | ||
686 | /* Check Extended Next Page support */ | 718 | /* Check Extended Next Page support */ |
687 | ad_reg = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_ADVERTISE); | 719 | ad_reg = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_ADVERTISE); |
@@ -722,7 +754,7 @@ static enum amd_xgbe_phy_an amd_xgbe_an_start(struct phy_device *phydev) | |||
722 | int ret; | 754 | int ret; |
723 | 755 | ||
724 | /* Be sure we aren't looping trying to negotiate */ | 756 | /* Be sure we aren't looping trying to negotiate */ |
725 | if (priv->mode == AMD_XGBE_MODE_KR) { | 757 | if (amd_xgbe_phy_in_kr_mode(phydev)) { |
726 | if (priv->kr_state != AMD_XGBE_RX_READY) | 758 | if (priv->kr_state != AMD_XGBE_RX_READY) |
727 | return AMD_XGBE_AN_NO_LINK; | 759 | return AMD_XGBE_AN_NO_LINK; |
728 | priv->kr_state = AMD_XGBE_RX_BPA; | 760 | priv->kr_state = AMD_XGBE_RX_BPA; |
@@ -785,6 +817,13 @@ static enum amd_xgbe_phy_an amd_xgbe_an_start(struct phy_device *phydev) | |||
785 | /* Enable and start auto-negotiation */ | 817 | /* Enable and start auto-negotiation */ |
786 | phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_INT, 0); | 818 | phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_INT, 0); |
787 | 819 | ||
820 | ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_KR_CTRL); | ||
821 | if (ret < 0) | ||
822 | return AMD_XGBE_AN_ERROR; | ||
823 | |||
824 | ret |= MDIO_KR_CTRL_PDETECT; | ||
825 | phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_KR_CTRL, ret); | ||
826 | |||
788 | ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1); | 827 | ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1); |
789 | if (ret < 0) | 828 | if (ret < 0) |
790 | return AMD_XGBE_AN_ERROR; | 829 | return AMD_XGBE_AN_ERROR; |
@@ -825,8 +864,8 @@ static enum amd_xgbe_phy_an amd_xgbe_an_page_received(struct phy_device *phydev) | |||
825 | enum amd_xgbe_phy_rx *state; | 864 | enum amd_xgbe_phy_rx *state; |
826 | int ret; | 865 | int ret; |
827 | 866 | ||
828 | state = (priv->mode == AMD_XGBE_MODE_KR) ? &priv->kr_state | 867 | state = amd_xgbe_phy_in_kr_mode(phydev) ? &priv->kr_state |
829 | : &priv->kx_state; | 868 | : &priv->kx_state; |
830 | 869 | ||
831 | switch (*state) { | 870 | switch (*state) { |
832 | case AMD_XGBE_RX_BPA: | 871 | case AMD_XGBE_RX_BPA: |
@@ -846,7 +885,13 @@ static enum amd_xgbe_phy_an amd_xgbe_an_page_received(struct phy_device *phydev) | |||
846 | 885 | ||
847 | static enum amd_xgbe_phy_an amd_xgbe_an_incompat_link(struct phy_device *phydev) | 886 | static enum amd_xgbe_phy_an amd_xgbe_an_incompat_link(struct phy_device *phydev) |
848 | { | 887 | { |
849 | return amd_xgbe_an_switch_mode(phydev); | 888 | int ret; |
889 | |||
890 | ret = amd_xgbe_phy_switch_mode(phydev); | ||
891 | if (ret) | ||
892 | return AMD_XGBE_AN_ERROR; | ||
893 | |||
894 | return AMD_XGBE_AN_START; | ||
850 | } | 895 | } |
851 | 896 | ||
852 | static void amd_xgbe_an_state_machine(struct work_struct *work) | 897 | static void amd_xgbe_an_state_machine(struct work_struct *work) |
@@ -859,6 +904,10 @@ static void amd_xgbe_an_state_machine(struct work_struct *work) | |||
859 | int sleep; | 904 | int sleep; |
860 | unsigned int an_supported = 0; | 905 | unsigned int an_supported = 0; |
861 | 906 | ||
907 | /* Start in KX mode */ | ||
908 | if (amd_xgbe_phy_set_mode(phydev, AMD_XGBE_MODE_KX)) | ||
909 | priv->an_state = AMD_XGBE_AN_ERROR; | ||
910 | |||
862 | while (1) { | 911 | while (1) { |
863 | mutex_lock(&priv->an_mutex); | 912 | mutex_lock(&priv->an_mutex); |
864 | 913 | ||
@@ -866,8 +915,9 @@ static void amd_xgbe_an_state_machine(struct work_struct *work) | |||
866 | 915 | ||
867 | switch (priv->an_state) { | 916 | switch (priv->an_state) { |
868 | case AMD_XGBE_AN_START: | 917 | case AMD_XGBE_AN_START: |
869 | priv->an_state = amd_xgbe_an_start(phydev); | ||
870 | an_supported = 0; | 918 | an_supported = 0; |
919 | priv->parallel_detect = 0; | ||
920 | priv->an_state = amd_xgbe_an_start(phydev); | ||
871 | break; | 921 | break; |
872 | 922 | ||
873 | case AMD_XGBE_AN_EVENT: | 923 | case AMD_XGBE_AN_EVENT: |
@@ -884,6 +934,7 @@ static void amd_xgbe_an_state_machine(struct work_struct *work) | |||
884 | break; | 934 | break; |
885 | 935 | ||
886 | case AMD_XGBE_AN_COMPLETE: | 936 | case AMD_XGBE_AN_COMPLETE: |
937 | priv->parallel_detect = an_supported ? 0 : 1; | ||
887 | netdev_info(phydev->attached_dev, "%s successful\n", | 938 | netdev_info(phydev->attached_dev, "%s successful\n", |
888 | an_supported ? "Auto negotiation" | 939 | an_supported ? "Auto negotiation" |
889 | : "Parallel detection"); | 940 | : "Parallel detection"); |
@@ -1018,7 +1069,6 @@ static int amd_xgbe_phy_config_aneg(struct phy_device *phydev) | |||
1018 | { | 1069 | { |
1019 | struct amd_xgbe_phy_priv *priv = phydev->priv; | 1070 | struct amd_xgbe_phy_priv *priv = phydev->priv; |
1020 | u32 mmd_mask = phydev->c45_ids.devices_in_package; | 1071 | u32 mmd_mask = phydev->c45_ids.devices_in_package; |
1021 | int ret; | ||
1022 | 1072 | ||
1023 | if (phydev->autoneg != AUTONEG_ENABLE) | 1073 | if (phydev->autoneg != AUTONEG_ENABLE) |
1024 | return amd_xgbe_phy_setup_forced(phydev); | 1074 | return amd_xgbe_phy_setup_forced(phydev); |
@@ -1027,11 +1077,6 @@ static int amd_xgbe_phy_config_aneg(struct phy_device *phydev) | |||
1027 | if (!(mmd_mask & MDIO_DEVS_AN)) | 1077 | if (!(mmd_mask & MDIO_DEVS_AN)) |
1028 | return -EINVAL; | 1078 | return -EINVAL; |
1029 | 1079 | ||
1030 | /* Get the current speed mode */ | ||
1031 | ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL2); | ||
1032 | if (ret < 0) | ||
1033 | return ret; | ||
1034 | |||
1035 | /* Start/Restart the auto-negotiation state machine */ | 1080 | /* Start/Restart the auto-negotiation state machine */ |
1036 | mutex_lock(&priv->an_mutex); | 1081 | mutex_lock(&priv->an_mutex); |
1037 | priv->an_result = AMD_XGBE_AN_READY; | 1082 | priv->an_result = AMD_XGBE_AN_READY; |
@@ -1121,18 +1166,14 @@ static int amd_xgbe_phy_read_status(struct phy_device *phydev) | |||
1121 | { | 1166 | { |
1122 | struct amd_xgbe_phy_priv *priv = phydev->priv; | 1167 | struct amd_xgbe_phy_priv *priv = phydev->priv; |
1123 | u32 mmd_mask = phydev->c45_ids.devices_in_package; | 1168 | u32 mmd_mask = phydev->c45_ids.devices_in_package; |
1124 | int ret, mode, ad_ret, lp_ret; | 1169 | int ret, ad_ret, lp_ret; |
1125 | 1170 | ||
1126 | ret = amd_xgbe_phy_update_link(phydev); | 1171 | ret = amd_xgbe_phy_update_link(phydev); |
1127 | if (ret) | 1172 | if (ret) |
1128 | return ret; | 1173 | return ret; |
1129 | 1174 | ||
1130 | mode = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL2); | 1175 | if ((phydev->autoneg == AUTONEG_ENABLE) && |
1131 | if (mode < 0) | 1176 | !priv->parallel_detect) { |
1132 | return mode; | ||
1133 | mode &= MDIO_PCS_CTRL2_TYPE; | ||
1134 | |||
1135 | if (phydev->autoneg == AUTONEG_ENABLE) { | ||
1136 | if (!(mmd_mask & MDIO_DEVS_AN)) | 1177 | if (!(mmd_mask & MDIO_DEVS_AN)) |
1137 | return -EINVAL; | 1178 | return -EINVAL; |
1138 | 1179 | ||
@@ -1163,40 +1204,39 @@ static int amd_xgbe_phy_read_status(struct phy_device *phydev) | |||
1163 | ad_ret &= lp_ret; | 1204 | ad_ret &= lp_ret; |
1164 | if (ad_ret & 0x80) { | 1205 | if (ad_ret & 0x80) { |
1165 | phydev->speed = SPEED_10000; | 1206 | phydev->speed = SPEED_10000; |
1166 | if (mode != MDIO_PCS_CTRL2_10GBR) { | 1207 | ret = amd_xgbe_phy_set_mode(phydev, AMD_XGBE_MODE_KR); |
1167 | ret = amd_xgbe_phy_xgmii_mode(phydev); | 1208 | if (ret) |
1168 | if (ret < 0) | 1209 | return ret; |
1169 | return ret; | ||
1170 | } | ||
1171 | } else { | 1210 | } else { |
1172 | int (*mode_fcn)(struct phy_device *); | 1211 | switch (priv->speed_set) { |
1173 | 1212 | case AMD_XGBE_PHY_SPEEDSET_1000_10000: | |
1174 | if (priv->speed_set == | ||
1175 | AMD_XGBE_PHY_SPEEDSET_1000_10000) { | ||
1176 | phydev->speed = SPEED_1000; | 1213 | phydev->speed = SPEED_1000; |
1177 | mode_fcn = amd_xgbe_phy_gmii_mode; | 1214 | break; |
1178 | } else { | 1215 | |
1216 | case AMD_XGBE_PHY_SPEEDSET_2500_10000: | ||
1179 | phydev->speed = SPEED_2500; | 1217 | phydev->speed = SPEED_2500; |
1180 | mode_fcn = amd_xgbe_phy_gmii_2500_mode; | 1218 | break; |
1181 | } | 1219 | } |
1182 | 1220 | ||
1183 | if (mode == MDIO_PCS_CTRL2_10GBR) { | 1221 | ret = amd_xgbe_phy_set_mode(phydev, AMD_XGBE_MODE_KX); |
1184 | ret = mode_fcn(phydev); | 1222 | if (ret) |
1185 | if (ret < 0) | 1223 | return ret; |
1186 | return ret; | ||
1187 | } | ||
1188 | } | 1224 | } |
1189 | 1225 | ||
1190 | phydev->duplex = DUPLEX_FULL; | 1226 | phydev->duplex = DUPLEX_FULL; |
1191 | } else { | 1227 | } else { |
1192 | if (mode == MDIO_PCS_CTRL2_10GBR) { | 1228 | if (amd_xgbe_phy_in_kr_mode(phydev)) { |
1193 | phydev->speed = SPEED_10000; | 1229 | phydev->speed = SPEED_10000; |
1194 | } else { | 1230 | } else { |
1195 | if (priv->speed_set == | 1231 | switch (priv->speed_set) { |
1196 | AMD_XGBE_PHY_SPEEDSET_1000_10000) | 1232 | case AMD_XGBE_PHY_SPEEDSET_1000_10000: |
1197 | phydev->speed = SPEED_1000; | 1233 | phydev->speed = SPEED_1000; |
1198 | else | 1234 | break; |
1235 | |||
1236 | case AMD_XGBE_PHY_SPEEDSET_2500_10000: | ||
1199 | phydev->speed = SPEED_2500; | 1237 | phydev->speed = SPEED_2500; |
1238 | break; | ||
1239 | } | ||
1200 | } | 1240 | } |
1201 | phydev->duplex = DUPLEX_FULL; | 1241 | phydev->duplex = DUPLEX_FULL; |
1202 | phydev->pause = 0; | 1242 | phydev->pause = 0; |
@@ -1329,14 +1369,6 @@ static int amd_xgbe_phy_probe(struct phy_device *phydev) | |||
1329 | 1369 | ||
1330 | priv->link = 1; | 1370 | priv->link = 1; |
1331 | 1371 | ||
1332 | ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL2); | ||
1333 | if (ret < 0) | ||
1334 | goto err_sir1; | ||
1335 | if ((ret & MDIO_PCS_CTRL2_TYPE) == MDIO_PCS_CTRL2_10GBR) | ||
1336 | priv->mode = AMD_XGBE_MODE_KR; | ||
1337 | else | ||
1338 | priv->mode = AMD_XGBE_MODE_KX; | ||
1339 | |||
1340 | mutex_init(&priv->an_mutex); | 1372 | mutex_init(&priv->an_mutex); |
1341 | INIT_WORK(&priv->an_work, amd_xgbe_an_state_machine); | 1373 | INIT_WORK(&priv->an_work, amd_xgbe_an_state_machine); |
1342 | priv->an_workqueue = create_singlethread_workqueue(wq_name); | 1374 | priv->an_workqueue = create_singlethread_workqueue(wq_name); |
diff --git a/drivers/net/phy/bcm7xxx.c b/drivers/net/phy/bcm7xxx.c index fdce1ea28790..09dd6e1dc6e1 100644 --- a/drivers/net/phy/bcm7xxx.c +++ b/drivers/net/phy/bcm7xxx.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/delay.h> | 14 | #include <linux/delay.h> |
15 | #include <linux/bitops.h> | 15 | #include <linux/bitops.h> |
16 | #include <linux/brcmphy.h> | 16 | #include <linux/brcmphy.h> |
17 | #include <linux/mdio.h> | ||
17 | 18 | ||
18 | /* Broadcom BCM7xxx internal PHY registers */ | 19 | /* Broadcom BCM7xxx internal PHY registers */ |
19 | #define MII_BCM7XXX_CHANNEL_WIDTH 0x2000 | 20 | #define MII_BCM7XXX_CHANNEL_WIDTH 0x2000 |
@@ -146,6 +147,53 @@ static int bcm7xxx_28nm_afe_config_init(struct phy_device *phydev) | |||
146 | return 0; | 147 | return 0; |
147 | } | 148 | } |
148 | 149 | ||
150 | static int bcm7xxx_apd_enable(struct phy_device *phydev) | ||
151 | { | ||
152 | int val; | ||
153 | |||
154 | /* Enable powering down of the DLL during auto-power down */ | ||
155 | val = bcm54xx_shadow_read(phydev, BCM54XX_SHD_SCR3); | ||
156 | if (val < 0) | ||
157 | return val; | ||
158 | |||
159 | val |= BCM54XX_SHD_SCR3_DLLAPD_DIS; | ||
160 | bcm54xx_shadow_write(phydev, BCM54XX_SHD_SCR3, val); | ||
161 | |||
162 | /* Enable auto-power down */ | ||
163 | val = bcm54xx_shadow_read(phydev, BCM54XX_SHD_APD); | ||
164 | if (val < 0) | ||
165 | return val; | ||
166 | |||
167 | val |= BCM54XX_SHD_APD_EN; | ||
168 | return bcm54xx_shadow_write(phydev, BCM54XX_SHD_APD, val); | ||
169 | } | ||
170 | |||
171 | static int bcm7xxx_eee_enable(struct phy_device *phydev) | ||
172 | { | ||
173 | int val; | ||
174 | |||
175 | val = phy_read_mmd_indirect(phydev, BRCM_CL45VEN_EEE_CONTROL, | ||
176 | MDIO_MMD_AN, phydev->addr); | ||
177 | if (val < 0) | ||
178 | return val; | ||
179 | |||
180 | /* Enable general EEE feature at the PHY level */ | ||
181 | val |= LPI_FEATURE_EN | LPI_FEATURE_EN_DIG1000X; | ||
182 | |||
183 | phy_write_mmd_indirect(phydev, BRCM_CL45VEN_EEE_CONTROL, | ||
184 | MDIO_MMD_AN, phydev->addr, val); | ||
185 | |||
186 | /* Advertise supported modes */ | ||
187 | val = phy_read_mmd_indirect(phydev, MDIO_AN_EEE_ADV, | ||
188 | MDIO_MMD_AN, phydev->addr); | ||
189 | |||
190 | val |= (MDIO_AN_EEE_ADV_100TX | MDIO_AN_EEE_ADV_1000T); | ||
191 | phy_write_mmd_indirect(phydev, MDIO_AN_EEE_ADV, | ||
192 | MDIO_MMD_AN, phydev->addr, val); | ||
193 | |||
194 | return 0; | ||
195 | } | ||
196 | |||
149 | static int bcm7xxx_28nm_config_init(struct phy_device *phydev) | 197 | static int bcm7xxx_28nm_config_init(struct phy_device *phydev) |
150 | { | 198 | { |
151 | int ret; | 199 | int ret; |
@@ -154,7 +202,15 @@ static int bcm7xxx_28nm_config_init(struct phy_device *phydev) | |||
154 | if (ret) | 202 | if (ret) |
155 | return ret; | 203 | return ret; |
156 | 204 | ||
157 | return bcm7xxx_28nm_afe_config_init(phydev); | 205 | ret = bcm7xxx_28nm_afe_config_init(phydev); |
206 | if (ret) | ||
207 | return ret; | ||
208 | |||
209 | ret = bcm7xxx_eee_enable(phydev); | ||
210 | if (ret) | ||
211 | return ret; | ||
212 | |||
213 | return bcm7xxx_apd_enable(phydev); | ||
158 | } | 214 | } |
159 | 215 | ||
160 | static int bcm7xxx_28nm_resume(struct phy_device *phydev) | 216 | static int bcm7xxx_28nm_resume(struct phy_device *phydev) |
@@ -263,44 +319,28 @@ static int bcm7xxx_dummy_config_init(struct phy_device *phydev) | |||
263 | return 0; | 319 | return 0; |
264 | } | 320 | } |
265 | 321 | ||
322 | #define BCM7XXX_28NM_GPHY(_oui, _name) \ | ||
323 | { \ | ||
324 | .phy_id = (_oui), \ | ||
325 | .phy_id_mask = 0xfffffff0, \ | ||
326 | .name = _name, \ | ||
327 | .features = PHY_GBIT_FEATURES | \ | ||
328 | SUPPORTED_Pause | SUPPORTED_Asym_Pause, \ | ||
329 | .flags = PHY_IS_INTERNAL, \ | ||
330 | .config_init = bcm7xxx_28nm_afe_config_init, \ | ||
331 | .config_aneg = genphy_config_aneg, \ | ||
332 | .read_status = genphy_read_status, \ | ||
333 | .resume = bcm7xxx_28nm_resume, \ | ||
334 | .driver = { .owner = THIS_MODULE }, \ | ||
335 | } | ||
336 | |||
266 | static struct phy_driver bcm7xxx_driver[] = { | 337 | static struct phy_driver bcm7xxx_driver[] = { |
338 | BCM7XXX_28NM_GPHY(PHY_ID_BCM7250, "Broadcom BCM7250"), | ||
339 | BCM7XXX_28NM_GPHY(PHY_ID_BCM7364, "Broadcom BCM7364"), | ||
340 | BCM7XXX_28NM_GPHY(PHY_ID_BCM7366, "Broadcom BCM7366"), | ||
341 | BCM7XXX_28NM_GPHY(PHY_ID_BCM7439, "Broadcom BCM7439"), | ||
342 | BCM7XXX_28NM_GPHY(PHY_ID_BCM7445, "Broadcom BCM7445"), | ||
267 | { | 343 | { |
268 | .phy_id = PHY_ID_BCM7366, | ||
269 | .phy_id_mask = 0xfffffff0, | ||
270 | .name = "Broadcom BCM7366", | ||
271 | .features = PHY_GBIT_FEATURES | | ||
272 | SUPPORTED_Pause | SUPPORTED_Asym_Pause, | ||
273 | .flags = PHY_IS_INTERNAL, | ||
274 | .config_init = bcm7xxx_28nm_afe_config_init, | ||
275 | .config_aneg = genphy_config_aneg, | ||
276 | .read_status = genphy_read_status, | ||
277 | .resume = bcm7xxx_28nm_resume, | ||
278 | .driver = { .owner = THIS_MODULE }, | ||
279 | }, { | ||
280 | .phy_id = PHY_ID_BCM7439, | ||
281 | .phy_id_mask = 0xfffffff0, | ||
282 | .name = "Broadcom BCM7439", | ||
283 | .features = PHY_GBIT_FEATURES | | ||
284 | SUPPORTED_Pause | SUPPORTED_Asym_Pause, | ||
285 | .flags = PHY_IS_INTERNAL, | ||
286 | .config_init = bcm7xxx_28nm_afe_config_init, | ||
287 | .config_aneg = genphy_config_aneg, | ||
288 | .read_status = genphy_read_status, | ||
289 | .resume = bcm7xxx_28nm_resume, | ||
290 | .driver = { .owner = THIS_MODULE }, | ||
291 | }, { | ||
292 | .phy_id = PHY_ID_BCM7445, | ||
293 | .phy_id_mask = 0xfffffff0, | ||
294 | .name = "Broadcom BCM7445", | ||
295 | .features = PHY_GBIT_FEATURES | | ||
296 | SUPPORTED_Pause | SUPPORTED_Asym_Pause, | ||
297 | .flags = PHY_IS_INTERNAL, | ||
298 | .config_init = bcm7xxx_28nm_config_init, | ||
299 | .config_aneg = genphy_config_aneg, | ||
300 | .read_status = genphy_read_status, | ||
301 | .resume = bcm7xxx_28nm_afe_config_init, | ||
302 | .driver = { .owner = THIS_MODULE }, | ||
303 | }, { | ||
304 | .phy_id = PHY_BCM_OUI_4, | 344 | .phy_id = PHY_BCM_OUI_4, |
305 | .phy_id_mask = 0xffff0000, | 345 | .phy_id_mask = 0xffff0000, |
306 | .name = "Broadcom BCM7XXX 40nm", | 346 | .name = "Broadcom BCM7XXX 40nm", |
@@ -329,6 +369,8 @@ static struct phy_driver bcm7xxx_driver[] = { | |||
329 | } }; | 369 | } }; |
330 | 370 | ||
331 | static struct mdio_device_id __maybe_unused bcm7xxx_tbl[] = { | 371 | static struct mdio_device_id __maybe_unused bcm7xxx_tbl[] = { |
372 | { PHY_ID_BCM7250, 0xfffffff0, }, | ||
373 | { PHY_ID_BCM7364, 0xfffffff0, }, | ||
332 | { PHY_ID_BCM7366, 0xfffffff0, }, | 374 | { PHY_ID_BCM7366, 0xfffffff0, }, |
333 | { PHY_ID_BCM7439, 0xfffffff0, }, | 375 | { PHY_ID_BCM7439, 0xfffffff0, }, |
334 | { PHY_ID_BCM7445, 0xfffffff0, }, | 376 | { PHY_ID_BCM7445, 0xfffffff0, }, |
diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c index 34088d60da74..854f2c9a7b2b 100644 --- a/drivers/net/phy/broadcom.c +++ b/drivers/net/phy/broadcom.c | |||
@@ -25,132 +25,10 @@ | |||
25 | #define BRCM_PHY_REV(phydev) \ | 25 | #define BRCM_PHY_REV(phydev) \ |
26 | ((phydev)->drv->phy_id & ~((phydev)->drv->phy_id_mask)) | 26 | ((phydev)->drv->phy_id & ~((phydev)->drv->phy_id_mask)) |
27 | 27 | ||
28 | /* | ||
29 | * Broadcom LED source encodings. These are used in BCM5461, BCM5481, | ||
30 | * BCM5482, and possibly some others. | ||
31 | */ | ||
32 | #define BCM_LED_SRC_LINKSPD1 0x0 | ||
33 | #define BCM_LED_SRC_LINKSPD2 0x1 | ||
34 | #define BCM_LED_SRC_XMITLED 0x2 | ||
35 | #define BCM_LED_SRC_ACTIVITYLED 0x3 | ||
36 | #define BCM_LED_SRC_FDXLED 0x4 | ||
37 | #define BCM_LED_SRC_SLAVE 0x5 | ||
38 | #define BCM_LED_SRC_INTR 0x6 | ||
39 | #define BCM_LED_SRC_QUALITY 0x7 | ||
40 | #define BCM_LED_SRC_RCVLED 0x8 | ||
41 | #define BCM_LED_SRC_MULTICOLOR1 0xa | ||
42 | #define BCM_LED_SRC_OPENSHORT 0xb | ||
43 | #define BCM_LED_SRC_OFF 0xe /* Tied high */ | ||
44 | #define BCM_LED_SRC_ON 0xf /* Tied low */ | ||
45 | |||
46 | |||
47 | /* | ||
48 | * BCM5482: Shadow registers | ||
49 | * Shadow values go into bits [14:10] of register 0x1c to select a shadow | ||
50 | * register to access. | ||
51 | */ | ||
52 | /* 00101: Spare Control Register 3 */ | ||
53 | #define BCM54XX_SHD_SCR3 0x05 | ||
54 | #define BCM54XX_SHD_SCR3_DEF_CLK125 0x0001 | ||
55 | #define BCM54XX_SHD_SCR3_DLLAPD_DIS 0x0002 | ||
56 | #define BCM54XX_SHD_SCR3_TRDDAPD 0x0004 | ||
57 | |||
58 | /* 01010: Auto Power-Down */ | ||
59 | #define BCM54XX_SHD_APD 0x0a | ||
60 | #define BCM54XX_SHD_APD_EN 0x0020 | ||
61 | |||
62 | #define BCM5482_SHD_LEDS1 0x0d /* 01101: LED Selector 1 */ | ||
63 | /* LED3 / ~LINKSPD[2] selector */ | ||
64 | #define BCM5482_SHD_LEDS1_LED3(src) ((src & 0xf) << 4) | ||
65 | /* LED1 / ~LINKSPD[1] selector */ | ||
66 | #define BCM5482_SHD_LEDS1_LED1(src) ((src & 0xf) << 0) | ||
67 | #define BCM54XX_SHD_RGMII_MODE 0x0b /* 01011: RGMII Mode Selector */ | ||
68 | #define BCM5482_SHD_SSD 0x14 /* 10100: Secondary SerDes control */ | ||
69 | #define BCM5482_SHD_SSD_LEDM 0x0008 /* SSD LED Mode enable */ | ||
70 | #define BCM5482_SHD_SSD_EN 0x0001 /* SSD enable */ | ||
71 | #define BCM5482_SHD_MODE 0x1f /* 11111: Mode Control Register */ | ||
72 | #define BCM5482_SHD_MODE_1000BX 0x0001 /* Enable 1000BASE-X registers */ | ||
73 | |||
74 | |||
75 | /* | ||
76 | * EXPANSION SHADOW ACCESS REGISTERS. (PHY REG 0x15, 0x16, and 0x17) | ||
77 | */ | ||
78 | #define MII_BCM54XX_EXP_AADJ1CH0 0x001f | ||
79 | #define MII_BCM54XX_EXP_AADJ1CH0_SWP_ABCD_OEN 0x0200 | ||
80 | #define MII_BCM54XX_EXP_AADJ1CH0_SWSEL_THPF 0x0100 | ||
81 | #define MII_BCM54XX_EXP_AADJ1CH3 0x601f | ||
82 | #define MII_BCM54XX_EXP_AADJ1CH3_ADCCKADJ 0x0002 | ||
83 | #define MII_BCM54XX_EXP_EXP08 0x0F08 | ||
84 | #define MII_BCM54XX_EXP_EXP08_RJCT_2MHZ 0x0001 | ||
85 | #define MII_BCM54XX_EXP_EXP08_EARLY_DAC_WAKE 0x0200 | ||
86 | #define MII_BCM54XX_EXP_EXP75 0x0f75 | ||
87 | #define MII_BCM54XX_EXP_EXP75_VDACCTRL 0x003c | ||
88 | #define MII_BCM54XX_EXP_EXP75_CM_OSC 0x0001 | ||
89 | #define MII_BCM54XX_EXP_EXP96 0x0f96 | ||
90 | #define MII_BCM54XX_EXP_EXP96_MYST 0x0010 | ||
91 | #define MII_BCM54XX_EXP_EXP97 0x0f97 | ||
92 | #define MII_BCM54XX_EXP_EXP97_MYST 0x0c0c | ||
93 | |||
94 | /* | ||
95 | * BCM5482: Secondary SerDes registers | ||
96 | */ | ||
97 | #define BCM5482_SSD_1000BX_CTL 0x00 /* 1000BASE-X Control */ | ||
98 | #define BCM5482_SSD_1000BX_CTL_PWRDOWN 0x0800 /* Power-down SSD */ | ||
99 | #define BCM5482_SSD_SGMII_SLAVE 0x15 /* SGMII Slave Register */ | ||
100 | #define BCM5482_SSD_SGMII_SLAVE_EN 0x0002 /* Slave mode enable */ | ||
101 | #define BCM5482_SSD_SGMII_SLAVE_AD 0x0001 /* Slave auto-detection */ | ||
102 | |||
103 | |||
104 | /*****************************************************************************/ | ||
105 | /* Fast Ethernet Transceiver definitions. */ | ||
106 | /*****************************************************************************/ | ||
107 | |||
108 | #define MII_BRCM_FET_INTREG 0x1a /* Interrupt register */ | ||
109 | #define MII_BRCM_FET_IR_MASK 0x0100 /* Mask all interrupts */ | ||
110 | #define MII_BRCM_FET_IR_LINK_EN 0x0200 /* Link status change enable */ | ||
111 | #define MII_BRCM_FET_IR_SPEED_EN 0x0400 /* Link speed change enable */ | ||
112 | #define MII_BRCM_FET_IR_DUPLEX_EN 0x0800 /* Duplex mode change enable */ | ||
113 | #define MII_BRCM_FET_IR_ENABLE 0x4000 /* Interrupt enable */ | ||
114 | |||
115 | #define MII_BRCM_FET_BRCMTEST 0x1f /* Brcm test register */ | ||
116 | #define MII_BRCM_FET_BT_SRE 0x0080 /* Shadow register enable */ | ||
117 | |||
118 | |||
119 | /*** Shadow register definitions ***/ | ||
120 | |||
121 | #define MII_BRCM_FET_SHDW_MISCCTRL 0x10 /* Shadow misc ctrl */ | ||
122 | #define MII_BRCM_FET_SHDW_MC_FAME 0x4000 /* Force Auto MDIX enable */ | ||
123 | |||
124 | #define MII_BRCM_FET_SHDW_AUXMODE4 0x1a /* Auxiliary mode 4 */ | ||
125 | #define MII_BRCM_FET_SHDW_AM4_LED_MASK 0x0003 | ||
126 | #define MII_BRCM_FET_SHDW_AM4_LED_MODE1 0x0001 | ||
127 | |||
128 | #define MII_BRCM_FET_SHDW_AUXSTAT2 0x1b /* Auxiliary status 2 */ | ||
129 | #define MII_BRCM_FET_SHDW_AS2_APDE 0x0020 /* Auto power down enable */ | ||
130 | |||
131 | |||
132 | MODULE_DESCRIPTION("Broadcom PHY driver"); | 28 | MODULE_DESCRIPTION("Broadcom PHY driver"); |
133 | MODULE_AUTHOR("Maciej W. Rozycki"); | 29 | MODULE_AUTHOR("Maciej W. Rozycki"); |
134 | MODULE_LICENSE("GPL"); | 30 | MODULE_LICENSE("GPL"); |
135 | 31 | ||
136 | /* | ||
137 | * Indirect register access functions for the 1000BASE-T/100BASE-TX/10BASE-T | ||
138 | * 0x1c shadow registers. | ||
139 | */ | ||
140 | static int bcm54xx_shadow_read(struct phy_device *phydev, u16 shadow) | ||
141 | { | ||
142 | phy_write(phydev, MII_BCM54XX_SHD, MII_BCM54XX_SHD_VAL(shadow)); | ||
143 | return MII_BCM54XX_SHD_DATA(phy_read(phydev, MII_BCM54XX_SHD)); | ||
144 | } | ||
145 | |||
146 | static int bcm54xx_shadow_write(struct phy_device *phydev, u16 shadow, u16 val) | ||
147 | { | ||
148 | return phy_write(phydev, MII_BCM54XX_SHD, | ||
149 | MII_BCM54XX_SHD_WRITE | | ||
150 | MII_BCM54XX_SHD_VAL(shadow) | | ||
151 | MII_BCM54XX_SHD_DATA(val)); | ||
152 | } | ||
153 | |||
154 | /* Indirect register access functions for the Expansion Registers */ | 32 | /* Indirect register access functions for the Expansion Registers */ |
155 | static int bcm54xx_exp_read(struct phy_device *phydev, u16 regnum) | 33 | static int bcm54xx_exp_read(struct phy_device *phydev, u16 regnum) |
156 | { | 34 | { |
diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c index c301e4cb37ca..87648b306551 100644 --- a/drivers/net/phy/dp83640.c +++ b/drivers/net/phy/dp83640.c | |||
@@ -721,7 +721,7 @@ static inline u16 exts_chan_to_edata(int ch) | |||
721 | } | 721 | } |
722 | 722 | ||
723 | static int decode_evnt(struct dp83640_private *dp83640, | 723 | static int decode_evnt(struct dp83640_private *dp83640, |
724 | void *data, u16 ests) | 724 | void *data, int len, u16 ests) |
725 | { | 725 | { |
726 | struct phy_txts *phy_txts; | 726 | struct phy_txts *phy_txts; |
727 | struct ptp_clock_event event; | 727 | struct ptp_clock_event event; |
@@ -729,6 +729,16 @@ static int decode_evnt(struct dp83640_private *dp83640, | |||
729 | int words = (ests >> EVNT_TS_LEN_SHIFT) & EVNT_TS_LEN_MASK; | 729 | int words = (ests >> EVNT_TS_LEN_SHIFT) & EVNT_TS_LEN_MASK; |
730 | u16 ext_status = 0; | 730 | u16 ext_status = 0; |
731 | 731 | ||
732 | /* calculate length of the event timestamp status message */ | ||
733 | if (ests & MULT_EVNT) | ||
734 | parsed = (words + 2) * sizeof(u16); | ||
735 | else | ||
736 | parsed = (words + 1) * sizeof(u16); | ||
737 | |||
738 | /* check if enough data is available */ | ||
739 | if (len < parsed) | ||
740 | return len; | ||
741 | |||
732 | if (ests & MULT_EVNT) { | 742 | if (ests & MULT_EVNT) { |
733 | ext_status = *(u16 *) data; | 743 | ext_status = *(u16 *) data; |
734 | data += sizeof(ext_status); | 744 | data += sizeof(ext_status); |
@@ -747,10 +757,7 @@ static int decode_evnt(struct dp83640_private *dp83640, | |||
747 | dp83640->edata.ns_lo = phy_txts->ns_lo; | 757 | dp83640->edata.ns_lo = phy_txts->ns_lo; |
748 | } | 758 | } |
749 | 759 | ||
750 | if (ext_status) { | 760 | if (!ext_status) { |
751 | parsed = words + 2; | ||
752 | } else { | ||
753 | parsed = words + 1; | ||
754 | i = ((ests >> EVNT_NUM_SHIFT) & EVNT_NUM_MASK) - EXT_EVENT; | 761 | i = ((ests >> EVNT_NUM_SHIFT) & EVNT_NUM_MASK) - EXT_EVENT; |
755 | ext_status = exts_chan_to_edata(i); | 762 | ext_status = exts_chan_to_edata(i); |
756 | } | 763 | } |
@@ -768,7 +775,7 @@ static int decode_evnt(struct dp83640_private *dp83640, | |||
768 | } | 775 | } |
769 | } | 776 | } |
770 | 777 | ||
771 | return parsed * sizeof(u16); | 778 | return parsed; |
772 | } | 779 | } |
773 | 780 | ||
774 | static int match(struct sk_buff *skb, unsigned int type, struct rxts *rxts) | 781 | static int match(struct sk_buff *skb, unsigned int type, struct rxts *rxts) |
@@ -905,9 +912,9 @@ static void decode_status_frame(struct dp83640_private *dp83640, | |||
905 | decode_txts(dp83640, phy_txts); | 912 | decode_txts(dp83640, phy_txts); |
906 | size = sizeof(*phy_txts); | 913 | size = sizeof(*phy_txts); |
907 | 914 | ||
908 | } else if (PSF_EVNT == type && len >= sizeof(*phy_txts)) { | 915 | } else if (PSF_EVNT == type) { |
909 | 916 | ||
910 | size = decode_evnt(dp83640, ptr, ests); | 917 | size = decode_evnt(dp83640, ptr, len, ests); |
911 | 918 | ||
912 | } else { | 919 | } else { |
913 | size = 0; | 920 | size = 0; |
@@ -1141,7 +1148,7 @@ static void dp83640_remove(struct phy_device *phydev) | |||
1141 | kfree_skb(skb); | 1148 | kfree_skb(skb); |
1142 | 1149 | ||
1143 | while ((skb = skb_dequeue(&dp83640->tx_queue)) != NULL) | 1150 | while ((skb = skb_dequeue(&dp83640->tx_queue)) != NULL) |
1144 | skb_complete_tx_timestamp(skb, NULL); | 1151 | kfree_skb(skb); |
1145 | 1152 | ||
1146 | clock = dp83640_clock_get(dp83640->clock); | 1153 | clock = dp83640_clock_get(dp83640->clock); |
1147 | 1154 | ||
@@ -1398,7 +1405,7 @@ static void dp83640_txtstamp(struct phy_device *phydev, | |||
1398 | 1405 | ||
1399 | case HWTSTAMP_TX_ONESTEP_SYNC: | 1406 | case HWTSTAMP_TX_ONESTEP_SYNC: |
1400 | if (is_sync(skb, type)) { | 1407 | if (is_sync(skb, type)) { |
1401 | skb_complete_tx_timestamp(skb, NULL); | 1408 | kfree_skb(skb); |
1402 | return; | 1409 | return; |
1403 | } | 1410 | } |
1404 | /* fall through */ | 1411 | /* fall through */ |
@@ -1409,7 +1416,7 @@ static void dp83640_txtstamp(struct phy_device *phydev, | |||
1409 | 1416 | ||
1410 | case HWTSTAMP_TX_OFF: | 1417 | case HWTSTAMP_TX_OFF: |
1411 | default: | 1418 | default: |
1412 | skb_complete_tx_timestamp(skb, NULL); | 1419 | kfree_skb(skb); |
1413 | break; | 1420 | break; |
1414 | } | 1421 | } |
1415 | } | 1422 | } |
diff --git a/drivers/net/phy/fixed.c b/drivers/net/phy/fixed.c index d60d875cb445..5b19fbbda6d4 100644 --- a/drivers/net/phy/fixed.c +++ b/drivers/net/phy/fixed.c | |||
@@ -124,6 +124,17 @@ static int fixed_mdio_read(struct mii_bus *bus, int phy_addr, int reg_num) | |||
124 | if (reg_num >= MII_REGS_NUM) | 124 | if (reg_num >= MII_REGS_NUM) |
125 | return -1; | 125 | return -1; |
126 | 126 | ||
127 | /* We do not support emulating Clause 45 over Clause 22 register reads | ||
128 | * return an error instead of bogus data. | ||
129 | */ | ||
130 | switch (reg_num) { | ||
131 | case MII_MMD_CTRL: | ||
132 | case MII_MMD_DATA: | ||
133 | return -1; | ||
134 | default: | ||
135 | break; | ||
136 | } | ||
137 | |||
127 | list_for_each_entry(fp, &fmb->phys, node) { | 138 | list_for_each_entry(fp, &fmb->phys, node) { |
128 | if (fp->addr == phy_addr) { | 139 | if (fp->addr == phy_addr) { |
129 | /* Issue callback if user registered it. */ | 140 | /* Issue callback if user registered it. */ |
diff --git a/drivers/net/phy/mdio-bcm-unimac.c b/drivers/net/phy/mdio-bcm-unimac.c new file mode 100644 index 000000000000..5b643e588e8f --- /dev/null +++ b/drivers/net/phy/mdio-bcm-unimac.c | |||
@@ -0,0 +1,213 @@ | |||
1 | /* | ||
2 | * Broadcom UniMAC MDIO bus controller driver | ||
3 | * | ||
4 | * Copyright (C) 2014, Broadcom Corporation | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/phy.h> | ||
14 | #include <linux/platform_device.h> | ||
15 | #include <linux/sched.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/io.h> | ||
18 | #include <linux/delay.h> | ||
19 | |||
20 | #include <linux/of.h> | ||
21 | #include <linux/of_platform.h> | ||
22 | #include <linux/of_mdio.h> | ||
23 | |||
24 | #define MDIO_CMD 0x00 | ||
25 | #define MDIO_START_BUSY (1 << 29) | ||
26 | #define MDIO_READ_FAIL (1 << 28) | ||
27 | #define MDIO_RD (2 << 26) | ||
28 | #define MDIO_WR (1 << 26) | ||
29 | #define MDIO_PMD_SHIFT 21 | ||
30 | #define MDIO_PMD_MASK 0x1F | ||
31 | #define MDIO_REG_SHIFT 16 | ||
32 | #define MDIO_REG_MASK 0x1F | ||
33 | |||
34 | #define MDIO_CFG 0x04 | ||
35 | #define MDIO_C22 (1 << 0) | ||
36 | #define MDIO_C45 0 | ||
37 | #define MDIO_CLK_DIV_SHIFT 4 | ||
38 | #define MDIO_CLK_DIV_MASK 0x3F | ||
39 | #define MDIO_SUPP_PREAMBLE (1 << 12) | ||
40 | |||
41 | struct unimac_mdio_priv { | ||
42 | struct mii_bus *mii_bus; | ||
43 | void __iomem *base; | ||
44 | }; | ||
45 | |||
46 | static inline void unimac_mdio_start(struct unimac_mdio_priv *priv) | ||
47 | { | ||
48 | u32 reg; | ||
49 | |||
50 | reg = __raw_readl(priv->base + MDIO_CMD); | ||
51 | reg |= MDIO_START_BUSY; | ||
52 | __raw_writel(reg, priv->base + MDIO_CMD); | ||
53 | } | ||
54 | |||
55 | static inline unsigned int unimac_mdio_busy(struct unimac_mdio_priv *priv) | ||
56 | { | ||
57 | return __raw_readl(priv->base + MDIO_CMD) & MDIO_START_BUSY; | ||
58 | } | ||
59 | |||
60 | static int unimac_mdio_read(struct mii_bus *bus, int phy_id, int reg) | ||
61 | { | ||
62 | struct unimac_mdio_priv *priv = bus->priv; | ||
63 | unsigned int timeout = 1000; | ||
64 | u32 cmd; | ||
65 | |||
66 | /* Prepare the read operation */ | ||
67 | cmd = MDIO_RD | (phy_id << MDIO_PMD_SHIFT) | (reg << MDIO_REG_SHIFT); | ||
68 | __raw_writel(cmd, priv->base + MDIO_CMD); | ||
69 | |||
70 | /* Start MDIO transaction */ | ||
71 | unimac_mdio_start(priv); | ||
72 | |||
73 | do { | ||
74 | if (!unimac_mdio_busy(priv)) | ||
75 | break; | ||
76 | |||
77 | usleep_range(1000, 2000); | ||
78 | } while (timeout--); | ||
79 | |||
80 | if (!timeout) | ||
81 | return -ETIMEDOUT; | ||
82 | |||
83 | cmd = __raw_readl(priv->base + MDIO_CMD); | ||
84 | if (cmd & MDIO_READ_FAIL) | ||
85 | return -EIO; | ||
86 | |||
87 | return cmd & 0xffff; | ||
88 | } | ||
89 | |||
90 | static int unimac_mdio_write(struct mii_bus *bus, int phy_id, | ||
91 | int reg, u16 val) | ||
92 | { | ||
93 | struct unimac_mdio_priv *priv = bus->priv; | ||
94 | unsigned int timeout = 1000; | ||
95 | u32 cmd; | ||
96 | |||
97 | /* Prepare the write operation */ | ||
98 | cmd = MDIO_WR | (phy_id << MDIO_PMD_SHIFT) | | ||
99 | (reg << MDIO_REG_SHIFT) | (0xffff & val); | ||
100 | __raw_writel(cmd, priv->base + MDIO_CMD); | ||
101 | |||
102 | unimac_mdio_start(priv); | ||
103 | |||
104 | do { | ||
105 | if (!unimac_mdio_busy(priv)) | ||
106 | break; | ||
107 | |||
108 | usleep_range(1000, 2000); | ||
109 | } while (timeout--); | ||
110 | |||
111 | if (!timeout) | ||
112 | return -ETIMEDOUT; | ||
113 | |||
114 | return 0; | ||
115 | } | ||
116 | |||
117 | static int unimac_mdio_probe(struct platform_device *pdev) | ||
118 | { | ||
119 | struct unimac_mdio_priv *priv; | ||
120 | struct device_node *np; | ||
121 | struct mii_bus *bus; | ||
122 | struct resource *r; | ||
123 | int ret; | ||
124 | |||
125 | np = pdev->dev.of_node; | ||
126 | |||
127 | priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); | ||
128 | if (!priv) | ||
129 | return -ENOMEM; | ||
130 | |||
131 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
132 | |||
133 | /* Just ioremap, as this MDIO block is usually integrated into an | ||
134 | * Ethernet MAC controller register range | ||
135 | */ | ||
136 | priv->base = devm_ioremap(&pdev->dev, r->start, resource_size(r)); | ||
137 | if (!priv->base) { | ||
138 | dev_err(&pdev->dev, "failed to remap register\n"); | ||
139 | return -ENOMEM; | ||
140 | } | ||
141 | |||
142 | priv->mii_bus = mdiobus_alloc(); | ||
143 | if (!priv->mii_bus) | ||
144 | return -ENOMEM; | ||
145 | |||
146 | bus = priv->mii_bus; | ||
147 | bus->priv = priv; | ||
148 | bus->name = "unimac MII bus"; | ||
149 | bus->parent = &pdev->dev; | ||
150 | bus->read = unimac_mdio_read; | ||
151 | bus->write = unimac_mdio_write; | ||
152 | snprintf(bus->id, MII_BUS_ID_SIZE, "%s", pdev->name); | ||
153 | |||
154 | bus->irq = kcalloc(PHY_MAX_ADDR, sizeof(int), GFP_KERNEL); | ||
155 | if (!bus->irq) { | ||
156 | ret = -ENOMEM; | ||
157 | goto out_mdio_free; | ||
158 | } | ||
159 | |||
160 | ret = of_mdiobus_register(bus, np); | ||
161 | if (ret) { | ||
162 | dev_err(&pdev->dev, "MDIO bus registration failed\n"); | ||
163 | goto out_mdio_irq; | ||
164 | } | ||
165 | |||
166 | platform_set_drvdata(pdev, priv); | ||
167 | |||
168 | dev_info(&pdev->dev, "Broadcom UniMAC MDIO bus at 0x%p\n", priv->base); | ||
169 | |||
170 | return 0; | ||
171 | |||
172 | out_mdio_irq: | ||
173 | kfree(bus->irq); | ||
174 | out_mdio_free: | ||
175 | mdiobus_free(bus); | ||
176 | return ret; | ||
177 | } | ||
178 | |||
179 | static int unimac_mdio_remove(struct platform_device *pdev) | ||
180 | { | ||
181 | struct unimac_mdio_priv *priv = platform_get_drvdata(pdev); | ||
182 | |||
183 | mdiobus_unregister(priv->mii_bus); | ||
184 | kfree(priv->mii_bus->irq); | ||
185 | mdiobus_free(priv->mii_bus); | ||
186 | |||
187 | return 0; | ||
188 | } | ||
189 | |||
190 | static struct of_device_id unimac_mdio_ids[] = { | ||
191 | { .compatible = "brcm,genet-mdio-v4", }, | ||
192 | { .compatible = "brcm,genet-mdio-v3", }, | ||
193 | { .compatible = "brcm,genet-mdio-v2", }, | ||
194 | { .compatible = "brcm,genet-mdio-v1", }, | ||
195 | { .compatible = "brcm,unimac-mdio", }, | ||
196 | { /* sentinel */ }, | ||
197 | }; | ||
198 | |||
199 | static struct platform_driver unimac_mdio_driver = { | ||
200 | .driver = { | ||
201 | .name = "unimac-mdio", | ||
202 | .owner = THIS_MODULE, | ||
203 | .of_match_table = unimac_mdio_ids, | ||
204 | }, | ||
205 | .probe = unimac_mdio_probe, | ||
206 | .remove = unimac_mdio_remove, | ||
207 | }; | ||
208 | module_platform_driver(unimac_mdio_driver); | ||
209 | |||
210 | MODULE_AUTHOR("Broadcom Corporation"); | ||
211 | MODULE_DESCRIPTION("Broadcom UniMAC MDIO bus controller"); | ||
212 | MODULE_LICENSE("GPL"); | ||
213 | MODULE_ALIAS("platform:unimac-mdio"); | ||
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 4eaadcfcb0fe..50051f271b10 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c | |||
@@ -553,8 +553,14 @@ static ssize_t | |||
553 | phy_interface_show(struct device *dev, struct device_attribute *attr, char *buf) | 553 | phy_interface_show(struct device *dev, struct device_attribute *attr, char *buf) |
554 | { | 554 | { |
555 | struct phy_device *phydev = to_phy_device(dev); | 555 | struct phy_device *phydev = to_phy_device(dev); |
556 | const char *mode = NULL; | ||
556 | 557 | ||
557 | return sprintf(buf, "%s\n", phy_modes(phydev->interface)); | 558 | if (phy_is_internal(phydev)) |
559 | mode = "internal"; | ||
560 | else | ||
561 | mode = phy_modes(phydev->interface); | ||
562 | |||
563 | return sprintf(buf, "%s\n", mode); | ||
558 | } | 564 | } |
559 | static DEVICE_ATTR_RO(phy_interface); | 565 | static DEVICE_ATTR_RO(phy_interface); |
560 | 566 | ||
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index a854d38c231d..1dfffdc9dfc3 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c | |||
@@ -955,7 +955,7 @@ static inline void mmd_phy_indirect(struct mii_bus *bus, int prtad, int devad, | |||
955 | * 3) Write reg 13 // MMD Data Command for MMD DEVAD | 955 | * 3) Write reg 13 // MMD Data Command for MMD DEVAD |
956 | * 3) Read reg 14 // Read MMD data | 956 | * 3) Read reg 14 // Read MMD data |
957 | */ | 957 | */ |
958 | static int phy_read_mmd_indirect(struct phy_device *phydev, int prtad, | 958 | int phy_read_mmd_indirect(struct phy_device *phydev, int prtad, |
959 | int devad, int addr) | 959 | int devad, int addr) |
960 | { | 960 | { |
961 | struct phy_driver *phydrv = phydev->drv; | 961 | struct phy_driver *phydrv = phydev->drv; |
@@ -971,6 +971,7 @@ static int phy_read_mmd_indirect(struct phy_device *phydev, int prtad, | |||
971 | } | 971 | } |
972 | return value; | 972 | return value; |
973 | } | 973 | } |
974 | EXPORT_SYMBOL(phy_read_mmd_indirect); | ||
974 | 975 | ||
975 | /** | 976 | /** |
976 | * phy_write_mmd_indirect - writes data to the MMD registers | 977 | * phy_write_mmd_indirect - writes data to the MMD registers |
@@ -988,7 +989,7 @@ static int phy_read_mmd_indirect(struct phy_device *phydev, int prtad, | |||
988 | * 3) Write reg 13 // MMD Data Command for MMD DEVAD | 989 | * 3) Write reg 13 // MMD Data Command for MMD DEVAD |
989 | * 3) Write reg 14 // Write MMD data | 990 | * 3) Write reg 14 // Write MMD data |
990 | */ | 991 | */ |
991 | static void phy_write_mmd_indirect(struct phy_device *phydev, int prtad, | 992 | void phy_write_mmd_indirect(struct phy_device *phydev, int prtad, |
992 | int devad, int addr, u32 data) | 993 | int devad, int addr, u32 data) |
993 | { | 994 | { |
994 | struct phy_driver *phydrv = phydev->drv; | 995 | struct phy_driver *phydrv = phydev->drv; |
@@ -1002,6 +1003,7 @@ static void phy_write_mmd_indirect(struct phy_device *phydev, int prtad, | |||
1002 | phydrv->write_mmd_indirect(phydev, prtad, devad, addr, data); | 1003 | phydrv->write_mmd_indirect(phydev, prtad, devad, addr, data); |
1003 | } | 1004 | } |
1004 | } | 1005 | } |
1006 | EXPORT_SYMBOL(phy_write_mmd_indirect); | ||
1005 | 1007 | ||
1006 | /** | 1008 | /** |
1007 | * phy_init_eee - init and check the EEE feature | 1009 | * phy_init_eee - init and check the EEE feature |
@@ -1017,12 +1019,14 @@ int phy_init_eee(struct phy_device *phydev, bool clk_stop_enable) | |||
1017 | { | 1019 | { |
1018 | /* According to 802.3az,the EEE is supported only in full duplex-mode. | 1020 | /* According to 802.3az,the EEE is supported only in full duplex-mode. |
1019 | * Also EEE feature is active when core is operating with MII, GMII | 1021 | * Also EEE feature is active when core is operating with MII, GMII |
1020 | * or RGMII. | 1022 | * or RGMII. Internal PHYs are also allowed to proceed and should |
1023 | * return an error if they do not support EEE. | ||
1021 | */ | 1024 | */ |
1022 | if ((phydev->duplex == DUPLEX_FULL) && | 1025 | if ((phydev->duplex == DUPLEX_FULL) && |
1023 | ((phydev->interface == PHY_INTERFACE_MODE_MII) || | 1026 | ((phydev->interface == PHY_INTERFACE_MODE_MII) || |
1024 | (phydev->interface == PHY_INTERFACE_MODE_GMII) || | 1027 | (phydev->interface == PHY_INTERFACE_MODE_GMII) || |
1025 | (phydev->interface == PHY_INTERFACE_MODE_RGMII))) { | 1028 | (phydev->interface == PHY_INTERFACE_MODE_RGMII) || |
1029 | phy_is_internal(phydev))) { | ||
1026 | int eee_lp, eee_cap, eee_adv; | 1030 | int eee_lp, eee_cap, eee_adv; |
1027 | u32 lp, cap, adv; | 1031 | u32 lp, cap, adv; |
1028 | int status; | 1032 | int status; |
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index ca5ec3e18d36..3fc91e89f5a5 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c | |||
@@ -230,13 +230,13 @@ static int get_phy_c45_ids(struct mii_bus *bus, int addr, u32 *phy_id, | |||
230 | for (i = 1; | 230 | for (i = 1; |
231 | i < num_ids && c45_ids->devices_in_package == 0; | 231 | i < num_ids && c45_ids->devices_in_package == 0; |
232 | i++) { | 232 | i++) { |
233 | reg_addr = MII_ADDR_C45 | i << 16 | 6; | 233 | reg_addr = MII_ADDR_C45 | i << 16 | MDIO_DEVS2; |
234 | phy_reg = mdiobus_read(bus, addr, reg_addr); | 234 | phy_reg = mdiobus_read(bus, addr, reg_addr); |
235 | if (phy_reg < 0) | 235 | if (phy_reg < 0) |
236 | return -EIO; | 236 | return -EIO; |
237 | c45_ids->devices_in_package = (phy_reg & 0xffff) << 16; | 237 | c45_ids->devices_in_package = (phy_reg & 0xffff) << 16; |
238 | 238 | ||
239 | reg_addr = MII_ADDR_C45 | i << 16 | 5; | 239 | reg_addr = MII_ADDR_C45 | i << 16 | MDIO_DEVS1; |
240 | phy_reg = mdiobus_read(bus, addr, reg_addr); | 240 | phy_reg = mdiobus_read(bus, addr, reg_addr); |
241 | if (phy_reg < 0) | 241 | if (phy_reg < 0) |
242 | return -EIO; | 242 | return -EIO; |