1 // SPDX-License-Identifier: MIT 2 /* 3 * Microsemi PHY drivers 4 * 5 * 6 * Copyright (c) 2016 Microsemi Corporation 7 * 8 * Author: John Haechten 9 * 10 */ 11 12 #include <miiphy.h> 13 #include <bitfield.h> 14 #include <time.h> 15 #include <linux/delay.h> 16 17 /* Microsemi PHY ID's */ 18 #define PHY_ID_VSC8530 0x00070560 19 #define PHY_ID_VSC8531 0x00070570 20 #define PHY_ID_VSC8540 0x00070760 21 #define PHY_ID_VSC8541 0x00070770 22 #define PHY_ID_VSC8574 0x000704a0 23 #define PHY_ID_VSC8584 0x000707c0 24 25 /* Microsemi VSC85xx PHY Register Pages */ 26 #define MSCC_EXT_PAGE_ACCESS 31 /* Page Access Register */ 27 #define MSCC_PHY_PAGE_STD 0x0000 /* Standard registers */ 28 #define MSCC_PHY_PAGE_EXT1 0x0001 /* Extended registers - page 1 */ 29 #define MSCC_PHY_PAGE_EXT2 0x0002 /* Extended registers - page 2 */ 30 #define MSCC_PHY_PAGE_EXT3 0x0003 /* Extended registers - page 3 */ 31 #define MSCC_PHY_PAGE_EXT4 0x0004 /* Extended registers - page 4 */ 32 #define MSCC_PHY_PAGE_GPIO 0x0010 /* GPIO registers */ 33 #define MSCC_PHY_PAGE_TEST 0x2A30 /* TEST Page registers */ 34 #define MSCC_PHY_PAGE_TR 0x52B5 /* Token Ring Page registers */ 35 36 /* Std Page Register 18 */ 37 #define MSCC_PHY_BYPASS_CONTROL 18 38 #define PARALLEL_DET_IGNORE_ADVERTISED BIT(3) 39 40 /* Std Page Register 22 */ 41 #define MSCC_PHY_EXT_CNTL_STATUS 22 42 #define SMI_BROADCAST_WR_EN BIT(0) 43 44 /* Std Page Register 24 */ 45 #define MSCC_PHY_EXT_PHY_CNTL_2 24 46 47 /* Std Page Register 28 - PHY AUX Control/Status */ 48 #define MIIM_AUX_CNTRL_STAT_REG 28 49 #define MIIM_AUX_CNTRL_STAT_ACTIPHY_TO (0x0004) 50 #define MIIM_AUX_CNTRL_STAT_F_DUPLEX (0x0020) 51 #define MIIM_AUX_CNTRL_STAT_SPEED_MASK (0x0018) 52 #define MIIM_AUX_CNTRL_STAT_SPEED_POS (3) 53 #define MIIM_AUX_CNTRL_STAT_SPEED_10M (0x0) 54 #define MIIM_AUX_CNTRL_STAT_SPEED_100M (0x1) 55 #define MIIM_AUX_CNTRL_STAT_SPEED_1000M (0x2) 56 57 /* Std Page Register 23 - Extended PHY CTRL_1 */ 58 #define MSCC_PHY_EXT_PHY_CNTL_1_REG 23 59 #define MAC_IF_SELECTION_MASK (0x1800) 60 #define MAC_IF_SELECTION_GMII (0) 61 #define MAC_IF_SELECTION_RMII (1) 62 #define MAC_IF_SELECTION_RGMII (2) 63 #define MAC_IF_SELECTION_POS (11) 64 #define MAC_IF_SELECTION_WIDTH (2) 65 #define VSC8584_MAC_IF_SELECTION_MASK BIT(12) 66 #define VSC8584_MAC_IF_SELECTION_SGMII 0 67 #define VSC8584_MAC_IF_SELECTION_1000BASEX 1 68 #define VSC8584_MAC_IF_SELECTION_POS 12 69 #define MEDIA_OP_MODE_MASK GENMASK(10, 8) 70 #define MEDIA_OP_MODE_COPPER 0 71 #define MEDIA_OP_MODE_SERDES 1 72 #define MEDIA_OP_MODE_1000BASEX 2 73 #define MEDIA_OP_MODE_100BASEFX 3 74 #define MEDIA_OP_MODE_AMS_COPPER_SERDES 5 75 #define MEDIA_OP_MODE_AMS_COPPER_1000BASEX 6 76 #define MEDIA_OP_MODE_AMS_COPPER_100BASEFX 7 77 #define MEDIA_OP_MODE_POS 8 78 79 /* Extended Page 1 Register 20E1 */ 80 #define MSCC_PHY_ACTIPHY_CNTL 20 81 #define PHY_ADDR_REVERSED BIT(9) 82 83 /* Extended Page 1 Register 23E1 */ 84 85 #define MSCC_PHY_EXT_PHY_CNTL_4 23 86 #define PHY_CNTL_4_ADDR_POS 11 87 88 /* Extended Page 1 Register 25E1 */ 89 #define MSCC_PHY_VERIPHY_CNTL_2 25 90 91 /* Extended Page 1 Register 26E1 */ 92 #define MSCC_PHY_VERIPHY_CNTL_3 26 93 94 /* Extended Page 2 Register 16E2 */ 95 #define MSCC_PHY_CU_PMD_TX_CNTL 16 96 97 /* Extended Page 2 Register 20E2 */ 98 #define MSCC_PHY_RGMII_CNTL_REG 20 99 #define VSC_FAST_LINK_FAIL2_ENA_MASK (0x8000) 100 #define RX_CLK_OUT_MASK (0x0800) 101 #define RX_CLK_OUT_POS (11) 102 #define RX_CLK_OUT_WIDTH (1) 103 #define RX_CLK_OUT_NORMAL (0) 104 #define RX_CLK_OUT_DISABLE (1) 105 #define RGMII_RX_CLK_DELAY_POS (4) 106 #define RGMII_RX_CLK_DELAY_WIDTH (3) 107 #define RGMII_RX_CLK_DELAY_MASK (0x0070) 108 #define RGMII_TX_CLK_DELAY_POS (0) 109 #define RGMII_TX_CLK_DELAY_WIDTH (3) 110 #define RGMII_TX_CLK_DELAY_MASK (0x0007) 111 112 /* Extended Page 2 Register 27E2 */ 113 #define MSCC_PHY_WOL_MAC_CONTROL 27 114 #define EDGE_RATE_CNTL_POS (5) 115 #define EDGE_RATE_CNTL_WIDTH (3) 116 #define EDGE_RATE_CNTL_MASK (0x00E0) 117 #define RMII_CLK_OUT_ENABLE_POS (4) 118 #define RMII_CLK_OUT_ENABLE_WIDTH (1) 119 #define RMII_CLK_OUT_ENABLE_MASK (0x10) 120 121 /* Extended Page 3 Register 22E3 */ 122 #define MSCC_PHY_SERDES_TX_CRC_ERR_CNT 22 123 124 /* Extended page GPIO register 00G */ 125 #define MSCC_DW8051_CNTL_STATUS 0 126 #define MICRO_NSOFT_RESET BIT(15) 127 #define RUN_FROM_INT_ROM BIT(14) 128 #define AUTOINC_ADDR BIT(13) 129 #define PATCH_RAM_CLK BIT(12) 130 #define MICRO_PATCH_EN BIT(7) 131 #define DW8051_CLK_EN BIT(4) 132 #define MICRO_CLK_EN BIT(3) 133 #define MICRO_CLK_DIVIDE(x) ((x) >> 1) 134 #define MSCC_DW8051_VLD_MASK 0xf1ff 135 136 /* Extended page GPIO register 09G */ 137 #define MSCC_TRAP_ROM_ADDR(x) ((x) * 2 + 1) 138 #define MSCC_TRAP_ROM_ADDR_SERDES_INIT 0x3eb7 139 140 /* Extended page GPIO register 10G */ 141 #define MSCC_PATCH_RAM_ADDR(x) (((x) + 1) * 2) 142 #define MSCC_PATCH_RAM_ADDR_SERDES_INIT 0x4012 143 144 /* Extended page GPIO register 11G */ 145 #define MSCC_INT_MEM_ADDR 11 146 147 /* Extended page GPIO register 12G */ 148 #define MSCC_INT_MEM_CNTL 12 149 #define READ_SFR (BIT(14) | BIT(13)) 150 #define READ_PRAM BIT(14) 151 #define READ_ROM BIT(13) 152 #define READ_RAM (0x00 << 13) 153 #define INT_MEM_WRITE_EN BIT(12) 154 #define EN_PATCH_RAM_TRAP_ADDR(x) BIT((x) + 7) 155 #define INT_MEM_DATA_M GENMASK(7, 0) 156 #define INT_MEM_DATA(x) (INT_MEM_DATA_M & (x)) 157 158 /* Extended page GPIO register 18G */ 159 #define MSCC_PHY_PROC_CMD 18 160 #define PROC_CMD_NCOMPLETED BIT(15) 161 #define PROC_CMD_FAILED BIT(14) 162 #define PROC_CMD_SGMII_PORT(x) ((x) << 8) 163 #define PROC_CMD_FIBER_PORT(x) BIT(8 + (x) % 4) 164 #define PROC_CMD_QSGMII_PORT (BIT(11) | BIT(10)) 165 #define PROC_CMD_RST_CONF_PORT BIT(7) 166 #define PROC_CMD_RECONF_PORT (0 << 7) 167 #define PROC_CMD_READ_MOD_WRITE_PORT BIT(6) 168 #define PROC_CMD_WRITE BIT(6) 169 #define PROC_CMD_READ (0 << 6) 170 #define PROC_CMD_FIBER_DISABLE BIT(5) 171 #define PROC_CMD_FIBER_100BASE_FX BIT(4) 172 #define PROC_CMD_FIBER_1000BASE_X (0 << 4) 173 #define PROC_CMD_SGMII_MAC (BIT(5) | BIT(4)) 174 #define PROC_CMD_QSGMII_MAC BIT(5) 175 #define PROC_CMD_NO_MAC_CONF (0x00 << 4) 176 #define PROC_CMD_1588_DEFAULT_INIT BIT(4) 177 #define PROC_CMD_NOP GENMASK(3, 0) 178 #define PROC_CMD_PHY_INIT (BIT(3) | BIT(1)) 179 #define PROC_CMD_CRC16 BIT(3) 180 #define PROC_CMD_FIBER_MEDIA_CONF BIT(0) 181 #define PROC_CMD_MCB_ACCESS_MAC_CONF (0x0000 << 0) 182 #define PROC_CMD_NCOMPLETED_TIMEOUT_MS 500 183 184 /* Extended page GPIO register 19G */ 185 #define MSCC_PHY_MAC_CFG_FASTLINK 19 186 #define MAC_CFG_MASK GENMASK(15, 14) 187 #define MAC_CFG_SGMII (0x00 << 14) 188 #define MAC_CFG_QSGMII BIT(14) 189 190 /* Test Registers */ 191 #define MSCC_PHY_TEST_PAGE_5 5 192 193 #define MSCC_PHY_TEST_PAGE_8 8 194 #define TR_CLK_DISABLE BIT(15) 195 196 #define MSCC_PHY_TEST_PAGE_9 9 197 #define MSCC_PHY_TEST_PAGE_20 20 198 #define MSCC_PHY_TEST_PAGE_24 24 199 200 /* Token Ring Page 0x52B5 Registers */ 201 #define MSCC_PHY_REG_TR_ADDR_16 16 202 #define MSCC_PHY_REG_TR_DATA_17 17 203 #define MSCC_PHY_REG_TR_DATA_18 18 204 205 /* Token Ring - Read Value in */ 206 #define MSCC_PHY_TR_16_READ (0xA000) 207 /* Token Ring - Write Value out */ 208 #define MSCC_PHY_TR_16_WRITE (0x8000) 209 210 /* Token Ring Registers */ 211 #define MSCC_PHY_TR_LINKDETCTRL_POS (3) 212 #define MSCC_PHY_TR_LINKDETCTRL_WIDTH (2) 213 #define MSCC_PHY_TR_LINKDETCTRL_VAL (3) 214 #define MSCC_PHY_TR_LINKDETCTRL_MASK (0x0018) 215 #define MSCC_PHY_TR_LINKDETCTRL_ADDR (0x07F8) 216 217 #define MSCC_PHY_TR_VGATHRESH100_POS (0) 218 #define MSCC_PHY_TR_VGATHRESH100_WIDTH (7) 219 #define MSCC_PHY_TR_VGATHRESH100_VAL (0x0018) 220 #define MSCC_PHY_TR_VGATHRESH100_MASK (0x007f) 221 #define MSCC_PHY_TR_VGATHRESH100_ADDR (0x0FA4) 222 223 #define MSCC_PHY_TR_VGAGAIN10_U_POS (0) 224 #define MSCC_PHY_TR_VGAGAIN10_U_WIDTH (1) 225 #define MSCC_PHY_TR_VGAGAIN10_U_MASK (0x0001) 226 #define MSCC_PHY_TR_VGAGAIN10_U_VAL (0) 227 228 #define MSCC_PHY_TR_VGAGAIN10_L_POS (12) 229 #define MSCC_PHY_TR_VGAGAIN10_L_WIDTH (4) 230 #define MSCC_PHY_TR_VGAGAIN10_L_MASK (0xf000) 231 #define MSCC_PHY_TR_VGAGAIN10_L_VAL (0x0001) 232 #define MSCC_PHY_TR_VGAGAIN10_ADDR (0x0F92) 233 234 /* General Timeout Values */ 235 #define MSCC_PHY_RESET_TIMEOUT (100) 236 #define MSCC_PHY_MICRO_TIMEOUT (500) 237 238 #define VSC8584_REVB 0x0001 239 #define MSCC_DEV_REV_MASK GENMASK(3, 0) 240 241 #define MSCC_VSC8574_REVB_INT8051_FW_START_ADDR 0x4000 242 #define MSCC_VSC8574_REVB_INT8051_FW_CRC 0x29e8 243 244 #define MSCC_VSC8584_REVB_INT8051_FW_START_ADDR 0xe800 245 #define MSCC_VSC8584_REVB_INT8051_FW_CRC 0xfb48 246 247 /* RGMII/GMII Clock Delay (Skew) Options */ enum vsc_phy_rgmii_skew { 248 VSC_PHY_RGMII_DELAY_200_PS, 249 VSC_PHY_RGMII_DELAY_800_PS, 250 VSC_PHY_RGMII_DELAY_1100_PS, 251 VSC_PHY_RGMII_DELAY_1700_PS, 252 VSC_PHY_RGMII_DELAY_2000_PS, 253 VSC_PHY_RGMII_DELAY_2300_PS, 254 VSC_PHY_RGMII_DELAY_2600_PS, 255 VSC_PHY_RGMII_DELAY_3400_PS, 256 }; 257 258 /* MAC i/f Clock Edge Rage Control (Slew), See Reg27E2 */ enum 259 vsc_phy_clk_slew { 260 VSC_PHY_CLK_SLEW_RATE_0, 261 VSC_PHY_CLK_SLEW_RATE_1, 262 VSC_PHY_CLK_SLEW_RATE_2, 263 VSC_PHY_CLK_SLEW_RATE_3, 264 VSC_PHY_CLK_SLEW_RATE_4, 265 VSC_PHY_CLK_SLEW_RATE_5, 266 VSC_PHY_CLK_SLEW_RATE_6, 267 VSC_PHY_CLK_SLEW_RATE_7, 268 }; 269 270 struct vsc85xx_priv { 271 int (*config_pre)(struct phy_device *phydev); 272 }; 273 274 static void vsc8584_csr_write(struct mii_dev *bus, int phy0, u16 addr, u32 val) 275 { 276 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18, 277 val >> 16); 278 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17, 279 val & GENMASK(15, 0)); 280 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16, 281 MSCC_PHY_TR_16_WRITE | addr); 282 } 283 284 static int vsc8584_cmd(struct mii_dev *bus, int phy, u16 val) 285 { 286 unsigned long deadline; 287 u16 reg_val; 288 289 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, 290 MSCC_PHY_PAGE_GPIO); 291 292 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_PROC_CMD, 293 PROC_CMD_NCOMPLETED | val); 294 295 deadline = timer_get_us() + PROC_CMD_NCOMPLETED_TIMEOUT_MS * 1000; 296 do { 297 reg_val = bus->read(bus, phy, MDIO_DEVAD_NONE, 298 MSCC_PHY_PROC_CMD); 299 } while (timer_get_us() <= deadline && 300 (reg_val & PROC_CMD_NCOMPLETED) && 301 !(reg_val & PROC_CMD_FAILED)); 302 303 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, 304 MSCC_PHY_PAGE_STD); 305 306 if (reg_val & PROC_CMD_FAILED) 307 return -EIO; 308 if (reg_val & PROC_CMD_NCOMPLETED) 309 return -ETIMEDOUT; 310 311 return 0; 312 } 313 314 static int vsc8584_micro_deassert_reset(struct mii_dev *bus, int phy, 315 bool patch_en) 316 { 317 u32 enable, release; 318 319 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, 320 MSCC_PHY_PAGE_GPIO); 321 322 enable = RUN_FROM_INT_ROM | MICRO_CLK_EN | DW8051_CLK_EN; 323 release = MICRO_NSOFT_RESET | RUN_FROM_INT_ROM | DW8051_CLK_EN | 324 MICRO_CLK_EN; 325 326 if (patch_en) { 327 enable |= MICRO_PATCH_EN; 328 release |= MICRO_PATCH_EN; 329 330 /* Clear all patches */ 331 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL, 332 READ_RAM); 333 } 334 335 /* 336 * Enable 8051 Micro clock; CLEAR/SET patch present; disable PRAM clock 337 * override and addr. auto-incr; operate at 125 MHz 338 */ 339 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_DW8051_CNTL_STATUS, enable); 340 /* Release 8051 Micro SW reset */ 341 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_DW8051_CNTL_STATUS, release); 342 343 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, 344 MSCC_PHY_PAGE_STD); 345 346 return 0; 347 } 348 349 static int vsc8584_micro_assert_reset(struct mii_dev *bus, int phy) 350 { 351 int ret; 352 u16 reg; 353 354 ret = vsc8584_cmd(bus, phy, PROC_CMD_NOP); 355 if (ret) 356 return ret; 357 358 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, 359 MSCC_PHY_PAGE_GPIO); 360 361 reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL); 362 reg &= ~EN_PATCH_RAM_TRAP_ADDR(4); 363 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL, reg); 364 365 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_TRAP_ROM_ADDR(4), 0x005b); 366 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_PATCH_RAM_ADDR(4), 0x005b); 367 368 reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL); 369 reg |= EN_PATCH_RAM_TRAP_ADDR(4); 370 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL, reg); 371 372 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_PROC_CMD, PROC_CMD_NOP); 373 374 reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_DW8051_CNTL_STATUS); 375 reg &= ~MICRO_NSOFT_RESET; 376 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_DW8051_CNTL_STATUS, reg); 377 378 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_PROC_CMD, 379 PROC_CMD_MCB_ACCESS_MAC_CONF | PROC_CMD_SGMII_PORT(0) | 380 PROC_CMD_NO_MAC_CONF | PROC_CMD_READ); 381 382 reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL); 383 reg &= ~EN_PATCH_RAM_TRAP_ADDR(4); 384 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL, reg); 385 386 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, 387 MSCC_PHY_PAGE_STD); 388 389 return 0; 390 } 391 392 static const u8 fw_patch_vsc8574[] = { 393 0x46, 0x4a, 0x02, 0x43, 0x37, 0x02, 0x46, 0x26, 0x02, 0x46, 0x77, 0x02, 394 0x45, 0x60, 0x02, 0x45, 0xaf, 0xed, 0xff, 0xe5, 0xfc, 0x54, 0x38, 0x64, 395 0x20, 0x70, 0x08, 0x65, 0xff, 0x70, 0x04, 0xed, 0x44, 0x80, 0xff, 0x22, 396 0x8f, 0x19, 0x7b, 0xbb, 0x7d, 0x0e, 0x7f, 0x04, 0x12, 0x3d, 0xd7, 0xef, 397 0x4e, 0x60, 0x03, 0x02, 0x41, 0xf9, 0xe4, 0xf5, 0x1a, 0x74, 0x01, 0x7e, 398 0x00, 0xa8, 0x1a, 0x08, 0x80, 0x05, 0xc3, 0x33, 0xce, 0x33, 0xce, 0xd8, 399 0xf9, 0xff, 0xef, 0x55, 0x19, 0x70, 0x03, 0x02, 0x41, 0xed, 0x85, 0x1a, 400 0xfb, 0x7b, 0xbb, 0xe4, 0xfd, 0xff, 0x12, 0x3d, 0xd7, 0xef, 0x4e, 0x60, 401 0x03, 0x02, 0x41, 0xed, 0xe5, 0x1a, 0x54, 0x02, 0x75, 0x1d, 0x00, 0x25, 402 0xe0, 0x25, 0xe0, 0xf5, 0x1c, 0xe4, 0x78, 0xc5, 0xf6, 0xd2, 0x0a, 0x12, 403 0x41, 0xfa, 0x7b, 0xff, 0x7d, 0x12, 0x7f, 0x07, 0x12, 0x3d, 0xd7, 0xef, 404 0x4e, 0x60, 0x03, 0x02, 0x41, 0xe7, 0xc2, 0x0a, 0x74, 0xc7, 0x25, 0x1a, 405 0xf9, 0x74, 0xe7, 0x25, 0x1a, 0xf8, 0xe6, 0x27, 0xf5, 0x1b, 0xe5, 0x1d, 406 0x24, 0x5b, 0x12, 0x45, 0xea, 0x12, 0x3e, 0xda, 0x7b, 0xfc, 0x7d, 0x11, 407 0x7f, 0x07, 0x12, 0x3d, 0xd7, 0x78, 0xcc, 0xef, 0xf6, 0x78, 0xc1, 0xe6, 408 0xfe, 0xef, 0xd3, 0x9e, 0x40, 0x06, 0x78, 0xcc, 0xe6, 0x78, 0xc1, 0xf6, 409 0x12, 0x41, 0xfa, 0x7b, 0xec, 0x7d, 0x12, 0x7f, 0x07, 0x12, 0x3d, 0xd7, 410 0x78, 0xcb, 0xef, 0xf6, 0xbf, 0x07, 0x06, 0x78, 0xc3, 0x76, 0x1a, 0x80, 411 0x1f, 0x78, 0xc5, 0xe6, 0xff, 0x60, 0x0f, 0xc3, 0xe5, 0x1b, 0x9f, 0xff, 412 0x78, 0xcb, 0xe6, 0x85, 0x1b, 0xf0, 0xa4, 0x2f, 0x80, 0x07, 0x78, 0xcb, 413 0xe6, 0x85, 0x1b, 0xf0, 0xa4, 0x78, 0xc3, 0xf6, 0xe4, 0x78, 0xc2, 0xf6, 414 0x78, 0xc2, 0xe6, 0xff, 0xc3, 0x08, 0x96, 0x40, 0x03, 0x02, 0x41, 0xd1, 415 0xef, 0x54, 0x03, 0x60, 0x33, 0x14, 0x60, 0x46, 0x24, 0xfe, 0x60, 0x42, 416 0x04, 0x70, 0x4b, 0xef, 0x24, 0x02, 0xff, 0xe4, 0x33, 0xfe, 0xef, 0x78, 417 0x02, 0xce, 0xa2, 0xe7, 0x13, 0xce, 0x13, 0xd8, 0xf8, 0xff, 0xe5, 0x1d, 418 0x24, 0x5c, 0xcd, 0xe5, 0x1c, 0x34, 0xf0, 0xcd, 0x2f, 0xff, 0xed, 0x3e, 419 0xfe, 0x12, 0x46, 0x0d, 0x7d, 0x11, 0x80, 0x0b, 0x78, 0xc2, 0xe6, 0x70, 420 0x04, 0x7d, 0x11, 0x80, 0x02, 0x7d, 0x12, 0x7f, 0x07, 0x12, 0x3e, 0x9a, 421 0x8e, 0x1e, 0x8f, 0x1f, 0x80, 0x03, 0xe5, 0x1e, 0xff, 0x78, 0xc5, 0xe6, 422 0x06, 0x24, 0xcd, 0xf8, 0xa6, 0x07, 0x78, 0xc2, 0x06, 0xe6, 0xb4, 0x1a, 423 0x0a, 0xe5, 0x1d, 0x24, 0x5c, 0x12, 0x45, 0xea, 0x12, 0x3e, 0xda, 0x78, 424 0xc5, 0xe6, 0x65, 0x1b, 0x70, 0x82, 0x75, 0xdb, 0x20, 0x75, 0xdb, 0x28, 425 0x12, 0x46, 0x02, 0x12, 0x46, 0x02, 0xe5, 0x1a, 0x12, 0x45, 0xf5, 0xe5, 426 0x1a, 0xc3, 0x13, 0x12, 0x45, 0xf5, 0x78, 0xc5, 0x16, 0xe6, 0x24, 0xcd, 427 0xf8, 0xe6, 0xff, 0x7e, 0x08, 0x1e, 0xef, 0xa8, 0x06, 0x08, 0x80, 0x02, 428 0xc3, 0x13, 0xd8, 0xfc, 0xfd, 0xc4, 0x33, 0x54, 0xe0, 0xf5, 0xdb, 0xef, 429 0xa8, 0x06, 0x08, 0x80, 0x02, 0xc3, 0x13, 0xd8, 0xfc, 0xfd, 0xc4, 0x33, 430 0x54, 0xe0, 0x44, 0x08, 0xf5, 0xdb, 0xee, 0x70, 0xd8, 0x78, 0xc5, 0xe6, 431 0x70, 0xc8, 0x75, 0xdb, 0x10, 0x02, 0x40, 0xfd, 0x78, 0xc2, 0xe6, 0xc3, 432 0x94, 0x17, 0x50, 0x0e, 0xe5, 0x1d, 0x24, 0x62, 0x12, 0x42, 0x08, 0xe5, 433 0x1d, 0x24, 0x5c, 0x12, 0x42, 0x08, 0x20, 0x0a, 0x03, 0x02, 0x40, 0x76, 434 0x05, 0x1a, 0xe5, 0x1a, 0xc3, 0x94, 0x04, 0x50, 0x03, 0x02, 0x40, 0x3a, 435 0x22, 0xe5, 0x1d, 0x24, 0x5c, 0xff, 0xe5, 0x1c, 0x34, 0xf0, 0xfe, 0x12, 436 0x46, 0x0d, 0x22, 0xff, 0xe5, 0x1c, 0x34, 0xf0, 0xfe, 0x12, 0x46, 0x0d, 437 0x22, 0xe4, 0xf5, 0x19, 0x12, 0x46, 0x43, 0x20, 0xe7, 0x1e, 0x7b, 0xfe, 438 0x12, 0x42, 0xf9, 0xef, 0xc4, 0x33, 0x33, 0x54, 0xc0, 0xff, 0xc0, 0x07, 439 0x7b, 0x54, 0x12, 0x42, 0xf9, 0xd0, 0xe0, 0x4f, 0xff, 0x74, 0x2a, 0x25, 440 0x19, 0xf8, 0xa6, 0x07, 0x12, 0x46, 0x43, 0x20, 0xe7, 0x03, 0x02, 0x42, 441 0xdf, 0x54, 0x03, 0x64, 0x03, 0x70, 0x03, 0x02, 0x42, 0xcf, 0x7b, 0xcb, 442 0x12, 0x43, 0x2c, 0x8f, 0xfb, 0x7b, 0x30, 0x7d, 0x03, 0xe4, 0xff, 0x12, 443 0x3d, 0xd7, 0xc3, 0xef, 0x94, 0x02, 0xee, 0x94, 0x00, 0x50, 0x2a, 0x12, 444 0x42, 0xec, 0xef, 0x4e, 0x70, 0x23, 0x12, 0x43, 0x04, 0x60, 0x0a, 0x12, 445 0x43, 0x12, 0x70, 0x0c, 0x12, 0x43, 0x1f, 0x70, 0x07, 0x12, 0x46, 0x39, 446 0x7b, 0x03, 0x80, 0x07, 0x12, 0x46, 0x39, 0x12, 0x46, 0x43, 0xfb, 0x7a, 447 0x00, 0x7d, 0x54, 0x80, 0x3e, 0x12, 0x42, 0xec, 0xef, 0x4e, 0x70, 0x24, 448 0x12, 0x43, 0x04, 0x60, 0x0a, 0x12, 0x43, 0x12, 0x70, 0x0f, 0x12, 0x43, 449 0x1f, 0x70, 0x0a, 0x12, 0x46, 0x39, 0xe4, 0xfb, 0xfa, 0x7d, 0xee, 0x80, 450 0x1e, 0x12, 0x46, 0x39, 0x7b, 0x01, 0x7a, 0x00, 0x7d, 0xee, 0x80, 0x13, 451 0x12, 0x46, 0x39, 0x12, 0x46, 0x43, 0x54, 0x40, 0xfe, 0xc4, 0x13, 0x13, 452 0x54, 0x03, 0xfb, 0x7a, 0x00, 0x7d, 0xee, 0x12, 0x38, 0xbd, 0x7b, 0xff, 453 0x12, 0x43, 0x2c, 0xef, 0x4e, 0x70, 0x07, 0x74, 0x2a, 0x25, 0x19, 0xf8, 454 0xe4, 0xf6, 0x05, 0x19, 0xe5, 0x19, 0xc3, 0x94, 0x02, 0x50, 0x03, 0x02, 455 0x42, 0x15, 0x22, 0xe5, 0x19, 0x24, 0x17, 0xfd, 0x7b, 0x20, 0x7f, 0x04, 456 0x12, 0x3d, 0xd7, 0x22, 0xe5, 0x19, 0x24, 0x17, 0xfd, 0x7f, 0x04, 0x12, 457 0x3d, 0xd7, 0x22, 0x7b, 0x22, 0x7d, 0x18, 0x7f, 0x06, 0x12, 0x3d, 0xd7, 458 0xef, 0x64, 0x01, 0x4e, 0x22, 0x7d, 0x1c, 0xe4, 0xff, 0x12, 0x3e, 0x9a, 459 0xef, 0x54, 0x1b, 0x64, 0x0a, 0x22, 0x7b, 0xcc, 0x7d, 0x10, 0xff, 0x12, 460 0x3d, 0xd7, 0xef, 0x64, 0x01, 0x4e, 0x22, 0xe5, 0x19, 0x24, 0x17, 0xfd, 461 0x7f, 0x04, 0x12, 0x3d, 0xd7, 0x22, 0xd2, 0x08, 0x75, 0xfb, 0x03, 0xab, 462 0x7e, 0xaa, 0x7d, 0x7d, 0x19, 0x7f, 0x03, 0x12, 0x3e, 0xda, 0xe5, 0x7e, 463 0x54, 0x0f, 0x24, 0xf3, 0x60, 0x03, 0x02, 0x43, 0xe9, 0x12, 0x46, 0x5a, 464 0x12, 0x46, 0x61, 0xd8, 0xfb, 0xff, 0x20, 0xe2, 0x35, 0x13, 0x92, 0x0c, 465 0xef, 0xa2, 0xe1, 0x92, 0x0b, 0x30, 0x0c, 0x2a, 0xe4, 0xf5, 0x10, 0x7b, 466 0xfe, 0x12, 0x43, 0xff, 0xef, 0xc4, 0x33, 0x33, 0x54, 0xc0, 0xff, 0xc0, 467 0x07, 0x7b, 0x54, 0x12, 0x43, 0xff, 0xd0, 0xe0, 0x4f, 0xff, 0x74, 0x2a, 468 0x25, 0x10, 0xf8, 0xa6, 0x07, 0x05, 0x10, 0xe5, 0x10, 0xc3, 0x94, 0x02, 469 0x40, 0xd9, 0x12, 0x46, 0x5a, 0x12, 0x46, 0x61, 0xd8, 0xfb, 0x54, 0x05, 470 0x64, 0x04, 0x70, 0x27, 0x78, 0xc4, 0xe6, 0x78, 0xc6, 0xf6, 0xe5, 0x7d, 471 0xff, 0x33, 0x95, 0xe0, 0xef, 0x54, 0x0f, 0x78, 0xc4, 0xf6, 0x12, 0x44, 472 0x0a, 0x20, 0x0c, 0x0c, 0x12, 0x46, 0x5a, 0x12, 0x46, 0x61, 0xd8, 0xfb, 473 0x13, 0x92, 0x0d, 0x22, 0xc2, 0x0d, 0x22, 0x12, 0x46, 0x5a, 0x12, 0x46, 474 0x61, 0xd8, 0xfb, 0x54, 0x05, 0x64, 0x05, 0x70, 0x1e, 0x78, 0xc4, 0x7d, 475 0xb8, 0x12, 0x43, 0xf5, 0x78, 0xc1, 0x7d, 0x74, 0x12, 0x43, 0xf5, 0xe4, 476 0x78, 0xc1, 0xf6, 0x22, 0x7b, 0x01, 0x7a, 0x00, 0x7d, 0xee, 0x7f, 0x92, 477 0x12, 0x38, 0xbd, 0x22, 0xe6, 0xfb, 0x7a, 0x00, 0x7f, 0x92, 0x12, 0x38, 478 0xbd, 0x22, 0xe5, 0x10, 0x24, 0x17, 0xfd, 0x7f, 0x04, 0x12, 0x3d, 0xd7, 479 0x22, 0x78, 0xc1, 0xe6, 0xfb, 0x7a, 0x00, 0x7d, 0x74, 0x7f, 0x92, 0x12, 480 0x38, 0xbd, 0xe4, 0x78, 0xc1, 0xf6, 0xf5, 0x11, 0x74, 0x01, 0x7e, 0x00, 481 0xa8, 0x11, 0x08, 0x80, 0x05, 0xc3, 0x33, 0xce, 0x33, 0xce, 0xd8, 0xf9, 482 0xff, 0x78, 0xc4, 0xe6, 0xfd, 0xef, 0x5d, 0x60, 0x44, 0x85, 0x11, 0xfb, 483 0xe5, 0x11, 0x54, 0x02, 0x25, 0xe0, 0x25, 0xe0, 0xfe, 0xe4, 0x24, 0x5b, 484 0xfb, 0xee, 0x12, 0x45, 0xed, 0x12, 0x3e, 0xda, 0x7b, 0x40, 0x7d, 0x11, 485 0x7f, 0x07, 0x12, 0x3d, 0xd7, 0x74, 0xc7, 0x25, 0x11, 0xf8, 0xa6, 0x07, 486 0x7b, 0x11, 0x7d, 0x12, 0x7f, 0x07, 0x12, 0x3d, 0xd7, 0xef, 0x4e, 0x60, 487 0x09, 0x74, 0xe7, 0x25, 0x11, 0xf8, 0x76, 0x04, 0x80, 0x07, 0x74, 0xe7, 488 0x25, 0x11, 0xf8, 0x76, 0x0a, 0x05, 0x11, 0xe5, 0x11, 0xc3, 0x94, 0x04, 489 0x40, 0x9a, 0x78, 0xc6, 0xe6, 0x70, 0x15, 0x78, 0xc4, 0xe6, 0x60, 0x10, 490 0x75, 0xd9, 0x38, 0x75, 0xdb, 0x10, 0x7d, 0xfe, 0x12, 0x44, 0xb8, 0x7d, 491 0x76, 0x12, 0x44, 0xb8, 0x79, 0xc6, 0xe7, 0x78, 0xc4, 0x66, 0xff, 0x60, 492 0x03, 0x12, 0x40, 0x25, 0x78, 0xc4, 0xe6, 0x70, 0x09, 0xfb, 0xfa, 0x7d, 493 0xfe, 0x7f, 0x8e, 0x12, 0x38, 0xbd, 0x22, 0x7b, 0x01, 0x7a, 0x00, 0x7f, 494 0x8e, 0x12, 0x38, 0xbd, 0x22, 0xe4, 0xf5, 0xfb, 0x7d, 0x1c, 0xe4, 0xff, 495 0x12, 0x3e, 0x9a, 0xad, 0x07, 0xac, 0x06, 0xec, 0x54, 0xc0, 0xff, 0xed, 496 0x54, 0x3f, 0x4f, 0xf5, 0x20, 0x30, 0x06, 0x2c, 0x30, 0x01, 0x08, 0xa2, 497 0x04, 0x72, 0x03, 0x92, 0x07, 0x80, 0x21, 0x30, 0x04, 0x06, 0x7b, 0xcc, 498 0x7d, 0x11, 0x80, 0x0d, 0x30, 0x03, 0x06, 0x7b, 0xcc, 0x7d, 0x10, 0x80, 499 0x04, 0x7b, 0x66, 0x7d, 0x16, 0xe4, 0xff, 0x12, 0x3d, 0xd7, 0xee, 0x4f, 500 0x24, 0xff, 0x92, 0x07, 0xaf, 0xfb, 0x74, 0x26, 0x2f, 0xf8, 0xe6, 0xff, 501 0xa6, 0x20, 0x20, 0x07, 0x39, 0x8f, 0x20, 0x30, 0x07, 0x34, 0x30, 0x00, 502 0x31, 0x20, 0x04, 0x2e, 0x20, 0x03, 0x2b, 0xe4, 0xf5, 0xff, 0x75, 0xfc, 503 0xc2, 0xe5, 0xfc, 0x30, 0xe0, 0xfb, 0xaf, 0xfe, 0xef, 0x20, 0xe3, 0x1a, 504 0xae, 0xfd, 0x44, 0x08, 0xf5, 0xfe, 0x75, 0xfc, 0x80, 0xe5, 0xfc, 0x30, 505 0xe0, 0xfb, 0x8f, 0xfe, 0x8e, 0xfd, 0x75, 0xfc, 0x80, 0xe5, 0xfc, 0x30, 506 0xe0, 0xfb, 0x05, 0xfb, 0xaf, 0xfb, 0xef, 0xc3, 0x94, 0x04, 0x50, 0x03, 507 0x02, 0x44, 0xc5, 0xe4, 0xf5, 0xfb, 0x22, 0xe5, 0x7e, 0x54, 0x0f, 0x64, 508 0x01, 0x70, 0x23, 0xe5, 0x7e, 0x30, 0xe4, 0x1e, 0x90, 0x47, 0xd0, 0xe0, 509 0x44, 0x02, 0xf0, 0x54, 0xfb, 0xf0, 0x90, 0x47, 0xd4, 0xe0, 0x44, 0x04, 510 0xf0, 0x7b, 0x03, 0x7d, 0x5b, 0x7f, 0x5d, 0x12, 0x36, 0x29, 0x7b, 0x0e, 511 0x80, 0x1c, 0x90, 0x47, 0xd0, 0xe0, 0x54, 0xfd, 0xf0, 0x44, 0x04, 0xf0, 512 0x90, 0x47, 0xd4, 0xe0, 0x54, 0xfb, 0xf0, 0x7b, 0x02, 0x7d, 0x5b, 0x7f, 513 0x5d, 0x12, 0x36, 0x29, 0x7b, 0x06, 0x7d, 0x60, 0x7f, 0x63, 0x12, 0x36, 514 0x29, 0x22, 0xe5, 0x7e, 0x30, 0xe5, 0x35, 0x30, 0xe4, 0x0b, 0x7b, 0x02, 515 0x7d, 0x33, 0x7f, 0x35, 0x12, 0x36, 0x29, 0x80, 0x10, 0x7b, 0x01, 0x7d, 516 0x33, 0x7f, 0x35, 0x12, 0x36, 0x29, 0x90, 0x47, 0xd2, 0xe0, 0x44, 0x04, 517 0xf0, 0x90, 0x47, 0xd2, 0xe0, 0x54, 0xf7, 0xf0, 0x90, 0x47, 0xd1, 0xe0, 518 0x44, 0x10, 0xf0, 0x7b, 0x05, 0x7d, 0x84, 0x7f, 0x86, 0x12, 0x36, 0x29, 519 0x22, 0xfb, 0xe5, 0x1c, 0x34, 0xf0, 0xfa, 0x7d, 0x10, 0x7f, 0x07, 0x22, 520 0x54, 0x01, 0xc4, 0x33, 0x54, 0xe0, 0xf5, 0xdb, 0x44, 0x08, 0xf5, 0xdb, 521 0x22, 0xf5, 0xdb, 0x75, 0xdb, 0x08, 0xf5, 0xdb, 0x75, 0xdb, 0x08, 0x22, 522 0xab, 0x07, 0xaa, 0x06, 0x7d, 0x10, 0x7f, 0x07, 0x12, 0x3e, 0xda, 0x7b, 523 0xff, 0x7d, 0x10, 0x7f, 0x07, 0x12, 0x3d, 0xd7, 0xef, 0x4e, 0x60, 0xf3, 524 0x22, 0x12, 0x44, 0xc2, 0x30, 0x0c, 0x03, 0x12, 0x42, 0x12, 0x78, 0xc4, 525 0xe6, 0xff, 0x60, 0x03, 0x12, 0x40, 0x25, 0x22, 0xe5, 0x19, 0x24, 0x17, 526 0x54, 0x1f, 0x44, 0x80, 0xff, 0x22, 0x74, 0x2a, 0x25, 0x19, 0xf8, 0xe6, 527 0x22, 0x12, 0x46, 0x72, 0x12, 0x46, 0x68, 0x90, 0x47, 0xfa, 0xe0, 0x54, 528 0xf8, 0x44, 0x02, 0xf0, 0x22, 0xe5, 0x7e, 0xae, 0x7d, 0x78, 0x04, 0x22, 529 0xce, 0xa2, 0xe7, 0x13, 0xce, 0x13, 0x22, 0xe4, 0x78, 0xc4, 0xf6, 0xc2, 530 0x0d, 0x78, 0xc1, 0xf6, 0x22, 0xc2, 0x0c, 0xc2, 0x0b, 0x22, 0x22, 531 }; 532 533 static const u8 fw_patch_vsc8584[] = { 534 0xe8, 0x59, 0x02, 0xe8, 0x12, 0x02, 0xe8, 0x42, 0x02, 0xe8, 0x5a, 0x02, 535 0xe8, 0x5b, 0x02, 0xe8, 0x5c, 0xe5, 0x69, 0x54, 0x0f, 0x24, 0xf7, 0x60, 536 0x27, 0x24, 0xfc, 0x60, 0x23, 0x24, 0x08, 0x70, 0x14, 0xe5, 0x69, 0xae, 537 0x68, 0x78, 0x04, 0xce, 0xa2, 0xe7, 0x13, 0xce, 0x13, 0xd8, 0xf8, 0x7e, 538 0x00, 0x54, 0x0f, 0x80, 0x00, 0x7b, 0x01, 0x7a, 0x00, 0x7d, 0xee, 0x7f, 539 0x92, 0x12, 0x50, 0xee, 0x22, 0xe4, 0xf5, 0x10, 0x85, 0x10, 0xfb, 0x7d, 540 0x1c, 0xe4, 0xff, 0x12, 0x59, 0xea, 0x05, 0x10, 0xe5, 0x10, 0xc3, 0x94, 541 0x04, 0x40, 0xed, 0x22, 0x22, 0x22, 0x22, 0x22, 542 }; 543 544 static int vsc8584_get_fw_crc(struct mii_dev *bus, int phy, u16 start, 545 u16 *crc, const u8 *fw_patch, int fw_size) 546 { 547 int ret; 548 549 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, 550 MSCC_PHY_PAGE_EXT1); 551 552 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_VERIPHY_CNTL_2, start); 553 /* Add one byte to size for the one added by the patch_fw function */ 554 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_VERIPHY_CNTL_3, 555 fw_size + 1); 556 557 ret = vsc8584_cmd(bus, phy, PROC_CMD_CRC16); 558 if (ret) 559 goto out; 560 561 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, 562 MSCC_PHY_PAGE_EXT1); 563 564 *crc = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_VERIPHY_CNTL_2); 565 566 out: 567 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, 568 MSCC_PHY_PAGE_STD); 569 570 return ret; 571 } 572 573 static int vsc8584_patch_fw(struct mii_dev *bus, int phy, const u8 *fw_patch, 574 int fw_size) 575 { 576 int i, ret; 577 578 ret = vsc8584_micro_assert_reset(bus, phy); 579 if (ret) { 580 pr_err("%s: failed to assert reset of micro\n", __func__); 581 return ret; 582 } 583 584 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, 585 MSCC_PHY_PAGE_GPIO); 586 587 /* 588 * Hold 8051 Micro in SW Reset, Enable auto incr address and patch clock 589 * Disable the 8051 Micro clock 590 */ 591 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_DW8051_CNTL_STATUS, 592 RUN_FROM_INT_ROM | AUTOINC_ADDR | PATCH_RAM_CLK | 593 MICRO_CLK_EN | MICRO_CLK_DIVIDE(2)); 594 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL, READ_PRAM | 595 INT_MEM_WRITE_EN | INT_MEM_DATA(2)); 596 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_ADDR, 0x0000); 597 598 for (i = 0; i < fw_size; i++) 599 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL, 600 READ_PRAM | INT_MEM_WRITE_EN | fw_patch[i]); 601 602 /* Clear internal memory access */ 603 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL, READ_RAM); 604 605 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, 606 MSCC_PHY_PAGE_STD); 607 608 return 0; 609 } 610 611 static bool vsc8574_is_serdes_init(struct mii_dev *bus, int phy) 612 { 613 u16 reg; 614 bool ret; 615 616 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, 617 MSCC_PHY_PAGE_GPIO); 618 619 reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_TRAP_ROM_ADDR(1)); 620 if (reg != MSCC_TRAP_ROM_ADDR_SERDES_INIT) { 621 ret = false; 622 goto out; 623 } 624 625 reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_PATCH_RAM_ADDR(1)); 626 if (reg != MSCC_PATCH_RAM_ADDR_SERDES_INIT) { 627 ret = false; 628 goto out; 629 } 630 631 reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL); 632 if (reg != EN_PATCH_RAM_TRAP_ADDR(1)) { 633 ret = false; 634 goto out; 635 } 636 637 reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_DW8051_CNTL_STATUS); 638 if ((MICRO_NSOFT_RESET | RUN_FROM_INT_ROM | DW8051_CLK_EN | 639 MICRO_CLK_EN) != (reg & MSCC_DW8051_VLD_MASK)) { 640 ret = false; 641 goto out; 642 } 643 644 ret = true; 645 646 out: 647 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, 648 MSCC_PHY_PAGE_GPIO); 649 650 return ret; 651 } 652 653 static int vsc8574_config_pre_init(struct phy_device *phydev) 654 { 655 struct mii_dev *bus = phydev->bus; 656 u16 crc, reg, phy0, addr; 657 bool serdes_init; 658 int ret; 659 660 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, 661 MSCC_PHY_PAGE_EXT1); 662 addr = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_EXT_PHY_CNTL_4); 663 addr >>= PHY_CNTL_4_ADDR_POS; 664 665 reg = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_ACTIPHY_CNTL); 666 if (reg & PHY_ADDR_REVERSED) 667 phy0 = phydev->addr + addr; 668 else 669 phy0 = phydev->addr - addr; 670 671 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, 672 MSCC_PHY_PAGE_STD); 673 674 /* all writes below are broadcasted to all PHYs in the same package */ 675 reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS); 676 reg |= SMI_BROADCAST_WR_EN; 677 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS, reg); 678 679 /* 680 * The below register writes are tweaking analog and electrical 681 * configuration that were determined through characterization by PHY 682 * engineers. These don't mean anything more than "these are the best 683 * values". 684 */ 685 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_PHY_CNTL_2, 0x0040); 686 687 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, 688 MSCC_PHY_PAGE_TEST); 689 690 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_20, 0x4320); 691 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_24, 0x0c00); 692 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_9, 0x18ca); 693 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_5, 0x1b20); 694 695 reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8); 696 reg |= TR_CLK_DISABLE; 697 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8, reg); 698 699 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, 700 MSCC_PHY_PAGE_TR); 701 702 vsc8584_csr_write(bus, phy0, 0x0fae, 0x000401bd); 703 vsc8584_csr_write(bus, phy0, 0x0fac, 0x000f000f); 704 vsc8584_csr_write(bus, phy0, 0x17a0, 0x00a0f147); 705 vsc8584_csr_write(bus, phy0, 0x0fe4, 0x00052f54); 706 vsc8584_csr_write(bus, phy0, 0x1792, 0x0027303d); 707 vsc8584_csr_write(bus, phy0, 0x07fe, 0x00000704); 708 vsc8584_csr_write(bus, phy0, 0x0fe0, 0x00060150); 709 vsc8584_csr_write(bus, phy0, 0x0f82, 0x0012b00a); 710 vsc8584_csr_write(bus, phy0, 0x0f80, 0x00000d74); 711 vsc8584_csr_write(bus, phy0, 0x02e0, 0x00000012); 712 vsc8584_csr_write(bus, phy0, 0x03a2, 0x00050208); 713 vsc8584_csr_write(bus, phy0, 0x03b2, 0x00009186); 714 vsc8584_csr_write(bus, phy0, 0x0fb0, 0x000e3700); 715 vsc8584_csr_write(bus, phy0, 0x1688, 0x00049f81); 716 vsc8584_csr_write(bus, phy0, 0x0fd2, 0x0000ffff); 717 vsc8584_csr_write(bus, phy0, 0x168a, 0x00039fa2); 718 vsc8584_csr_write(bus, phy0, 0x1690, 0x0020640b); 719 vsc8584_csr_write(bus, phy0, 0x0258, 0x00002220); 720 vsc8584_csr_write(bus, phy0, 0x025a, 0x00002a20); 721 vsc8584_csr_write(bus, phy0, 0x025c, 0x00003060); 722 vsc8584_csr_write(bus, phy0, 0x025e, 0x00003fa0); 723 vsc8584_csr_write(bus, phy0, 0x03a6, 0x0000e0f0); 724 vsc8584_csr_write(bus, phy0, 0x0f92, 0x00001489); 725 vsc8584_csr_write(bus, phy0, 0x16a2, 0x00007000); 726 vsc8584_csr_write(bus, phy0, 0x16a6, 0x00071448); 727 vsc8584_csr_write(bus, phy0, 0x16a0, 0x00eeffdd); 728 vsc8584_csr_write(bus, phy0, 0x0fe8, 0x0091b06c); 729 vsc8584_csr_write(bus, phy0, 0x0fea, 0x00041600); 730 vsc8584_csr_write(bus, phy0, 0x16b0, 0x00eeff00); 731 vsc8584_csr_write(bus, phy0, 0x16b2, 0x00007000); 732 vsc8584_csr_write(bus, phy0, 0x16b4, 0x00000814); 733 vsc8584_csr_write(bus, phy0, 0x0f90, 0x00688980); 734 vsc8584_csr_write(bus, phy0, 0x03a4, 0x0000d8f0); 735 vsc8584_csr_write(bus, phy0, 0x0fc0, 0x00000400); 736 vsc8584_csr_write(bus, phy0, 0x07fa, 0x0050100f); 737 vsc8584_csr_write(bus, phy0, 0x0796, 0x00000003); 738 vsc8584_csr_write(bus, phy0, 0x07f8, 0x00c3ff98); 739 vsc8584_csr_write(bus, phy0, 0x0fa4, 0x0018292a); 740 vsc8584_csr_write(bus, phy0, 0x168c, 0x00d2c46f); 741 vsc8584_csr_write(bus, phy0, 0x17a2, 0x00000620); 742 vsc8584_csr_write(bus, phy0, 0x16a4, 0x0013132f); 743 vsc8584_csr_write(bus, phy0, 0x16a8, 0x00000000); 744 vsc8584_csr_write(bus, phy0, 0x0ffc, 0x00c0a028); 745 vsc8584_csr_write(bus, phy0, 0x0fec, 0x00901c09); 746 vsc8584_csr_write(bus, phy0, 0x0fee, 0x0004a6a1); 747 vsc8584_csr_write(bus, phy0, 0x0ffe, 0x00b01807); 748 749 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, 750 MSCC_PHY_PAGE_EXT2); 751 752 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_CU_PMD_TX_CNTL, 0x028e); 753 754 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, 755 MSCC_PHY_PAGE_TR); 756 757 vsc8584_csr_write(bus, phy0, 0x0486, 0x0008a518); 758 vsc8584_csr_write(bus, phy0, 0x0488, 0x006dc696); 759 vsc8584_csr_write(bus, phy0, 0x048a, 0x00000912); 760 vsc8584_csr_write(bus, phy0, 0x048e, 0x00000db6); 761 vsc8584_csr_write(bus, phy0, 0x049c, 0x00596596); 762 vsc8584_csr_write(bus, phy0, 0x049e, 0x00000514); 763 vsc8584_csr_write(bus, phy0, 0x04a2, 0x00410280); 764 vsc8584_csr_write(bus, phy0, 0x04a4, 0x00000000); 765 vsc8584_csr_write(bus, phy0, 0x04a6, 0x00000000); 766 vsc8584_csr_write(bus, phy0, 0x04a8, 0x00000000); 767 vsc8584_csr_write(bus, phy0, 0x04aa, 0x00000000); 768 vsc8584_csr_write(bus, phy0, 0x04ae, 0x007df7dd); 769 vsc8584_csr_write(bus, phy0, 0x04b0, 0x006d95d4); 770 vsc8584_csr_write(bus, phy0, 0x04b2, 0x00492410); 771 772 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, 773 MSCC_PHY_PAGE_TEST); 774 775 reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8); 776 reg &= ~TR_CLK_DISABLE; 777 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8, reg); 778 779 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, 780 MSCC_PHY_PAGE_STD); 781 782 /* end of write broadcasting */ 783 reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS); 784 reg &= ~SMI_BROADCAST_WR_EN; 785 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS, reg); 786 787 ret = vsc8584_get_fw_crc(bus, phy0, 788 MSCC_VSC8574_REVB_INT8051_FW_START_ADDR, &crc, 789 fw_patch_vsc8574, 790 ARRAY_SIZE(fw_patch_vsc8574)); 791 if (ret) 792 goto out; 793 794 if (crc == MSCC_VSC8574_REVB_INT8051_FW_CRC) { 795 serdes_init = vsc8574_is_serdes_init(bus, phy0); 796 797 if (!serdes_init) { 798 ret = vsc8584_micro_assert_reset(bus, phy0); 799 if (ret) { 800 pr_err("failed to assert reset of micro\n"); 801 return ret; 802 } 803 } 804 } else { 805 pr_debug("FW CRC is not the expected one, patching FW\n"); 806 807 serdes_init = false; 808 809 if (vsc8584_patch_fw(bus, phy0, fw_patch_vsc8574, 810 ARRAY_SIZE(fw_patch_vsc8574))) 811 pr_warn("failed to patch FW, expect non-optimal device\n"); 812 } 813 814 if (!serdes_init) { 815 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, 816 MSCC_PHY_PAGE_GPIO); 817 818 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_TRAP_ROM_ADDR(1), 819 MSCC_TRAP_ROM_ADDR_SERDES_INIT); 820 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PATCH_RAM_ADDR(1), 821 MSCC_PATCH_RAM_ADDR_SERDES_INIT); 822 823 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL, 824 EN_PATCH_RAM_TRAP_ADDR(1)); 825 826 vsc8584_micro_deassert_reset(bus, phy0, false); 827 828 ret = vsc8584_get_fw_crc(bus, phy0, 829 MSCC_VSC8574_REVB_INT8051_FW_START_ADDR, 830 &crc, fw_patch_vsc8574, 831 ARRAY_SIZE(fw_patch_vsc8574)); 832 if (ret) 833 goto out; 834 835 if (crc != MSCC_VSC8574_REVB_INT8051_FW_CRC) 836 pr_warn("FW CRC after patching is not the expected one, expect non-optimal device\n"); 837 } 838 839 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, 840 MSCC_PHY_PAGE_GPIO); 841 842 ret = vsc8584_cmd(bus, phy0, PROC_CMD_1588_DEFAULT_INIT | 843 PROC_CMD_PHY_INIT); 844 845 out: 846 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, 847 MSCC_PHY_PAGE_STD); 848 849 return ret; 850 } 851 852 static int vsc8584_config_pre_init(struct phy_device *phydev) 853 { 854 struct mii_dev *bus = phydev->bus; 855 u16 reg, crc, phy0, addr; 856 int ret; 857 858 if ((phydev->phy_id & MSCC_DEV_REV_MASK) != VSC8584_REVB) { 859 pr_warn("VSC8584 revA not officially supported, skipping firmware patching. Use at your own risk.\n"); 860 return 0; 861 } 862 863 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, 864 MSCC_PHY_PAGE_EXT1); 865 addr = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_EXT_PHY_CNTL_4); 866 addr >>= PHY_CNTL_4_ADDR_POS; 867 868 reg = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_ACTIPHY_CNTL); 869 if (reg & PHY_ADDR_REVERSED) 870 phy0 = phydev->addr + addr; 871 else 872 phy0 = phydev->addr - addr; 873 874 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, 875 MSCC_PHY_PAGE_STD); 876 877 /* all writes below are broadcasted to all PHYs in the same package */ 878 reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS); 879 reg |= SMI_BROADCAST_WR_EN; 880 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS, reg); 881 882 /* 883 * The below register writes are tweaking analog and electrical 884 * configuration that were determined through characterization by PHY 885 * engineers. These don't mean anything more than "these are the best 886 * values". 887 */ 888 reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_BYPASS_CONTROL); 889 reg |= PARALLEL_DET_IGNORE_ADVERTISED; 890 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_BYPASS_CONTROL, reg); 891 892 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, 893 MSCC_PHY_PAGE_EXT3); 894 895 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_SERDES_TX_CRC_ERR_CNT, 896 0x2000); 897 898 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, 899 MSCC_PHY_PAGE_TEST); 900 901 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_5, 0x1f20); 902 903 reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8); 904 reg |= TR_CLK_DISABLE; 905 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8, reg); 906 907 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, 908 MSCC_PHY_PAGE_TR); 909 910 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16, 0xafa4); 911 912 reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18); 913 reg &= ~0x007f; 914 reg |= 0x0019; 915 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18, reg); 916 917 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16, 0x8fa4); 918 919 vsc8584_csr_write(bus, phy0, 0x07fa, 0x0050100f); 920 vsc8584_csr_write(bus, phy0, 0x1688, 0x00049f81); 921 vsc8584_csr_write(bus, phy0, 0x0f90, 0x00688980); 922 vsc8584_csr_write(bus, phy0, 0x03a4, 0x0000d8f0); 923 vsc8584_csr_write(bus, phy0, 0x0fc0, 0x00000400); 924 vsc8584_csr_write(bus, phy0, 0x0f82, 0x0012b002); 925 vsc8584_csr_write(bus, phy0, 0x1686, 0x00000004); 926 vsc8584_csr_write(bus, phy0, 0x168c, 0x00d2c46f); 927 vsc8584_csr_write(bus, phy0, 0x17a2, 0x00000620); 928 vsc8584_csr_write(bus, phy0, 0x16a0, 0x00eeffdd); 929 vsc8584_csr_write(bus, phy0, 0x16a6, 0x00071448); 930 vsc8584_csr_write(bus, phy0, 0x16a4, 0x0013132f); 931 vsc8584_csr_write(bus, phy0, 0x16a8, 0x00000000); 932 vsc8584_csr_write(bus, phy0, 0x0ffc, 0x00c0a028); 933 vsc8584_csr_write(bus, phy0, 0x0fe8, 0x0091b06c); 934 vsc8584_csr_write(bus, phy0, 0x0fea, 0x00041600); 935 vsc8584_csr_write(bus, phy0, 0x0f80, 0x00fffaff); 936 vsc8584_csr_write(bus, phy0, 0x0fec, 0x00901809); 937 vsc8584_csr_write(bus, phy0, 0x0ffe, 0x00b01007); 938 vsc8584_csr_write(bus, phy0, 0x16b0, 0x00eeff00); 939 vsc8584_csr_write(bus, phy0, 0x16b2, 0x00007000); 940 vsc8584_csr_write(bus, phy0, 0x16b4, 0x00000814); 941 942 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, 943 MSCC_PHY_PAGE_EXT2); 944 945 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_CU_PMD_TX_CNTL, 0x028e); 946 947 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, 948 MSCC_PHY_PAGE_TR); 949 950 vsc8584_csr_write(bus, phy0, 0x0486, 0x0008a518); 951 vsc8584_csr_write(bus, phy0, 0x0488, 0x006dc696); 952 vsc8584_csr_write(bus, phy0, 0x048a, 0x00000912); 953 954 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, 955 MSCC_PHY_PAGE_TEST); 956 957 reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8); 958 reg &= ~TR_CLK_DISABLE; 959 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8, reg); 960 961 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, 962 MSCC_PHY_PAGE_STD); 963 964 /* end of write broadcasting */ 965 reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS); 966 reg &= ~SMI_BROADCAST_WR_EN; 967 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS, reg); 968 969 ret = vsc8584_get_fw_crc(bus, phy0, 970 MSCC_VSC8584_REVB_INT8051_FW_START_ADDR, &crc, 971 fw_patch_vsc8584, 972 ARRAY_SIZE(fw_patch_vsc8584)); 973 if (ret) 974 goto out; 975 976 if (crc != MSCC_VSC8584_REVB_INT8051_FW_CRC) { 977 debug("FW CRC is not the expected one, patching FW...\n"); 978 if (vsc8584_patch_fw(bus, phy0, fw_patch_vsc8584, 979 ARRAY_SIZE(fw_patch_vsc8584))) 980 pr_warn("failed to patch FW, expect non-optimal device\n"); 981 } 982 983 vsc8584_micro_deassert_reset(bus, phy0, false); 984 985 ret = vsc8584_get_fw_crc(bus, phy0, 986 MSCC_VSC8584_REVB_INT8051_FW_START_ADDR, &crc, 987 fw_patch_vsc8584, 988 ARRAY_SIZE(fw_patch_vsc8584)); 989 if (ret) 990 goto out; 991 992 if (crc != MSCC_VSC8584_REVB_INT8051_FW_CRC) 993 pr_warn("FW CRC after patching is not the expected one, expect non-optimal device\n"); 994 995 ret = vsc8584_micro_assert_reset(bus, phy0); 996 if (ret) 997 goto out; 998 999 vsc8584_micro_deassert_reset(bus, phy0, true); 1000 1001 out: 1002 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, 1003 MSCC_PHY_PAGE_STD); 1004 1005 return ret; 1006 } 1007 1008 static int mscc_vsc8531_vsc8541_init_scripts(struct phy_device *phydev) 1009 { 1010 u16 reg_val; 1011 1012 /* Set to Access Token Ring Registers */ 1013 phy_write(phydev, MDIO_DEVAD_NONE, 1014 MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_TR); 1015 1016 /* Update LinkDetectCtrl default to optimized values */ 1017 /* Determined during Silicon Validation Testing */ 1018 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16, 1019 (MSCC_PHY_TR_LINKDETCTRL_ADDR | MSCC_PHY_TR_16_READ)); 1020 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17); 1021 reg_val = bitfield_replace(reg_val, MSCC_PHY_TR_LINKDETCTRL_POS, 1022 MSCC_PHY_TR_LINKDETCTRL_WIDTH, 1023 MSCC_PHY_TR_LINKDETCTRL_VAL); 1024 1025 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17, reg_val); 1026 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16, 1027 (MSCC_PHY_TR_LINKDETCTRL_ADDR | MSCC_PHY_TR_16_WRITE)); 1028 1029 /* Update VgaThresh100 defaults to optimized values */ 1030 /* Determined during Silicon Validation Testing */ 1031 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16, 1032 (MSCC_PHY_TR_VGATHRESH100_ADDR | MSCC_PHY_TR_16_READ)); 1033 1034 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18); 1035 reg_val = bitfield_replace(reg_val, MSCC_PHY_TR_VGATHRESH100_POS, 1036 MSCC_PHY_TR_VGATHRESH100_WIDTH, 1037 MSCC_PHY_TR_VGATHRESH100_VAL); 1038 1039 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18, reg_val); 1040 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16, 1041 (MSCC_PHY_TR_VGATHRESH100_ADDR | MSCC_PHY_TR_16_WRITE)); 1042 1043 /* Update VgaGain10 defaults to optimized values */ 1044 /* Determined during Silicon Validation Testing */ 1045 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16, 1046 (MSCC_PHY_TR_VGAGAIN10_ADDR | MSCC_PHY_TR_16_READ)); 1047 1048 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18); 1049 reg_val = bitfield_replace(reg_val, MSCC_PHY_TR_VGAGAIN10_U_POS, 1050 MSCC_PHY_TR_VGAGAIN10_U_WIDTH, 1051 MSCC_PHY_TR_VGAGAIN10_U_VAL); 1052 1053 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18, reg_val); 1054 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17); 1055 reg_val = bitfield_replace(reg_val, MSCC_PHY_TR_VGAGAIN10_L_POS, 1056 MSCC_PHY_TR_VGAGAIN10_L_WIDTH, 1057 MSCC_PHY_TR_VGAGAIN10_L_VAL); 1058 1059 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17, reg_val); 1060 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16, 1061 (MSCC_PHY_TR_VGAGAIN10_ADDR | MSCC_PHY_TR_16_WRITE)); 1062 1063 /* Set back to Access Standard Page Registers */ 1064 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, 1065 MSCC_PHY_PAGE_STD); 1066 1067 return 0; 1068 } 1069 1070 static int mscc_parse_status(struct phy_device *phydev) 1071 { 1072 u16 speed; 1073 u16 mii_reg; 1074 1075 mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_AUX_CNTRL_STAT_REG); 1076 1077 if (mii_reg & MIIM_AUX_CNTRL_STAT_F_DUPLEX) 1078 phydev->duplex = DUPLEX_FULL; 1079 else 1080 phydev->duplex = DUPLEX_HALF; 1081 1082 speed = mii_reg & MIIM_AUX_CNTRL_STAT_SPEED_MASK; 1083 speed = speed >> MIIM_AUX_CNTRL_STAT_SPEED_POS; 1084 1085 switch (speed) { 1086 case MIIM_AUX_CNTRL_STAT_SPEED_1000M: 1087 phydev->speed = SPEED_1000; 1088 break; 1089 case MIIM_AUX_CNTRL_STAT_SPEED_100M: 1090 phydev->speed = SPEED_100; 1091 break; 1092 case MIIM_AUX_CNTRL_STAT_SPEED_10M: 1093 phydev->speed = SPEED_10; 1094 break; 1095 default: 1096 phydev->speed = SPEED_10; 1097 break; 1098 } 1099 1100 return 0; 1101 } 1102 1103 static int mscc_startup(struct phy_device *phydev) 1104 { 1105 int retval; 1106 1107 retval = genphy_update_link(phydev); 1108 1109 if (retval) 1110 return retval; 1111 1112 return mscc_parse_status(phydev); 1113 } 1114 1115 static int mscc_phy_soft_reset(struct phy_device *phydev) 1116 { 1117 int retval = 0; 1118 u16 timeout = MSCC_PHY_RESET_TIMEOUT; 1119 u16 reg_val = 0; 1120 1121 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, 1122 MSCC_PHY_PAGE_STD); 1123 1124 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR); 1125 phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, (reg_val | BMCR_RESET)); 1126 1127 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR); 1128 1129 while ((reg_val & BMCR_RESET) && (timeout > 0)) { 1130 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR); 1131 timeout--; 1132 udelay(1000); /* 1 ms */ 1133 } 1134 1135 if (timeout == 0) { 1136 printf("MSCC PHY Soft_Reset Error: mac i/f = 0x%x\n", 1137 phydev->interface); 1138 retval = -ETIME; 1139 } 1140 1141 return retval; 1142 } 1143 1144 static int vsc8531_vsc8541_mac_config(struct phy_device *phydev) 1145 { 1146 u16 reg_val = 0; 1147 u16 mac_if = 0; 1148 u16 rx_clk_out = 0; 1149 1150 /* For VSC8530/31 the only MAC modes are RMII/RGMII. */ 1151 /* For VSC8540/41 the only MAC modes are (G)MII and RMII/RGMII. */ 1152 /* Setup MAC Configuration */ 1153 switch (phydev->interface) { 1154 case PHY_INTERFACE_MODE_MII: 1155 case PHY_INTERFACE_MODE_GMII: 1156 /* Set Reg23.12:11=0 */ 1157 mac_if = MAC_IF_SELECTION_GMII; 1158 /* Set Reg20E2.11=1 */ 1159 rx_clk_out = RX_CLK_OUT_DISABLE; 1160 break; 1161 1162 case PHY_INTERFACE_MODE_RMII: 1163 /* Set Reg23.12:11=1 */ 1164 mac_if = MAC_IF_SELECTION_RMII; 1165 /* Set Reg20E2.11=0 */ 1166 rx_clk_out = RX_CLK_OUT_NORMAL; 1167 break; 1168 1169 case PHY_INTERFACE_MODE_RGMII: 1170 /* Set Reg23.12:11=2 */ 1171 mac_if = MAC_IF_SELECTION_RGMII; 1172 /* Set Reg20E2.11=0 */ 1173 rx_clk_out = RX_CLK_OUT_NORMAL; 1174 break; 1175 1176 default: 1177 printf("MSCC PHY - INVALID MAC i/f Config: mac i/f = 0x%x\n", 1178 phydev->interface); 1179 return -EINVAL; 1180 } 1181 1182 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, 1183 MSCC_PHY_PAGE_STD); 1184 1185 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, 1186 MSCC_PHY_EXT_PHY_CNTL_1_REG); 1187 /* Set MAC i/f bits Reg23.12:11 */ 1188 reg_val = bitfield_replace(reg_val, MAC_IF_SELECTION_POS, 1189 MAC_IF_SELECTION_WIDTH, mac_if); 1190 /* Update Reg23.12:11 */ 1191 phy_write(phydev, MDIO_DEVAD_NONE, 1192 MSCC_PHY_EXT_PHY_CNTL_1_REG, reg_val); 1193 /* Setup ExtPg_2 Register Access */ 1194 phy_write(phydev, MDIO_DEVAD_NONE, 1195 MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_EXT2); 1196 /* Read Reg20E2 */ 1197 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, 1198 MSCC_PHY_RGMII_CNTL_REG); 1199 reg_val = bitfield_replace(reg_val, RX_CLK_OUT_POS, 1200 RX_CLK_OUT_WIDTH, rx_clk_out); 1201 /* Update Reg20E2.11 */ 1202 phy_write(phydev, MDIO_DEVAD_NONE, 1203 MSCC_PHY_RGMII_CNTL_REG, reg_val); 1204 /* Before leaving - Change back to Std Page Register Access */ 1205 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, 1206 MSCC_PHY_PAGE_STD); 1207 1208 return 0; 1209 } 1210 1211 static int vsc8531_config(struct phy_device *phydev) 1212 { 1213 int retval = -EINVAL; 1214 u16 reg_val; 1215 u16 rmii_clk_out; 1216 enum vsc_phy_rgmii_skew rx_clk_skew = VSC_PHY_RGMII_DELAY_1700_PS; 1217 enum vsc_phy_rgmii_skew tx_clk_skew = VSC_PHY_RGMII_DELAY_800_PS; 1218 enum vsc_phy_clk_slew edge_rate = VSC_PHY_CLK_SLEW_RATE_4; 1219 1220 /* For VSC8530/31 and VSC8540/41 the init scripts are the same */ 1221 mscc_vsc8531_vsc8541_init_scripts(phydev); 1222 1223 /* For VSC8530/31 the only MAC modes are RMII/RGMII. */ 1224 switch (phydev->interface) { 1225 case PHY_INTERFACE_MODE_RMII: 1226 case PHY_INTERFACE_MODE_RGMII: 1227 retval = vsc8531_vsc8541_mac_config(phydev); 1228 if (retval != 0) 1229 return retval; 1230 1231 retval = mscc_phy_soft_reset(phydev); 1232 if (retval != 0) 1233 return retval; 1234 break; 1235 default: 1236 printf("PHY 8530/31 MAC i/f Config Error: mac i/f = 0x%x\n", 1237 phydev->interface); 1238 return -EINVAL; 1239 } 1240 /* Default RMII Clk Output to 0=OFF/1=ON */ 1241 rmii_clk_out = 0; 1242 1243 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, 1244 MSCC_PHY_PAGE_EXT2); 1245 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG); 1246 1247 /* Reg20E2 - Update RGMII RX_Clk Skews. */ 1248 reg_val = bitfield_replace(reg_val, RGMII_RX_CLK_DELAY_POS, 1249 RGMII_RX_CLK_DELAY_WIDTH, rx_clk_skew); 1250 /* Reg20E2 - Update RGMII TX_Clk Skews. */ 1251 reg_val = bitfield_replace(reg_val, RGMII_TX_CLK_DELAY_POS, 1252 RGMII_TX_CLK_DELAY_WIDTH, tx_clk_skew); 1253 1254 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG, reg_val); 1255 1256 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL); 1257 /* Reg27E2 - Update Clk Slew Rate. */ 1258 reg_val = bitfield_replace(reg_val, EDGE_RATE_CNTL_POS, 1259 EDGE_RATE_CNTL_WIDTH, edge_rate); 1260 /* Reg27E2 - Update RMII Clk Out. */ 1261 reg_val = bitfield_replace(reg_val, RMII_CLK_OUT_ENABLE_POS, 1262 RMII_CLK_OUT_ENABLE_WIDTH, rmii_clk_out); 1263 /* Update Reg27E2 */ 1264 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL, reg_val); 1265 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, 1266 MSCC_PHY_PAGE_STD); 1267 1268 return genphy_config_aneg(phydev); 1269 } 1270 1271 static int vsc8541_config(struct phy_device *phydev) 1272 { 1273 int retval = -EINVAL; 1274 u16 reg_val; 1275 u16 rmii_clk_out; 1276 enum vsc_phy_rgmii_skew rx_clk_skew = VSC_PHY_RGMII_DELAY_1700_PS; 1277 enum vsc_phy_rgmii_skew tx_clk_skew = VSC_PHY_RGMII_DELAY_800_PS; 1278 enum vsc_phy_clk_slew edge_rate = VSC_PHY_CLK_SLEW_RATE_4; 1279 1280 /* For VSC8530/31 and VSC8540/41 the init scripts are the same */ 1281 mscc_vsc8531_vsc8541_init_scripts(phydev); 1282 1283 /* For VSC8540/41 the only MAC modes are (G)MII and RMII/RGMII. */ 1284 switch (phydev->interface) { 1285 case PHY_INTERFACE_MODE_MII: 1286 case PHY_INTERFACE_MODE_GMII: 1287 case PHY_INTERFACE_MODE_RMII: 1288 case PHY_INTERFACE_MODE_RGMII: 1289 retval = vsc8531_vsc8541_mac_config(phydev); 1290 if (retval != 0) 1291 return retval; 1292 1293 retval = mscc_phy_soft_reset(phydev); 1294 if (retval != 0) 1295 return retval; 1296 break; 1297 default: 1298 printf("PHY 8541 MAC i/f config Error: mac i/f = 0x%x\n", 1299 phydev->interface); 1300 return -EINVAL; 1301 } 1302 /* Default RMII Clk Output to 0=OFF/1=ON */ 1303 rmii_clk_out = 0; 1304 1305 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, 1306 MSCC_PHY_PAGE_EXT2); 1307 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG); 1308 /* Reg20E2 - Update RGMII RX_Clk Skews. */ 1309 reg_val = bitfield_replace(reg_val, RGMII_RX_CLK_DELAY_POS, 1310 RGMII_RX_CLK_DELAY_WIDTH, rx_clk_skew); 1311 /* Reg20E2 - Update RGMII TX_Clk Skews. */ 1312 reg_val = bitfield_replace(reg_val, RGMII_TX_CLK_DELAY_POS, 1313 RGMII_TX_CLK_DELAY_WIDTH, tx_clk_skew); 1314 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG, reg_val); 1315 1316 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL); 1317 /* Reg27E2 - Update Clk Slew Rate. */ 1318 reg_val = bitfield_replace(reg_val, EDGE_RATE_CNTL_POS, 1319 EDGE_RATE_CNTL_WIDTH, edge_rate); 1320 /* Reg27E2 - Update RMII Clk Out. */ 1321 reg_val = bitfield_replace(reg_val, RMII_CLK_OUT_ENABLE_POS, 1322 RMII_CLK_OUT_ENABLE_WIDTH, rmii_clk_out); 1323 /* Update Reg27E2 */ 1324 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL, reg_val); 1325 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, 1326 MSCC_PHY_PAGE_STD); 1327 1328 return genphy_config_aneg(phydev); 1329 } 1330 1331 static int vsc8584_config_init(struct phy_device *phydev) 1332 { 1333 struct vsc85xx_priv *priv = phydev->priv; 1334 int ret; 1335 u16 addr; 1336 u16 reg_val; 1337 u16 val; 1338 1339 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, 1340 MSCC_PHY_PAGE_EXT1); 1341 addr = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_EXT_PHY_CNTL_4); 1342 addr >>= PHY_CNTL_4_ADDR_POS; 1343 1344 ret = priv->config_pre(phydev); 1345 if (ret) 1346 return ret; 1347 1348 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, 1349 MSCC_PHY_PAGE_GPIO); 1350 1351 if (phydev->interface == PHY_INTERFACE_MODE_QSGMII) 1352 val = MAC_CFG_QSGMII; 1353 else 1354 val = MAC_CFG_SGMII; 1355 1356 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_MAC_CFG_FASTLINK); 1357 reg_val &= ~MAC_CFG_MASK; 1358 reg_val |= val; 1359 ret = phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_MAC_CFG_FASTLINK, 1360 reg_val); 1361 if (ret) 1362 return ret; 1363 1364 reg_val = PROC_CMD_MCB_ACCESS_MAC_CONF | PROC_CMD_RST_CONF_PORT | 1365 PROC_CMD_READ_MOD_WRITE_PORT; 1366 if (phydev->interface == PHY_INTERFACE_MODE_QSGMII) 1367 reg_val |= PROC_CMD_QSGMII_MAC; 1368 else 1369 reg_val |= PROC_CMD_SGMII_MAC; 1370 1371 ret = vsc8584_cmd(phydev->bus, phydev->addr, reg_val); 1372 if (ret) 1373 return ret; 1374 1375 mdelay(10); 1376 1377 /* Disable SerDes for 100Base-FX */ 1378 ret = vsc8584_cmd(phydev->bus, phydev->addr, PROC_CMD_FIBER_MEDIA_CONF | 1379 PROC_CMD_FIBER_PORT(addr) | PROC_CMD_FIBER_DISABLE | 1380 PROC_CMD_READ_MOD_WRITE_PORT | 1381 PROC_CMD_RST_CONF_PORT | PROC_CMD_FIBER_100BASE_FX); 1382 if (ret) 1383 return ret; 1384 1385 /* Disable SerDes for 1000Base-X */ 1386 ret = vsc8584_cmd(phydev->bus, phydev->addr, PROC_CMD_FIBER_MEDIA_CONF | 1387 PROC_CMD_FIBER_PORT(addr) | PROC_CMD_FIBER_DISABLE | 1388 PROC_CMD_READ_MOD_WRITE_PORT | 1389 PROC_CMD_RST_CONF_PORT | PROC_CMD_FIBER_1000BASE_X); 1390 if (ret) 1391 return ret; 1392 1393 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, 1394 MSCC_PHY_PAGE_STD); 1395 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, 1396 MSCC_PHY_EXT_PHY_CNTL_1_REG); 1397 reg_val &= ~(MEDIA_OP_MODE_MASK | VSC8584_MAC_IF_SELECTION_MASK); 1398 reg_val |= MEDIA_OP_MODE_COPPER | 1399 (VSC8584_MAC_IF_SELECTION_SGMII << 1400 VSC8584_MAC_IF_SELECTION_POS); 1401 ret = phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_EXT_PHY_CNTL_1_REG, 1402 reg_val); 1403 1404 ret = mscc_phy_soft_reset(phydev); 1405 if (ret != 0) 1406 return ret; 1407 1408 return genphy_config(phydev); 1409 } 1410 1411 static struct vsc85xx_priv vsc8574_priv = { 1412 .config_pre = vsc8574_config_pre_init, 1413 }; 1414 1415 static int vsc8574_config(struct phy_device *phydev) 1416 { 1417 phydev->priv = &vsc8574_priv; 1418 1419 return vsc8584_config_init(phydev); 1420 } 1421 1422 static struct vsc85xx_priv vsc8584_priv = { 1423 .config_pre = vsc8584_config_pre_init, 1424 }; 1425 1426 static int vsc8584_config(struct phy_device *phydev) 1427 { 1428 phydev->priv = &vsc8584_priv; 1429 1430 return vsc8584_config_init(phydev); 1431 } 1432 1433 static struct phy_driver VSC8530_driver = { 1434 .name = "Microsemi VSC8530", 1435 .uid = PHY_ID_VSC8530, 1436 .mask = 0x000ffff0, 1437 .features = PHY_BASIC_FEATURES, 1438 .config = &vsc8531_config, 1439 .startup = &mscc_startup, 1440 .shutdown = &genphy_shutdown, 1441 }; 1442 1443 static struct phy_driver VSC8531_driver = { 1444 .name = "Microsemi VSC8531", 1445 .uid = PHY_ID_VSC8531, 1446 .mask = 0x000ffff0, 1447 .features = PHY_GBIT_FEATURES, 1448 .config = &vsc8531_config, 1449 .startup = &mscc_startup, 1450 .shutdown = &genphy_shutdown, 1451 }; 1452 1453 static struct phy_driver VSC8540_driver = { 1454 .name = "Microsemi VSC8540", 1455 .uid = PHY_ID_VSC8540, 1456 .mask = 0x000ffff0, 1457 .features = PHY_BASIC_FEATURES, 1458 .config = &vsc8541_config, 1459 .startup = &mscc_startup, 1460 .shutdown = &genphy_shutdown, 1461 }; 1462 1463 static struct phy_driver VSC8541_driver = { 1464 .name = "Microsemi VSC8541", 1465 .uid = PHY_ID_VSC8541, 1466 .mask = 0x000ffff0, 1467 .features = PHY_GBIT_FEATURES, 1468 .config = &vsc8541_config, 1469 .startup = &mscc_startup, 1470 .shutdown = &genphy_shutdown, 1471 }; 1472 1473 static struct phy_driver VSC8574_driver = { 1474 .name = "Microsemi VSC8574", 1475 .uid = PHY_ID_VSC8574, 1476 .mask = 0x000ffff0, 1477 .features = PHY_GBIT_FEATURES, 1478 .config = &vsc8574_config, 1479 .startup = &mscc_startup, 1480 .shutdown = &genphy_shutdown, 1481 }; 1482 1483 static struct phy_driver VSC8584_driver = { 1484 .name = "Microsemi VSC8584", 1485 .uid = PHY_ID_VSC8584, 1486 .mask = 0x000ffff0, 1487 .features = PHY_GBIT_FEATURES, 1488 .config = &vsc8584_config, 1489 .startup = &mscc_startup, 1490 .shutdown = &genphy_shutdown, 1491 }; 1492 1493 int phy_mscc_init(void) 1494 { 1495 phy_register(&VSC8530_driver); 1496 phy_register(&VSC8531_driver); 1497 phy_register(&VSC8540_driver); 1498 phy_register(&VSC8541_driver); 1499 phy_register(&VSC8574_driver); 1500 phy_register(&VSC8584_driver); 1501 1502 return 0; 1503 } 1504