1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2023, Linaro Limited 4 */ 5 6 #include <linux/clk.h> 7 #include <linux/ethtool.h> 8 #include <linux/module.h> 9 #include <linux/of.h> 10 #include <linux/phy/phy.h> 11 #include <linux/platform_device.h> 12 #include <linux/regmap.h> 13 14 #include "phy-qcom-qmp-pcs-sgmii.h" 15 #include "phy-qcom-qmp-qserdes-com-v5.h" 16 #include "phy-qcom-qmp-qserdes-txrx-v5.h" 17 18 #define QSERDES_QMP_PLL 0x0 19 #define QSERDES_RX 0x600 20 #define QSERDES_TX 0x400 21 #define QSERDES_PCS 0xc00 22 23 #define QSERDES_COM_C_READY BIT(0) 24 #define QSERDES_PCS_READY BIT(0) 25 #define QSERDES_PCS_SGMIIPHY_READY BIT(7) 26 #define QSERDES_COM_C_PLL_LOCKED BIT(1) 27 28 struct qcom_dwmac_sgmii_phy_data { 29 struct regmap *regmap; 30 struct clk *refclk; 31 int speed; 32 }; 33 34 static void qcom_dwmac_sgmii_phy_init_1g(struct regmap *regmap) 35 { 36 regmap_write(regmap, QSERDES_PCS + QPHY_PCS_SW_RESET, 0x01); 37 regmap_write(regmap, QSERDES_PCS + QPHY_PCS_POWER_DOWN_CONTROL, 0x01); 38 39 regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_PLL_IVCO, 0x0F); 40 regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_CP_CTRL_MODE0, 0x06); 41 regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_PLL_RCTRL_MODE0, 0x16); 42 regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_PLL_CCTRL_MODE0, 0x36); 43 regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_SYSCLK_EN_SEL, 0x1A); 44 regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_LOCK_CMP1_MODE0, 0x0A); 45 regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_LOCK_CMP2_MODE0, 0x1A); 46 regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_DEC_START_MODE0, 0x82); 47 regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_DIV_FRAC_START1_MODE0, 0x55); 48 regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_DIV_FRAC_START2_MODE0, 0x55); 49 regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_DIV_FRAC_START3_MODE0, 0x03); 50 regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_VCO_TUNE1_MODE0, 0x24); 51 52 regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_VCO_TUNE2_MODE0, 0x02); 53 regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_VCO_TUNE_INITVAL2, 0x00); 54 regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_HSCLK_SEL, 0x04); 55 regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_HSCLK_HS_SWITCH_SEL, 0x00); 56 regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_CORECLK_DIV_MODE0, 0x0A); 57 regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_CORE_CLK_EN, 0x00); 58 regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xB9); 59 regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1E); 60 regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_BIN_VCOCAL_HSCLK_SEL, 0x11); 61 62 regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_TX_BAND, 0x05); 63 regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_SLEW_CNTL, 0x0A); 64 regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_RES_CODE_LANE_OFFSET_TX, 0x09); 65 regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_RES_CODE_LANE_OFFSET_RX, 0x09); 66 regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_LANE_MODE_1, 0x05); 67 regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_LANE_MODE_3, 0x00); 68 regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_RCV_DETECT_LVL_2, 0x12); 69 regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_TRAN_DRVR_EMP_EN, 0x0C); 70 71 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_FO_GAIN, 0x0A); 72 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_SO_GAIN, 0x06); 73 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_FASTLOCK_FO_GAIN, 0x0A); 74 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7F); 75 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_LOW, 0x00); 76 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x01); 77 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_PI_CONTROLS, 0x81); 78 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_PI_CTRL2, 0x80); 79 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_TERM_BW, 0x04); 80 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_VGA_CAL_CNTRL2, 0x08); 81 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_GM_CAL, 0x0F); 82 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL1, 0x04); 83 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL2, 0x00); 84 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4A); 85 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0A); 86 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_IDAC_TSETTLE_LOW, 0x80); 87 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_IDAC_TSETTLE_HIGH, 0x01); 88 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_IDAC_MEASURE_TIME, 0x20); 89 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x17); 90 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x00); 91 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_SIGDET_CNTRL, 0x0F); 92 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_SIGDET_DEGLITCH_CNTRL, 0x1E); 93 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_BAND, 0x05); 94 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_00_LOW, 0xE0); 95 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_00_HIGH, 0xC8); 96 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_00_HIGH2, 0xC8); 97 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_00_HIGH3, 0x09); 98 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_00_HIGH4, 0xB1); 99 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_01_LOW, 0xE0); 100 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_01_HIGH, 0xC8); 101 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_01_HIGH2, 0xC8); 102 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_01_HIGH3, 0x09); 103 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_01_HIGH4, 0xB1); 104 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_10_LOW, 0xE0); 105 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_10_HIGH, 0xC8); 106 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_10_HIGH2, 0xC8); 107 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_10_HIGH3, 0x3B); 108 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_10_HIGH4, 0xB7); 109 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_DCC_CTRL1, 0x0C); 110 111 regmap_write(regmap, QSERDES_PCS + QPHY_PCS_LINE_RESET_TIME, 0x0C); 112 regmap_write(regmap, QSERDES_PCS + QPHY_PCS_TX_LARGE_AMP_DRV_LVL, 0x1F); 113 regmap_write(regmap, QSERDES_PCS + QPHY_PCS_TX_SMALL_AMP_DRV_LVL, 0x03); 114 regmap_write(regmap, QSERDES_PCS + QPHY_PCS_TX_MID_TERM_CTRL1, 0x83); 115 regmap_write(regmap, QSERDES_PCS + QPHY_PCS_TX_MID_TERM_CTRL2, 0x08); 116 regmap_write(regmap, QSERDES_PCS + QPHY_PCS_SGMII_MISC_CTRL8, 0x0C); 117 regmap_write(regmap, QSERDES_PCS + QPHY_PCS_SW_RESET, 0x00); 118 119 regmap_write(regmap, QSERDES_PCS + QPHY_PCS_PHY_START, 0x01); 120 } 121 122 static void qcom_dwmac_sgmii_phy_init_2p5g(struct regmap *regmap) 123 { 124 regmap_write(regmap, QSERDES_PCS + QPHY_PCS_SW_RESET, 0x01); 125 regmap_write(regmap, QSERDES_PCS + QPHY_PCS_POWER_DOWN_CONTROL, 0x01); 126 127 regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_PLL_IVCO, 0x0F); 128 regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_CP_CTRL_MODE0, 0x06); 129 regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_PLL_RCTRL_MODE0, 0x16); 130 regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_PLL_CCTRL_MODE0, 0x36); 131 regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_SYSCLK_EN_SEL, 0x1A); 132 regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_LOCK_CMP1_MODE0, 0x1A); 133 regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_LOCK_CMP2_MODE0, 0x41); 134 regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_DEC_START_MODE0, 0x7A); 135 regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_DIV_FRAC_START1_MODE0, 0x00); 136 regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_DIV_FRAC_START2_MODE0, 0x20); 137 regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_DIV_FRAC_START3_MODE0, 0x01); 138 regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_VCO_TUNE1_MODE0, 0xA1); 139 140 regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_VCO_TUNE2_MODE0, 0x02); 141 regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_VCO_TUNE_INITVAL2, 0x00); 142 regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_HSCLK_SEL, 0x03); 143 regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_HSCLK_HS_SWITCH_SEL, 0x00); 144 regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_CORECLK_DIV_MODE0, 0x05); 145 regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_CORE_CLK_EN, 0x00); 146 regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xCD); 147 regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1C); 148 regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_BIN_VCOCAL_HSCLK_SEL, 0x11); 149 150 regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_TX_BAND, 0x04); 151 regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_SLEW_CNTL, 0x0A); 152 regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_RES_CODE_LANE_OFFSET_TX, 0x09); 153 regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_RES_CODE_LANE_OFFSET_RX, 0x02); 154 regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_LANE_MODE_1, 0x05); 155 regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_LANE_MODE_3, 0x00); 156 regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_RCV_DETECT_LVL_2, 0x12); 157 regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_TRAN_DRVR_EMP_EN, 0x0C); 158 159 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_FO_GAIN, 0x0A); 160 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_SO_GAIN, 0x06); 161 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_FASTLOCK_FO_GAIN, 0x0A); 162 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7F); 163 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_LOW, 0x00); 164 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x01); 165 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_PI_CONTROLS, 0x81); 166 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_PI_CTRL2, 0x80); 167 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_TERM_BW, 0x00); 168 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_VGA_CAL_CNTRL2, 0x08); 169 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_GM_CAL, 0x0F); 170 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL1, 0x04); 171 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL2, 0x00); 172 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4A); 173 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0A); 174 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_IDAC_TSETTLE_LOW, 0x80); 175 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_IDAC_TSETTLE_HIGH, 0x01); 176 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_IDAC_MEASURE_TIME, 0x20); 177 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x17); 178 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x00); 179 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_SIGDET_CNTRL, 0x0F); 180 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_SIGDET_DEGLITCH_CNTRL, 0x1E); 181 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_BAND, 0x18); 182 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_00_LOW, 0x18); 183 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_00_HIGH, 0xC8); 184 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_00_HIGH2, 0xC8); 185 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_00_HIGH3, 0x0C); 186 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_00_HIGH4, 0xB8); 187 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_01_LOW, 0xE0); 188 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_01_HIGH, 0xC8); 189 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_01_HIGH2, 0xC8); 190 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_01_HIGH3, 0x09); 191 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_01_HIGH4, 0xB1); 192 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_10_LOW, 0xE0); 193 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_10_HIGH, 0xC8); 194 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_10_HIGH2, 0xC8); 195 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_10_HIGH3, 0x3B); 196 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_10_HIGH4, 0xB7); 197 regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_DCC_CTRL1, 0x0C); 198 199 regmap_write(regmap, QSERDES_PCS + QPHY_PCS_LINE_RESET_TIME, 0x0C); 200 regmap_write(regmap, QSERDES_PCS + QPHY_PCS_TX_LARGE_AMP_DRV_LVL, 0x1F); 201 regmap_write(regmap, QSERDES_PCS + QPHY_PCS_TX_SMALL_AMP_DRV_LVL, 0x03); 202 regmap_write(regmap, QSERDES_PCS + QPHY_PCS_TX_MID_TERM_CTRL1, 0x83); 203 regmap_write(regmap, QSERDES_PCS + QPHY_PCS_TX_MID_TERM_CTRL2, 0x08); 204 regmap_write(regmap, QSERDES_PCS + QPHY_PCS_SGMII_MISC_CTRL8, 0x8C); 205 regmap_write(regmap, QSERDES_PCS + QPHY_PCS_SW_RESET, 0x00); 206 207 regmap_write(regmap, QSERDES_PCS + QPHY_PCS_PHY_START, 0x01); 208 } 209 210 static inline int 211 qcom_dwmac_sgmii_phy_poll_status(struct regmap *regmap, unsigned int reg, 212 unsigned int bit) 213 { 214 unsigned int val; 215 216 return regmap_read_poll_timeout(regmap, reg, val, 217 val & bit, 1500, 750000); 218 } 219 220 static int qcom_dwmac_sgmii_phy_calibrate(struct phy *phy) 221 { 222 struct qcom_dwmac_sgmii_phy_data *data = phy_get_drvdata(phy); 223 struct device *dev = phy->dev.parent; 224 225 switch (data->speed) { 226 case SPEED_10: 227 case SPEED_100: 228 case SPEED_1000: 229 qcom_dwmac_sgmii_phy_init_1g(data->regmap); 230 break; 231 case SPEED_2500: 232 qcom_dwmac_sgmii_phy_init_2p5g(data->regmap); 233 break; 234 } 235 236 if (qcom_dwmac_sgmii_phy_poll_status(data->regmap, 237 QSERDES_QMP_PLL + QSERDES_V5_COM_C_READY_STATUS, 238 QSERDES_COM_C_READY)) { 239 dev_err(dev, "QSERDES_COM_C_READY_STATUS timed-out"); 240 return -ETIMEDOUT; 241 } 242 243 if (qcom_dwmac_sgmii_phy_poll_status(data->regmap, 244 QSERDES_PCS + QPHY_PCS_PCS_READY_STATUS, 245 QSERDES_PCS_READY)) { 246 dev_err(dev, "PCS_READY timed-out"); 247 return -ETIMEDOUT; 248 } 249 250 if (qcom_dwmac_sgmii_phy_poll_status(data->regmap, 251 QSERDES_PCS + QPHY_PCS_PCS_READY_STATUS, 252 QSERDES_PCS_SGMIIPHY_READY)) { 253 dev_err(dev, "SGMIIPHY_READY timed-out"); 254 return -ETIMEDOUT; 255 } 256 257 if (qcom_dwmac_sgmii_phy_poll_status(data->regmap, 258 QSERDES_QMP_PLL + QSERDES_V5_COM_CMN_STATUS, 259 QSERDES_COM_C_PLL_LOCKED)) { 260 dev_err(dev, "PLL Lock Status timed-out"); 261 return -ETIMEDOUT; 262 } 263 264 return 0; 265 } 266 267 static int qcom_dwmac_sgmii_phy_power_on(struct phy *phy) 268 { 269 struct qcom_dwmac_sgmii_phy_data *data = phy_get_drvdata(phy); 270 271 return clk_prepare_enable(data->refclk); 272 } 273 274 static int qcom_dwmac_sgmii_phy_power_off(struct phy *phy) 275 { 276 struct qcom_dwmac_sgmii_phy_data *data = phy_get_drvdata(phy); 277 278 regmap_write(data->regmap, QSERDES_PCS + QPHY_PCS_TX_MID_TERM_CTRL2, 0x08); 279 regmap_write(data->regmap, QSERDES_PCS + QPHY_PCS_SW_RESET, 0x01); 280 udelay(100); 281 regmap_write(data->regmap, QSERDES_PCS + QPHY_PCS_SW_RESET, 0x00); 282 regmap_write(data->regmap, QSERDES_PCS + QPHY_PCS_PHY_START, 0x01); 283 284 clk_disable_unprepare(data->refclk); 285 286 return 0; 287 } 288 289 static int qcom_dwmac_sgmii_phy_set_speed(struct phy *phy, int speed) 290 { 291 struct qcom_dwmac_sgmii_phy_data *data = phy_get_drvdata(phy); 292 293 if (speed != data->speed) 294 data->speed = speed; 295 296 return qcom_dwmac_sgmii_phy_calibrate(phy); 297 } 298 299 static const struct phy_ops qcom_dwmac_sgmii_phy_ops = { 300 .power_on = qcom_dwmac_sgmii_phy_power_on, 301 .power_off = qcom_dwmac_sgmii_phy_power_off, 302 .set_speed = qcom_dwmac_sgmii_phy_set_speed, 303 .calibrate = qcom_dwmac_sgmii_phy_calibrate, 304 .owner = THIS_MODULE, 305 }; 306 307 static const struct regmap_config qcom_dwmac_sgmii_phy_regmap_cfg = { 308 .reg_bits = 32, 309 .val_bits = 32, 310 .reg_stride = 4, 311 .use_relaxed_mmio = true, 312 .disable_locking = true, 313 }; 314 315 static int qcom_dwmac_sgmii_phy_probe(struct platform_device *pdev) 316 { 317 struct qcom_dwmac_sgmii_phy_data *data; 318 struct device *dev = &pdev->dev; 319 struct phy_provider *provider; 320 void __iomem *base; 321 struct phy *phy; 322 323 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 324 if (!data) 325 return -ENOMEM; 326 327 data->speed = SPEED_10; 328 329 base = devm_platform_ioremap_resource(pdev, 0); 330 if (IS_ERR(base)) 331 return PTR_ERR(base); 332 333 data->regmap = devm_regmap_init_mmio(dev, base, 334 &qcom_dwmac_sgmii_phy_regmap_cfg); 335 if (IS_ERR(data->regmap)) 336 return PTR_ERR(data->regmap); 337 338 phy = devm_phy_create(dev, NULL, &qcom_dwmac_sgmii_phy_ops); 339 if (IS_ERR(phy)) 340 return PTR_ERR(phy); 341 342 data->refclk = devm_clk_get(dev, "sgmi_ref"); 343 if (IS_ERR(data->refclk)) 344 return PTR_ERR(data->refclk); 345 346 provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); 347 if (IS_ERR(provider)) 348 return PTR_ERR(provider); 349 350 phy_set_drvdata(phy, data); 351 352 return 0; 353 } 354 355 static const struct of_device_id qcom_dwmac_sgmii_phy_of_match[] = { 356 { .compatible = "qcom,sa8775p-dwmac-sgmii-phy" }, 357 { }, 358 }; 359 MODULE_DEVICE_TABLE(of, qcom_dwmac_sgmii_phy_of_match); 360 361 static struct platform_driver qcom_dwmac_sgmii_phy_driver = { 362 .probe = qcom_dwmac_sgmii_phy_probe, 363 .driver = { 364 .name = "qcom-dwmac-sgmii-phy", 365 .of_match_table = qcom_dwmac_sgmii_phy_of_match, 366 } 367 }; 368 369 module_platform_driver(qcom_dwmac_sgmii_phy_driver); 370 371 MODULE_DESCRIPTION("Qualcomm DWMAC SGMII PHY driver"); 372 MODULE_LICENSE("GPL"); 373