1 // SPDX-License-Identifier: MIT
3 * Microsemi PHY drivers
6 * Copyright (c) 2016 Microsemi Corporation
8 * Author: John Haechten
15 #include <linux/delay.h>
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
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 */
36 /* Std Page Register 18 */
37 #define MSCC_PHY_BYPASS_CONTROL 18
38 #define PARALLEL_DET_IGNORE_ADVERTISED BIT(3)
40 /* Std Page Register 22 */
41 #define MSCC_PHY_EXT_CNTL_STATUS 22
42 #define SMI_BROADCAST_WR_EN BIT(0)
44 /* Std Page Register 24 */
45 #define MSCC_PHY_EXT_PHY_CNTL_2 24
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)
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
79 /* Extended Page 1 Register 20E1 */
80 #define MSCC_PHY_ACTIPHY_CNTL 20
81 #define PHY_ADDR_REVERSED BIT(9)
83 /* Extended Page 1 Register 23E1 */
85 #define MSCC_PHY_EXT_PHY_CNTL_4 23
86 #define PHY_CNTL_4_ADDR_POS 11
88 /* Extended Page 1 Register 25E1 */
89 #define MSCC_PHY_VERIPHY_CNTL_2 25
91 /* Extended Page 1 Register 26E1 */
92 #define MSCC_PHY_VERIPHY_CNTL_3 26
94 /* Extended Page 2 Register 16E2 */
95 #define MSCC_PHY_CU_PMD_TX_CNTL 16
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)
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)
121 /* Extended Page 3 Register 22E3 */
122 #define MSCC_PHY_SERDES_TX_CRC_ERR_CNT 22
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
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
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
144 /* Extended page GPIO register 11G */
145 #define MSCC_INT_MEM_ADDR 11
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))
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
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)
191 #define MSCC_PHY_TEST_PAGE_5 5
193 #define MSCC_PHY_TEST_PAGE_8 8
194 #define TR_CLK_DISABLE BIT(15)
196 #define MSCC_PHY_TEST_PAGE_9 9
197 #define MSCC_PHY_TEST_PAGE_20 20
198 #define MSCC_PHY_TEST_PAGE_24 24
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
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)
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)
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)
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)
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)
234 /* General Timeout Values */
235 #define MSCC_PHY_RESET_TIMEOUT (100)
236 #define MSCC_PHY_MICRO_TIMEOUT (500)
238 #define VSC8584_REVB 0x0001
239 #define MSCC_DEV_REV_MASK GENMASK(3, 0)
241 #define MSCC_VSC8574_REVB_INT8051_FW_START_ADDR 0x4000
242 #define MSCC_VSC8574_REVB_INT8051_FW_CRC 0x29e8
244 #define MSCC_VSC8584_REVB_INT8051_FW_START_ADDR 0xe800
245 #define MSCC_VSC8584_REVB_INT8051_FW_CRC 0xfb48
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,
258 /* MAC i/f Clock Edge Rage Control (Slew), See Reg27E2 */ enum
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,
270 struct vsc85xx_priv {
271 int (*config_pre)(struct phy_device *phydev);
274 static void vsc8584_csr_write(struct mii_dev *bus, int phy0, u16 addr, u32 val)
276 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18,
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);
284 static int vsc8584_cmd(struct mii_dev *bus, int phy, u16 val)
286 unsigned long deadline;
289 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
292 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_PROC_CMD,
293 PROC_CMD_NCOMPLETED | val);
295 deadline = timer_get_us() + PROC_CMD_NCOMPLETED_TIMEOUT_MS * 1000;
297 reg_val = bus->read(bus, phy, MDIO_DEVAD_NONE,
299 } while (timer_get_us() <= deadline &&
300 (reg_val & PROC_CMD_NCOMPLETED) &&
301 !(reg_val & PROC_CMD_FAILED));
303 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
306 if (reg_val & PROC_CMD_FAILED)
308 if (reg_val & PROC_CMD_NCOMPLETED)
314 static int vsc8584_micro_deassert_reset(struct mii_dev *bus, int phy,
319 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
322 enable = RUN_FROM_INT_ROM | MICRO_CLK_EN | DW8051_CLK_EN;
323 release = MICRO_NSOFT_RESET | RUN_FROM_INT_ROM | DW8051_CLK_EN |
327 enable |= MICRO_PATCH_EN;
328 release |= MICRO_PATCH_EN;
330 /* Clear all patches */
331 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL,
336 * Enable 8051 Micro clock; CLEAR/SET patch present; disable PRAM clock
337 * override and addr. auto-incr; operate at 125 MHz
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);
343 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
349 static int vsc8584_micro_assert_reset(struct mii_dev *bus, int phy)
354 ret = vsc8584_cmd(bus, phy, PROC_CMD_NOP);
358 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
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);
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);
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);
372 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_PROC_CMD, PROC_CMD_NOP);
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);
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);
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);
386 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
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,
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,
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)
549 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
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,
557 ret = vsc8584_cmd(bus, phy, PROC_CMD_CRC16);
561 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
564 *crc = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_VERIPHY_CNTL_2);
567 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
573 static int vsc8584_patch_fw(struct mii_dev *bus, int phy, const u8 *fw_patch,
578 ret = vsc8584_micro_assert_reset(bus, phy);
580 pr_err("%s: failed to assert reset of micro\n", __func__);
584 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
588 * Hold 8051 Micro in SW Reset, Enable auto incr address and patch clock
589 * Disable the 8051 Micro clock
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);
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]);
602 /* Clear internal memory access */
603 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL, READ_RAM);
605 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
611 static bool vsc8574_is_serdes_init(struct mii_dev *bus, int phy)
616 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
619 reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_TRAP_ROM_ADDR(1));
620 if (reg != MSCC_TRAP_ROM_ADDR_SERDES_INIT) {
625 reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_PATCH_RAM_ADDR(1));
626 if (reg != MSCC_PATCH_RAM_ADDR_SERDES_INIT) {
631 reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL);
632 if (reg != EN_PATCH_RAM_TRAP_ADDR(1)) {
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)) {
647 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
653 static int vsc8574_config_pre_init(struct phy_device *phydev)
655 struct mii_dev *bus = phydev->bus;
656 u16 crc, reg, phy0, addr;
660 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
662 addr = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_EXT_PHY_CNTL_4);
663 addr >>= PHY_CNTL_4_ADDR_POS;
665 reg = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_ACTIPHY_CNTL);
666 if (reg & PHY_ADDR_REVERSED)
667 phy0 = phydev->addr + addr;
669 phy0 = phydev->addr - addr;
671 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
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);
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
685 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_PHY_CNTL_2, 0x0040);
687 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
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);
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);
699 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
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);
749 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
752 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_CU_PMD_TX_CNTL, 0x028e);
754 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
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);
772 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
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);
779 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
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);
787 ret = vsc8584_get_fw_crc(bus, phy0,
788 MSCC_VSC8574_REVB_INT8051_FW_START_ADDR, &crc,
790 ARRAY_SIZE(fw_patch_vsc8574));
794 if (crc == MSCC_VSC8574_REVB_INT8051_FW_CRC) {
795 serdes_init = vsc8574_is_serdes_init(bus, phy0);
798 ret = vsc8584_micro_assert_reset(bus, phy0);
800 pr_err("failed to assert reset of micro\n");
805 pr_debug("FW CRC is not the expected one, patching FW\n");
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");
815 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
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);
823 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL,
824 EN_PATCH_RAM_TRAP_ADDR(1));
826 vsc8584_micro_deassert_reset(bus, phy0, false);
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));
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");
839 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
842 ret = vsc8584_cmd(bus, phy0, PROC_CMD_1588_DEFAULT_INIT |
846 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
852 static int vsc8584_config_pre_init(struct phy_device *phydev)
854 struct mii_dev *bus = phydev->bus;
855 u16 reg, crc, phy0, addr;
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");
863 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
865 addr = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_EXT_PHY_CNTL_4);
866 addr >>= PHY_CNTL_4_ADDR_POS;
868 reg = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_ACTIPHY_CNTL);
869 if (reg & PHY_ADDR_REVERSED)
870 phy0 = phydev->addr + addr;
872 phy0 = phydev->addr - addr;
874 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
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);
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
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);
892 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
895 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_SERDES_TX_CRC_ERR_CNT,
898 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
901 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_5, 0x1f20);
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);
907 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
910 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16, 0xafa4);
912 reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18);
915 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18, reg);
917 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16, 0x8fa4);
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);
942 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
945 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_CU_PMD_TX_CNTL, 0x028e);
947 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
950 vsc8584_csr_write(bus, phy0, 0x0486, 0x0008a518);
951 vsc8584_csr_write(bus, phy0, 0x0488, 0x006dc696);
952 vsc8584_csr_write(bus, phy0, 0x048a, 0x00000912);
954 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
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);
961 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
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);
969 ret = vsc8584_get_fw_crc(bus, phy0,
970 MSCC_VSC8584_REVB_INT8051_FW_START_ADDR, &crc,
972 ARRAY_SIZE(fw_patch_vsc8584));
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");
983 vsc8584_micro_deassert_reset(bus, phy0, false);
985 ret = vsc8584_get_fw_crc(bus, phy0,
986 MSCC_VSC8584_REVB_INT8051_FW_START_ADDR, &crc,
988 ARRAY_SIZE(fw_patch_vsc8584));
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");
995 ret = vsc8584_micro_assert_reset(bus, phy0);
999 vsc8584_micro_deassert_reset(bus, phy0, true);
1002 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1008 static int mscc_vsc8531_vsc8541_init_scripts(struct phy_device *phydev)
1012 /* Set to Access Token Ring Registers */
1013 phy_write(phydev, MDIO_DEVAD_NONE,
1014 MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_TR);
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);
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));
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));
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);
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));
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));
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);
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);
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));
1063 /* Set back to Access Standard Page Registers */
1064 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1070 static int mscc_parse_status(struct phy_device *phydev)
1075 mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_AUX_CNTRL_STAT_REG);
1077 if (mii_reg & MIIM_AUX_CNTRL_STAT_F_DUPLEX)
1078 phydev->duplex = DUPLEX_FULL;
1080 phydev->duplex = DUPLEX_HALF;
1082 speed = mii_reg & MIIM_AUX_CNTRL_STAT_SPEED_MASK;
1083 speed = speed >> MIIM_AUX_CNTRL_STAT_SPEED_POS;
1086 case MIIM_AUX_CNTRL_STAT_SPEED_1000M:
1087 phydev->speed = SPEED_1000;
1089 case MIIM_AUX_CNTRL_STAT_SPEED_100M:
1090 phydev->speed = SPEED_100;
1092 case MIIM_AUX_CNTRL_STAT_SPEED_10M:
1093 phydev->speed = SPEED_10;
1096 phydev->speed = SPEED_10;
1103 static int mscc_startup(struct phy_device *phydev)
1107 retval = genphy_update_link(phydev);
1112 return mscc_parse_status(phydev);
1115 static int mscc_phy_soft_reset(struct phy_device *phydev)
1118 u16 timeout = MSCC_PHY_RESET_TIMEOUT;
1121 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1124 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
1125 phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, (reg_val | BMCR_RESET));
1127 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
1129 while ((reg_val & BMCR_RESET) && (timeout > 0)) {
1130 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
1132 udelay(1000); /* 1 ms */
1136 printf("MSCC PHY Soft_Reset Error: mac i/f = 0x%x\n",
1144 static int vsc8531_vsc8541_mac_config(struct phy_device *phydev)
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;
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;
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;
1177 printf("MSCC PHY - INVALID MAC i/f Config: mac i/f = 0x%x\n",
1182 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
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);
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,
1211 static int vsc8531_config(struct phy_device *phydev)
1213 int retval = -EINVAL;
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;
1220 /* For VSC8530/31 and VSC8540/41 the init scripts are the same */
1221 mscc_vsc8531_vsc8541_init_scripts(phydev);
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);
1231 retval = mscc_phy_soft_reset(phydev);
1236 printf("PHY 8530/31 MAC i/f Config Error: mac i/f = 0x%x\n",
1240 /* Default RMII Clk Output to 0=OFF/1=ON */
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);
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);
1254 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG, reg_val);
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,
1268 return genphy_config_aneg(phydev);
1271 static int vsc8541_config(struct phy_device *phydev)
1273 int retval = -EINVAL;
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;
1280 /* For VSC8530/31 and VSC8540/41 the init scripts are the same */
1281 mscc_vsc8531_vsc8541_init_scripts(phydev);
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);
1293 retval = mscc_phy_soft_reset(phydev);
1298 printf("PHY 8541 MAC i/f config Error: mac i/f = 0x%x\n",
1302 /* Default RMII Clk Output to 0=OFF/1=ON */
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);
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,
1328 return genphy_config_aneg(phydev);
1331 static int vsc8584_config_init(struct phy_device *phydev)
1333 struct vsc85xx_priv *priv = phydev->priv;
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;
1344 ret = priv->config_pre(phydev);
1348 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1349 MSCC_PHY_PAGE_GPIO);
1351 if (phydev->interface == PHY_INTERFACE_MODE_QSGMII)
1352 val = MAC_CFG_QSGMII;
1354 val = MAC_CFG_SGMII;
1356 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_MAC_CFG_FASTLINK);
1357 reg_val &= ~MAC_CFG_MASK;
1359 ret = phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_MAC_CFG_FASTLINK,
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;
1369 reg_val |= PROC_CMD_SGMII_MAC;
1371 ret = vsc8584_cmd(phydev->bus, phydev->addr, reg_val);
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);
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);
1393 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
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,
1404 ret = mscc_phy_soft_reset(phydev);
1408 return genphy_config(phydev);
1411 static struct vsc85xx_priv vsc8574_priv = {
1412 .config_pre = vsc8574_config_pre_init,
1415 static int vsc8574_config(struct phy_device *phydev)
1417 phydev->priv = &vsc8574_priv;
1419 return vsc8584_config_init(phydev);
1422 static struct vsc85xx_priv vsc8584_priv = {
1423 .config_pre = vsc8584_config_pre_init,
1426 static int vsc8584_config(struct phy_device *phydev)
1428 phydev->priv = &vsc8584_priv;
1430 return vsc8584_config_init(phydev);
1433 static struct phy_driver VSC8530_driver = {
1434 .name = "Microsemi VSC8530",
1435 .uid = PHY_ID_VSC8530,
1437 .features = PHY_BASIC_FEATURES,
1438 .config = &vsc8531_config,
1439 .startup = &mscc_startup,
1440 .shutdown = &genphy_shutdown,
1443 static struct phy_driver VSC8531_driver = {
1444 .name = "Microsemi VSC8531",
1445 .uid = PHY_ID_VSC8531,
1447 .features = PHY_GBIT_FEATURES,
1448 .config = &vsc8531_config,
1449 .startup = &mscc_startup,
1450 .shutdown = &genphy_shutdown,
1453 static struct phy_driver VSC8540_driver = {
1454 .name = "Microsemi VSC8540",
1455 .uid = PHY_ID_VSC8540,
1457 .features = PHY_BASIC_FEATURES,
1458 .config = &vsc8541_config,
1459 .startup = &mscc_startup,
1460 .shutdown = &genphy_shutdown,
1463 static struct phy_driver VSC8541_driver = {
1464 .name = "Microsemi VSC8541",
1465 .uid = PHY_ID_VSC8541,
1467 .features = PHY_GBIT_FEATURES,
1468 .config = &vsc8541_config,
1469 .startup = &mscc_startup,
1470 .shutdown = &genphy_shutdown,
1473 static struct phy_driver VSC8574_driver = {
1474 .name = "Microsemi VSC8574",
1475 .uid = PHY_ID_VSC8574,
1477 .features = PHY_GBIT_FEATURES,
1478 .config = &vsc8574_config,
1479 .startup = &mscc_startup,
1480 .shutdown = &genphy_shutdown,
1483 static struct phy_driver VSC8584_driver = {
1484 .name = "Microsemi VSC8584",
1485 .uid = PHY_ID_VSC8584,
1487 .features = PHY_GBIT_FEATURES,
1488 .config = &vsc8584_config,
1489 .startup = &mscc_startup,
1490 .shutdown = &genphy_shutdown,
1493 int phy_mscc_init(void)
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);