Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: phy: mscc: improved serdes calibration applied to VSC8514

The current IB serdes calibration algorithm (performed by the onboard 8051)
has proven to be unstable for the VSC8514 QSGMII phy.
A new algorithm has been developed based on
'Frequency-offset Jittered-Injection' or 'FoJi' method which solves
all known issues. This patch disables the 8051 algorithm and
replaces it with the new FoJi algorithm.
The calibration is now performed in a new file (mscc_serdes.c),
which can act as an placeholder for future serdes configurations.

Fixes: e4f9ba642f0b ("net: phy: mscc: add support for VSC8514 PHY.")
Signed-off-by: Steen Hegelund <steen.hegelund@microchip.com>
Signed-off-by: Bjarni Jonasson <bjarni.jonasson@microchip.com>
Tested-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Bjarni Jonasson and committed by
David S. Miller
85e97f0b 3cc2c646

+840 -166
+1
drivers/net/phy/mscc/Makefile
··· 4 4 5 5 obj-$(CONFIG_MICROSEMI_PHY) := mscc.o 6 6 mscc-objs := mscc_main.o 7 + mscc-objs += mscc_serdes.o 7 8 8 9 ifdef CONFIG_MACSEC 9 10 mscc-objs += mscc_macsec.o
+16
drivers/net/phy/mscc/mscc.h
··· 339 339 #define VSC8584_REVB 0x0001 340 340 #define MSCC_DEV_REV_MASK GENMASK(3, 0) 341 341 342 + #define MSCC_ROM_TRAP_SERDES_6G_CFG 0x1E48 343 + #define MSCC_RAM_TRAP_SERDES_6G_CFG 0x1E4F 344 + #define PATCH_VEC_ZERO_EN 0x0100 345 + 342 346 struct reg_val { 343 347 u16 reg; 344 348 u32 val; ··· 423 419 enum csr_target { 424 420 MACRO_CTRL = 0x07, 425 421 }; 422 + 423 + u32 vsc85xx_csr_read(struct phy_device *phydev, 424 + enum csr_target target, u32 reg); 425 + 426 + int vsc85xx_csr_write(struct phy_device *phydev, 427 + enum csr_target target, u32 reg, u32 val); 428 + 429 + int phy_base_write(struct phy_device *phydev, u32 regnum, u16 val); 430 + int phy_base_read(struct phy_device *phydev, u32 regnum); 431 + int phy_update_mcb_s6g(struct phy_device *phydev, u32 reg, u8 mcb); 432 + int phy_commit_mcb_s6g(struct phy_device *phydev, u32 reg, u8 mcb); 433 + int vsc8584_cmd(struct phy_device *phydev, u16 val); 426 434 427 435 #if IS_ENABLED(CONFIG_MACSEC) 428 436 int vsc8584_macsec_init(struct phy_device *phydev);
+142 -166
drivers/net/phy/mscc/mscc_main.c
··· 17 17 #include <linux/of.h> 18 18 #include <linux/netdevice.h> 19 19 #include <dt-bindings/net/mscc-phy-vsc8531.h> 20 - 20 + #include "mscc_serdes.h" 21 21 #include "mscc.h" 22 22 23 23 static const struct vsc85xx_hw_stat vsc85xx_hw_stats[] = { ··· 689 689 } 690 690 691 691 /* phydev->bus->mdio_lock should be locked when using this function */ 692 - static int phy_base_write(struct phy_device *phydev, u32 regnum, u16 val) 692 + int phy_base_write(struct phy_device *phydev, u32 regnum, u16 val) 693 693 { 694 694 if (unlikely(!mutex_is_locked(&phydev->mdio.bus->mdio_lock))) { 695 695 dev_err(&phydev->mdio.dev, "MDIO bus lock not held!\n"); ··· 700 700 } 701 701 702 702 /* phydev->bus->mdio_lock should be locked when using this function */ 703 - static int phy_base_read(struct phy_device *phydev, u32 regnum) 703 + int phy_base_read(struct phy_device *phydev, u32 regnum) 704 704 { 705 705 if (unlikely(!mutex_is_locked(&phydev->mdio.bus->mdio_lock))) { 706 706 dev_err(&phydev->mdio.dev, "MDIO bus lock not held!\n"); ··· 710 710 return __phy_package_read(phydev, regnum); 711 711 } 712 712 713 - static u32 vsc85xx_csr_read(struct phy_device *phydev, 714 - enum csr_target target, u32 reg) 713 + u32 vsc85xx_csr_read(struct phy_device *phydev, 714 + enum csr_target target, u32 reg) 715 715 { 716 716 unsigned long deadline; 717 717 u32 val, val_l, val_h; ··· 764 764 return (val_h << 16) | val_l; 765 765 } 766 766 767 - static int vsc85xx_csr_write(struct phy_device *phydev, 768 - enum csr_target target, u32 reg, u32 val) 767 + int vsc85xx_csr_write(struct phy_device *phydev, 768 + enum csr_target target, u32 reg, u32 val) 769 769 { 770 770 unsigned long deadline; 771 771 ··· 826 826 } 827 827 828 828 /* bus->mdio_lock should be locked when using this function */ 829 - static int vsc8584_cmd(struct phy_device *phydev, u16 val) 829 + int vsc8584_cmd(struct phy_device *phydev, u16 val) 830 830 { 831 831 unsigned long deadline; 832 832 u16 reg_val; ··· 1734 1734 return 0; 1735 1735 } 1736 1736 1737 + static int __phy_write_mcb_s6g(struct phy_device *phydev, u32 reg, u8 mcb, 1738 + u32 op) 1739 + { 1740 + unsigned long deadline; 1741 + u32 val; 1742 + int ret; 1743 + 1744 + ret = vsc85xx_csr_write(phydev, PHY_MCB_TARGET, reg, 1745 + op | (1 << mcb)); 1746 + if (ret) 1747 + return -EINVAL; 1748 + 1749 + deadline = jiffies + msecs_to_jiffies(PROC_CMD_NCOMPLETED_TIMEOUT_MS); 1750 + do { 1751 + usleep_range(500, 1000); 1752 + val = vsc85xx_csr_read(phydev, PHY_MCB_TARGET, reg); 1753 + 1754 + if (val == 0xffffffff) 1755 + return -EIO; 1756 + 1757 + } while (time_before(jiffies, deadline) && (val & op)); 1758 + 1759 + if (val & op) 1760 + return -ETIMEDOUT; 1761 + 1762 + return 0; 1763 + } 1764 + 1765 + /* Trigger a read to the specified MCB */ 1766 + int phy_update_mcb_s6g(struct phy_device *phydev, u32 reg, u8 mcb) 1767 + { 1768 + return __phy_write_mcb_s6g(phydev, reg, mcb, PHY_MCB_S6G_READ); 1769 + } 1770 + 1771 + /* Trigger a write to the specified MCB */ 1772 + int phy_commit_mcb_s6g(struct phy_device *phydev, u32 reg, u8 mcb) 1773 + { 1774 + return __phy_write_mcb_s6g(phydev, reg, mcb, PHY_MCB_S6G_WRITE); 1775 + } 1776 + 1777 + static int vsc8514_config_host_serdes(struct phy_device *phydev) 1778 + { 1779 + int ret; 1780 + u16 val; 1781 + 1782 + ret = phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, 1783 + MSCC_PHY_PAGE_EXTENDED_GPIO); 1784 + if (ret) 1785 + return ret; 1786 + 1787 + val = phy_base_read(phydev, MSCC_PHY_MAC_CFG_FASTLINK); 1788 + val &= ~MAC_CFG_MASK; 1789 + val |= MAC_CFG_QSGMII; 1790 + ret = phy_base_write(phydev, MSCC_PHY_MAC_CFG_FASTLINK, val); 1791 + if (ret) 1792 + return ret; 1793 + 1794 + ret = phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, 1795 + MSCC_PHY_PAGE_STANDARD); 1796 + if (ret) 1797 + return ret; 1798 + 1799 + ret = vsc8584_cmd(phydev, PROC_CMD_NOP); 1800 + if (ret) 1801 + return ret; 1802 + 1803 + ret = vsc8584_cmd(phydev, 1804 + PROC_CMD_MCB_ACCESS_MAC_CONF | 1805 + PROC_CMD_RST_CONF_PORT | 1806 + PROC_CMD_READ_MOD_WRITE_PORT | PROC_CMD_QSGMII_MAC); 1807 + if (ret) { 1808 + dev_err(&phydev->mdio.dev, "%s: QSGMII error: %d\n", 1809 + __func__, ret); 1810 + return ret; 1811 + } 1812 + 1813 + /* Apply 6G SerDes FOJI Algorithm 1814 + * Initial condition requirement: 1815 + * 1. hold 8051 in reset 1816 + * 2. disable patch vector 0, in order to allow IB cal poll during FoJi 1817 + * 3. deassert 8051 reset after change patch vector status 1818 + * 4. proceed with FoJi (vsc85xx_sd6g_config_v2) 1819 + */ 1820 + vsc8584_micro_assert_reset(phydev); 1821 + val = phy_base_read(phydev, MSCC_INT_MEM_CNTL); 1822 + /* clear bit 8, to disable patch vector 0 */ 1823 + val &= ~PATCH_VEC_ZERO_EN; 1824 + ret = phy_base_write(phydev, MSCC_INT_MEM_CNTL, val); 1825 + /* Enable 8051 clock, don't set patch present, disable PRAM clock override */ 1826 + vsc8584_micro_deassert_reset(phydev, false); 1827 + 1828 + return vsc85xx_sd6g_config_v2(phydev); 1829 + } 1830 + 1737 1831 static int vsc8514_config_pre_init(struct phy_device *phydev) 1738 1832 { 1739 1833 /* These are the settings to override the silicon default ··· 1897 1803 reg &= ~SMI_BROADCAST_WR_EN; 1898 1804 phy_base_write(phydev, MSCC_PHY_EXT_CNTL_STATUS, reg); 1899 1805 1900 - return 0; 1901 - } 1806 + /* Add pre-patching commands to: 1807 + * 1. enable 8051 clock, operate 8051 clock at 125 MHz 1808 + * instead of HW default 62.5MHz 1809 + * 2. write patch vector 0, to skip IB cal polling executed 1810 + * as part of the 0x80E0 ROM command 1811 + */ 1812 + vsc8584_micro_deassert_reset(phydev, false); 1902 1813 1903 - static int __phy_write_mcb_s6g(struct phy_device *phydev, u32 reg, u8 mcb, 1904 - u32 op) 1905 - { 1906 - unsigned long deadline; 1907 - u32 val; 1908 - int ret; 1909 - 1910 - ret = vsc85xx_csr_write(phydev, PHY_MCB_TARGET, reg, 1911 - op | (1 << mcb)); 1814 + vsc8584_micro_assert_reset(phydev); 1815 + phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, 1816 + MSCC_PHY_PAGE_EXTENDED_GPIO); 1817 + /* ROM address to trap, for patch vector 0 */ 1818 + reg = MSCC_ROM_TRAP_SERDES_6G_CFG; 1819 + ret = phy_base_write(phydev, MSCC_TRAP_ROM_ADDR(1), reg); 1912 1820 if (ret) 1913 - return -EINVAL; 1821 + goto err; 1822 + /* RAM address to jump to, when patch vector 0 enabled */ 1823 + reg = MSCC_RAM_TRAP_SERDES_6G_CFG; 1824 + ret = phy_base_write(phydev, MSCC_PATCH_RAM_ADDR(1), reg); 1825 + if (ret) 1826 + goto err; 1827 + reg = phy_base_read(phydev, MSCC_INT_MEM_CNTL); 1828 + reg |= PATCH_VEC_ZERO_EN; /* bit 8, enable patch vector 0 */ 1829 + ret = phy_base_write(phydev, MSCC_INT_MEM_CNTL, reg); 1830 + if (ret) 1831 + goto err; 1914 1832 1915 - deadline = jiffies + msecs_to_jiffies(PROC_CMD_NCOMPLETED_TIMEOUT_MS); 1916 - do { 1917 - usleep_range(500, 1000); 1918 - val = vsc85xx_csr_read(phydev, PHY_MCB_TARGET, reg); 1919 - 1920 - if (val == 0xffffffff) 1921 - return -EIO; 1922 - 1923 - } while (time_before(jiffies, deadline) && (val & op)); 1924 - 1925 - if (val & op) 1926 - return -ETIMEDOUT; 1927 - 1928 - return 0; 1929 - } 1930 - 1931 - /* Trigger a read to the specified MCB */ 1932 - static int phy_update_mcb_s6g(struct phy_device *phydev, u32 reg, u8 mcb) 1933 - { 1934 - return __phy_write_mcb_s6g(phydev, reg, mcb, PHY_MCB_S6G_READ); 1935 - } 1936 - 1937 - /* Trigger a write to the specified MCB */ 1938 - static int phy_commit_mcb_s6g(struct phy_device *phydev, u32 reg, u8 mcb) 1939 - { 1940 - return __phy_write_mcb_s6g(phydev, reg, mcb, PHY_MCB_S6G_WRITE); 1833 + /* Enable 8051 clock, don't set patch present 1834 + * yet, disable PRAM clock override 1835 + */ 1836 + vsc8584_micro_deassert_reset(phydev, false); 1837 + return ret; 1838 + err: 1839 + /* restore 8051 and bail w error */ 1840 + vsc8584_micro_deassert_reset(phydev, false); 1841 + return ret; 1941 1842 } 1942 1843 1943 1844 static int vsc8514_config_init(struct phy_device *phydev) 1944 1845 { 1945 1846 struct vsc8531_private *vsc8531 = phydev->priv; 1946 - unsigned long deadline; 1947 1847 int ret, i; 1948 - u16 val; 1949 - u32 reg; 1950 1848 1951 1849 phydev->mdix_ctrl = ETH_TP_MDI_AUTO; 1952 1850 ··· 1955 1869 * do the correct init sequence for all PHYs that are package-critical 1956 1870 * in this pre-init function. 1957 1871 */ 1958 - if (phy_package_init_once(phydev)) 1959 - vsc8514_config_pre_init(phydev); 1960 - 1961 - ret = phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, 1962 - MSCC_PHY_PAGE_EXTENDED_GPIO); 1963 - if (ret) 1964 - goto err; 1965 - 1966 - val = phy_base_read(phydev, MSCC_PHY_MAC_CFG_FASTLINK); 1967 - 1968 - val &= ~MAC_CFG_MASK; 1969 - val |= MAC_CFG_QSGMII; 1970 - ret = phy_base_write(phydev, MSCC_PHY_MAC_CFG_FASTLINK, val); 1971 - if (ret) 1972 - goto err; 1973 - 1974 - ret = phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, 1975 - MSCC_PHY_PAGE_STANDARD); 1976 - if (ret) 1977 - goto err; 1978 - 1979 - ret = vsc8584_cmd(phydev, 1980 - PROC_CMD_MCB_ACCESS_MAC_CONF | 1981 - PROC_CMD_RST_CONF_PORT | 1982 - PROC_CMD_READ_MOD_WRITE_PORT | PROC_CMD_QSGMII_MAC); 1983 - if (ret) 1984 - goto err; 1985 - 1986 - /* 6g mcb */ 1987 - phy_update_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0); 1988 - /* lcpll mcb */ 1989 - phy_update_mcb_s6g(phydev, PHY_S6G_LCPLL_CFG, 0); 1990 - /* pll5gcfg0 */ 1991 - ret = vsc85xx_csr_write(phydev, PHY_MCB_TARGET, 1992 - PHY_S6G_PLL5G_CFG0, 0x7036f145); 1993 - if (ret) 1994 - goto err; 1995 - 1996 - phy_commit_mcb_s6g(phydev, PHY_S6G_LCPLL_CFG, 0); 1997 - /* pllcfg */ 1998 - ret = vsc85xx_csr_write(phydev, PHY_MCB_TARGET, 1999 - PHY_S6G_PLL_CFG, 2000 - (3 << PHY_S6G_PLL_ENA_OFFS_POS) | 2001 - (120 << PHY_S6G_PLL_FSM_CTRL_DATA_POS) 2002 - | (0 << PHY_S6G_PLL_FSM_ENA_POS)); 2003 - if (ret) 2004 - goto err; 2005 - 2006 - /* commoncfg */ 2007 - ret = vsc85xx_csr_write(phydev, PHY_MCB_TARGET, 2008 - PHY_S6G_COMMON_CFG, 2009 - (0 << PHY_S6G_SYS_RST_POS) | 2010 - (0 << PHY_S6G_ENA_LANE_POS) | 2011 - (0 << PHY_S6G_ENA_LOOP_POS) | 2012 - (0 << PHY_S6G_QRATE_POS) | 2013 - (3 << PHY_S6G_IF_MODE_POS)); 2014 - if (ret) 2015 - goto err; 2016 - 2017 - /* misccfg */ 2018 - ret = vsc85xx_csr_write(phydev, PHY_MCB_TARGET, 2019 - PHY_S6G_MISC_CFG, 1); 2020 - if (ret) 2021 - goto err; 2022 - 2023 - /* gpcfg */ 2024 - ret = vsc85xx_csr_write(phydev, PHY_MCB_TARGET, 2025 - PHY_S6G_GPC_CFG, 768); 2026 - if (ret) 2027 - goto err; 2028 - 2029 - phy_commit_mcb_s6g(phydev, PHY_S6G_DFT_CFG2, 0); 2030 - 2031 - deadline = jiffies + msecs_to_jiffies(PROC_CMD_NCOMPLETED_TIMEOUT_MS); 2032 - do { 2033 - usleep_range(500, 1000); 2034 - phy_update_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 2035 - 0); /* read 6G MCB into CSRs */ 2036 - reg = vsc85xx_csr_read(phydev, PHY_MCB_TARGET, 2037 - PHY_S6G_PLL_STATUS); 2038 - if (reg == 0xffffffff) { 2039 - phy_unlock_mdio_bus(phydev); 2040 - return -EIO; 2041 - } 2042 - 2043 - } while (time_before(jiffies, deadline) && (reg & BIT(12))); 2044 - 2045 - if (reg & BIT(12)) { 2046 - phy_unlock_mdio_bus(phydev); 2047 - return -ETIMEDOUT; 2048 - } 2049 - 2050 - /* misccfg */ 2051 - ret = vsc85xx_csr_write(phydev, PHY_MCB_TARGET, 2052 - PHY_S6G_MISC_CFG, 0); 2053 - if (ret) 2054 - goto err; 2055 - 2056 - phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0); 2057 - 2058 - deadline = jiffies + msecs_to_jiffies(PROC_CMD_NCOMPLETED_TIMEOUT_MS); 2059 - do { 2060 - usleep_range(500, 1000); 2061 - phy_update_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 2062 - 0); /* read 6G MCB into CSRs */ 2063 - reg = vsc85xx_csr_read(phydev, PHY_MCB_TARGET, 2064 - PHY_S6G_IB_STATUS0); 2065 - if (reg == 0xffffffff) { 2066 - phy_unlock_mdio_bus(phydev); 2067 - return -EIO; 2068 - } 2069 - 2070 - } while (time_before(jiffies, deadline) && !(reg & BIT(8))); 2071 - 2072 - if (!(reg & BIT(8))) { 2073 - phy_unlock_mdio_bus(phydev); 2074 - return -ETIMEDOUT; 1872 + if (phy_package_init_once(phydev)) { 1873 + ret = vsc8514_config_pre_init(phydev); 1874 + if (ret) 1875 + goto err; 1876 + ret = vsc8514_config_host_serdes(phydev); 1877 + if (ret) 1878 + goto err; 2075 1879 } 2076 1880 2077 1881 phy_unlock_mdio_bus(phydev);
+650
drivers/net/phy/mscc/mscc_serdes.c
··· 1 + // SPDX-License-Identifier: (GPL-2.0 OR MIT) 2 + /* 3 + * Driver for Microsemi VSC85xx PHYs 4 + * 5 + * Author: Bjarni Jonasson <bjarni.jonassoni@microchip.com> 6 + * License: Dual MIT/GPL 7 + * Copyright (c) 2021 Microsemi Corporation 8 + */ 9 + 10 + #include <linux/phy.h> 11 + #include "mscc_serdes.h" 12 + #include "mscc.h" 13 + 14 + static int pll5g_detune(struct phy_device *phydev) 15 + { 16 + u32 rd_dat; 17 + int ret; 18 + 19 + rd_dat = vsc85xx_csr_read(phydev, MACRO_CTRL, PHY_S6G_PLL5G_CFG2); 20 + rd_dat &= ~PHY_S6G_PLL5G_CFG2_GAIN_MASK; 21 + rd_dat |= PHY_S6G_PLL5G_CFG2_ENA_GAIN; 22 + ret = vsc85xx_csr_write(phydev, MACRO_CTRL, 23 + PHY_S6G_PLL5G_CFG2, rd_dat); 24 + if (ret) 25 + dev_err(&phydev->mdio.dev, "%s: write error\n", __func__); 26 + return ret; 27 + } 28 + 29 + static int pll5g_tune(struct phy_device *phydev) 30 + { 31 + u32 rd_dat; 32 + int ret; 33 + 34 + rd_dat = vsc85xx_csr_read(phydev, MACRO_CTRL, PHY_S6G_PLL5G_CFG2); 35 + rd_dat &= ~PHY_S6G_PLL5G_CFG2_ENA_GAIN; 36 + ret = vsc85xx_csr_write(phydev, MACRO_CTRL, 37 + PHY_S6G_PLL5G_CFG2, rd_dat); 38 + if (ret) 39 + dev_err(&phydev->mdio.dev, "%s: write error\n", __func__); 40 + return ret; 41 + } 42 + 43 + static int vsc85xx_sd6g_pll_cfg_wr(struct phy_device *phydev, 44 + const u32 pll_ena_offs, 45 + const u32 pll_fsm_ctrl_data, 46 + const u32 pll_fsm_ena) 47 + { 48 + int ret; 49 + 50 + ret = vsc85xx_csr_write(phydev, MACRO_CTRL, 51 + PHY_S6G_PLL_CFG, 52 + (pll_fsm_ena << PHY_S6G_PLL_ENA_OFFS_POS) | 53 + (pll_fsm_ctrl_data << PHY_S6G_PLL_FSM_CTRL_DATA_POS) | 54 + (pll_ena_offs << PHY_S6G_PLL_FSM_ENA_POS)); 55 + if (ret) 56 + dev_err(&phydev->mdio.dev, "%s: write error\n", __func__); 57 + return ret; 58 + } 59 + 60 + static int vsc85xx_sd6g_common_cfg_wr(struct phy_device *phydev, 61 + const u32 sys_rst, 62 + const u32 ena_lane, 63 + const u32 ena_loop, 64 + const u32 qrate, 65 + const u32 if_mode, 66 + const u32 pwd_tx) 67 + { 68 + /* ena_loop = 8 for eloop */ 69 + /* = 4 for floop */ 70 + /* = 2 for iloop */ 71 + /* = 1 for ploop */ 72 + /* qrate = 1 for SGMII, 0 for QSGMII */ 73 + /* if_mode = 1 for SGMII, 3 for QSGMII */ 74 + 75 + int ret; 76 + 77 + ret = vsc85xx_csr_write(phydev, MACRO_CTRL, 78 + PHY_S6G_COMMON_CFG, 79 + (sys_rst << PHY_S6G_SYS_RST_POS) | 80 + (ena_lane << PHY_S6G_ENA_LANE_POS) | 81 + (ena_loop << PHY_S6G_ENA_LOOP_POS) | 82 + (qrate << PHY_S6G_QRATE_POS) | 83 + (if_mode << PHY_S6G_IF_MODE_POS)); 84 + if (ret) 85 + dev_err(&phydev->mdio.dev, "%s: write error\n", __func__); 86 + return ret; 87 + } 88 + 89 + static int vsc85xx_sd6g_des_cfg_wr(struct phy_device *phydev, 90 + const u32 des_phy_ctrl, 91 + const u32 des_mbtr_ctrl, 92 + const u32 des_bw_hyst, 93 + const u32 des_bw_ana, 94 + const u32 des_cpmd_sel) 95 + { 96 + u32 reg_val; 97 + int ret; 98 + 99 + /* configurable terms */ 100 + reg_val = (des_phy_ctrl << PHY_S6G_DES_PHY_CTRL_POS) | 101 + (des_mbtr_ctrl << PHY_S6G_DES_MBTR_CTRL_POS) | 102 + (des_cpmd_sel << PHY_S6G_DES_CPMD_SEL_POS) | 103 + (des_bw_hyst << PHY_S6G_DES_BW_HYST_POS) | 104 + (des_bw_ana << PHY_S6G_DES_BW_ANA_POS); 105 + ret = vsc85xx_csr_write(phydev, MACRO_CTRL, 106 + PHY_S6G_DES_CFG, 107 + reg_val); 108 + if (ret) 109 + dev_err(&phydev->mdio.dev, "%s: write error\n", __func__); 110 + return ret; 111 + } 112 + 113 + static int vsc85xx_sd6g_ib_cfg0_wr(struct phy_device *phydev, 114 + const u32 ib_rtrm_adj, 115 + const u32 ib_sig_det_clk_sel, 116 + const u32 ib_reg_pat_sel_offset, 117 + const u32 ib_cal_ena) 118 + { 119 + u32 base_val; 120 + u32 reg_val; 121 + int ret; 122 + 123 + /* constant terms */ 124 + base_val = 0x60a85837; 125 + /* configurable terms */ 126 + reg_val = base_val | (ib_rtrm_adj << 25) | 127 + (ib_sig_det_clk_sel << 16) | 128 + (ib_reg_pat_sel_offset << 8) | 129 + (ib_cal_ena << 3); 130 + ret = vsc85xx_csr_write(phydev, MACRO_CTRL, 131 + PHY_S6G_IB_CFG0, 132 + reg_val); 133 + if (ret) 134 + dev_err(&phydev->mdio.dev, "%s: write error\n", __func__); 135 + return ret; 136 + } 137 + 138 + static int vsc85xx_sd6g_ib_cfg1_wr(struct phy_device *phydev, 139 + const u32 ib_tjtag, 140 + const u32 ib_tsdet, 141 + const u32 ib_scaly, 142 + const u32 ib_frc_offset, 143 + const u32 ib_filt_offset) 144 + { 145 + u32 ib_filt_val; 146 + u32 reg_val = 0; 147 + int ret; 148 + 149 + /* constant terms */ 150 + ib_filt_val = 0xe0; 151 + /* configurable terms */ 152 + reg_val = (ib_tjtag << 17) + (ib_tsdet << 12) + (ib_scaly << 8) + 153 + ib_filt_val + (ib_filt_offset << 4) + (ib_frc_offset << 0); 154 + ret = vsc85xx_csr_write(phydev, MACRO_CTRL, 155 + PHY_S6G_IB_CFG1, 156 + reg_val); 157 + if (ret) 158 + dev_err(&phydev->mdio.dev, "%s: write error\n", __func__); 159 + return ret; 160 + } 161 + 162 + static int vsc85xx_sd6g_ib_cfg2_wr(struct phy_device *phydev, 163 + const u32 ib_tinfv, 164 + const u32 ib_tcalv, 165 + const u32 ib_ureg) 166 + { 167 + u32 ib_cfg2_val; 168 + u32 base_val; 169 + int ret; 170 + 171 + /* constant terms */ 172 + base_val = 0x0f878010; 173 + /* configurable terms */ 174 + ib_cfg2_val = base_val | ((ib_tinfv) << 28) | ((ib_tcalv) << 5) | 175 + (ib_ureg << 0); 176 + ret = vsc85xx_csr_write(phydev, MACRO_CTRL, 177 + PHY_S6G_IB_CFG2, 178 + ib_cfg2_val); 179 + if (ret) 180 + dev_err(&phydev->mdio.dev, "%s: write error\n", __func__); 181 + return ret; 182 + } 183 + 184 + static int vsc85xx_sd6g_ib_cfg3_wr(struct phy_device *phydev, 185 + const u32 ib_ini_hp, 186 + const u32 ib_ini_mid, 187 + const u32 ib_ini_lp, 188 + const u32 ib_ini_offset) 189 + { 190 + u32 reg_val; 191 + int ret; 192 + 193 + reg_val = (ib_ini_hp << 24) + (ib_ini_mid << 16) + 194 + (ib_ini_lp << 8) + (ib_ini_offset << 0); 195 + ret = vsc85xx_csr_write(phydev, MACRO_CTRL, 196 + PHY_S6G_IB_CFG3, 197 + reg_val); 198 + if (ret) 199 + dev_err(&phydev->mdio.dev, "%s: write error\n", __func__); 200 + return ret; 201 + } 202 + 203 + static int vsc85xx_sd6g_ib_cfg4_wr(struct phy_device *phydev, 204 + const u32 ib_max_hp, 205 + const u32 ib_max_mid, 206 + const u32 ib_max_lp, 207 + const u32 ib_max_offset) 208 + { 209 + u32 reg_val; 210 + int ret; 211 + 212 + reg_val = (ib_max_hp << 24) + (ib_max_mid << 16) + 213 + (ib_max_lp << 8) + (ib_max_offset << 0); 214 + ret = vsc85xx_csr_write(phydev, MACRO_CTRL, 215 + PHY_S6G_IB_CFG4, 216 + reg_val); 217 + if (ret) 218 + dev_err(&phydev->mdio.dev, "%s: write error\n", __func__); 219 + return ret; 220 + } 221 + 222 + static int vsc85xx_sd6g_misc_cfg_wr(struct phy_device *phydev, 223 + const u32 lane_rst) 224 + { 225 + int ret; 226 + 227 + ret = vsc85xx_csr_write(phydev, MACRO_CTRL, 228 + PHY_S6G_MISC_CFG, 229 + lane_rst); 230 + if (ret) 231 + dev_err(&phydev->mdio.dev, "%s: write error\n", __func__); 232 + return ret; 233 + } 234 + 235 + static int vsc85xx_sd6g_gp_cfg_wr(struct phy_device *phydev, const u32 gp_cfg_val) 236 + { 237 + int ret; 238 + 239 + ret = vsc85xx_csr_write(phydev, MACRO_CTRL, 240 + PHY_S6G_GP_CFG, 241 + gp_cfg_val); 242 + if (ret) 243 + dev_err(&phydev->mdio.dev, "%s: write error\n", __func__); 244 + return ret; 245 + } 246 + 247 + static int vsc85xx_sd6g_dft_cfg2_wr(struct phy_device *phydev, 248 + const u32 rx_ji_ampl, 249 + const u32 rx_step_freq, 250 + const u32 rx_ji_ena, 251 + const u32 rx_waveform_sel, 252 + const u32 rx_freqoff_dir, 253 + const u32 rx_freqoff_ena) 254 + { 255 + u32 reg_val; 256 + int ret; 257 + 258 + /* configurable terms */ 259 + reg_val = (rx_ji_ampl << 8) | (rx_step_freq << 4) | 260 + (rx_ji_ena << 3) | (rx_waveform_sel << 2) | 261 + (rx_freqoff_dir << 1) | rx_freqoff_ena; 262 + ret = vsc85xx_csr_write(phydev, MACRO_CTRL, 263 + PHY_S6G_IB_DFT_CFG2, 264 + reg_val); 265 + if (ret) 266 + dev_err(&phydev->mdio.dev, "%s: write error\n", __func__); 267 + return ret; 268 + } 269 + 270 + static int vsc85xx_sd6g_dft_cfg0_wr(struct phy_device *phydev, 271 + const u32 prbs_sel, 272 + const u32 test_mode, 273 + const u32 rx_dft_ena) 274 + { 275 + u32 reg_val; 276 + int ret; 277 + 278 + /* configurable terms */ 279 + reg_val = (prbs_sel << 20) | (test_mode << 16) | (rx_dft_ena << 2); 280 + ret = vsc85xx_csr_write(phydev, MACRO_CTRL, 281 + PHY_S6G_DFT_CFG0, 282 + reg_val); 283 + if (ret) 284 + dev_err(&phydev->mdio.dev, "%s: write error\n", __func__); 285 + return ret; 286 + } 287 + 288 + /* Access LCPLL Cfg_0 */ 289 + static int vsc85xx_pll5g_cfg0_wr(struct phy_device *phydev, 290 + const u32 selbgv820) 291 + { 292 + u32 base_val; 293 + u32 reg_val; 294 + int ret; 295 + 296 + /* constant terms */ 297 + base_val = 0x7036f145; 298 + /* configurable terms */ 299 + reg_val = base_val | (selbgv820 << 23); 300 + ret = vsc85xx_csr_write(phydev, MACRO_CTRL, 301 + PHY_S6G_PLL5G_CFG0, reg_val); 302 + if (ret) 303 + dev_err(&phydev->mdio.dev, "%s: write error\n", __func__); 304 + return ret; 305 + } 306 + 307 + int vsc85xx_sd6g_config_v2(struct phy_device *phydev) 308 + { 309 + u32 ib_sig_det_clk_sel_cal = 0; 310 + u32 ib_sig_det_clk_sel_mm = 7; 311 + u32 pll_fsm_ctrl_data = 60; 312 + unsigned long deadline; 313 + u32 des_bw_ana_val = 3; 314 + u32 ib_tsdet_cal = 16; 315 + u32 ib_tsdet_mm = 5; 316 + u32 ib_rtrm_adj; 317 + u32 if_mode = 1; 318 + u32 gp_iter = 5; 319 + u32 val32 = 0; 320 + u32 qrate = 1; 321 + u32 iter; 322 + int val = 0; 323 + int ret; 324 + 325 + phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD); 326 + 327 + /* Detune/Unlock LCPLL */ 328 + ret = pll5g_detune(phydev); 329 + if (ret) 330 + return ret; 331 + 332 + /* 0. Reset RCPLL */ 333 + ret = vsc85xx_sd6g_pll_cfg_wr(phydev, 3, pll_fsm_ctrl_data, 0); 334 + if (ret) 335 + return ret; 336 + ret = vsc85xx_sd6g_common_cfg_wr(phydev, 0, 0, 0, qrate, if_mode, 0); 337 + if (ret) 338 + return ret; 339 + ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0); 340 + if (ret) 341 + return ret; 342 + ret = vsc85xx_sd6g_des_cfg_wr(phydev, 6, 2, 5, des_bw_ana_val, 0); 343 + if (ret) 344 + return ret; 345 + 346 + /* 1. Configure sd6g for SGMII prior to sd6g_IB_CAL */ 347 + ib_rtrm_adj = 13; 348 + ret = vsc85xx_sd6g_ib_cfg0_wr(phydev, ib_rtrm_adj, ib_sig_det_clk_sel_mm, 0, 0); 349 + if (ret) 350 + return ret; 351 + ret = vsc85xx_sd6g_ib_cfg1_wr(phydev, 8, ib_tsdet_mm, 15, 0, 1); 352 + if (ret) 353 + return ret; 354 + ret = vsc85xx_sd6g_ib_cfg2_wr(phydev, 3, 13, 5); 355 + if (ret) 356 + return ret; 357 + ret = vsc85xx_sd6g_ib_cfg3_wr(phydev, 0, 31, 1, 31); 358 + if (ret) 359 + return ret; 360 + ret = vsc85xx_sd6g_ib_cfg4_wr(phydev, 63, 63, 2, 63); 361 + if (ret) 362 + return ret; 363 + ret = vsc85xx_sd6g_common_cfg_wr(phydev, 1, 1, 0, qrate, if_mode, 0); 364 + if (ret) 365 + return ret; 366 + ret = vsc85xx_sd6g_misc_cfg_wr(phydev, 1); 367 + if (ret) 368 + return ret; 369 + ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0); 370 + if (ret) 371 + return ret; 372 + 373 + /* 2. Start rcpll_fsm */ 374 + ret = vsc85xx_sd6g_pll_cfg_wr(phydev, 3, pll_fsm_ctrl_data, 1); 375 + if (ret) 376 + return ret; 377 + ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0); 378 + if (ret) 379 + return ret; 380 + 381 + deadline = jiffies + msecs_to_jiffies(PROC_CMD_NCOMPLETED_TIMEOUT_MS); 382 + do { 383 + usleep_range(500, 1000); 384 + ret = phy_update_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0); 385 + if (ret) 386 + return ret; 387 + val32 = vsc85xx_csr_read(phydev, MACRO_CTRL, 388 + PHY_S6G_PLL_STATUS); 389 + /* wait for bit 12 to clear */ 390 + } while (time_before(jiffies, deadline) && (val32 & BIT(12))); 391 + 392 + if (val32 & BIT(12)) 393 + return -ETIMEDOUT; 394 + 395 + /* 4. Release digital reset and disable transmitter */ 396 + ret = vsc85xx_sd6g_misc_cfg_wr(phydev, 0); 397 + if (ret) 398 + return ret; 399 + ret = vsc85xx_sd6g_common_cfg_wr(phydev, 1, 1, 0, qrate, if_mode, 1); 400 + if (ret) 401 + return ret; 402 + ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0); 403 + if (ret) 404 + return ret; 405 + 406 + /* 5. Apply a frequency offset on RX-side (using internal FoJi logic) */ 407 + ret = vsc85xx_sd6g_gp_cfg_wr(phydev, 768); 408 + if (ret) 409 + return ret; 410 + ret = vsc85xx_sd6g_dft_cfg2_wr(phydev, 0, 2, 0, 0, 0, 1); 411 + if (ret) 412 + return ret; 413 + ret = vsc85xx_sd6g_dft_cfg0_wr(phydev, 0, 0, 1); 414 + if (ret) 415 + return ret; 416 + ret = vsc85xx_sd6g_des_cfg_wr(phydev, 6, 2, 5, des_bw_ana_val, 2); 417 + if (ret) 418 + return ret; 419 + ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0); 420 + if (ret) 421 + return ret; 422 + 423 + /* 6. Prepare required settings for IBCAL */ 424 + ret = vsc85xx_sd6g_ib_cfg1_wr(phydev, 8, ib_tsdet_cal, 15, 1, 0); 425 + if (ret) 426 + return ret; 427 + ret = vsc85xx_sd6g_ib_cfg0_wr(phydev, ib_rtrm_adj, ib_sig_det_clk_sel_cal, 0, 0); 428 + if (ret) 429 + return ret; 430 + ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0); 431 + if (ret) 432 + return ret; 433 + 434 + /* 7. Start IB_CAL */ 435 + ret = vsc85xx_sd6g_ib_cfg0_wr(phydev, ib_rtrm_adj, 436 + ib_sig_det_clk_sel_cal, 0, 1); 437 + if (ret) 438 + return ret; 439 + ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0); 440 + if (ret) 441 + return ret; 442 + /* 11 cycles (for ViperA) or 5 cycles (for ViperB & Elise) w/ SW clock */ 443 + for (iter = 0; iter < gp_iter; iter++) { 444 + /* set gp(0) */ 445 + ret = vsc85xx_sd6g_gp_cfg_wr(phydev, 769); 446 + if (ret) 447 + return ret; 448 + ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0); 449 + if (ret) 450 + return ret; 451 + /* clear gp(0) */ 452 + ret = vsc85xx_sd6g_gp_cfg_wr(phydev, 768); 453 + if (ret) 454 + return ret; 455 + ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0); 456 + if (ret) 457 + return ret; 458 + } 459 + 460 + ret = vsc85xx_sd6g_ib_cfg1_wr(phydev, 8, ib_tsdet_cal, 15, 1, 1); 461 + if (ret) 462 + return ret; 463 + ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0); 464 + if (ret) 465 + return ret; 466 + ret = vsc85xx_sd6g_ib_cfg1_wr(phydev, 8, ib_tsdet_cal, 15, 0, 1); 467 + if (ret) 468 + return ret; 469 + ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0); 470 + if (ret) 471 + return ret; 472 + 473 + /* 8. Wait for IB cal to complete */ 474 + deadline = jiffies + msecs_to_jiffies(PROC_CMD_NCOMPLETED_TIMEOUT_MS); 475 + do { 476 + usleep_range(500, 1000); 477 + ret = phy_update_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0); 478 + if (ret) 479 + return ret; 480 + val32 = vsc85xx_csr_read(phydev, MACRO_CTRL, 481 + PHY_S6G_IB_STATUS0); 482 + /* wait for bit 8 to set */ 483 + } while (time_before(jiffies, deadline) && (~val32 & BIT(8))); 484 + 485 + if (~val32 & BIT(8)) 486 + return -ETIMEDOUT; 487 + 488 + /* 9. Restore cfg values for mission mode */ 489 + ret = vsc85xx_sd6g_ib_cfg0_wr(phydev, ib_rtrm_adj, ib_sig_det_clk_sel_mm, 0, 1); 490 + if (ret) 491 + return ret; 492 + ret = vsc85xx_sd6g_ib_cfg1_wr(phydev, 8, ib_tsdet_mm, 15, 0, 1); 493 + if (ret) 494 + return ret; 495 + ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0); 496 + if (ret) 497 + return ret; 498 + 499 + /* 10. Re-enable transmitter */ 500 + ret = vsc85xx_sd6g_common_cfg_wr(phydev, 1, 1, 0, qrate, if_mode, 0); 501 + if (ret) 502 + return ret; 503 + ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0); 504 + if (ret) 505 + return ret; 506 + 507 + /* 11. Disable frequency offset generation (using internal FoJi logic) */ 508 + ret = vsc85xx_sd6g_dft_cfg2_wr(phydev, 0, 0, 0, 0, 0, 0); 509 + if (ret) 510 + return ret; 511 + ret = vsc85xx_sd6g_dft_cfg0_wr(phydev, 0, 0, 0); 512 + if (ret) 513 + return ret; 514 + ret = vsc85xx_sd6g_des_cfg_wr(phydev, 6, 2, 5, des_bw_ana_val, 0); 515 + if (ret) 516 + return ret; 517 + ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0); 518 + if (ret) 519 + return ret; 520 + 521 + /* Tune/Re-lock LCPLL */ 522 + ret = pll5g_tune(phydev); 523 + if (ret) 524 + return ret; 525 + 526 + /* 12. Configure for Final Configuration and Settings */ 527 + /* a. Reset RCPLL */ 528 + ret = vsc85xx_sd6g_pll_cfg_wr(phydev, 3, pll_fsm_ctrl_data, 0); 529 + if (ret) 530 + return ret; 531 + ret = vsc85xx_sd6g_common_cfg_wr(phydev, 0, 1, 0, qrate, if_mode, 0); 532 + if (ret) 533 + return ret; 534 + ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0); 535 + if (ret) 536 + return ret; 537 + 538 + /* b. Configure sd6g for desired operating mode */ 539 + phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_EXTENDED_GPIO); 540 + ret = phy_base_read(phydev, MSCC_PHY_MAC_CFG_FASTLINK); 541 + if ((ret & MAC_CFG_MASK) == MAC_CFG_QSGMII) { 542 + /* QSGMII */ 543 + pll_fsm_ctrl_data = 120; 544 + qrate = 0; 545 + if_mode = 3; 546 + des_bw_ana_val = 5; 547 + val = PROC_CMD_MCB_ACCESS_MAC_CONF | PROC_CMD_RST_CONF_PORT | 548 + PROC_CMD_READ_MOD_WRITE_PORT | PROC_CMD_QSGMII_MAC; 549 + 550 + ret = vsc8584_cmd(phydev, val); 551 + if (ret) { 552 + dev_err(&phydev->mdio.dev, "%s: QSGMII error: %d\n", 553 + __func__, ret); 554 + return ret; 555 + } 556 + 557 + phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD); 558 + } else if ((ret & MAC_CFG_MASK) == MAC_CFG_SGMII) { 559 + /* SGMII */ 560 + pll_fsm_ctrl_data = 60; 561 + qrate = 1; 562 + if_mode = 1; 563 + des_bw_ana_val = 3; 564 + 565 + val = PROC_CMD_MCB_ACCESS_MAC_CONF | PROC_CMD_RST_CONF_PORT | 566 + PROC_CMD_READ_MOD_WRITE_PORT | PROC_CMD_SGMII_MAC; 567 + 568 + ret = vsc8584_cmd(phydev, val); 569 + if (ret) { 570 + dev_err(&phydev->mdio.dev, "%s: SGMII error: %d\n", 571 + __func__, ret); 572 + return ret; 573 + } 574 + 575 + phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD); 576 + } else { 577 + dev_err(&phydev->mdio.dev, "%s: invalid mac_if: %x\n", 578 + __func__, ret); 579 + } 580 + 581 + ret = phy_update_mcb_s6g(phydev, PHY_S6G_LCPLL_CFG, 0); 582 + if (ret) 583 + return ret; 584 + ret = phy_update_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0); 585 + if (ret) 586 + return ret; 587 + ret = vsc85xx_pll5g_cfg0_wr(phydev, 4); 588 + if (ret) 589 + return ret; 590 + ret = phy_commit_mcb_s6g(phydev, PHY_S6G_LCPLL_CFG, 0); 591 + if (ret) 592 + return ret; 593 + ret = vsc85xx_sd6g_des_cfg_wr(phydev, 6, 2, 5, des_bw_ana_val, 0); 594 + if (ret) 595 + return ret; 596 + ret = vsc85xx_sd6g_ib_cfg0_wr(phydev, ib_rtrm_adj, ib_sig_det_clk_sel_mm, 0, 1); 597 + if (ret) 598 + return ret; 599 + ret = vsc85xx_sd6g_ib_cfg1_wr(phydev, 8, ib_tsdet_mm, 15, 0, 1); 600 + if (ret) 601 + return ret; 602 + ret = vsc85xx_sd6g_common_cfg_wr(phydev, 1, 1, 0, qrate, if_mode, 0); 603 + if (ret) 604 + return ret; 605 + ret = vsc85xx_sd6g_ib_cfg2_wr(phydev, 3, 13, 5); 606 + if (ret) 607 + return ret; 608 + ret = vsc85xx_sd6g_ib_cfg3_wr(phydev, 0, 31, 1, 31); 609 + if (ret) 610 + return ret; 611 + ret = vsc85xx_sd6g_ib_cfg4_wr(phydev, 63, 63, 2, 63); 612 + if (ret) 613 + return ret; 614 + ret = vsc85xx_sd6g_misc_cfg_wr(phydev, 1); 615 + if (ret) 616 + return ret; 617 + ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0); 618 + if (ret) 619 + return ret; 620 + 621 + /* 13. Start rcpll_fsm */ 622 + ret = vsc85xx_sd6g_pll_cfg_wr(phydev, 3, pll_fsm_ctrl_data, 1); 623 + if (ret) 624 + return ret; 625 + ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0); 626 + if (ret) 627 + return ret; 628 + 629 + /* 14. Wait for PLL cal to complete */ 630 + deadline = jiffies + msecs_to_jiffies(PROC_CMD_NCOMPLETED_TIMEOUT_MS); 631 + do { 632 + usleep_range(500, 1000); 633 + ret = phy_update_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0); 634 + if (ret) 635 + return ret; 636 + val32 = vsc85xx_csr_read(phydev, MACRO_CTRL, 637 + PHY_S6G_PLL_STATUS); 638 + /* wait for bit 12 to clear */ 639 + } while (time_before(jiffies, deadline) && (val32 & BIT(12))); 640 + 641 + if (val32 & BIT(12)) 642 + return -ETIMEDOUT; 643 + 644 + /* release lane reset */ 645 + ret = vsc85xx_sd6g_misc_cfg_wr(phydev, 0); 646 + if (ret) 647 + return ret; 648 + 649 + return phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0); 650 + }
+31
drivers/net/phy/mscc/mscc_serdes.h
··· 1 + /* SPDX-License-Identifier: (GPL-2.0 OR MIT) */ 2 + /* 3 + * Driver for Microsemi VSC85xx PHYs 4 + * 5 + * Copyright (c) 2021 Microsemi Corporation 6 + */ 7 + 8 + #ifndef _MSCC_SERDES_PHY_H_ 9 + #define _MSCC_SERDES_PHY_H_ 10 + 11 + #define PHY_S6G_PLL5G_CFG2_GAIN_MASK GENMASK(9, 5) 12 + #define PHY_S6G_PLL5G_CFG2_ENA_GAIN 1 13 + 14 + #define PHY_S6G_DES_PHY_CTRL_POS 13 15 + #define PHY_S6G_DES_MBTR_CTRL_POS 10 16 + #define PHY_S6G_DES_CPMD_SEL_POS 8 17 + #define PHY_S6G_DES_BW_HYST_POS 5 18 + #define PHY_S6G_DES_BW_ANA_POS 1 19 + #define PHY_S6G_DES_CFG 0x21 20 + #define PHY_S6G_IB_CFG0 0x22 21 + #define PHY_S6G_IB_CFG1 0x23 22 + #define PHY_S6G_IB_CFG2 0x24 23 + #define PHY_S6G_IB_CFG3 0x25 24 + #define PHY_S6G_IB_CFG4 0x26 25 + #define PHY_S6G_GP_CFG 0x2E 26 + #define PHY_S6G_DFT_CFG0 0x35 27 + #define PHY_S6G_IB_DFT_CFG2 0x37 28 + 29 + int vsc85xx_sd6g_config_v2(struct phy_device *phydev); 30 + 31 + #endif /* _MSCC_PHY_SERDES_H_ */