1 // SPDX-License-Identifier: MIT
3 * Microsemi PHY drivers
6 * Copyright (c) 2016 Microsemi Corporation
8 * Author: John Haechten
16 #include <linux/bitops.h>
17 #include <linux/delay.h>
19 /* Microsemi PHY ID's */
20 #define PHY_ID_VSC8530 0x00070560
21 #define PHY_ID_VSC8531 0x00070570
22 #define PHY_ID_VSC8540 0x00070760
23 #define PHY_ID_VSC8541 0x00070770
24 #define PHY_ID_VSC8574 0x000704a0
25 #define PHY_ID_VSC8584 0x000707c0
27 /* Microsemi VSC85xx PHY Register Pages */
28 #define MSCC_EXT_PAGE_ACCESS 31 /* Page Access Register */
29 #define MSCC_PHY_PAGE_STD 0x0000 /* Standard registers */
30 #define MSCC_PHY_PAGE_EXT1 0x0001 /* Extended registers - page 1 */
31 #define MSCC_PHY_PAGE_EXT2 0x0002 /* Extended registers - page 2 */
32 #define MSCC_PHY_PAGE_EXT3 0x0003 /* Extended registers - page 3 */
33 #define MSCC_PHY_PAGE_EXT4 0x0004 /* Extended registers - page 4 */
34 #define MSCC_PHY_PAGE_GPIO 0x0010 /* GPIO registers */
35 #define MSCC_PHY_PAGE_TEST 0x2A30 /* TEST Page registers */
36 #define MSCC_PHY_PAGE_TR 0x52B5 /* Token Ring Page registers */
38 /* Std Page Register 18 */
39 #define MSCC_PHY_BYPASS_CONTROL 18
40 #define PARALLEL_DET_IGNORE_ADVERTISED BIT(3)
42 /* Std Page Register 22 */
43 #define MSCC_PHY_EXT_CNTL_STATUS 22
44 #define SMI_BROADCAST_WR_EN BIT(0)
46 /* Std Page Register 24 */
47 #define MSCC_PHY_EXT_PHY_CNTL_2 24
49 /* Std Page Register 28 - PHY AUX Control/Status */
50 #define MIIM_AUX_CNTRL_STAT_REG 28
51 #define MIIM_AUX_CNTRL_STAT_ACTIPHY_TO (0x0004)
52 #define MIIM_AUX_CNTRL_STAT_F_DUPLEX (0x0020)
53 #define MIIM_AUX_CNTRL_STAT_SPEED_MASK (0x0018)
54 #define MIIM_AUX_CNTRL_STAT_SPEED_POS (3)
55 #define MIIM_AUX_CNTRL_STAT_SPEED_10M (0x0)
56 #define MIIM_AUX_CNTRL_STAT_SPEED_100M (0x1)
57 #define MIIM_AUX_CNTRL_STAT_SPEED_1000M (0x2)
59 /* Std Page Register 23 - Extended PHY CTRL_1 */
60 #define MSCC_PHY_EXT_PHY_CNTL_1_REG 23
61 #define MAC_IF_SELECTION_MASK (0x1800)
62 #define MAC_IF_SELECTION_GMII (0)
63 #define MAC_IF_SELECTION_RMII (1)
64 #define MAC_IF_SELECTION_RGMII (2)
65 #define MAC_IF_SELECTION_POS (11)
66 #define MAC_IF_SELECTION_WIDTH (2)
67 #define VSC8584_MAC_IF_SELECTION_MASK BIT(12)
68 #define VSC8584_MAC_IF_SELECTION_SGMII 0
69 #define VSC8584_MAC_IF_SELECTION_1000BASEX 1
70 #define VSC8584_MAC_IF_SELECTION_POS 12
71 #define MEDIA_OP_MODE_MASK GENMASK(10, 8)
72 #define MEDIA_OP_MODE_COPPER 0
73 #define MEDIA_OP_MODE_SERDES 1
74 #define MEDIA_OP_MODE_1000BASEX 2
75 #define MEDIA_OP_MODE_100BASEFX 3
76 #define MEDIA_OP_MODE_AMS_COPPER_SERDES 5
77 #define MEDIA_OP_MODE_AMS_COPPER_1000BASEX 6
78 #define MEDIA_OP_MODE_AMS_COPPER_100BASEFX 7
79 #define MEDIA_OP_MODE_POS 8
81 /* Extended Page 1 Register 20E1 */
82 #define MSCC_PHY_ACTIPHY_CNTL 20
83 #define PHY_ADDR_REVERSED BIT(9)
85 /* Extended Page 1 Register 23E1 */
87 #define MSCC_PHY_EXT_PHY_CNTL_4 23
88 #define PHY_CNTL_4_ADDR_POS 11
90 /* Extended Page 1 Register 25E1 */
91 #define MSCC_PHY_VERIPHY_CNTL_2 25
93 /* Extended Page 1 Register 26E1 */
94 #define MSCC_PHY_VERIPHY_CNTL_3 26
96 /* Extended Page 2 Register 16E2 */
97 #define MSCC_PHY_CU_PMD_TX_CNTL 16
99 /* Extended Page 2 Register 20E2 */
100 #define MSCC_PHY_RGMII_CNTL_REG 20
101 #define VSC_FAST_LINK_FAIL2_ENA_MASK (0x8000)
102 #define RX_CLK_OUT_MASK (0x0800)
103 #define RX_CLK_OUT_POS (11)
104 #define RX_CLK_OUT_WIDTH (1)
105 #define RX_CLK_OUT_NORMAL (0)
106 #define RX_CLK_OUT_DISABLE (1)
107 #define RGMII_RX_CLK_DELAY_POS (4)
108 #define RGMII_RX_CLK_DELAY_WIDTH (3)
109 #define RGMII_RX_CLK_DELAY_MASK (0x0070)
110 #define RGMII_TX_CLK_DELAY_POS (0)
111 #define RGMII_TX_CLK_DELAY_WIDTH (3)
112 #define RGMII_TX_CLK_DELAY_MASK (0x0007)
114 /* Extended Page 2 Register 27E2 */
115 #define MSCC_PHY_WOL_MAC_CONTROL 27
116 #define EDGE_RATE_CNTL_POS (5)
117 #define EDGE_RATE_CNTL_WIDTH (3)
118 #define EDGE_RATE_CNTL_MASK (0x00E0)
119 #define RMII_CLK_OUT_ENABLE_POS (4)
120 #define RMII_CLK_OUT_ENABLE_WIDTH (1)
121 #define RMII_CLK_OUT_ENABLE_MASK (0x10)
123 /* Extended Page 3 Register 22E3 */
124 #define MSCC_PHY_SERDES_TX_CRC_ERR_CNT 22
126 /* Extended page GPIO register 00G */
127 #define MSCC_DW8051_CNTL_STATUS 0
128 #define MICRO_NSOFT_RESET BIT(15)
129 #define RUN_FROM_INT_ROM BIT(14)
130 #define AUTOINC_ADDR BIT(13)
131 #define PATCH_RAM_CLK BIT(12)
132 #define MICRO_PATCH_EN BIT(7)
133 #define DW8051_CLK_EN BIT(4)
134 #define MICRO_CLK_EN BIT(3)
135 #define MICRO_CLK_DIVIDE(x) ((x) >> 1)
136 #define MSCC_DW8051_VLD_MASK 0xf1ff
138 /* Extended page GPIO register 09G */
139 #define MSCC_TRAP_ROM_ADDR(x) ((x) * 2 + 1)
140 #define MSCC_TRAP_ROM_ADDR_SERDES_INIT 0x3eb7
142 /* Extended page GPIO register 10G */
143 #define MSCC_PATCH_RAM_ADDR(x) (((x) + 1) * 2)
144 #define MSCC_PATCH_RAM_ADDR_SERDES_INIT 0x4012
146 /* Extended page GPIO register 11G */
147 #define MSCC_INT_MEM_ADDR 11
149 /* Extended page GPIO register 12G */
150 #define MSCC_INT_MEM_CNTL 12
151 #define READ_SFR (BIT(14) | BIT(13))
152 #define READ_PRAM BIT(14)
153 #define READ_ROM BIT(13)
154 #define READ_RAM (0x00 << 13)
155 #define INT_MEM_WRITE_EN BIT(12)
156 #define EN_PATCH_RAM_TRAP_ADDR(x) BIT((x) + 7)
157 #define INT_MEM_DATA_M GENMASK(7, 0)
158 #define INT_MEM_DATA(x) (INT_MEM_DATA_M & (x))
160 /* Extended page GPIO register 18G */
161 #define MSCC_PHY_PROC_CMD 18
162 #define PROC_CMD_NCOMPLETED BIT(15)
163 #define PROC_CMD_FAILED BIT(14)
164 #define PROC_CMD_SGMII_PORT(x) ((x) << 8)
165 #define PROC_CMD_FIBER_PORT(x) BIT(8 + (x) % 4)
166 #define PROC_CMD_QSGMII_PORT (BIT(11) | BIT(10))
167 #define PROC_CMD_RST_CONF_PORT BIT(7)
168 #define PROC_CMD_RECONF_PORT (0 << 7)
169 #define PROC_CMD_READ_MOD_WRITE_PORT BIT(6)
170 #define PROC_CMD_WRITE BIT(6)
171 #define PROC_CMD_READ (0 << 6)
172 #define PROC_CMD_FIBER_DISABLE BIT(5)
173 #define PROC_CMD_FIBER_100BASE_FX BIT(4)
174 #define PROC_CMD_FIBER_1000BASE_X (0 << 4)
175 #define PROC_CMD_SGMII_MAC (BIT(5) | BIT(4))
176 #define PROC_CMD_QSGMII_MAC BIT(5)
177 #define PROC_CMD_NO_MAC_CONF (0x00 << 4)
178 #define PROC_CMD_1588_DEFAULT_INIT BIT(4)
179 #define PROC_CMD_NOP GENMASK(3, 0)
180 #define PROC_CMD_PHY_INIT (BIT(3) | BIT(1))
181 #define PROC_CMD_CRC16 BIT(3)
182 #define PROC_CMD_FIBER_MEDIA_CONF BIT(0)
183 #define PROC_CMD_MCB_ACCESS_MAC_CONF (0x0000 << 0)
184 #define PROC_CMD_NCOMPLETED_TIMEOUT_MS 500
186 /* Extended page GPIO register 19G */
187 #define MSCC_PHY_MAC_CFG_FASTLINK 19
188 #define MAC_CFG_MASK GENMASK(15, 14)
189 #define MAC_CFG_SGMII (0x00 << 14)
190 #define MAC_CFG_QSGMII BIT(14)
193 #define MSCC_PHY_TEST_PAGE_5 5
195 #define MSCC_PHY_TEST_PAGE_8 8
196 #define TR_CLK_DISABLE BIT(15)
198 #define MSCC_PHY_TEST_PAGE_9 9
199 #define MSCC_PHY_TEST_PAGE_20 20
200 #define MSCC_PHY_TEST_PAGE_24 24
202 /* Token Ring Page 0x52B5 Registers */
203 #define MSCC_PHY_REG_TR_ADDR_16 16
204 #define MSCC_PHY_REG_TR_DATA_17 17
205 #define MSCC_PHY_REG_TR_DATA_18 18
207 /* Token Ring - Read Value in */
208 #define MSCC_PHY_TR_16_READ (0xA000)
209 /* Token Ring - Write Value out */
210 #define MSCC_PHY_TR_16_WRITE (0x8000)
212 /* Token Ring Registers */
213 #define MSCC_PHY_TR_LINKDETCTRL_POS (3)
214 #define MSCC_PHY_TR_LINKDETCTRL_WIDTH (2)
215 #define MSCC_PHY_TR_LINKDETCTRL_VAL (3)
216 #define MSCC_PHY_TR_LINKDETCTRL_MASK (0x0018)
217 #define MSCC_PHY_TR_LINKDETCTRL_ADDR (0x07F8)
219 #define MSCC_PHY_TR_VGATHRESH100_POS (0)
220 #define MSCC_PHY_TR_VGATHRESH100_WIDTH (7)
221 #define MSCC_PHY_TR_VGATHRESH100_VAL (0x0018)
222 #define MSCC_PHY_TR_VGATHRESH100_MASK (0x007f)
223 #define MSCC_PHY_TR_VGATHRESH100_ADDR (0x0FA4)
225 #define MSCC_PHY_TR_VGAGAIN10_U_POS (0)
226 #define MSCC_PHY_TR_VGAGAIN10_U_WIDTH (1)
227 #define MSCC_PHY_TR_VGAGAIN10_U_MASK (0x0001)
228 #define MSCC_PHY_TR_VGAGAIN10_U_VAL (0)
230 #define MSCC_PHY_TR_VGAGAIN10_L_POS (12)
231 #define MSCC_PHY_TR_VGAGAIN10_L_WIDTH (4)
232 #define MSCC_PHY_TR_VGAGAIN10_L_MASK (0xf000)
233 #define MSCC_PHY_TR_VGAGAIN10_L_VAL (0x0001)
234 #define MSCC_PHY_TR_VGAGAIN10_ADDR (0x0F92)
236 /* General Timeout Values */
237 #define MSCC_PHY_RESET_TIMEOUT (100)
238 #define MSCC_PHY_MICRO_TIMEOUT (500)
240 #define VSC8584_REVB 0x0001
241 #define MSCC_DEV_REV_MASK GENMASK(3, 0)
243 #define MSCC_VSC8574_REVB_INT8051_FW_START_ADDR 0x4000
244 #define MSCC_VSC8574_REVB_INT8051_FW_CRC 0x29e8
246 #define MSCC_VSC8584_REVB_INT8051_FW_START_ADDR 0xe800
247 #define MSCC_VSC8584_REVB_INT8051_FW_CRC 0xfb48
249 /* RGMII/GMII Clock Delay (Skew) Options */ enum vsc_phy_rgmii_skew {
250 VSC_PHY_RGMII_DELAY_200_PS,
251 VSC_PHY_RGMII_DELAY_800_PS,
252 VSC_PHY_RGMII_DELAY_1100_PS,
253 VSC_PHY_RGMII_DELAY_1700_PS,
254 VSC_PHY_RGMII_DELAY_2000_PS,
255 VSC_PHY_RGMII_DELAY_2300_PS,
256 VSC_PHY_RGMII_DELAY_2600_PS,
257 VSC_PHY_RGMII_DELAY_3400_PS,
260 /* MAC i/f Clock Edge Rage Control (Slew), See Reg27E2 */ enum
262 VSC_PHY_CLK_SLEW_RATE_0,
263 VSC_PHY_CLK_SLEW_RATE_1,
264 VSC_PHY_CLK_SLEW_RATE_2,
265 VSC_PHY_CLK_SLEW_RATE_3,
266 VSC_PHY_CLK_SLEW_RATE_4,
267 VSC_PHY_CLK_SLEW_RATE_5,
268 VSC_PHY_CLK_SLEW_RATE_6,
269 VSC_PHY_CLK_SLEW_RATE_7,
272 struct vsc85xx_priv {
273 int (*config_pre)(struct phy_device *phydev);
276 static void vsc8584_csr_write(struct mii_dev *bus, int phy0, u16 addr, u32 val)
278 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18,
280 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17,
281 val & GENMASK(15, 0));
282 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
283 MSCC_PHY_TR_16_WRITE | addr);
286 static int vsc8584_cmd(struct mii_dev *bus, int phy, u16 val)
288 unsigned long deadline;
291 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
294 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_PROC_CMD,
295 PROC_CMD_NCOMPLETED | val);
297 deadline = timer_get_us() + PROC_CMD_NCOMPLETED_TIMEOUT_MS * 1000;
299 reg_val = bus->read(bus, phy, MDIO_DEVAD_NONE,
301 } while (timer_get_us() <= deadline &&
302 (reg_val & PROC_CMD_NCOMPLETED) &&
303 !(reg_val & PROC_CMD_FAILED));
305 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
308 if (reg_val & PROC_CMD_FAILED)
310 if (reg_val & PROC_CMD_NCOMPLETED)
316 static int vsc8584_micro_deassert_reset(struct mii_dev *bus, int phy,
321 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
324 enable = RUN_FROM_INT_ROM | MICRO_CLK_EN | DW8051_CLK_EN;
325 release = MICRO_NSOFT_RESET | RUN_FROM_INT_ROM | DW8051_CLK_EN |
329 enable |= MICRO_PATCH_EN;
330 release |= MICRO_PATCH_EN;
332 /* Clear all patches */
333 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL,
338 * Enable 8051 Micro clock; CLEAR/SET patch present; disable PRAM clock
339 * override and addr. auto-incr; operate at 125 MHz
341 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_DW8051_CNTL_STATUS, enable);
342 /* Release 8051 Micro SW reset */
343 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_DW8051_CNTL_STATUS, release);
345 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
351 static int vsc8584_micro_assert_reset(struct mii_dev *bus, int phy)
356 ret = vsc8584_cmd(bus, phy, PROC_CMD_NOP);
360 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
363 reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL);
364 reg &= ~EN_PATCH_RAM_TRAP_ADDR(4);
365 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL, reg);
367 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_TRAP_ROM_ADDR(4), 0x005b);
368 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_PATCH_RAM_ADDR(4), 0x005b);
370 reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL);
371 reg |= EN_PATCH_RAM_TRAP_ADDR(4);
372 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL, reg);
374 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_PROC_CMD, PROC_CMD_NOP);
376 reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_DW8051_CNTL_STATUS);
377 reg &= ~MICRO_NSOFT_RESET;
378 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_DW8051_CNTL_STATUS, reg);
380 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_PROC_CMD,
381 PROC_CMD_MCB_ACCESS_MAC_CONF | PROC_CMD_SGMII_PORT(0) |
382 PROC_CMD_NO_MAC_CONF | PROC_CMD_READ);
384 reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL);
385 reg &= ~EN_PATCH_RAM_TRAP_ADDR(4);
386 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL, reg);
388 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
394 static const u8 fw_patch_vsc8574[] = {
395 0x46, 0x4a, 0x02, 0x43, 0x37, 0x02, 0x46, 0x26, 0x02, 0x46, 0x77, 0x02,
396 0x45, 0x60, 0x02, 0x45, 0xaf, 0xed, 0xff, 0xe5, 0xfc, 0x54, 0x38, 0x64,
397 0x20, 0x70, 0x08, 0x65, 0xff, 0x70, 0x04, 0xed, 0x44, 0x80, 0xff, 0x22,
398 0x8f, 0x19, 0x7b, 0xbb, 0x7d, 0x0e, 0x7f, 0x04, 0x12, 0x3d, 0xd7, 0xef,
399 0x4e, 0x60, 0x03, 0x02, 0x41, 0xf9, 0xe4, 0xf5, 0x1a, 0x74, 0x01, 0x7e,
400 0x00, 0xa8, 0x1a, 0x08, 0x80, 0x05, 0xc3, 0x33, 0xce, 0x33, 0xce, 0xd8,
401 0xf9, 0xff, 0xef, 0x55, 0x19, 0x70, 0x03, 0x02, 0x41, 0xed, 0x85, 0x1a,
402 0xfb, 0x7b, 0xbb, 0xe4, 0xfd, 0xff, 0x12, 0x3d, 0xd7, 0xef, 0x4e, 0x60,
403 0x03, 0x02, 0x41, 0xed, 0xe5, 0x1a, 0x54, 0x02, 0x75, 0x1d, 0x00, 0x25,
404 0xe0, 0x25, 0xe0, 0xf5, 0x1c, 0xe4, 0x78, 0xc5, 0xf6, 0xd2, 0x0a, 0x12,
405 0x41, 0xfa, 0x7b, 0xff, 0x7d, 0x12, 0x7f, 0x07, 0x12, 0x3d, 0xd7, 0xef,
406 0x4e, 0x60, 0x03, 0x02, 0x41, 0xe7, 0xc2, 0x0a, 0x74, 0xc7, 0x25, 0x1a,
407 0xf9, 0x74, 0xe7, 0x25, 0x1a, 0xf8, 0xe6, 0x27, 0xf5, 0x1b, 0xe5, 0x1d,
408 0x24, 0x5b, 0x12, 0x45, 0xea, 0x12, 0x3e, 0xda, 0x7b, 0xfc, 0x7d, 0x11,
409 0x7f, 0x07, 0x12, 0x3d, 0xd7, 0x78, 0xcc, 0xef, 0xf6, 0x78, 0xc1, 0xe6,
410 0xfe, 0xef, 0xd3, 0x9e, 0x40, 0x06, 0x78, 0xcc, 0xe6, 0x78, 0xc1, 0xf6,
411 0x12, 0x41, 0xfa, 0x7b, 0xec, 0x7d, 0x12, 0x7f, 0x07, 0x12, 0x3d, 0xd7,
412 0x78, 0xcb, 0xef, 0xf6, 0xbf, 0x07, 0x06, 0x78, 0xc3, 0x76, 0x1a, 0x80,
413 0x1f, 0x78, 0xc5, 0xe6, 0xff, 0x60, 0x0f, 0xc3, 0xe5, 0x1b, 0x9f, 0xff,
414 0x78, 0xcb, 0xe6, 0x85, 0x1b, 0xf0, 0xa4, 0x2f, 0x80, 0x07, 0x78, 0xcb,
415 0xe6, 0x85, 0x1b, 0xf0, 0xa4, 0x78, 0xc3, 0xf6, 0xe4, 0x78, 0xc2, 0xf6,
416 0x78, 0xc2, 0xe6, 0xff, 0xc3, 0x08, 0x96, 0x40, 0x03, 0x02, 0x41, 0xd1,
417 0xef, 0x54, 0x03, 0x60, 0x33, 0x14, 0x60, 0x46, 0x24, 0xfe, 0x60, 0x42,
418 0x04, 0x70, 0x4b, 0xef, 0x24, 0x02, 0xff, 0xe4, 0x33, 0xfe, 0xef, 0x78,
419 0x02, 0xce, 0xa2, 0xe7, 0x13, 0xce, 0x13, 0xd8, 0xf8, 0xff, 0xe5, 0x1d,
420 0x24, 0x5c, 0xcd, 0xe5, 0x1c, 0x34, 0xf0, 0xcd, 0x2f, 0xff, 0xed, 0x3e,
421 0xfe, 0x12, 0x46, 0x0d, 0x7d, 0x11, 0x80, 0x0b, 0x78, 0xc2, 0xe6, 0x70,
422 0x04, 0x7d, 0x11, 0x80, 0x02, 0x7d, 0x12, 0x7f, 0x07, 0x12, 0x3e, 0x9a,
423 0x8e, 0x1e, 0x8f, 0x1f, 0x80, 0x03, 0xe5, 0x1e, 0xff, 0x78, 0xc5, 0xe6,
424 0x06, 0x24, 0xcd, 0xf8, 0xa6, 0x07, 0x78, 0xc2, 0x06, 0xe6, 0xb4, 0x1a,
425 0x0a, 0xe5, 0x1d, 0x24, 0x5c, 0x12, 0x45, 0xea, 0x12, 0x3e, 0xda, 0x78,
426 0xc5, 0xe6, 0x65, 0x1b, 0x70, 0x82, 0x75, 0xdb, 0x20, 0x75, 0xdb, 0x28,
427 0x12, 0x46, 0x02, 0x12, 0x46, 0x02, 0xe5, 0x1a, 0x12, 0x45, 0xf5, 0xe5,
428 0x1a, 0xc3, 0x13, 0x12, 0x45, 0xf5, 0x78, 0xc5, 0x16, 0xe6, 0x24, 0xcd,
429 0xf8, 0xe6, 0xff, 0x7e, 0x08, 0x1e, 0xef, 0xa8, 0x06, 0x08, 0x80, 0x02,
430 0xc3, 0x13, 0xd8, 0xfc, 0xfd, 0xc4, 0x33, 0x54, 0xe0, 0xf5, 0xdb, 0xef,
431 0xa8, 0x06, 0x08, 0x80, 0x02, 0xc3, 0x13, 0xd8, 0xfc, 0xfd, 0xc4, 0x33,
432 0x54, 0xe0, 0x44, 0x08, 0xf5, 0xdb, 0xee, 0x70, 0xd8, 0x78, 0xc5, 0xe6,
433 0x70, 0xc8, 0x75, 0xdb, 0x10, 0x02, 0x40, 0xfd, 0x78, 0xc2, 0xe6, 0xc3,
434 0x94, 0x17, 0x50, 0x0e, 0xe5, 0x1d, 0x24, 0x62, 0x12, 0x42, 0x08, 0xe5,
435 0x1d, 0x24, 0x5c, 0x12, 0x42, 0x08, 0x20, 0x0a, 0x03, 0x02, 0x40, 0x76,
436 0x05, 0x1a, 0xe5, 0x1a, 0xc3, 0x94, 0x04, 0x50, 0x03, 0x02, 0x40, 0x3a,
437 0x22, 0xe5, 0x1d, 0x24, 0x5c, 0xff, 0xe5, 0x1c, 0x34, 0xf0, 0xfe, 0x12,
438 0x46, 0x0d, 0x22, 0xff, 0xe5, 0x1c, 0x34, 0xf0, 0xfe, 0x12, 0x46, 0x0d,
439 0x22, 0xe4, 0xf5, 0x19, 0x12, 0x46, 0x43, 0x20, 0xe7, 0x1e, 0x7b, 0xfe,
440 0x12, 0x42, 0xf9, 0xef, 0xc4, 0x33, 0x33, 0x54, 0xc0, 0xff, 0xc0, 0x07,
441 0x7b, 0x54, 0x12, 0x42, 0xf9, 0xd0, 0xe0, 0x4f, 0xff, 0x74, 0x2a, 0x25,
442 0x19, 0xf8, 0xa6, 0x07, 0x12, 0x46, 0x43, 0x20, 0xe7, 0x03, 0x02, 0x42,
443 0xdf, 0x54, 0x03, 0x64, 0x03, 0x70, 0x03, 0x02, 0x42, 0xcf, 0x7b, 0xcb,
444 0x12, 0x43, 0x2c, 0x8f, 0xfb, 0x7b, 0x30, 0x7d, 0x03, 0xe4, 0xff, 0x12,
445 0x3d, 0xd7, 0xc3, 0xef, 0x94, 0x02, 0xee, 0x94, 0x00, 0x50, 0x2a, 0x12,
446 0x42, 0xec, 0xef, 0x4e, 0x70, 0x23, 0x12, 0x43, 0x04, 0x60, 0x0a, 0x12,
447 0x43, 0x12, 0x70, 0x0c, 0x12, 0x43, 0x1f, 0x70, 0x07, 0x12, 0x46, 0x39,
448 0x7b, 0x03, 0x80, 0x07, 0x12, 0x46, 0x39, 0x12, 0x46, 0x43, 0xfb, 0x7a,
449 0x00, 0x7d, 0x54, 0x80, 0x3e, 0x12, 0x42, 0xec, 0xef, 0x4e, 0x70, 0x24,
450 0x12, 0x43, 0x04, 0x60, 0x0a, 0x12, 0x43, 0x12, 0x70, 0x0f, 0x12, 0x43,
451 0x1f, 0x70, 0x0a, 0x12, 0x46, 0x39, 0xe4, 0xfb, 0xfa, 0x7d, 0xee, 0x80,
452 0x1e, 0x12, 0x46, 0x39, 0x7b, 0x01, 0x7a, 0x00, 0x7d, 0xee, 0x80, 0x13,
453 0x12, 0x46, 0x39, 0x12, 0x46, 0x43, 0x54, 0x40, 0xfe, 0xc4, 0x13, 0x13,
454 0x54, 0x03, 0xfb, 0x7a, 0x00, 0x7d, 0xee, 0x12, 0x38, 0xbd, 0x7b, 0xff,
455 0x12, 0x43, 0x2c, 0xef, 0x4e, 0x70, 0x07, 0x74, 0x2a, 0x25, 0x19, 0xf8,
456 0xe4, 0xf6, 0x05, 0x19, 0xe5, 0x19, 0xc3, 0x94, 0x02, 0x50, 0x03, 0x02,
457 0x42, 0x15, 0x22, 0xe5, 0x19, 0x24, 0x17, 0xfd, 0x7b, 0x20, 0x7f, 0x04,
458 0x12, 0x3d, 0xd7, 0x22, 0xe5, 0x19, 0x24, 0x17, 0xfd, 0x7f, 0x04, 0x12,
459 0x3d, 0xd7, 0x22, 0x7b, 0x22, 0x7d, 0x18, 0x7f, 0x06, 0x12, 0x3d, 0xd7,
460 0xef, 0x64, 0x01, 0x4e, 0x22, 0x7d, 0x1c, 0xe4, 0xff, 0x12, 0x3e, 0x9a,
461 0xef, 0x54, 0x1b, 0x64, 0x0a, 0x22, 0x7b, 0xcc, 0x7d, 0x10, 0xff, 0x12,
462 0x3d, 0xd7, 0xef, 0x64, 0x01, 0x4e, 0x22, 0xe5, 0x19, 0x24, 0x17, 0xfd,
463 0x7f, 0x04, 0x12, 0x3d, 0xd7, 0x22, 0xd2, 0x08, 0x75, 0xfb, 0x03, 0xab,
464 0x7e, 0xaa, 0x7d, 0x7d, 0x19, 0x7f, 0x03, 0x12, 0x3e, 0xda, 0xe5, 0x7e,
465 0x54, 0x0f, 0x24, 0xf3, 0x60, 0x03, 0x02, 0x43, 0xe9, 0x12, 0x46, 0x5a,
466 0x12, 0x46, 0x61, 0xd8, 0xfb, 0xff, 0x20, 0xe2, 0x35, 0x13, 0x92, 0x0c,
467 0xef, 0xa2, 0xe1, 0x92, 0x0b, 0x30, 0x0c, 0x2a, 0xe4, 0xf5, 0x10, 0x7b,
468 0xfe, 0x12, 0x43, 0xff, 0xef, 0xc4, 0x33, 0x33, 0x54, 0xc0, 0xff, 0xc0,
469 0x07, 0x7b, 0x54, 0x12, 0x43, 0xff, 0xd0, 0xe0, 0x4f, 0xff, 0x74, 0x2a,
470 0x25, 0x10, 0xf8, 0xa6, 0x07, 0x05, 0x10, 0xe5, 0x10, 0xc3, 0x94, 0x02,
471 0x40, 0xd9, 0x12, 0x46, 0x5a, 0x12, 0x46, 0x61, 0xd8, 0xfb, 0x54, 0x05,
472 0x64, 0x04, 0x70, 0x27, 0x78, 0xc4, 0xe6, 0x78, 0xc6, 0xf6, 0xe5, 0x7d,
473 0xff, 0x33, 0x95, 0xe0, 0xef, 0x54, 0x0f, 0x78, 0xc4, 0xf6, 0x12, 0x44,
474 0x0a, 0x20, 0x0c, 0x0c, 0x12, 0x46, 0x5a, 0x12, 0x46, 0x61, 0xd8, 0xfb,
475 0x13, 0x92, 0x0d, 0x22, 0xc2, 0x0d, 0x22, 0x12, 0x46, 0x5a, 0x12, 0x46,
476 0x61, 0xd8, 0xfb, 0x54, 0x05, 0x64, 0x05, 0x70, 0x1e, 0x78, 0xc4, 0x7d,
477 0xb8, 0x12, 0x43, 0xf5, 0x78, 0xc1, 0x7d, 0x74, 0x12, 0x43, 0xf5, 0xe4,
478 0x78, 0xc1, 0xf6, 0x22, 0x7b, 0x01, 0x7a, 0x00, 0x7d, 0xee, 0x7f, 0x92,
479 0x12, 0x38, 0xbd, 0x22, 0xe6, 0xfb, 0x7a, 0x00, 0x7f, 0x92, 0x12, 0x38,
480 0xbd, 0x22, 0xe5, 0x10, 0x24, 0x17, 0xfd, 0x7f, 0x04, 0x12, 0x3d, 0xd7,
481 0x22, 0x78, 0xc1, 0xe6, 0xfb, 0x7a, 0x00, 0x7d, 0x74, 0x7f, 0x92, 0x12,
482 0x38, 0xbd, 0xe4, 0x78, 0xc1, 0xf6, 0xf5, 0x11, 0x74, 0x01, 0x7e, 0x00,
483 0xa8, 0x11, 0x08, 0x80, 0x05, 0xc3, 0x33, 0xce, 0x33, 0xce, 0xd8, 0xf9,
484 0xff, 0x78, 0xc4, 0xe6, 0xfd, 0xef, 0x5d, 0x60, 0x44, 0x85, 0x11, 0xfb,
485 0xe5, 0x11, 0x54, 0x02, 0x25, 0xe0, 0x25, 0xe0, 0xfe, 0xe4, 0x24, 0x5b,
486 0xfb, 0xee, 0x12, 0x45, 0xed, 0x12, 0x3e, 0xda, 0x7b, 0x40, 0x7d, 0x11,
487 0x7f, 0x07, 0x12, 0x3d, 0xd7, 0x74, 0xc7, 0x25, 0x11, 0xf8, 0xa6, 0x07,
488 0x7b, 0x11, 0x7d, 0x12, 0x7f, 0x07, 0x12, 0x3d, 0xd7, 0xef, 0x4e, 0x60,
489 0x09, 0x74, 0xe7, 0x25, 0x11, 0xf8, 0x76, 0x04, 0x80, 0x07, 0x74, 0xe7,
490 0x25, 0x11, 0xf8, 0x76, 0x0a, 0x05, 0x11, 0xe5, 0x11, 0xc3, 0x94, 0x04,
491 0x40, 0x9a, 0x78, 0xc6, 0xe6, 0x70, 0x15, 0x78, 0xc4, 0xe6, 0x60, 0x10,
492 0x75, 0xd9, 0x38, 0x75, 0xdb, 0x10, 0x7d, 0xfe, 0x12, 0x44, 0xb8, 0x7d,
493 0x76, 0x12, 0x44, 0xb8, 0x79, 0xc6, 0xe7, 0x78, 0xc4, 0x66, 0xff, 0x60,
494 0x03, 0x12, 0x40, 0x25, 0x78, 0xc4, 0xe6, 0x70, 0x09, 0xfb, 0xfa, 0x7d,
495 0xfe, 0x7f, 0x8e, 0x12, 0x38, 0xbd, 0x22, 0x7b, 0x01, 0x7a, 0x00, 0x7f,
496 0x8e, 0x12, 0x38, 0xbd, 0x22, 0xe4, 0xf5, 0xfb, 0x7d, 0x1c, 0xe4, 0xff,
497 0x12, 0x3e, 0x9a, 0xad, 0x07, 0xac, 0x06, 0xec, 0x54, 0xc0, 0xff, 0xed,
498 0x54, 0x3f, 0x4f, 0xf5, 0x20, 0x30, 0x06, 0x2c, 0x30, 0x01, 0x08, 0xa2,
499 0x04, 0x72, 0x03, 0x92, 0x07, 0x80, 0x21, 0x30, 0x04, 0x06, 0x7b, 0xcc,
500 0x7d, 0x11, 0x80, 0x0d, 0x30, 0x03, 0x06, 0x7b, 0xcc, 0x7d, 0x10, 0x80,
501 0x04, 0x7b, 0x66, 0x7d, 0x16, 0xe4, 0xff, 0x12, 0x3d, 0xd7, 0xee, 0x4f,
502 0x24, 0xff, 0x92, 0x07, 0xaf, 0xfb, 0x74, 0x26, 0x2f, 0xf8, 0xe6, 0xff,
503 0xa6, 0x20, 0x20, 0x07, 0x39, 0x8f, 0x20, 0x30, 0x07, 0x34, 0x30, 0x00,
504 0x31, 0x20, 0x04, 0x2e, 0x20, 0x03, 0x2b, 0xe4, 0xf5, 0xff, 0x75, 0xfc,
505 0xc2, 0xe5, 0xfc, 0x30, 0xe0, 0xfb, 0xaf, 0xfe, 0xef, 0x20, 0xe3, 0x1a,
506 0xae, 0xfd, 0x44, 0x08, 0xf5, 0xfe, 0x75, 0xfc, 0x80, 0xe5, 0xfc, 0x30,
507 0xe0, 0xfb, 0x8f, 0xfe, 0x8e, 0xfd, 0x75, 0xfc, 0x80, 0xe5, 0xfc, 0x30,
508 0xe0, 0xfb, 0x05, 0xfb, 0xaf, 0xfb, 0xef, 0xc3, 0x94, 0x04, 0x50, 0x03,
509 0x02, 0x44, 0xc5, 0xe4, 0xf5, 0xfb, 0x22, 0xe5, 0x7e, 0x54, 0x0f, 0x64,
510 0x01, 0x70, 0x23, 0xe5, 0x7e, 0x30, 0xe4, 0x1e, 0x90, 0x47, 0xd0, 0xe0,
511 0x44, 0x02, 0xf0, 0x54, 0xfb, 0xf0, 0x90, 0x47, 0xd4, 0xe0, 0x44, 0x04,
512 0xf0, 0x7b, 0x03, 0x7d, 0x5b, 0x7f, 0x5d, 0x12, 0x36, 0x29, 0x7b, 0x0e,
513 0x80, 0x1c, 0x90, 0x47, 0xd0, 0xe0, 0x54, 0xfd, 0xf0, 0x44, 0x04, 0xf0,
514 0x90, 0x47, 0xd4, 0xe0, 0x54, 0xfb, 0xf0, 0x7b, 0x02, 0x7d, 0x5b, 0x7f,
515 0x5d, 0x12, 0x36, 0x29, 0x7b, 0x06, 0x7d, 0x60, 0x7f, 0x63, 0x12, 0x36,
516 0x29, 0x22, 0xe5, 0x7e, 0x30, 0xe5, 0x35, 0x30, 0xe4, 0x0b, 0x7b, 0x02,
517 0x7d, 0x33, 0x7f, 0x35, 0x12, 0x36, 0x29, 0x80, 0x10, 0x7b, 0x01, 0x7d,
518 0x33, 0x7f, 0x35, 0x12, 0x36, 0x29, 0x90, 0x47, 0xd2, 0xe0, 0x44, 0x04,
519 0xf0, 0x90, 0x47, 0xd2, 0xe0, 0x54, 0xf7, 0xf0, 0x90, 0x47, 0xd1, 0xe0,
520 0x44, 0x10, 0xf0, 0x7b, 0x05, 0x7d, 0x84, 0x7f, 0x86, 0x12, 0x36, 0x29,
521 0x22, 0xfb, 0xe5, 0x1c, 0x34, 0xf0, 0xfa, 0x7d, 0x10, 0x7f, 0x07, 0x22,
522 0x54, 0x01, 0xc4, 0x33, 0x54, 0xe0, 0xf5, 0xdb, 0x44, 0x08, 0xf5, 0xdb,
523 0x22, 0xf5, 0xdb, 0x75, 0xdb, 0x08, 0xf5, 0xdb, 0x75, 0xdb, 0x08, 0x22,
524 0xab, 0x07, 0xaa, 0x06, 0x7d, 0x10, 0x7f, 0x07, 0x12, 0x3e, 0xda, 0x7b,
525 0xff, 0x7d, 0x10, 0x7f, 0x07, 0x12, 0x3d, 0xd7, 0xef, 0x4e, 0x60, 0xf3,
526 0x22, 0x12, 0x44, 0xc2, 0x30, 0x0c, 0x03, 0x12, 0x42, 0x12, 0x78, 0xc4,
527 0xe6, 0xff, 0x60, 0x03, 0x12, 0x40, 0x25, 0x22, 0xe5, 0x19, 0x24, 0x17,
528 0x54, 0x1f, 0x44, 0x80, 0xff, 0x22, 0x74, 0x2a, 0x25, 0x19, 0xf8, 0xe6,
529 0x22, 0x12, 0x46, 0x72, 0x12, 0x46, 0x68, 0x90, 0x47, 0xfa, 0xe0, 0x54,
530 0xf8, 0x44, 0x02, 0xf0, 0x22, 0xe5, 0x7e, 0xae, 0x7d, 0x78, 0x04, 0x22,
531 0xce, 0xa2, 0xe7, 0x13, 0xce, 0x13, 0x22, 0xe4, 0x78, 0xc4, 0xf6, 0xc2,
532 0x0d, 0x78, 0xc1, 0xf6, 0x22, 0xc2, 0x0c, 0xc2, 0x0b, 0x22, 0x22,
535 static const u8 fw_patch_vsc8584[] = {
536 0xe8, 0x59, 0x02, 0xe8, 0x12, 0x02, 0xe8, 0x42, 0x02, 0xe8, 0x5a, 0x02,
537 0xe8, 0x5b, 0x02, 0xe8, 0x5c, 0xe5, 0x69, 0x54, 0x0f, 0x24, 0xf7, 0x60,
538 0x27, 0x24, 0xfc, 0x60, 0x23, 0x24, 0x08, 0x70, 0x14, 0xe5, 0x69, 0xae,
539 0x68, 0x78, 0x04, 0xce, 0xa2, 0xe7, 0x13, 0xce, 0x13, 0xd8, 0xf8, 0x7e,
540 0x00, 0x54, 0x0f, 0x80, 0x00, 0x7b, 0x01, 0x7a, 0x00, 0x7d, 0xee, 0x7f,
541 0x92, 0x12, 0x50, 0xee, 0x22, 0xe4, 0xf5, 0x10, 0x85, 0x10, 0xfb, 0x7d,
542 0x1c, 0xe4, 0xff, 0x12, 0x59, 0xea, 0x05, 0x10, 0xe5, 0x10, 0xc3, 0x94,
543 0x04, 0x40, 0xed, 0x22, 0x22, 0x22, 0x22, 0x22,
546 static int vsc8584_get_fw_crc(struct mii_dev *bus, int phy, u16 start,
547 u16 *crc, const u8 *fw_patch, int fw_size)
551 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
554 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_VERIPHY_CNTL_2, start);
555 /* Add one byte to size for the one added by the patch_fw function */
556 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_VERIPHY_CNTL_3,
559 ret = vsc8584_cmd(bus, phy, PROC_CMD_CRC16);
563 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
566 *crc = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_VERIPHY_CNTL_2);
569 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
575 static int vsc8584_patch_fw(struct mii_dev *bus, int phy, const u8 *fw_patch,
580 ret = vsc8584_micro_assert_reset(bus, phy);
582 pr_err("%s: failed to assert reset of micro\n", __func__);
586 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
590 * Hold 8051 Micro in SW Reset, Enable auto incr address and patch clock
591 * Disable the 8051 Micro clock
593 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_DW8051_CNTL_STATUS,
594 RUN_FROM_INT_ROM | AUTOINC_ADDR | PATCH_RAM_CLK |
595 MICRO_CLK_EN | MICRO_CLK_DIVIDE(2));
596 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL, READ_PRAM |
597 INT_MEM_WRITE_EN | INT_MEM_DATA(2));
598 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_ADDR, 0x0000);
600 for (i = 0; i < fw_size; i++)
601 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL,
602 READ_PRAM | INT_MEM_WRITE_EN | fw_patch[i]);
604 /* Clear internal memory access */
605 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL, READ_RAM);
607 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
613 static bool vsc8574_is_serdes_init(struct mii_dev *bus, int phy)
618 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
621 reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_TRAP_ROM_ADDR(1));
622 if (reg != MSCC_TRAP_ROM_ADDR_SERDES_INIT) {
627 reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_PATCH_RAM_ADDR(1));
628 if (reg != MSCC_PATCH_RAM_ADDR_SERDES_INIT) {
633 reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL);
634 if (reg != EN_PATCH_RAM_TRAP_ADDR(1)) {
639 reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_DW8051_CNTL_STATUS);
640 if ((MICRO_NSOFT_RESET | RUN_FROM_INT_ROM | DW8051_CLK_EN |
641 MICRO_CLK_EN) != (reg & MSCC_DW8051_VLD_MASK)) {
649 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
655 static int vsc8574_config_pre_init(struct phy_device *phydev)
657 struct mii_dev *bus = phydev->bus;
658 u16 crc, reg, phy0, addr;
662 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
664 addr = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_EXT_PHY_CNTL_4);
665 addr >>= PHY_CNTL_4_ADDR_POS;
667 reg = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_ACTIPHY_CNTL);
668 if (reg & PHY_ADDR_REVERSED)
669 phy0 = phydev->addr + addr;
671 phy0 = phydev->addr - addr;
673 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
676 /* all writes below are broadcasted to all PHYs in the same package */
677 reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS);
678 reg |= SMI_BROADCAST_WR_EN;
679 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS, reg);
682 * The below register writes are tweaking analog and electrical
683 * configuration that were determined through characterization by PHY
684 * engineers. These don't mean anything more than "these are the best
687 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_PHY_CNTL_2, 0x0040);
689 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
692 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_20, 0x4320);
693 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_24, 0x0c00);
694 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_9, 0x18ca);
695 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_5, 0x1b20);
697 reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8);
698 reg |= TR_CLK_DISABLE;
699 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8, reg);
701 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
704 vsc8584_csr_write(bus, phy0, 0x0fae, 0x000401bd);
705 vsc8584_csr_write(bus, phy0, 0x0fac, 0x000f000f);
706 vsc8584_csr_write(bus, phy0, 0x17a0, 0x00a0f147);
707 vsc8584_csr_write(bus, phy0, 0x0fe4, 0x00052f54);
708 vsc8584_csr_write(bus, phy0, 0x1792, 0x0027303d);
709 vsc8584_csr_write(bus, phy0, 0x07fe, 0x00000704);
710 vsc8584_csr_write(bus, phy0, 0x0fe0, 0x00060150);
711 vsc8584_csr_write(bus, phy0, 0x0f82, 0x0012b00a);
712 vsc8584_csr_write(bus, phy0, 0x0f80, 0x00000d74);
713 vsc8584_csr_write(bus, phy0, 0x02e0, 0x00000012);
714 vsc8584_csr_write(bus, phy0, 0x03a2, 0x00050208);
715 vsc8584_csr_write(bus, phy0, 0x03b2, 0x00009186);
716 vsc8584_csr_write(bus, phy0, 0x0fb0, 0x000e3700);
717 vsc8584_csr_write(bus, phy0, 0x1688, 0x00049f81);
718 vsc8584_csr_write(bus, phy0, 0x0fd2, 0x0000ffff);
719 vsc8584_csr_write(bus, phy0, 0x168a, 0x00039fa2);
720 vsc8584_csr_write(bus, phy0, 0x1690, 0x0020640b);
721 vsc8584_csr_write(bus, phy0, 0x0258, 0x00002220);
722 vsc8584_csr_write(bus, phy0, 0x025a, 0x00002a20);
723 vsc8584_csr_write(bus, phy0, 0x025c, 0x00003060);
724 vsc8584_csr_write(bus, phy0, 0x025e, 0x00003fa0);
725 vsc8584_csr_write(bus, phy0, 0x03a6, 0x0000e0f0);
726 vsc8584_csr_write(bus, phy0, 0x0f92, 0x00001489);
727 vsc8584_csr_write(bus, phy0, 0x16a2, 0x00007000);
728 vsc8584_csr_write(bus, phy0, 0x16a6, 0x00071448);
729 vsc8584_csr_write(bus, phy0, 0x16a0, 0x00eeffdd);
730 vsc8584_csr_write(bus, phy0, 0x0fe8, 0x0091b06c);
731 vsc8584_csr_write(bus, phy0, 0x0fea, 0x00041600);
732 vsc8584_csr_write(bus, phy0, 0x16b0, 0x00eeff00);
733 vsc8584_csr_write(bus, phy0, 0x16b2, 0x00007000);
734 vsc8584_csr_write(bus, phy0, 0x16b4, 0x00000814);
735 vsc8584_csr_write(bus, phy0, 0x0f90, 0x00688980);
736 vsc8584_csr_write(bus, phy0, 0x03a4, 0x0000d8f0);
737 vsc8584_csr_write(bus, phy0, 0x0fc0, 0x00000400);
738 vsc8584_csr_write(bus, phy0, 0x07fa, 0x0050100f);
739 vsc8584_csr_write(bus, phy0, 0x0796, 0x00000003);
740 vsc8584_csr_write(bus, phy0, 0x07f8, 0x00c3ff98);
741 vsc8584_csr_write(bus, phy0, 0x0fa4, 0x0018292a);
742 vsc8584_csr_write(bus, phy0, 0x168c, 0x00d2c46f);
743 vsc8584_csr_write(bus, phy0, 0x17a2, 0x00000620);
744 vsc8584_csr_write(bus, phy0, 0x16a4, 0x0013132f);
745 vsc8584_csr_write(bus, phy0, 0x16a8, 0x00000000);
746 vsc8584_csr_write(bus, phy0, 0x0ffc, 0x00c0a028);
747 vsc8584_csr_write(bus, phy0, 0x0fec, 0x00901c09);
748 vsc8584_csr_write(bus, phy0, 0x0fee, 0x0004a6a1);
749 vsc8584_csr_write(bus, phy0, 0x0ffe, 0x00b01807);
751 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
754 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_CU_PMD_TX_CNTL, 0x028e);
756 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
759 vsc8584_csr_write(bus, phy0, 0x0486, 0x0008a518);
760 vsc8584_csr_write(bus, phy0, 0x0488, 0x006dc696);
761 vsc8584_csr_write(bus, phy0, 0x048a, 0x00000912);
762 vsc8584_csr_write(bus, phy0, 0x048e, 0x00000db6);
763 vsc8584_csr_write(bus, phy0, 0x049c, 0x00596596);
764 vsc8584_csr_write(bus, phy0, 0x049e, 0x00000514);
765 vsc8584_csr_write(bus, phy0, 0x04a2, 0x00410280);
766 vsc8584_csr_write(bus, phy0, 0x04a4, 0x00000000);
767 vsc8584_csr_write(bus, phy0, 0x04a6, 0x00000000);
768 vsc8584_csr_write(bus, phy0, 0x04a8, 0x00000000);
769 vsc8584_csr_write(bus, phy0, 0x04aa, 0x00000000);
770 vsc8584_csr_write(bus, phy0, 0x04ae, 0x007df7dd);
771 vsc8584_csr_write(bus, phy0, 0x04b0, 0x006d95d4);
772 vsc8584_csr_write(bus, phy0, 0x04b2, 0x00492410);
774 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
777 reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8);
778 reg &= ~TR_CLK_DISABLE;
779 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8, reg);
781 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
784 /* end of write broadcasting */
785 reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS);
786 reg &= ~SMI_BROADCAST_WR_EN;
787 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS, reg);
789 ret = vsc8584_get_fw_crc(bus, phy0,
790 MSCC_VSC8574_REVB_INT8051_FW_START_ADDR, &crc,
792 ARRAY_SIZE(fw_patch_vsc8574));
796 if (crc == MSCC_VSC8574_REVB_INT8051_FW_CRC) {
797 serdes_init = vsc8574_is_serdes_init(bus, phy0);
800 ret = vsc8584_micro_assert_reset(bus, phy0);
802 pr_err("failed to assert reset of micro\n");
807 pr_debug("FW CRC is not the expected one, patching FW\n");
811 if (vsc8584_patch_fw(bus, phy0, fw_patch_vsc8574,
812 ARRAY_SIZE(fw_patch_vsc8574)))
813 pr_warn("failed to patch FW, expect non-optimal device\n");
817 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
820 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_TRAP_ROM_ADDR(1),
821 MSCC_TRAP_ROM_ADDR_SERDES_INIT);
822 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PATCH_RAM_ADDR(1),
823 MSCC_PATCH_RAM_ADDR_SERDES_INIT);
825 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL,
826 EN_PATCH_RAM_TRAP_ADDR(1));
828 vsc8584_micro_deassert_reset(bus, phy0, false);
830 ret = vsc8584_get_fw_crc(bus, phy0,
831 MSCC_VSC8574_REVB_INT8051_FW_START_ADDR,
832 &crc, fw_patch_vsc8574,
833 ARRAY_SIZE(fw_patch_vsc8574));
837 if (crc != MSCC_VSC8574_REVB_INT8051_FW_CRC)
838 pr_warn("FW CRC after patching is not the expected one, expect non-optimal device\n");
841 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
844 ret = vsc8584_cmd(bus, phy0, PROC_CMD_1588_DEFAULT_INIT |
848 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
854 static int vsc8584_config_pre_init(struct phy_device *phydev)
856 struct mii_dev *bus = phydev->bus;
857 u16 reg, crc, phy0, addr;
860 if ((phydev->phy_id & MSCC_DEV_REV_MASK) != VSC8584_REVB) {
861 pr_warn("VSC8584 revA not officially supported, skipping firmware patching. Use at your own risk.\n");
865 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
867 addr = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_EXT_PHY_CNTL_4);
868 addr >>= PHY_CNTL_4_ADDR_POS;
870 reg = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_ACTIPHY_CNTL);
871 if (reg & PHY_ADDR_REVERSED)
872 phy0 = phydev->addr + addr;
874 phy0 = phydev->addr - addr;
876 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
879 /* all writes below are broadcasted to all PHYs in the same package */
880 reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS);
881 reg |= SMI_BROADCAST_WR_EN;
882 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS, reg);
885 * The below register writes are tweaking analog and electrical
886 * configuration that were determined through characterization by PHY
887 * engineers. These don't mean anything more than "these are the best
890 reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_BYPASS_CONTROL);
891 reg |= PARALLEL_DET_IGNORE_ADVERTISED;
892 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_BYPASS_CONTROL, reg);
894 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
897 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_SERDES_TX_CRC_ERR_CNT,
900 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
903 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_5, 0x1f20);
905 reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8);
906 reg |= TR_CLK_DISABLE;
907 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8, reg);
909 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
912 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16, 0xafa4);
914 reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18);
917 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18, reg);
919 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16, 0x8fa4);
921 vsc8584_csr_write(bus, phy0, 0x07fa, 0x0050100f);
922 vsc8584_csr_write(bus, phy0, 0x1688, 0x00049f81);
923 vsc8584_csr_write(bus, phy0, 0x0f90, 0x00688980);
924 vsc8584_csr_write(bus, phy0, 0x03a4, 0x0000d8f0);
925 vsc8584_csr_write(bus, phy0, 0x0fc0, 0x00000400);
926 vsc8584_csr_write(bus, phy0, 0x0f82, 0x0012b002);
927 vsc8584_csr_write(bus, phy0, 0x1686, 0x00000004);
928 vsc8584_csr_write(bus, phy0, 0x168c, 0x00d2c46f);
929 vsc8584_csr_write(bus, phy0, 0x17a2, 0x00000620);
930 vsc8584_csr_write(bus, phy0, 0x16a0, 0x00eeffdd);
931 vsc8584_csr_write(bus, phy0, 0x16a6, 0x00071448);
932 vsc8584_csr_write(bus, phy0, 0x16a4, 0x0013132f);
933 vsc8584_csr_write(bus, phy0, 0x16a8, 0x00000000);
934 vsc8584_csr_write(bus, phy0, 0x0ffc, 0x00c0a028);
935 vsc8584_csr_write(bus, phy0, 0x0fe8, 0x0091b06c);
936 vsc8584_csr_write(bus, phy0, 0x0fea, 0x00041600);
937 vsc8584_csr_write(bus, phy0, 0x0f80, 0x00fffaff);
938 vsc8584_csr_write(bus, phy0, 0x0fec, 0x00901809);
939 vsc8584_csr_write(bus, phy0, 0x0ffe, 0x00b01007);
940 vsc8584_csr_write(bus, phy0, 0x16b0, 0x00eeff00);
941 vsc8584_csr_write(bus, phy0, 0x16b2, 0x00007000);
942 vsc8584_csr_write(bus, phy0, 0x16b4, 0x00000814);
944 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
947 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_CU_PMD_TX_CNTL, 0x028e);
949 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
952 vsc8584_csr_write(bus, phy0, 0x0486, 0x0008a518);
953 vsc8584_csr_write(bus, phy0, 0x0488, 0x006dc696);
954 vsc8584_csr_write(bus, phy0, 0x048a, 0x00000912);
956 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
959 reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8);
960 reg &= ~TR_CLK_DISABLE;
961 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8, reg);
963 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
966 /* end of write broadcasting */
967 reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS);
968 reg &= ~SMI_BROADCAST_WR_EN;
969 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS, reg);
971 ret = vsc8584_get_fw_crc(bus, phy0,
972 MSCC_VSC8584_REVB_INT8051_FW_START_ADDR, &crc,
974 ARRAY_SIZE(fw_patch_vsc8584));
978 if (crc != MSCC_VSC8584_REVB_INT8051_FW_CRC) {
979 debug("FW CRC is not the expected one, patching FW...\n");
980 if (vsc8584_patch_fw(bus, phy0, fw_patch_vsc8584,
981 ARRAY_SIZE(fw_patch_vsc8584)))
982 pr_warn("failed to patch FW, expect non-optimal device\n");
985 vsc8584_micro_deassert_reset(bus, phy0, false);
987 ret = vsc8584_get_fw_crc(bus, phy0,
988 MSCC_VSC8584_REVB_INT8051_FW_START_ADDR, &crc,
990 ARRAY_SIZE(fw_patch_vsc8584));
994 if (crc != MSCC_VSC8584_REVB_INT8051_FW_CRC)
995 pr_warn("FW CRC after patching is not the expected one, expect non-optimal device\n");
997 ret = vsc8584_micro_assert_reset(bus, phy0);
1001 vsc8584_micro_deassert_reset(bus, phy0, true);
1004 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1010 static int mscc_vsc8531_vsc8541_init_scripts(struct phy_device *phydev)
1014 /* Set to Access Token Ring Registers */
1015 phy_write(phydev, MDIO_DEVAD_NONE,
1016 MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_TR);
1018 /* Update LinkDetectCtrl default to optimized values */
1019 /* Determined during Silicon Validation Testing */
1020 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
1021 (MSCC_PHY_TR_LINKDETCTRL_ADDR | MSCC_PHY_TR_16_READ));
1022 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17);
1023 reg_val = bitfield_replace(reg_val, MSCC_PHY_TR_LINKDETCTRL_POS,
1024 MSCC_PHY_TR_LINKDETCTRL_WIDTH,
1025 MSCC_PHY_TR_LINKDETCTRL_VAL);
1027 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17, reg_val);
1028 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
1029 (MSCC_PHY_TR_LINKDETCTRL_ADDR | MSCC_PHY_TR_16_WRITE));
1031 /* Update VgaThresh100 defaults to optimized values */
1032 /* Determined during Silicon Validation Testing */
1033 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
1034 (MSCC_PHY_TR_VGATHRESH100_ADDR | MSCC_PHY_TR_16_READ));
1036 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18);
1037 reg_val = bitfield_replace(reg_val, MSCC_PHY_TR_VGATHRESH100_POS,
1038 MSCC_PHY_TR_VGATHRESH100_WIDTH,
1039 MSCC_PHY_TR_VGATHRESH100_VAL);
1041 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18, reg_val);
1042 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
1043 (MSCC_PHY_TR_VGATHRESH100_ADDR | MSCC_PHY_TR_16_WRITE));
1045 /* Update VgaGain10 defaults to optimized values */
1046 /* Determined during Silicon Validation Testing */
1047 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
1048 (MSCC_PHY_TR_VGAGAIN10_ADDR | MSCC_PHY_TR_16_READ));
1050 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18);
1051 reg_val = bitfield_replace(reg_val, MSCC_PHY_TR_VGAGAIN10_U_POS,
1052 MSCC_PHY_TR_VGAGAIN10_U_WIDTH,
1053 MSCC_PHY_TR_VGAGAIN10_U_VAL);
1055 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18, reg_val);
1056 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17);
1057 reg_val = bitfield_replace(reg_val, MSCC_PHY_TR_VGAGAIN10_L_POS,
1058 MSCC_PHY_TR_VGAGAIN10_L_WIDTH,
1059 MSCC_PHY_TR_VGAGAIN10_L_VAL);
1061 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17, reg_val);
1062 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
1063 (MSCC_PHY_TR_VGAGAIN10_ADDR | MSCC_PHY_TR_16_WRITE));
1065 /* Set back to Access Standard Page Registers */
1066 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1072 static int mscc_parse_status(struct phy_device *phydev)
1077 mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_AUX_CNTRL_STAT_REG);
1079 if (mii_reg & MIIM_AUX_CNTRL_STAT_F_DUPLEX)
1080 phydev->duplex = DUPLEX_FULL;
1082 phydev->duplex = DUPLEX_HALF;
1084 speed = mii_reg & MIIM_AUX_CNTRL_STAT_SPEED_MASK;
1085 speed = speed >> MIIM_AUX_CNTRL_STAT_SPEED_POS;
1088 case MIIM_AUX_CNTRL_STAT_SPEED_1000M:
1089 phydev->speed = SPEED_1000;
1091 case MIIM_AUX_CNTRL_STAT_SPEED_100M:
1092 phydev->speed = SPEED_100;
1094 case MIIM_AUX_CNTRL_STAT_SPEED_10M:
1095 phydev->speed = SPEED_10;
1098 phydev->speed = SPEED_10;
1105 static int mscc_startup(struct phy_device *phydev)
1109 retval = genphy_update_link(phydev);
1114 return mscc_parse_status(phydev);
1117 static int mscc_phy_soft_reset(struct phy_device *phydev)
1120 u16 timeout = MSCC_PHY_RESET_TIMEOUT;
1123 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1126 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
1127 phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, (reg_val | BMCR_RESET));
1129 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
1131 while ((reg_val & BMCR_RESET) && (timeout > 0)) {
1132 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
1134 udelay(1000); /* 1 ms */
1138 printf("MSCC PHY Soft_Reset Error: mac i/f = 0x%x\n",
1146 static int vsc8531_vsc8541_mac_config(struct phy_device *phydev)
1152 /* For VSC8530/31 the only MAC modes are RMII/RGMII. */
1153 /* For VSC8540/41 the only MAC modes are (G)MII and RMII/RGMII. */
1154 /* Setup MAC Configuration */
1155 switch (phydev->interface) {
1156 case PHY_INTERFACE_MODE_MII:
1157 case PHY_INTERFACE_MODE_GMII:
1158 /* Set Reg23.12:11=0 */
1159 mac_if = MAC_IF_SELECTION_GMII;
1160 /* Set Reg20E2.11=1 */
1161 rx_clk_out = RX_CLK_OUT_DISABLE;
1164 case PHY_INTERFACE_MODE_RMII:
1165 /* Set Reg23.12:11=1 */
1166 mac_if = MAC_IF_SELECTION_RMII;
1167 /* Set Reg20E2.11=0 */
1168 rx_clk_out = RX_CLK_OUT_NORMAL;
1171 case PHY_INTERFACE_MODE_RGMII:
1172 /* Set Reg23.12:11=2 */
1173 mac_if = MAC_IF_SELECTION_RGMII;
1174 /* Set Reg20E2.11=0 */
1175 rx_clk_out = RX_CLK_OUT_NORMAL;
1179 printf("MSCC PHY - INVALID MAC i/f Config: mac i/f = 0x%x\n",
1184 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1187 reg_val = phy_read(phydev, MDIO_DEVAD_NONE,
1188 MSCC_PHY_EXT_PHY_CNTL_1_REG);
1189 /* Set MAC i/f bits Reg23.12:11 */
1190 reg_val = bitfield_replace(reg_val, MAC_IF_SELECTION_POS,
1191 MAC_IF_SELECTION_WIDTH, mac_if);
1192 /* Update Reg23.12:11 */
1193 phy_write(phydev, MDIO_DEVAD_NONE,
1194 MSCC_PHY_EXT_PHY_CNTL_1_REG, reg_val);
1195 /* Setup ExtPg_2 Register Access */
1196 phy_write(phydev, MDIO_DEVAD_NONE,
1197 MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_EXT2);
1199 reg_val = phy_read(phydev, MDIO_DEVAD_NONE,
1200 MSCC_PHY_RGMII_CNTL_REG);
1201 reg_val = bitfield_replace(reg_val, RX_CLK_OUT_POS,
1202 RX_CLK_OUT_WIDTH, rx_clk_out);
1203 /* Update Reg20E2.11 */
1204 phy_write(phydev, MDIO_DEVAD_NONE,
1205 MSCC_PHY_RGMII_CNTL_REG, reg_val);
1206 /* Before leaving - Change back to Std Page Register Access */
1207 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1213 static int vsc8531_config(struct phy_device *phydev)
1215 int retval = -EINVAL;
1218 enum vsc_phy_rgmii_skew rx_clk_skew = VSC_PHY_RGMII_DELAY_1700_PS;
1219 enum vsc_phy_rgmii_skew tx_clk_skew = VSC_PHY_RGMII_DELAY_800_PS;
1220 enum vsc_phy_clk_slew edge_rate = VSC_PHY_CLK_SLEW_RATE_4;
1222 /* For VSC8530/31 and VSC8540/41 the init scripts are the same */
1223 mscc_vsc8531_vsc8541_init_scripts(phydev);
1225 /* For VSC8530/31 the only MAC modes are RMII/RGMII. */
1226 switch (phydev->interface) {
1227 case PHY_INTERFACE_MODE_RMII:
1228 case PHY_INTERFACE_MODE_RGMII:
1229 retval = vsc8531_vsc8541_mac_config(phydev);
1233 retval = mscc_phy_soft_reset(phydev);
1238 printf("PHY 8530/31 MAC i/f Config Error: mac i/f = 0x%x\n",
1242 /* Default RMII Clk Output to 0=OFF/1=ON */
1245 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1246 MSCC_PHY_PAGE_EXT2);
1247 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG);
1249 /* Reg20E2 - Update RGMII RX_Clk Skews. */
1250 reg_val = bitfield_replace(reg_val, RGMII_RX_CLK_DELAY_POS,
1251 RGMII_RX_CLK_DELAY_WIDTH, rx_clk_skew);
1252 /* Reg20E2 - Update RGMII TX_Clk Skews. */
1253 reg_val = bitfield_replace(reg_val, RGMII_TX_CLK_DELAY_POS,
1254 RGMII_TX_CLK_DELAY_WIDTH, tx_clk_skew);
1256 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG, reg_val);
1258 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL);
1259 /* Reg27E2 - Update Clk Slew Rate. */
1260 reg_val = bitfield_replace(reg_val, EDGE_RATE_CNTL_POS,
1261 EDGE_RATE_CNTL_WIDTH, edge_rate);
1262 /* Reg27E2 - Update RMII Clk Out. */
1263 reg_val = bitfield_replace(reg_val, RMII_CLK_OUT_ENABLE_POS,
1264 RMII_CLK_OUT_ENABLE_WIDTH, rmii_clk_out);
1265 /* Update Reg27E2 */
1266 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL, reg_val);
1267 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1270 return genphy_config_aneg(phydev);
1273 static int vsc8541_config(struct phy_device *phydev)
1275 int retval = -EINVAL;
1278 enum vsc_phy_rgmii_skew rx_clk_skew = VSC_PHY_RGMII_DELAY_1700_PS;
1279 enum vsc_phy_rgmii_skew tx_clk_skew = VSC_PHY_RGMII_DELAY_800_PS;
1280 enum vsc_phy_clk_slew edge_rate = VSC_PHY_CLK_SLEW_RATE_4;
1282 /* For VSC8530/31 and VSC8540/41 the init scripts are the same */
1283 mscc_vsc8531_vsc8541_init_scripts(phydev);
1285 /* For VSC8540/41 the only MAC modes are (G)MII and RMII/RGMII. */
1286 switch (phydev->interface) {
1287 case PHY_INTERFACE_MODE_MII:
1288 case PHY_INTERFACE_MODE_GMII:
1289 case PHY_INTERFACE_MODE_RMII:
1290 case PHY_INTERFACE_MODE_RGMII:
1291 retval = vsc8531_vsc8541_mac_config(phydev);
1295 retval = mscc_phy_soft_reset(phydev);
1300 printf("PHY 8541 MAC i/f config Error: mac i/f = 0x%x\n",
1304 /* Default RMII Clk Output to 0=OFF/1=ON */
1307 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1308 MSCC_PHY_PAGE_EXT2);
1309 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG);
1310 /* Reg20E2 - Update RGMII RX_Clk Skews. */
1311 reg_val = bitfield_replace(reg_val, RGMII_RX_CLK_DELAY_POS,
1312 RGMII_RX_CLK_DELAY_WIDTH, rx_clk_skew);
1313 /* Reg20E2 - Update RGMII TX_Clk Skews. */
1314 reg_val = bitfield_replace(reg_val, RGMII_TX_CLK_DELAY_POS,
1315 RGMII_TX_CLK_DELAY_WIDTH, tx_clk_skew);
1316 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG, reg_val);
1318 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL);
1319 /* Reg27E2 - Update Clk Slew Rate. */
1320 reg_val = bitfield_replace(reg_val, EDGE_RATE_CNTL_POS,
1321 EDGE_RATE_CNTL_WIDTH, edge_rate);
1322 /* Reg27E2 - Update RMII Clk Out. */
1323 reg_val = bitfield_replace(reg_val, RMII_CLK_OUT_ENABLE_POS,
1324 RMII_CLK_OUT_ENABLE_WIDTH, rmii_clk_out);
1325 /* Update Reg27E2 */
1326 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL, reg_val);
1327 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1330 return genphy_config_aneg(phydev);
1333 static int vsc8584_config_init(struct phy_device *phydev)
1335 struct vsc85xx_priv *priv = phydev->priv;
1341 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1342 MSCC_PHY_PAGE_EXT1);
1343 addr = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_EXT_PHY_CNTL_4);
1344 addr >>= PHY_CNTL_4_ADDR_POS;
1346 ret = priv->config_pre(phydev);
1350 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1351 MSCC_PHY_PAGE_GPIO);
1353 if (phydev->interface == PHY_INTERFACE_MODE_QSGMII)
1354 val = MAC_CFG_QSGMII;
1356 val = MAC_CFG_SGMII;
1358 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_MAC_CFG_FASTLINK);
1359 reg_val &= ~MAC_CFG_MASK;
1361 ret = phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_MAC_CFG_FASTLINK,
1366 reg_val = PROC_CMD_MCB_ACCESS_MAC_CONF | PROC_CMD_RST_CONF_PORT |
1367 PROC_CMD_READ_MOD_WRITE_PORT;
1368 if (phydev->interface == PHY_INTERFACE_MODE_QSGMII)
1369 reg_val |= PROC_CMD_QSGMII_MAC;
1371 reg_val |= PROC_CMD_SGMII_MAC;
1373 ret = vsc8584_cmd(phydev->bus, phydev->addr, reg_val);
1379 /* Disable SerDes for 100Base-FX */
1380 ret = vsc8584_cmd(phydev->bus, phydev->addr, PROC_CMD_FIBER_MEDIA_CONF |
1381 PROC_CMD_FIBER_PORT(addr) | PROC_CMD_FIBER_DISABLE |
1382 PROC_CMD_READ_MOD_WRITE_PORT |
1383 PROC_CMD_RST_CONF_PORT | PROC_CMD_FIBER_100BASE_FX);
1387 /* Disable SerDes for 1000Base-X */
1388 ret = vsc8584_cmd(phydev->bus, phydev->addr, PROC_CMD_FIBER_MEDIA_CONF |
1389 PROC_CMD_FIBER_PORT(addr) | PROC_CMD_FIBER_DISABLE |
1390 PROC_CMD_READ_MOD_WRITE_PORT |
1391 PROC_CMD_RST_CONF_PORT | PROC_CMD_FIBER_1000BASE_X);
1395 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1397 reg_val = phy_read(phydev, MDIO_DEVAD_NONE,
1398 MSCC_PHY_EXT_PHY_CNTL_1_REG);
1399 reg_val &= ~(MEDIA_OP_MODE_MASK | VSC8584_MAC_IF_SELECTION_MASK);
1400 reg_val |= MEDIA_OP_MODE_COPPER |
1401 (VSC8584_MAC_IF_SELECTION_SGMII <<
1402 VSC8584_MAC_IF_SELECTION_POS);
1403 ret = phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_EXT_PHY_CNTL_1_REG,
1406 ret = mscc_phy_soft_reset(phydev);
1410 return genphy_config(phydev);
1413 static struct vsc85xx_priv vsc8574_priv = {
1414 .config_pre = vsc8574_config_pre_init,
1417 static int vsc8574_config(struct phy_device *phydev)
1419 phydev->priv = &vsc8574_priv;
1421 return vsc8584_config_init(phydev);
1424 static struct vsc85xx_priv vsc8584_priv = {
1425 .config_pre = vsc8584_config_pre_init,
1428 static int vsc8584_config(struct phy_device *phydev)
1430 phydev->priv = &vsc8584_priv;
1432 return vsc8584_config_init(phydev);
1435 static struct phy_driver VSC8530_driver = {
1436 .name = "Microsemi VSC8530",
1437 .uid = PHY_ID_VSC8530,
1439 .features = PHY_BASIC_FEATURES,
1440 .config = &vsc8531_config,
1441 .startup = &mscc_startup,
1442 .shutdown = &genphy_shutdown,
1445 static struct phy_driver VSC8531_driver = {
1446 .name = "Microsemi VSC8531",
1447 .uid = PHY_ID_VSC8531,
1449 .features = PHY_GBIT_FEATURES,
1450 .config = &vsc8531_config,
1451 .startup = &mscc_startup,
1452 .shutdown = &genphy_shutdown,
1455 static struct phy_driver VSC8540_driver = {
1456 .name = "Microsemi VSC8540",
1457 .uid = PHY_ID_VSC8540,
1459 .features = PHY_BASIC_FEATURES,
1460 .config = &vsc8541_config,
1461 .startup = &mscc_startup,
1462 .shutdown = &genphy_shutdown,
1465 static struct phy_driver VSC8541_driver = {
1466 .name = "Microsemi VSC8541",
1467 .uid = PHY_ID_VSC8541,
1469 .features = PHY_GBIT_FEATURES,
1470 .config = &vsc8541_config,
1471 .startup = &mscc_startup,
1472 .shutdown = &genphy_shutdown,
1475 static struct phy_driver VSC8574_driver = {
1476 .name = "Microsemi VSC8574",
1477 .uid = PHY_ID_VSC8574,
1479 .features = PHY_GBIT_FEATURES,
1480 .config = &vsc8574_config,
1481 .startup = &mscc_startup,
1482 .shutdown = &genphy_shutdown,
1485 static struct phy_driver VSC8584_driver = {
1486 .name = "Microsemi VSC8584",
1487 .uid = PHY_ID_VSC8584,
1489 .features = PHY_GBIT_FEATURES,
1490 .config = &vsc8584_config,
1491 .startup = &mscc_startup,
1492 .shutdown = &genphy_shutdown,
1495 int phy_mscc_init(void)
1497 phy_register(&VSC8530_driver);
1498 phy_register(&VSC8531_driver);
1499 phy_register(&VSC8540_driver);
1500 phy_register(&VSC8541_driver);
1501 phy_register(&VSC8574_driver);
1502 phy_register(&VSC8584_driver);