1 // SPDX-License-Identifier: GPL-2.0 2 // Copyright (C) 2018 Microchip Technology 3 4 #include <linux/kernel.h> 5 #include <linux/module.h> 6 #include <linux/delay.h> 7 #include <linux/mii.h> 8 #include <linux/phy.h> 9 #include <linux/ethtool.h> 10 #include <linux/ethtool_netlink.h> 11 #include <linux/bitfield.h> 12 13 #define PHY_ID_LAN87XX 0x0007c150 14 #define PHY_ID_LAN937X 0x0007c180 15 16 /* External Register Control Register */ 17 #define LAN87XX_EXT_REG_CTL (0x14) 18 #define LAN87XX_EXT_REG_CTL_RD_CTL (0x1000) 19 #define LAN87XX_EXT_REG_CTL_WR_CTL (0x0800) 20 #define LAN87XX_REG_BANK_SEL_MASK GENMASK(10, 8) 21 #define LAN87XX_REG_ADDR_MASK GENMASK(7, 0) 22 23 /* External Register Read Data Register */ 24 #define LAN87XX_EXT_REG_RD_DATA (0x15) 25 26 /* External Register Write Data Register */ 27 #define LAN87XX_EXT_REG_WR_DATA (0x16) 28 29 /* Interrupt Source Register */ 30 #define LAN87XX_INTERRUPT_SOURCE (0x18) 31 #define LAN87XX_INTERRUPT_SOURCE_2 (0x08) 32 33 /* Interrupt Mask Register */ 34 #define LAN87XX_INTERRUPT_MASK (0x19) 35 #define LAN87XX_MASK_LINK_UP (0x0004) 36 #define LAN87XX_MASK_LINK_DOWN (0x0002) 37 38 #define LAN87XX_INTERRUPT_MASK_2 (0x09) 39 #define LAN87XX_MASK_COMM_RDY BIT(10) 40 41 /* MISC Control 1 Register */ 42 #define LAN87XX_CTRL_1 (0x11) 43 #define LAN87XX_MASK_RGMII_TXC_DLY_EN (0x4000) 44 #define LAN87XX_MASK_RGMII_RXC_DLY_EN (0x2000) 45 46 /* phyaccess nested types */ 47 #define PHYACC_ATTR_MODE_READ 0 48 #define PHYACC_ATTR_MODE_WRITE 1 49 #define PHYACC_ATTR_MODE_MODIFY 2 50 #define PHYACC_ATTR_MODE_POLL 3 51 52 #define PHYACC_ATTR_BANK_SMI 0 53 #define PHYACC_ATTR_BANK_MISC 1 54 #define PHYACC_ATTR_BANK_PCS 2 55 #define PHYACC_ATTR_BANK_AFE 3 56 #define PHYACC_ATTR_BANK_DSP 4 57 #define PHYACC_ATTR_BANK_MAX 7 58 59 /* measurement defines */ 60 #define LAN87XX_CABLE_TEST_OK 0 61 #define LAN87XX_CABLE_TEST_OPEN 1 62 #define LAN87XX_CABLE_TEST_SAME_SHORT 2 63 64 /* T1 Registers */ 65 #define T1_AFE_PORT_CFG1_REG 0x0B 66 #define T1_POWER_DOWN_CONTROL_REG 0x1A 67 #define T1_SLV_FD_MULT_CFG_REG 0x18 68 #define T1_CDR_CFG_PRE_LOCK_REG 0x05 69 #define T1_CDR_CFG_POST_LOCK_REG 0x06 70 #define T1_LCK_STG2_MUFACT_CFG_REG 0x1A 71 #define T1_LCK_STG3_MUFACT_CFG_REG 0x1B 72 #define T1_POST_LCK_MUFACT_CFG_REG 0x1C 73 #define T1_TX_RX_FIFO_CFG_REG 0x02 74 #define T1_TX_LPF_FIR_CFG_REG 0x55 75 #define T1_COEF_CLK_PWR_DN_CFG 0x04 76 #define T1_COEF_RW_CTL_CFG 0x0D 77 #define T1_SQI_CONFIG_REG 0x2E 78 #define T1_SQI_CONFIG2_REG 0x4A 79 #define T1_DCQ_SQI_REG 0xC3 80 #define T1_DCQ_SQI_MSK GENMASK(3, 1) 81 #define T1_MDIO_CONTROL2_REG 0x10 82 #define T1_INTERRUPT_SOURCE_REG 0x18 83 #define T1_INTERRUPT2_SOURCE_REG 0x08 84 #define T1_EQ_FD_STG1_FRZ_CFG 0x69 85 #define T1_EQ_FD_STG2_FRZ_CFG 0x6A 86 #define T1_EQ_FD_STG3_FRZ_CFG 0x6B 87 #define T1_EQ_FD_STG4_FRZ_CFG 0x6C 88 #define T1_EQ_WT_FD_LCK_FRZ_CFG 0x6D 89 #define T1_PST_EQ_LCK_STG1_FRZ_CFG 0x6E 90 91 #define T1_MODE_STAT_REG 0x11 92 #define T1_LINK_UP_MSK BIT(0) 93 94 /* SQI defines */ 95 #define LAN87XX_MAX_SQI 0x07 96 97 #define DRIVER_AUTHOR "Nisar Sayed <nisar.sayed@microchip.com>" 98 #define DRIVER_DESC "Microchip LAN87XX/LAN937x T1 PHY driver" 99 100 struct access_ereg_val { 101 u8 mode; 102 u8 bank; 103 u8 offset; 104 u16 val; 105 u16 mask; 106 }; 107 108 static int lan937x_dsp_workaround(struct phy_device *phydev, u16 ereg, u8 bank) 109 { 110 u8 prev_bank; 111 int rc = 0; 112 u16 val; 113 114 mutex_lock(&phydev->lock); 115 /* Read previous selected bank */ 116 rc = phy_read(phydev, LAN87XX_EXT_REG_CTL); 117 if (rc < 0) 118 goto out_unlock; 119 120 /* store the prev_bank */ 121 prev_bank = FIELD_GET(LAN87XX_REG_BANK_SEL_MASK, rc); 122 123 if (bank != prev_bank && bank == PHYACC_ATTR_BANK_DSP) { 124 val = ereg & ~LAN87XX_REG_ADDR_MASK; 125 126 val &= ~LAN87XX_EXT_REG_CTL_WR_CTL; 127 val |= LAN87XX_EXT_REG_CTL_RD_CTL; 128 129 /* access twice for DSP bank change,dummy access */ 130 rc = phy_write(phydev, LAN87XX_EXT_REG_CTL, val); 131 } 132 133 out_unlock: 134 mutex_unlock(&phydev->lock); 135 136 return rc; 137 } 138 139 static int access_ereg(struct phy_device *phydev, u8 mode, u8 bank, 140 u8 offset, u16 val) 141 { 142 u16 ereg = 0; 143 int rc = 0; 144 145 if (mode > PHYACC_ATTR_MODE_WRITE || bank > PHYACC_ATTR_BANK_MAX) 146 return -EINVAL; 147 148 if (bank == PHYACC_ATTR_BANK_SMI) { 149 if (mode == PHYACC_ATTR_MODE_WRITE) 150 rc = phy_write(phydev, offset, val); 151 else 152 rc = phy_read(phydev, offset); 153 return rc; 154 } 155 156 if (mode == PHYACC_ATTR_MODE_WRITE) { 157 ereg = LAN87XX_EXT_REG_CTL_WR_CTL; 158 rc = phy_write(phydev, LAN87XX_EXT_REG_WR_DATA, val); 159 if (rc < 0) 160 return rc; 161 } else { 162 ereg = LAN87XX_EXT_REG_CTL_RD_CTL; 163 } 164 165 ereg |= (bank << 8) | offset; 166 167 /* DSP bank access workaround for lan937x */ 168 if (phydev->phy_id == PHY_ID_LAN937X) { 169 rc = lan937x_dsp_workaround(phydev, ereg, bank); 170 if (rc < 0) 171 return rc; 172 } 173 174 rc = phy_write(phydev, LAN87XX_EXT_REG_CTL, ereg); 175 if (rc < 0) 176 return rc; 177 178 if (mode == PHYACC_ATTR_MODE_READ) 179 rc = phy_read(phydev, LAN87XX_EXT_REG_RD_DATA); 180 181 return rc; 182 } 183 184 static int access_ereg_modify_changed(struct phy_device *phydev, 185 u8 bank, u8 offset, u16 val, u16 mask) 186 { 187 int new = 0, rc = 0; 188 189 if (bank > PHYACC_ATTR_BANK_MAX) 190 return -EINVAL; 191 192 rc = access_ereg(phydev, PHYACC_ATTR_MODE_READ, bank, offset, val); 193 if (rc < 0) 194 return rc; 195 196 new = val | (rc & (mask ^ 0xFFFF)); 197 rc = access_ereg(phydev, PHYACC_ATTR_MODE_WRITE, bank, offset, new); 198 199 return rc; 200 } 201 202 static int access_smi_poll_timeout(struct phy_device *phydev, 203 u8 offset, u16 mask, u16 clr) 204 { 205 int val; 206 207 return phy_read_poll_timeout(phydev, offset, val, (val & mask) == clr, 208 150, 30000, true); 209 } 210 211 static int lan87xx_config_rgmii_delay(struct phy_device *phydev) 212 { 213 int rc; 214 215 if (!phy_interface_is_rgmii(phydev)) 216 return 0; 217 218 rc = access_ereg(phydev, PHYACC_ATTR_MODE_READ, 219 PHYACC_ATTR_BANK_MISC, LAN87XX_CTRL_1, 0); 220 if (rc < 0) 221 return rc; 222 223 switch (phydev->interface) { 224 case PHY_INTERFACE_MODE_RGMII: 225 rc &= ~LAN87XX_MASK_RGMII_TXC_DLY_EN; 226 rc &= ~LAN87XX_MASK_RGMII_RXC_DLY_EN; 227 break; 228 case PHY_INTERFACE_MODE_RGMII_ID: 229 rc |= LAN87XX_MASK_RGMII_TXC_DLY_EN; 230 rc |= LAN87XX_MASK_RGMII_RXC_DLY_EN; 231 break; 232 case PHY_INTERFACE_MODE_RGMII_RXID: 233 rc &= ~LAN87XX_MASK_RGMII_TXC_DLY_EN; 234 rc |= LAN87XX_MASK_RGMII_RXC_DLY_EN; 235 break; 236 case PHY_INTERFACE_MODE_RGMII_TXID: 237 rc |= LAN87XX_MASK_RGMII_TXC_DLY_EN; 238 rc &= ~LAN87XX_MASK_RGMII_RXC_DLY_EN; 239 break; 240 default: 241 return 0; 242 } 243 244 return access_ereg(phydev, PHYACC_ATTR_MODE_WRITE, 245 PHYACC_ATTR_BANK_MISC, LAN87XX_CTRL_1, rc); 246 } 247 248 static int lan87xx_phy_init(struct phy_device *phydev) 249 { 250 static const struct access_ereg_val init[] = { 251 /* TXPD/TXAMP6 Configs */ 252 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_AFE, 253 T1_AFE_PORT_CFG1_REG, 0x002D, 0 }, 254 /* HW_Init Hi and Force_ED */ 255 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_SMI, 256 T1_POWER_DOWN_CONTROL_REG, 0x0308, 0 }, 257 /* Equalizer Full Duplex Freeze - T1 Slave */ 258 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 259 T1_EQ_FD_STG1_FRZ_CFG, 0x0002, 0 }, 260 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 261 T1_EQ_FD_STG2_FRZ_CFG, 0x0002, 0 }, 262 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 263 T1_EQ_FD_STG3_FRZ_CFG, 0x0002, 0 }, 264 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 265 T1_EQ_FD_STG4_FRZ_CFG, 0x0002, 0 }, 266 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 267 T1_EQ_WT_FD_LCK_FRZ_CFG, 0x0002, 0 }, 268 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 269 T1_PST_EQ_LCK_STG1_FRZ_CFG, 0x0002, 0 }, 270 /* Slave Full Duplex Multi Configs */ 271 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 272 T1_SLV_FD_MULT_CFG_REG, 0x0D53, 0 }, 273 /* CDR Pre and Post Lock Configs */ 274 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 275 T1_CDR_CFG_PRE_LOCK_REG, 0x0AB2, 0 }, 276 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 277 T1_CDR_CFG_POST_LOCK_REG, 0x0AB3, 0 }, 278 /* Lock Stage 2-3 Multi Factor Config */ 279 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 280 T1_LCK_STG2_MUFACT_CFG_REG, 0x0AEA, 0 }, 281 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 282 T1_LCK_STG3_MUFACT_CFG_REG, 0x0AEB, 0 }, 283 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 284 T1_POST_LCK_MUFACT_CFG_REG, 0x0AEB, 0 }, 285 /* Pointer delay */ 286 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 287 T1_TX_RX_FIFO_CFG_REG, 0x1C00, 0 }, 288 /* Tx iir edits */ 289 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 290 T1_TX_LPF_FIR_CFG_REG, 0x1000, 0 }, 291 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 292 T1_TX_LPF_FIR_CFG_REG, 0x1861, 0 }, 293 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 294 T1_TX_LPF_FIR_CFG_REG, 0x1061, 0 }, 295 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 296 T1_TX_LPF_FIR_CFG_REG, 0x1922, 0 }, 297 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 298 T1_TX_LPF_FIR_CFG_REG, 0x1122, 0 }, 299 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 300 T1_TX_LPF_FIR_CFG_REG, 0x1983, 0 }, 301 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 302 T1_TX_LPF_FIR_CFG_REG, 0x1183, 0 }, 303 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 304 T1_TX_LPF_FIR_CFG_REG, 0x1944, 0 }, 305 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 306 T1_TX_LPF_FIR_CFG_REG, 0x1144, 0 }, 307 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 308 T1_TX_LPF_FIR_CFG_REG, 0x18c5, 0 }, 309 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 310 T1_TX_LPF_FIR_CFG_REG, 0x10c5, 0 }, 311 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 312 T1_TX_LPF_FIR_CFG_REG, 0x1846, 0 }, 313 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 314 T1_TX_LPF_FIR_CFG_REG, 0x1046, 0 }, 315 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 316 T1_TX_LPF_FIR_CFG_REG, 0x1807, 0 }, 317 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 318 T1_TX_LPF_FIR_CFG_REG, 0x1007, 0 }, 319 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 320 T1_TX_LPF_FIR_CFG_REG, 0x1808, 0 }, 321 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 322 T1_TX_LPF_FIR_CFG_REG, 0x1008, 0 }, 323 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 324 T1_TX_LPF_FIR_CFG_REG, 0x1809, 0 }, 325 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 326 T1_TX_LPF_FIR_CFG_REG, 0x1009, 0 }, 327 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 328 T1_TX_LPF_FIR_CFG_REG, 0x180A, 0 }, 329 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 330 T1_TX_LPF_FIR_CFG_REG, 0x100A, 0 }, 331 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 332 T1_TX_LPF_FIR_CFG_REG, 0x180B, 0 }, 333 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 334 T1_TX_LPF_FIR_CFG_REG, 0x100B, 0 }, 335 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 336 T1_TX_LPF_FIR_CFG_REG, 0x180C, 0 }, 337 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 338 T1_TX_LPF_FIR_CFG_REG, 0x100C, 0 }, 339 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 340 T1_TX_LPF_FIR_CFG_REG, 0x180D, 0 }, 341 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 342 T1_TX_LPF_FIR_CFG_REG, 0x100D, 0 }, 343 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 344 T1_TX_LPF_FIR_CFG_REG, 0x180E, 0 }, 345 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 346 T1_TX_LPF_FIR_CFG_REG, 0x100E, 0 }, 347 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 348 T1_TX_LPF_FIR_CFG_REG, 0x180F, 0 }, 349 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 350 T1_TX_LPF_FIR_CFG_REG, 0x100F, 0 }, 351 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 352 T1_TX_LPF_FIR_CFG_REG, 0x1810, 0 }, 353 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 354 T1_TX_LPF_FIR_CFG_REG, 0x1010, 0 }, 355 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 356 T1_TX_LPF_FIR_CFG_REG, 0x1811, 0 }, 357 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 358 T1_TX_LPF_FIR_CFG_REG, 0x1011, 0 }, 359 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 360 T1_TX_LPF_FIR_CFG_REG, 0x1000, 0 }, 361 /* Setup SQI measurement */ 362 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 363 T1_COEF_CLK_PWR_DN_CFG, 0x16d6, 0 }, 364 /* SQI enable */ 365 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 366 T1_SQI_CONFIG_REG, 0x9572, 0 }, 367 /* SQI select mode 5 */ 368 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 369 T1_SQI_CONFIG2_REG, 0x0001, 0 }, 370 /* Throws the first SQI reading */ 371 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 372 T1_COEF_RW_CTL_CFG, 0x0301, 0 }, 373 { PHYACC_ATTR_MODE_READ, PHYACC_ATTR_BANK_DSP, 374 T1_DCQ_SQI_REG, 0, 0 }, 375 /* Flag LPS and WUR as idle errors */ 376 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_SMI, 377 T1_MDIO_CONTROL2_REG, 0x0014, 0 }, 378 /* HW_Init toggle, undo force ED, TXPD off */ 379 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_SMI, 380 T1_POWER_DOWN_CONTROL_REG, 0x0200, 0 }, 381 /* Reset PCS to trigger hardware initialization */ 382 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_SMI, 383 T1_MDIO_CONTROL2_REG, 0x0094, 0 }, 384 /* Poll till Hardware is initialized */ 385 { PHYACC_ATTR_MODE_POLL, PHYACC_ATTR_BANK_SMI, 386 T1_MDIO_CONTROL2_REG, 0x0080, 0 }, 387 /* Tx AMP - 0x06 */ 388 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_AFE, 389 T1_AFE_PORT_CFG1_REG, 0x000C, 0 }, 390 /* Read INTERRUPT_SOURCE Register */ 391 { PHYACC_ATTR_MODE_READ, PHYACC_ATTR_BANK_SMI, 392 T1_INTERRUPT_SOURCE_REG, 0, 0 }, 393 /* Read INTERRUPT_SOURCE Register */ 394 { PHYACC_ATTR_MODE_READ, PHYACC_ATTR_BANK_MISC, 395 T1_INTERRUPT2_SOURCE_REG, 0, 0 }, 396 /* HW_Init Hi */ 397 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_SMI, 398 T1_POWER_DOWN_CONTROL_REG, 0x0300, 0 }, 399 }; 400 int rc, i; 401 402 /* phy Soft reset */ 403 rc = genphy_soft_reset(phydev); 404 if (rc < 0) 405 return rc; 406 407 /* PHY Initialization */ 408 for (i = 0; i < ARRAY_SIZE(init); i++) { 409 if (init[i].mode == PHYACC_ATTR_MODE_POLL && 410 init[i].bank == PHYACC_ATTR_BANK_SMI) { 411 rc = access_smi_poll_timeout(phydev, 412 init[i].offset, 413 init[i].val, 414 init[i].mask); 415 } else { 416 rc = access_ereg(phydev, init[i].mode, init[i].bank, 417 init[i].offset, init[i].val); 418 } 419 if (rc < 0) 420 return rc; 421 } 422 423 return lan87xx_config_rgmii_delay(phydev); 424 } 425 426 static int lan87xx_phy_config_intr(struct phy_device *phydev) 427 { 428 int rc, val = 0; 429 430 if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { 431 /* clear all interrupt */ 432 rc = phy_write(phydev, LAN87XX_INTERRUPT_MASK, val); 433 if (rc < 0) 434 return rc; 435 436 rc = phy_read(phydev, LAN87XX_INTERRUPT_SOURCE); 437 if (rc < 0) 438 return rc; 439 440 rc = access_ereg(phydev, PHYACC_ATTR_MODE_WRITE, 441 PHYACC_ATTR_BANK_MISC, 442 LAN87XX_INTERRUPT_MASK_2, val); 443 if (rc < 0) 444 return rc; 445 446 rc = access_ereg(phydev, PHYACC_ATTR_MODE_READ, 447 PHYACC_ATTR_BANK_MISC, 448 LAN87XX_INTERRUPT_SOURCE_2, 0); 449 if (rc < 0) 450 return rc; 451 452 /* enable link down and comm ready interrupt */ 453 val = LAN87XX_MASK_LINK_DOWN; 454 rc = phy_write(phydev, LAN87XX_INTERRUPT_MASK, val); 455 if (rc < 0) 456 return rc; 457 458 val = LAN87XX_MASK_COMM_RDY; 459 rc = access_ereg(phydev, PHYACC_ATTR_MODE_WRITE, 460 PHYACC_ATTR_BANK_MISC, 461 LAN87XX_INTERRUPT_MASK_2, val); 462 } else { 463 rc = phy_write(phydev, LAN87XX_INTERRUPT_MASK, val); 464 if (rc < 0) 465 return rc; 466 467 rc = phy_read(phydev, LAN87XX_INTERRUPT_SOURCE); 468 if (rc < 0) 469 return rc; 470 471 rc = access_ereg(phydev, PHYACC_ATTR_MODE_WRITE, 472 PHYACC_ATTR_BANK_MISC, 473 LAN87XX_INTERRUPT_MASK_2, val); 474 if (rc < 0) 475 return rc; 476 477 rc = access_ereg(phydev, PHYACC_ATTR_MODE_READ, 478 PHYACC_ATTR_BANK_MISC, 479 LAN87XX_INTERRUPT_SOURCE_2, 0); 480 } 481 482 return rc < 0 ? rc : 0; 483 } 484 485 static irqreturn_t lan87xx_handle_interrupt(struct phy_device *phydev) 486 { 487 int irq_status; 488 489 irq_status = access_ereg(phydev, PHYACC_ATTR_MODE_READ, 490 PHYACC_ATTR_BANK_MISC, 491 LAN87XX_INTERRUPT_SOURCE_2, 0); 492 if (irq_status < 0) { 493 phy_error(phydev); 494 return IRQ_NONE; 495 } 496 497 irq_status = phy_read(phydev, LAN87XX_INTERRUPT_SOURCE); 498 if (irq_status < 0) { 499 phy_error(phydev); 500 return IRQ_NONE; 501 } 502 503 if (irq_status == 0) 504 return IRQ_NONE; 505 506 phy_trigger_machine(phydev); 507 508 return IRQ_HANDLED; 509 } 510 511 static int lan87xx_config_init(struct phy_device *phydev) 512 { 513 int rc = lan87xx_phy_init(phydev); 514 515 return rc < 0 ? rc : 0; 516 } 517 518 static int microchip_cable_test_start_common(struct phy_device *phydev) 519 { 520 int bmcr, bmsr, ret; 521 522 /* If auto-negotiation is enabled, but not complete, the cable 523 * test never completes. So disable auto-neg. 524 */ 525 bmcr = phy_read(phydev, MII_BMCR); 526 if (bmcr < 0) 527 return bmcr; 528 529 bmsr = phy_read(phydev, MII_BMSR); 530 531 if (bmsr < 0) 532 return bmsr; 533 534 if (bmcr & BMCR_ANENABLE) { 535 ret = phy_modify(phydev, MII_BMCR, BMCR_ANENABLE, 0); 536 if (ret < 0) 537 return ret; 538 ret = genphy_soft_reset(phydev); 539 if (ret < 0) 540 return ret; 541 } 542 543 /* If the link is up, allow it some time to go down */ 544 if (bmsr & BMSR_LSTATUS) 545 msleep(1500); 546 547 return 0; 548 } 549 550 static int lan87xx_cable_test_start(struct phy_device *phydev) 551 { 552 static const struct access_ereg_val cable_test[] = { 553 /* min wait */ 554 {PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 93, 555 0, 0}, 556 /* max wait */ 557 {PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 94, 558 10, 0}, 559 /* pulse cycle */ 560 {PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 95, 561 90, 0}, 562 /* cable diag thresh */ 563 {PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 92, 564 60, 0}, 565 /* max gain */ 566 {PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 79, 567 31, 0}, 568 /* clock align for each iteration */ 569 {PHYACC_ATTR_MODE_MODIFY, PHYACC_ATTR_BANK_DSP, 55, 570 0, 0x0038}, 571 /* max cycle wait config */ 572 {PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 94, 573 70, 0}, 574 /* start cable diag*/ 575 {PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 90, 576 1, 0}, 577 }; 578 int rc, i; 579 580 rc = microchip_cable_test_start_common(phydev); 581 if (rc < 0) 582 return rc; 583 584 /* start cable diag */ 585 /* check if part is alive - if not, return diagnostic error */ 586 rc = access_ereg(phydev, PHYACC_ATTR_MODE_READ, PHYACC_ATTR_BANK_SMI, 587 0x00, 0); 588 if (rc < 0) 589 return rc; 590 591 /* master/slave specific configs */ 592 rc = access_ereg(phydev, PHYACC_ATTR_MODE_READ, PHYACC_ATTR_BANK_SMI, 593 0x0A, 0); 594 if (rc < 0) 595 return rc; 596 597 if ((rc & 0x4000) != 0x4000) { 598 /* DUT is Slave */ 599 rc = access_ereg_modify_changed(phydev, PHYACC_ATTR_BANK_AFE, 600 0x0E, 0x5, 0x7); 601 if (rc < 0) 602 return rc; 603 rc = access_ereg_modify_changed(phydev, PHYACC_ATTR_BANK_SMI, 604 0x1A, 0x8, 0x8); 605 if (rc < 0) 606 return rc; 607 } else { 608 /* DUT is Master */ 609 rc = access_ereg_modify_changed(phydev, PHYACC_ATTR_BANK_SMI, 610 0x10, 0x8, 0x40); 611 if (rc < 0) 612 return rc; 613 } 614 615 for (i = 0; i < ARRAY_SIZE(cable_test); i++) { 616 if (cable_test[i].mode == PHYACC_ATTR_MODE_MODIFY) { 617 rc = access_ereg_modify_changed(phydev, 618 cable_test[i].bank, 619 cable_test[i].offset, 620 cable_test[i].val, 621 cable_test[i].mask); 622 /* wait 50ms */ 623 msleep(50); 624 } else { 625 rc = access_ereg(phydev, cable_test[i].mode, 626 cable_test[i].bank, 627 cable_test[i].offset, 628 cable_test[i].val); 629 } 630 if (rc < 0) 631 return rc; 632 } 633 /* cable diag started */ 634 635 return 0; 636 } 637 638 static int lan87xx_cable_test_report_trans(u32 result) 639 { 640 switch (result) { 641 case LAN87XX_CABLE_TEST_OK: 642 return ETHTOOL_A_CABLE_RESULT_CODE_OK; 643 case LAN87XX_CABLE_TEST_OPEN: 644 return ETHTOOL_A_CABLE_RESULT_CODE_OPEN; 645 case LAN87XX_CABLE_TEST_SAME_SHORT: 646 return ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT; 647 default: 648 /* DIAGNOSTIC_ERROR */ 649 return ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC; 650 } 651 } 652 653 static int lan87xx_cable_test_report(struct phy_device *phydev) 654 { 655 int pos_peak_cycle = 0, pos_peak_in_phases = 0, pos_peak_phase = 0; 656 int neg_peak_cycle = 0, neg_peak_in_phases = 0, neg_peak_phase = 0; 657 int noise_margin = 20, time_margin = 89, jitter_var = 30; 658 int min_time_diff = 96, max_time_diff = 96 + time_margin; 659 bool fault = false, check_a = false, check_b = false; 660 int gain_idx = 0, pos_peak = 0, neg_peak = 0; 661 int pos_peak_time = 0, neg_peak_time = 0; 662 int pos_peak_in_phases_hybrid = 0; 663 int detect = -1; 664 665 gain_idx = access_ereg(phydev, PHYACC_ATTR_MODE_READ, 666 PHYACC_ATTR_BANK_DSP, 151, 0); 667 /* read non-hybrid results */ 668 pos_peak = access_ereg(phydev, PHYACC_ATTR_MODE_READ, 669 PHYACC_ATTR_BANK_DSP, 153, 0); 670 neg_peak = access_ereg(phydev, PHYACC_ATTR_MODE_READ, 671 PHYACC_ATTR_BANK_DSP, 154, 0); 672 pos_peak_time = access_ereg(phydev, PHYACC_ATTR_MODE_READ, 673 PHYACC_ATTR_BANK_DSP, 156, 0); 674 neg_peak_time = access_ereg(phydev, PHYACC_ATTR_MODE_READ, 675 PHYACC_ATTR_BANK_DSP, 157, 0); 676 677 pos_peak_cycle = (pos_peak_time >> 7) & 0x7F; 678 /* calculate non-hybrid values */ 679 pos_peak_phase = pos_peak_time & 0x7F; 680 pos_peak_in_phases = (pos_peak_cycle * 96) + pos_peak_phase; 681 neg_peak_cycle = (neg_peak_time >> 7) & 0x7F; 682 neg_peak_phase = neg_peak_time & 0x7F; 683 neg_peak_in_phases = (neg_peak_cycle * 96) + neg_peak_phase; 684 685 /* process values */ 686 check_a = 687 ((pos_peak_in_phases - neg_peak_in_phases) >= min_time_diff) && 688 ((pos_peak_in_phases - neg_peak_in_phases) < max_time_diff) && 689 pos_peak_in_phases_hybrid < pos_peak_in_phases && 690 (pos_peak_in_phases_hybrid < (neg_peak_in_phases + jitter_var)); 691 check_b = 692 ((neg_peak_in_phases - pos_peak_in_phases) >= min_time_diff) && 693 ((neg_peak_in_phases - pos_peak_in_phases) < max_time_diff) && 694 pos_peak_in_phases_hybrid < neg_peak_in_phases && 695 (pos_peak_in_phases_hybrid < (pos_peak_in_phases + jitter_var)); 696 697 if (pos_peak_in_phases > neg_peak_in_phases && check_a) 698 detect = 2; 699 else if ((neg_peak_in_phases > pos_peak_in_phases) && check_b) 700 detect = 1; 701 702 if (pos_peak > noise_margin && neg_peak > noise_margin && 703 gain_idx >= 0) { 704 if (detect == 1 || detect == 2) 705 fault = true; 706 } 707 708 if (!fault) 709 detect = 0; 710 711 ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A, 712 lan87xx_cable_test_report_trans(detect)); 713 714 return 0; 715 } 716 717 static int lan87xx_cable_test_get_status(struct phy_device *phydev, 718 bool *finished) 719 { 720 int rc = 0; 721 722 *finished = false; 723 724 /* check if cable diag was finished */ 725 rc = access_ereg(phydev, PHYACC_ATTR_MODE_READ, PHYACC_ATTR_BANK_DSP, 726 90, 0); 727 if (rc < 0) 728 return rc; 729 730 if ((rc & 2) == 2) { 731 /* stop cable diag*/ 732 rc = access_ereg(phydev, PHYACC_ATTR_MODE_WRITE, 733 PHYACC_ATTR_BANK_DSP, 734 90, 0); 735 if (rc < 0) 736 return rc; 737 738 *finished = true; 739 740 return lan87xx_cable_test_report(phydev); 741 } 742 743 return 0; 744 } 745 746 static int lan87xx_read_status(struct phy_device *phydev) 747 { 748 int rc = 0; 749 750 rc = phy_read(phydev, T1_MODE_STAT_REG); 751 if (rc < 0) 752 return rc; 753 754 if (rc & T1_LINK_UP_MSK) 755 phydev->link = 1; 756 else 757 phydev->link = 0; 758 759 phydev->speed = SPEED_UNKNOWN; 760 phydev->duplex = DUPLEX_UNKNOWN; 761 phydev->pause = 0; 762 phydev->asym_pause = 0; 763 764 rc = genphy_read_master_slave(phydev); 765 if (rc < 0) 766 return rc; 767 768 rc = genphy_read_status_fixed(phydev); 769 if (rc < 0) 770 return rc; 771 772 return rc; 773 } 774 775 static int lan87xx_config_aneg(struct phy_device *phydev) 776 { 777 u16 ctl = 0; 778 779 switch (phydev->master_slave_set) { 780 case MASTER_SLAVE_CFG_MASTER_FORCE: 781 ctl |= CTL1000_AS_MASTER; 782 break; 783 case MASTER_SLAVE_CFG_SLAVE_FORCE: 784 break; 785 case MASTER_SLAVE_CFG_UNKNOWN: 786 case MASTER_SLAVE_CFG_UNSUPPORTED: 787 return 0; 788 default: 789 phydev_warn(phydev, "Unsupported Master/Slave mode\n"); 790 return -EOPNOTSUPP; 791 } 792 793 return phy_modify_changed(phydev, MII_CTRL1000, CTL1000_AS_MASTER, ctl); 794 } 795 796 static int lan87xx_get_sqi(struct phy_device *phydev) 797 { 798 u8 sqi_value = 0; 799 int rc; 800 801 rc = access_ereg(phydev, PHYACC_ATTR_MODE_WRITE, 802 PHYACC_ATTR_BANK_DSP, T1_COEF_RW_CTL_CFG, 0x0301); 803 if (rc < 0) 804 return rc; 805 806 rc = access_ereg(phydev, PHYACC_ATTR_MODE_READ, 807 PHYACC_ATTR_BANK_DSP, T1_DCQ_SQI_REG, 0x0); 808 if (rc < 0) 809 return rc; 810 811 sqi_value = FIELD_GET(T1_DCQ_SQI_MSK, rc); 812 813 return sqi_value; 814 } 815 816 static int lan87xx_get_sqi_max(struct phy_device *phydev) 817 { 818 return LAN87XX_MAX_SQI; 819 } 820 821 static struct phy_driver microchip_t1_phy_driver[] = { 822 { 823 PHY_ID_MATCH_MODEL(PHY_ID_LAN87XX), 824 .name = "Microchip LAN87xx T1", 825 .flags = PHY_POLL_CABLE_TEST, 826 .features = PHY_BASIC_T1_FEATURES, 827 .config_init = lan87xx_config_init, 828 .config_intr = lan87xx_phy_config_intr, 829 .handle_interrupt = lan87xx_handle_interrupt, 830 .suspend = genphy_suspend, 831 .resume = genphy_resume, 832 .config_aneg = lan87xx_config_aneg, 833 .read_status = lan87xx_read_status, 834 .get_sqi = lan87xx_get_sqi, 835 .get_sqi_max = lan87xx_get_sqi_max, 836 .cable_test_start = lan87xx_cable_test_start, 837 .cable_test_get_status = lan87xx_cable_test_get_status, 838 }, 839 { 840 PHY_ID_MATCH_MODEL(PHY_ID_LAN937X), 841 .name = "Microchip LAN937x T1", 842 .flags = PHY_POLL_CABLE_TEST, 843 .features = PHY_BASIC_T1_FEATURES, 844 .config_init = lan87xx_config_init, 845 .config_intr = lan87xx_phy_config_intr, 846 .handle_interrupt = lan87xx_handle_interrupt, 847 .suspend = genphy_suspend, 848 .resume = genphy_resume, 849 .config_aneg = lan87xx_config_aneg, 850 .read_status = lan87xx_read_status, 851 .get_sqi = lan87xx_get_sqi, 852 .get_sqi_max = lan87xx_get_sqi_max, 853 .cable_test_start = lan87xx_cable_test_start, 854 .cable_test_get_status = lan87xx_cable_test_get_status, 855 } 856 }; 857 858 module_phy_driver(microchip_t1_phy_driver); 859 860 static struct mdio_device_id __maybe_unused microchip_t1_tbl[] = { 861 { PHY_ID_MATCH_MODEL(PHY_ID_LAN87XX) }, 862 { PHY_ID_MATCH_MODEL(PHY_ID_LAN937X) }, 863 { } 864 }; 865 866 MODULE_DEVICE_TABLE(mdio, microchip_t1_tbl); 867 868 MODULE_AUTHOR(DRIVER_AUTHOR); 869 MODULE_DESCRIPTION(DRIVER_DESC); 870 MODULE_LICENSE("GPL"); 871