summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKavya Sree Kotagiri <kavyasree.kotagiri@microchip.com>2019-04-22 07:51:35 -0400
committerDavid S. Miller <davem@davemloft.net>2019-04-23 13:47:58 -0400
commite4f9ba642f0b59a7ba3d34e7df7b82c732c31640 (patch)
tree8653333f3a549c40bd9ec2b8d24b87a8d0691879
parenta93f7fe134543649cf2e2d8fc2c50a8f4d742915 (diff)
net: phy: mscc: add support for VSC8514 PHY.
The VSC8514 PHY is a 4-ports PHY that is 10/100/1000BASE-T, 100BASE-FX, 1000BASE-X, can communicate with the MAC via QSGMII. The MAC interface protocol for each port within QSGMII can be either 1000BASE-X or SGMII, if the QSGMII MAC that the VSC8514 is connecting to supports this functionality. VSC8514 also supports SGMII MAC-side autonegotiation on each individual port, downshifting, can set the blinking pattern of each of its 4 LEDs, SyncE, 1000BASE-T Ring Resiliency as well as HP Auto-MDIX detection. This adds support for 10BASE-T, 100BASE-TX, and 1000BASE-T, QSGMII link with the MAC, downshifting, HP Auto-MDIX detection and blinking pattern for its 4 LEDs. The GPIO register bank is a set of registers that are common to all PHYs in the package. So any modification in any register of this bank affects all PHYs of the package. If the PHYs haven't been reset before booting the Linux kernel and were configured to use interrupts for e.g. link status updates, it is required to clear the interrupts mask register of all PHYs before being able to use interrupts with any PHY. The first PHY of the package that will be init will take care of clearing all PHYs interrupts mask registers. Thus, we need to keep track of the init sequence in the package, if it's already been done or if it's to be done. Most of the init sequence of a PHY of the package is common to all PHYs in the package, thus we use the SMI broadcast feature which enables us to propagate a write in one register of one PHY to all PHYs in the same package. Signed-off-by: Kavya Sree Kotagiri <kavyasree.kotagiri@microchip.com> Signed-off-by: Quentin Schulz <quentin.schulz@bootlin.com> Co-developed-by: Quentin Schulz <quentin.schulz@bootlin.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/phy/Kconfig2
-rw-r--r--drivers/net/phy/mscc.c467
2 files changed, 468 insertions, 1 deletions
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index d408b2eb2966..d6299710d634 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -408,7 +408,7 @@ config MICROCHIP_T1_PHY
408config MICROSEMI_PHY 408config MICROSEMI_PHY
409 tristate "Microsemi PHYs" 409 tristate "Microsemi PHYs"
410 ---help--- 410 ---help---
411 Currently supports VSC8530, VSC8531, VSC8540 and VSC8541 PHYs 411 Currently supports VSC8514, VSC8530, VSC8531, VSC8540 and VSC8541 PHYs
412 412
413config NATIONAL_PHY 413config NATIONAL_PHY
414 tristate "National Semiconductor PHYs" 414 tristate "National Semiconductor PHYs"
diff --git a/drivers/net/phy/mscc.c b/drivers/net/phy/mscc.c
index 623313f077d1..28676af97b42 100644
--- a/drivers/net/phy/mscc.c
+++ b/drivers/net/phy/mscc.c
@@ -85,12 +85,49 @@ enum rgmii_rx_clock_delay {
85#define LED_MODE_SEL_MASK(x) (GENMASK(3, 0) << LED_MODE_SEL_POS(x)) 85#define LED_MODE_SEL_MASK(x) (GENMASK(3, 0) << LED_MODE_SEL_POS(x))
86#define LED_MODE_SEL(x, mode) (((mode) << LED_MODE_SEL_POS(x)) & LED_MODE_SEL_MASK(x)) 86#define LED_MODE_SEL(x, mode) (((mode) << LED_MODE_SEL_POS(x)) & LED_MODE_SEL_MASK(x))
87 87
88#define MSCC_EXT_PAGE_CSR_CNTL_17 17
89#define MSCC_EXT_PAGE_CSR_CNTL_18 18
90
91#define MSCC_EXT_PAGE_CSR_CNTL_19 19
92#define MSCC_PHY_CSR_CNTL_19_REG_ADDR(x) (x)
93#define MSCC_PHY_CSR_CNTL_19_TARGET(x) ((x) << 12)
94#define MSCC_PHY_CSR_CNTL_19_READ BIT(14)
95#define MSCC_PHY_CSR_CNTL_19_CMD BIT(15)
96
97#define MSCC_EXT_PAGE_CSR_CNTL_20 20
98#define MSCC_PHY_CSR_CNTL_20_TARGET(x) (x)
99
100#define PHY_MCB_TARGET 0x07
101#define PHY_MCB_S6G_WRITE BIT(31)
102#define PHY_MCB_S6G_READ BIT(30)
103
104#define PHY_S6G_PLL5G_CFG0 0x06
105#define PHY_S6G_LCPLL_CFG 0x11
106#define PHY_S6G_PLL_CFG 0x2b
107#define PHY_S6G_COMMON_CFG 0x2c
108#define PHY_S6G_GPC_CFG 0x2e
109#define PHY_S6G_MISC_CFG 0x3b
110#define PHY_MCB_S6G_CFG 0x3f
111#define PHY_S6G_DFT_CFG2 0x3e
112#define PHY_S6G_PLL_STATUS 0x31
113#define PHY_S6G_IB_STATUS0 0x2f
114
115#define PHY_S6G_SYS_RST_POS 31
116#define PHY_S6G_ENA_LANE_POS 18
117#define PHY_S6G_ENA_LOOP_POS 8
118#define PHY_S6G_QRATE_POS 6
119#define PHY_S6G_IF_MODE_POS 4
120#define PHY_S6G_PLL_ENA_OFFS_POS 21
121#define PHY_S6G_PLL_FSM_CTRL_DATA_POS 8
122#define PHY_S6G_PLL_FSM_ENA_POS 7
123
88#define MSCC_EXT_PAGE_ACCESS 31 124#define MSCC_EXT_PAGE_ACCESS 31
89#define MSCC_PHY_PAGE_STANDARD 0x0000 /* Standard registers */ 125#define MSCC_PHY_PAGE_STANDARD 0x0000 /* Standard registers */
90#define MSCC_PHY_PAGE_EXTENDED 0x0001 /* Extended registers */ 126#define MSCC_PHY_PAGE_EXTENDED 0x0001 /* Extended registers */
91#define MSCC_PHY_PAGE_EXTENDED_2 0x0002 /* Extended reg - page 2 */ 127#define MSCC_PHY_PAGE_EXTENDED_2 0x0002 /* Extended reg - page 2 */
92#define MSCC_PHY_PAGE_EXTENDED_3 0x0003 /* Extended reg - page 3 */ 128#define MSCC_PHY_PAGE_EXTENDED_3 0x0003 /* Extended reg - page 3 */
93#define MSCC_PHY_PAGE_EXTENDED_4 0x0004 /* Extended reg - page 4 */ 129#define MSCC_PHY_PAGE_EXTENDED_4 0x0004 /* Extended reg - page 4 */
130#define MSCC_PHY_PAGE_CSR_CNTL MSCC_PHY_PAGE_EXTENDED_4
94/* Extended reg - GPIO; this is a bank of registers that are shared for all PHYs 131/* Extended reg - GPIO; this is a bank of registers that are shared for all PHYs
95 * in the same package. 132 * in the same package.
96 */ 133 */
@@ -216,6 +253,7 @@ enum rgmii_rx_clock_delay {
216#define MSCC_PHY_TR_MSB 18 253#define MSCC_PHY_TR_MSB 18
217 254
218/* Microsemi PHY ID's */ 255/* Microsemi PHY ID's */
256#define PHY_ID_VSC8514 0x00070670
219#define PHY_ID_VSC8530 0x00070560 257#define PHY_ID_VSC8530 0x00070560
220#define PHY_ID_VSC8531 0x00070570 258#define PHY_ID_VSC8531 0x00070570
221#define PHY_ID_VSC8540 0x00070760 259#define PHY_ID_VSC8540 0x00070760
@@ -1742,6 +1780,386 @@ static int vsc8584_did_interrupt(struct phy_device *phydev)
1742 return (rc < 0) ? 0 : rc & MII_VSC85XX_INT_MASK_MASK; 1780 return (rc < 0) ? 0 : rc & MII_VSC85XX_INT_MASK_MASK;
1743} 1781}
1744 1782
1783static int vsc8514_config_pre_init(struct phy_device *phydev)
1784{
1785 /* These are the settings to override the silicon default
1786 * values to handle hardware performance of PHY. They
1787 * are set at Power-On state and remain until PHY Reset.
1788 */
1789 const struct reg_val pre_init1[] = {
1790 {0x0f90, 0x00688980},
1791 {0x0786, 0x00000003},
1792 {0x07fa, 0x0050100f},
1793 {0x0f82, 0x0012b002},
1794 {0x1686, 0x00000004},
1795 {0x168c, 0x00d2c46f},
1796 {0x17a2, 0x00000620},
1797 {0x16a0, 0x00eeffdd},
1798 {0x16a6, 0x00071448},
1799 {0x16a4, 0x0013132f},
1800 {0x16a8, 0x00000000},
1801 {0x0ffc, 0x00c0a028},
1802 {0x0fe8, 0x0091b06c},
1803 {0x0fea, 0x00041600},
1804 {0x0f80, 0x00fffaff},
1805 {0x0fec, 0x00901809},
1806 {0x0ffe, 0x00b01007},
1807 {0x16b0, 0x00eeff00},
1808 {0x16b2, 0x00007000},
1809 {0x16b4, 0x00000814},
1810 };
1811 unsigned int i;
1812 u16 reg;
1813
1814 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
1815
1816 /* all writes below are broadcasted to all PHYs in the same package */
1817 reg = phy_base_read(phydev, MSCC_PHY_EXT_CNTL_STATUS);
1818 reg |= SMI_BROADCAST_WR_EN;
1819 phy_base_write(phydev, MSCC_PHY_EXT_CNTL_STATUS, reg);
1820
1821 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_TEST);
1822
1823 reg = phy_base_read(phydev, MSCC_PHY_TEST_PAGE_8);
1824 reg |= BIT(15);
1825 phy_base_write(phydev, MSCC_PHY_TEST_PAGE_8, reg);
1826
1827 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_TR);
1828
1829 for (i = 0; i < ARRAY_SIZE(pre_init1); i++)
1830 vsc8584_csr_write(phydev, pre_init1[i].reg, pre_init1[i].val);
1831
1832 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_TEST);
1833
1834 reg = phy_base_read(phydev, MSCC_PHY_TEST_PAGE_8);
1835 reg &= ~BIT(15);
1836 phy_base_write(phydev, MSCC_PHY_TEST_PAGE_8, reg);
1837
1838 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
1839
1840 reg = phy_base_read(phydev, MSCC_PHY_EXT_CNTL_STATUS);
1841 reg &= ~SMI_BROADCAST_WR_EN;
1842 phy_base_write(phydev, MSCC_PHY_EXT_CNTL_STATUS, reg);
1843
1844 return 0;
1845}
1846
1847static u32 vsc85xx_csr_ctrl_phy_read(struct phy_device *phydev,
1848 u32 target, u32 reg)
1849{
1850 unsigned long deadline;
1851 u32 val, val_l, val_h;
1852
1853 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_CSR_CNTL);
1854
1855 /* CSR registers are grouped under different Target IDs.
1856 * 6-bit Target_ID is split between MSCC_EXT_PAGE_CSR_CNTL_20 and
1857 * MSCC_EXT_PAGE_CSR_CNTL_19 registers.
1858 * Target_ID[5:2] maps to bits[3:0] of MSCC_EXT_PAGE_CSR_CNTL_20
1859 * and Target_ID[1:0] maps to bits[13:12] of MSCC_EXT_PAGE_CSR_CNTL_19.
1860 */
1861
1862 /* Setup the Target ID */
1863 phy_base_write(phydev, MSCC_EXT_PAGE_CSR_CNTL_20,
1864 MSCC_PHY_CSR_CNTL_20_TARGET(target >> 2));
1865
1866 /* Trigger CSR Action - Read into the CSR's */
1867 phy_base_write(phydev, MSCC_EXT_PAGE_CSR_CNTL_19,
1868 MSCC_PHY_CSR_CNTL_19_CMD | MSCC_PHY_CSR_CNTL_19_READ |
1869 MSCC_PHY_CSR_CNTL_19_REG_ADDR(reg) |
1870 MSCC_PHY_CSR_CNTL_19_TARGET(target & 0x3));
1871
1872 /* Wait for register access*/
1873 deadline = jiffies + msecs_to_jiffies(PROC_CMD_NCOMPLETED_TIMEOUT_MS);
1874 do {
1875 usleep_range(500, 1000);
1876 val = phy_base_read(phydev, MSCC_EXT_PAGE_CSR_CNTL_19);
1877 } while (time_before(jiffies, deadline) &&
1878 !(val & MSCC_PHY_CSR_CNTL_19_CMD));
1879
1880 if (!(val & MSCC_PHY_CSR_CNTL_19_CMD))
1881 return 0xffffffff;
1882
1883 /* Read the Least Significant Word (LSW) (17) */
1884 val_l = phy_base_read(phydev, MSCC_EXT_PAGE_CSR_CNTL_17);
1885
1886 /* Read the Most Significant Word (MSW) (18) */
1887 val_h = phy_base_read(phydev, MSCC_EXT_PAGE_CSR_CNTL_18);
1888
1889 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS,
1890 MSCC_PHY_PAGE_STANDARD);
1891
1892 return (val_h << 16) | val_l;
1893}
1894
1895static int vsc85xx_csr_ctrl_phy_write(struct phy_device *phydev,
1896 u32 target, u32 reg, u32 val)
1897{
1898 unsigned long deadline;
1899
1900 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_CSR_CNTL);
1901
1902 /* CSR registers are grouped under different Target IDs.
1903 * 6-bit Target_ID is split between MSCC_EXT_PAGE_CSR_CNTL_20 and
1904 * MSCC_EXT_PAGE_CSR_CNTL_19 registers.
1905 * Target_ID[5:2] maps to bits[3:0] of MSCC_EXT_PAGE_CSR_CNTL_20
1906 * and Target_ID[1:0] maps to bits[13:12] of MSCC_EXT_PAGE_CSR_CNTL_19.
1907 */
1908
1909 /* Setup the Target ID */
1910 phy_base_write(phydev, MSCC_EXT_PAGE_CSR_CNTL_20,
1911 MSCC_PHY_CSR_CNTL_20_TARGET(target >> 2));
1912
1913 /* Write the Least Significant Word (LSW) (17) */
1914 phy_base_write(phydev, MSCC_EXT_PAGE_CSR_CNTL_17, (u16)val);
1915
1916 /* Write the Most Significant Word (MSW) (18) */
1917 phy_base_write(phydev, MSCC_EXT_PAGE_CSR_CNTL_18, (u16)(val >> 16));
1918
1919 /* Trigger CSR Action - Write into the CSR's */
1920 phy_base_write(phydev, MSCC_EXT_PAGE_CSR_CNTL_19,
1921 MSCC_PHY_CSR_CNTL_19_CMD |
1922 MSCC_PHY_CSR_CNTL_19_REG_ADDR(reg) |
1923 MSCC_PHY_CSR_CNTL_19_TARGET(target & 0x3));
1924
1925 /* Wait for register access */
1926 deadline = jiffies + msecs_to_jiffies(PROC_CMD_NCOMPLETED_TIMEOUT_MS);
1927 do {
1928 usleep_range(500, 1000);
1929 val = phy_base_read(phydev, MSCC_EXT_PAGE_CSR_CNTL_19);
1930 } while (time_before(jiffies, deadline) &&
1931 !(val & MSCC_PHY_CSR_CNTL_19_CMD));
1932
1933 if (!(val & MSCC_PHY_CSR_CNTL_19_CMD))
1934 return -ETIMEDOUT;
1935
1936 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS,
1937 MSCC_PHY_PAGE_STANDARD);
1938
1939 return 0;
1940}
1941
1942static int __phy_write_mcb_s6g(struct phy_device *phydev, u32 reg, u8 mcb,
1943 u32 op)
1944{
1945 unsigned long deadline;
1946 u32 val;
1947 int ret;
1948
1949 ret = vsc85xx_csr_ctrl_phy_write(phydev, PHY_MCB_TARGET, reg,
1950 op | (1 << mcb));
1951 if (ret)
1952 return -EINVAL;
1953
1954 deadline = jiffies + msecs_to_jiffies(PROC_CMD_NCOMPLETED_TIMEOUT_MS);
1955 do {
1956 usleep_range(500, 1000);
1957 val = vsc85xx_csr_ctrl_phy_read(phydev, PHY_MCB_TARGET, reg);
1958
1959 if (val == 0xffffffff)
1960 return -EIO;
1961
1962 } while (time_before(jiffies, deadline) && (val & op));
1963
1964 if (val & op)
1965 return -ETIMEDOUT;
1966
1967 return 0;
1968}
1969
1970/* Trigger a read to the spcified MCB */
1971static int phy_update_mcb_s6g(struct phy_device *phydev, u32 reg, u8 mcb)
1972{
1973 return __phy_write_mcb_s6g(phydev, reg, mcb, PHY_MCB_S6G_READ);
1974}
1975
1976/* Trigger a write to the spcified MCB */
1977static int phy_commit_mcb_s6g(struct phy_device *phydev, u32 reg, u8 mcb)
1978{
1979 return __phy_write_mcb_s6g(phydev, reg, mcb, PHY_MCB_S6G_WRITE);
1980}
1981
1982static int vsc8514_config_init(struct phy_device *phydev)
1983{
1984 struct vsc8531_private *vsc8531 = phydev->priv;
1985 unsigned long deadline;
1986 u16 val, addr;
1987 int ret, i;
1988 u32 reg;
1989
1990 phydev->mdix_ctrl = ETH_TP_MDI_AUTO;
1991
1992 mutex_lock(&phydev->mdio.bus->mdio_lock);
1993
1994 __phy_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_EXTENDED);
1995
1996 addr = __phy_read(phydev, MSCC_PHY_EXT_PHY_CNTL_4);
1997 addr >>= PHY_CNTL_4_ADDR_POS;
1998
1999 val = __phy_read(phydev, MSCC_PHY_ACTIPHY_CNTL);
2000
2001 if (val & PHY_ADDR_REVERSED)
2002 vsc8531->base_addr = phydev->mdio.addr + addr;
2003 else
2004 vsc8531->base_addr = phydev->mdio.addr - addr;
2005
2006 /* Some parts of the init sequence are identical for every PHY in the
2007 * package. Some parts are modifying the GPIO register bank which is a
2008 * set of registers that are affecting all PHYs, a few resetting the
2009 * microprocessor common to all PHYs.
2010 * All PHYs' interrupts mask register has to be zeroed before enabling
2011 * any PHY's interrupt in this register.
2012 * For all these reasons, we need to do the init sequence once and only
2013 * once whatever is the first PHY in the package that is initialized and
2014 * do the correct init sequence for all PHYs that are package-critical
2015 * in this pre-init function.
2016 */
2017 if (!vsc8584_is_pkg_init(phydev, val & PHY_ADDR_REVERSED ? 1 : 0))
2018 vsc8514_config_pre_init(phydev);
2019
2020 vsc8531->pkg_init = true;
2021
2022 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS,
2023 MSCC_PHY_PAGE_EXTENDED_GPIO);
2024
2025 val = phy_base_read(phydev, MSCC_PHY_MAC_CFG_FASTLINK);
2026
2027 val &= ~MAC_CFG_MASK;
2028 val |= MAC_CFG_QSGMII;
2029 ret = phy_base_write(phydev, MSCC_PHY_MAC_CFG_FASTLINK, val);
2030
2031 if (ret)
2032 goto err;
2033
2034 ret = vsc8584_cmd(phydev,
2035 PROC_CMD_MCB_ACCESS_MAC_CONF |
2036 PROC_CMD_RST_CONF_PORT |
2037 PROC_CMD_READ_MOD_WRITE_PORT | PROC_CMD_QSGMII_MAC);
2038 if (ret)
2039 goto err;
2040
2041 /* 6g mcb */
2042 phy_update_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0);
2043 /* lcpll mcb */
2044 phy_update_mcb_s6g(phydev, PHY_S6G_LCPLL_CFG, 0);
2045 /* pll5gcfg0 */
2046 ret = vsc85xx_csr_ctrl_phy_write(phydev, PHY_MCB_TARGET,
2047 PHY_S6G_PLL5G_CFG0, 0x7036f145);
2048 if (ret)
2049 goto err;
2050
2051 phy_commit_mcb_s6g(phydev, PHY_S6G_LCPLL_CFG, 0);
2052 /* pllcfg */
2053 ret = vsc85xx_csr_ctrl_phy_write(phydev, PHY_MCB_TARGET,
2054 PHY_S6G_PLL_CFG,
2055 (3 << PHY_S6G_PLL_ENA_OFFS_POS) |
2056 (120 << PHY_S6G_PLL_FSM_CTRL_DATA_POS)
2057 | (0 << PHY_S6G_PLL_FSM_ENA_POS));
2058 if (ret)
2059 goto err;
2060
2061 /* commoncfg */
2062 ret = vsc85xx_csr_ctrl_phy_write(phydev, PHY_MCB_TARGET,
2063 PHY_S6G_COMMON_CFG,
2064 (0 << PHY_S6G_SYS_RST_POS) |
2065 (0 << PHY_S6G_ENA_LANE_POS) |
2066 (0 << PHY_S6G_ENA_LOOP_POS) |
2067 (0 << PHY_S6G_QRATE_POS) |
2068 (3 << PHY_S6G_IF_MODE_POS));
2069 if (ret)
2070 goto err;
2071
2072 /* misccfg */
2073 ret = vsc85xx_csr_ctrl_phy_write(phydev, PHY_MCB_TARGET,
2074 PHY_S6G_MISC_CFG, 1);
2075 if (ret)
2076 goto err;
2077
2078 /* gpcfg */
2079 ret = vsc85xx_csr_ctrl_phy_write(phydev, PHY_MCB_TARGET,
2080 PHY_S6G_GPC_CFG, 768);
2081 if (ret)
2082 goto err;
2083
2084 phy_commit_mcb_s6g(phydev, PHY_S6G_DFT_CFG2, 0);
2085
2086 deadline = jiffies + msecs_to_jiffies(PROC_CMD_NCOMPLETED_TIMEOUT_MS);
2087 do {
2088 usleep_range(500, 1000);
2089 phy_update_mcb_s6g(phydev, PHY_MCB_S6G_CFG,
2090 0); /* read 6G MCB into CSRs */
2091 reg = vsc85xx_csr_ctrl_phy_read(phydev, PHY_MCB_TARGET,
2092 PHY_S6G_PLL_STATUS);
2093 if (reg == 0xffffffff) {
2094 mutex_unlock(&phydev->mdio.bus->mdio_lock);
2095 return -EIO;
2096 }
2097
2098 } while (time_before(jiffies, deadline) && (reg & BIT(12)));
2099
2100 if (reg & BIT(12)) {
2101 mutex_unlock(&phydev->mdio.bus->mdio_lock);
2102 return -ETIMEDOUT;
2103 }
2104
2105 /* misccfg */
2106 ret = vsc85xx_csr_ctrl_phy_write(phydev, PHY_MCB_TARGET,
2107 PHY_S6G_MISC_CFG, 0);
2108 if (ret)
2109 goto err;
2110
2111 phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0);
2112
2113 deadline = jiffies + msecs_to_jiffies(PROC_CMD_NCOMPLETED_TIMEOUT_MS);
2114 do {
2115 usleep_range(500, 1000);
2116 phy_update_mcb_s6g(phydev, PHY_MCB_S6G_CFG,
2117 0); /* read 6G MCB into CSRs */
2118 reg = vsc85xx_csr_ctrl_phy_read(phydev, PHY_MCB_TARGET,
2119 PHY_S6G_IB_STATUS0);
2120 if (reg == 0xffffffff) {
2121 mutex_unlock(&phydev->mdio.bus->mdio_lock);
2122 return -EIO;
2123 }
2124
2125 } while (time_before(jiffies, deadline) && !(reg & BIT(8)));
2126
2127 if (!(reg & BIT(8))) {
2128 mutex_unlock(&phydev->mdio.bus->mdio_lock);
2129 return -ETIMEDOUT;
2130 }
2131
2132 mutex_unlock(&phydev->mdio.bus->mdio_lock);
2133
2134 ret = phy_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
2135
2136 if (ret)
2137 return ret;
2138
2139 ret = phy_modify(phydev, MSCC_PHY_EXT_PHY_CNTL_1, MEDIA_OP_MODE_MASK,
2140 MEDIA_OP_MODE_COPPER);
2141
2142 if (ret)
2143 return ret;
2144
2145 ret = genphy_soft_reset(phydev);
2146
2147 if (ret)
2148 return ret;
2149
2150 for (i = 0; i < vsc8531->nleds; i++) {
2151 ret = vsc85xx_led_cntl_set(phydev, i, vsc8531->leds_mode[i]);
2152 if (ret)
2153 return ret;
2154 }
2155
2156 return ret;
2157
2158err:
2159 mutex_unlock(&phydev->mdio.bus->mdio_lock);
2160 return ret;
2161}
2162
1745static int vsc85xx_ack_interrupt(struct phy_device *phydev) 2163static int vsc85xx_ack_interrupt(struct phy_device *phydev)
1746{ 2164{
1747 int rc = 0; 2165 int rc = 0;
@@ -1791,6 +2209,31 @@ static int vsc85xx_read_status(struct phy_device *phydev)
1791 return genphy_read_status(phydev); 2209 return genphy_read_status(phydev);
1792} 2210}
1793 2211
2212static int vsc8514_probe(struct phy_device *phydev)
2213{
2214 struct vsc8531_private *vsc8531;
2215 u32 default_mode[4] = {VSC8531_LINK_1000_ACTIVITY,
2216 VSC8531_LINK_100_ACTIVITY, VSC8531_LINK_ACTIVITY,
2217 VSC8531_DUPLEX_COLLISION};
2218
2219 vsc8531 = devm_kzalloc(&phydev->mdio.dev, sizeof(*vsc8531), GFP_KERNEL);
2220 if (!vsc8531)
2221 return -ENOMEM;
2222
2223 phydev->priv = vsc8531;
2224
2225 vsc8531->nleds = 4;
2226 vsc8531->supp_led_modes = VSC85XX_SUPP_LED_MODES;
2227 vsc8531->hw_stats = vsc85xx_hw_stats;
2228 vsc8531->nstats = ARRAY_SIZE(vsc85xx_hw_stats);
2229 vsc8531->stats = devm_kmalloc_array(&phydev->mdio.dev, vsc8531->nstats,
2230 sizeof(u64), GFP_KERNEL);
2231 if (!vsc8531->stats)
2232 return -ENOMEM;
2233
2234 return vsc85xx_dt_led_modes_get(phydev, default_mode);
2235}
2236
1794static int vsc8574_probe(struct phy_device *phydev) 2237static int vsc8574_probe(struct phy_device *phydev)
1795{ 2238{
1796 struct vsc8531_private *vsc8531; 2239 struct vsc8531_private *vsc8531;
@@ -1879,6 +2322,29 @@ static int vsc85xx_probe(struct phy_device *phydev)
1879/* Microsemi VSC85xx PHYs */ 2322/* Microsemi VSC85xx PHYs */
1880static struct phy_driver vsc85xx_driver[] = { 2323static struct phy_driver vsc85xx_driver[] = {
1881{ 2324{
2325 .phy_id = PHY_ID_VSC8514,
2326 .name = "Microsemi GE VSC8514 SyncE",
2327 .phy_id_mask = 0xfffffff0,
2328 .soft_reset = &genphy_soft_reset,
2329 .config_init = &vsc8514_config_init,
2330 .config_aneg = &vsc85xx_config_aneg,
2331 .read_status = &vsc85xx_read_status,
2332 .ack_interrupt = &vsc85xx_ack_interrupt,
2333 .config_intr = &vsc85xx_config_intr,
2334 .suspend = &genphy_suspend,
2335 .resume = &genphy_resume,
2336 .probe = &vsc8514_probe,
2337 .set_wol = &vsc85xx_wol_set,
2338 .get_wol = &vsc85xx_wol_get,
2339 .get_tunable = &vsc85xx_get_tunable,
2340 .set_tunable = &vsc85xx_set_tunable,
2341 .read_page = &vsc85xx_phy_read_page,
2342 .write_page = &vsc85xx_phy_write_page,
2343 .get_sset_count = &vsc85xx_get_sset_count,
2344 .get_strings = &vsc85xx_get_strings,
2345 .get_stats = &vsc85xx_get_stats,
2346},
2347{
1882 .phy_id = PHY_ID_VSC8530, 2348 .phy_id = PHY_ID_VSC8530,
1883 .name = "Microsemi FE VSC8530", 2349 .name = "Microsemi FE VSC8530",
1884 .phy_id_mask = 0xfffffff0, 2350 .phy_id_mask = 0xfffffff0,
@@ -2034,6 +2500,7 @@ static struct phy_driver vsc85xx_driver[] = {
2034module_phy_driver(vsc85xx_driver); 2500module_phy_driver(vsc85xx_driver);
2035 2501
2036static struct mdio_device_id __maybe_unused vsc85xx_tbl[] = { 2502static struct mdio_device_id __maybe_unused vsc85xx_tbl[] = {
2503 { PHY_ID_VSC8514, 0xfffffff0, },
2037 { PHY_ID_VSC8530, 0xfffffff0, }, 2504 { PHY_ID_VSC8530, 0xfffffff0, },
2038 { PHY_ID_VSC8531, 0xfffffff0, }, 2505 { PHY_ID_VSC8531, 0xfffffff0, },
2039 { PHY_ID_VSC8540, 0xfffffff0, }, 2506 { PHY_ID_VSC8540, 0xfffffff0, },