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>
18 #include <linux/printk.h>
20 /* Microsemi PHY ID's */
21 #define PHY_ID_VSC8530 0x00070560
22 #define PHY_ID_VSC8531 0x00070570
23 #define PHY_ID_VSC8502 0x00070630
24 #define PHY_ID_VSC8540 0x00070760
25 #define PHY_ID_VSC8541 0x00070770
26 #define PHY_ID_VSC8574 0x000704a0
27 #define PHY_ID_VSC8584 0x000707c0
29 /* Microsemi VSC85xx PHY Register Pages */
30 #define MSCC_EXT_PAGE_ACCESS 31 /* Page Access Register */
31 #define MSCC_PHY_PAGE_STD 0x0000 /* Standard registers */
32 #define MSCC_PHY_PAGE_EXT1 0x0001 /* Extended registers - page 1 */
33 #define MSCC_PHY_PAGE_EXT2 0x0002 /* Extended registers - page 2 */
34 #define MSCC_PHY_PAGE_EXT3 0x0003 /* Extended registers - page 3 */
35 #define MSCC_PHY_PAGE_EXT4 0x0004 /* Extended registers - page 4 */
36 #define MSCC_PHY_PAGE_GPIO 0x0010 /* GPIO registers */
37 #define MSCC_PHY_PAGE_TEST 0x2A30 /* TEST Page registers */
38 #define MSCC_PHY_PAGE_TR 0x52B5 /* Token Ring Page registers */
40 /* Std Page Register 18 */
41 #define MSCC_PHY_BYPASS_CONTROL 18
42 #define PARALLEL_DET_IGNORE_ADVERTISED BIT(3)
44 /* Std Page Register 22 */
45 #define MSCC_PHY_EXT_CNTL_STATUS 22
46 #define SMI_BROADCAST_WR_EN BIT(0)
48 /* Std Page Register 24 */
49 #define MSCC_PHY_EXT_PHY_CNTL_2 24
51 /* Std Page Register 28 - PHY AUX Control/Status */
52 #define MIIM_AUX_CNTRL_STAT_REG 28
53 #define MIIM_AUX_CNTRL_STAT_ACTIPHY_TO (0x0004)
54 #define MIIM_AUX_CNTRL_STAT_F_DUPLEX (0x0020)
55 #define MIIM_AUX_CNTRL_STAT_SPEED_MASK (0x0018)
56 #define MIIM_AUX_CNTRL_STAT_SPEED_POS (3)
57 #define MIIM_AUX_CNTRL_STAT_SPEED_10M (0x0)
58 #define MIIM_AUX_CNTRL_STAT_SPEED_100M (0x1)
59 #define MIIM_AUX_CNTRL_STAT_SPEED_1000M (0x2)
61 /* Std Page Register 23 - Extended PHY CTRL_1 */
62 #define MSCC_PHY_EXT_PHY_CNTL_1_REG 23
63 #define MAC_IF_SELECTION_MASK (0x1800)
64 #define MAC_IF_SELECTION_GMII (0)
65 #define MAC_IF_SELECTION_RMII (1)
66 #define MAC_IF_SELECTION_RGMII (2)
67 #define MAC_IF_SELECTION_POS (11)
68 #define MAC_IF_SELECTION_WIDTH (2)
69 #define VSC8584_MAC_IF_SELECTION_MASK BIT(12)
70 #define VSC8584_MAC_IF_SELECTION_SGMII 0
71 #define VSC8584_MAC_IF_SELECTION_1000BASEX 1
72 #define VSC8584_MAC_IF_SELECTION_POS 12
73 #define MEDIA_OP_MODE_MASK GENMASK(10, 8)
74 #define MEDIA_OP_MODE_COPPER 0
75 #define MEDIA_OP_MODE_SERDES 1
76 #define MEDIA_OP_MODE_1000BASEX 2
77 #define MEDIA_OP_MODE_100BASEFX 3
78 #define MEDIA_OP_MODE_AMS_COPPER_SERDES 5
79 #define MEDIA_OP_MODE_AMS_COPPER_1000BASEX 6
80 #define MEDIA_OP_MODE_AMS_COPPER_100BASEFX 7
81 #define MEDIA_OP_MODE_POS 8
83 /* Extended Page 1 Register 20E1 */
84 #define MSCC_PHY_ACTIPHY_CNTL 20
85 #define PHY_ADDR_REVERSED BIT(9)
87 /* Extended Page 1 Register 23E1 */
89 #define MSCC_PHY_EXT_PHY_CNTL_4 23
90 #define PHY_CNTL_4_ADDR_POS 11
92 /* Extended Page 1 Register 25E1 */
93 #define MSCC_PHY_VERIPHY_CNTL_2 25
95 /* Extended Page 1 Register 26E1 */
96 #define MSCC_PHY_VERIPHY_CNTL_3 26
98 /* Extended Page 2 Register 16E2 */
99 #define MSCC_PHY_CU_PMD_TX_CNTL 16
101 /* Extended Page 2 Register 20E2 */
102 #define MSCC_PHY_RGMII_CNTL_REG 20
103 #define VSC_FAST_LINK_FAIL2_ENA_MASK (0x8000)
104 #define RX_CLK_OUT_MASK (0x0800)
105 #define RX_CLK_OUT_POS (11)
106 #define RX_CLK_OUT_WIDTH (1)
107 #define RX_CLK_OUT_NORMAL (0)
108 #define RX_CLK_OUT_DISABLE (1)
109 #define RGMII_RX_CLK_DELAY_POS (4)
110 #define RGMII_RX_CLK_DELAY_WIDTH (3)
111 #define RGMII_RX_CLK_DELAY_MASK (0x0070)
112 #define RGMII_TX_CLK_DELAY_POS (0)
113 #define RGMII_TX_CLK_DELAY_WIDTH (3)
114 #define RGMII_TX_CLK_DELAY_MASK (0x0007)
116 /* Extended Page 2 Register 27E2 */
117 #define MSCC_PHY_WOL_MAC_CONTROL 27
118 #define EDGE_RATE_CNTL_POS (5)
119 #define EDGE_RATE_CNTL_WIDTH (3)
120 #define EDGE_RATE_CNTL_MASK (0x00E0)
121 #define RMII_CLK_OUT_ENABLE_POS (4)
122 #define RMII_CLK_OUT_ENABLE_WIDTH (1)
123 #define RMII_CLK_OUT_ENABLE_MASK (0x10)
125 /* Extended Page 3 Register 22E3 */
126 #define MSCC_PHY_SERDES_TX_CRC_ERR_CNT 22
128 /* Extended page GPIO register 00G */
129 #define MSCC_DW8051_CNTL_STATUS 0
130 #define MICRO_NSOFT_RESET BIT(15)
131 #define RUN_FROM_INT_ROM BIT(14)
132 #define AUTOINC_ADDR BIT(13)
133 #define PATCH_RAM_CLK BIT(12)
134 #define MICRO_PATCH_EN BIT(7)
135 #define DW8051_CLK_EN BIT(4)
136 #define MICRO_CLK_EN BIT(3)
137 #define MICRO_CLK_DIVIDE(x) ((x) >> 1)
138 #define MSCC_DW8051_VLD_MASK 0xf1ff
140 /* Extended page GPIO register 09G */
141 #define MSCC_TRAP_ROM_ADDR(x) ((x) * 2 + 1)
142 #define MSCC_TRAP_ROM_ADDR_SERDES_INIT 0x3eb7
144 /* Extended page GPIO register 10G */
145 #define MSCC_PATCH_RAM_ADDR(x) (((x) + 1) * 2)
146 #define MSCC_PATCH_RAM_ADDR_SERDES_INIT 0x4012
148 /* Extended page GPIO register 11G */
149 #define MSCC_INT_MEM_ADDR 11
151 /* Extended page GPIO register 12G */
152 #define MSCC_INT_MEM_CNTL 12
153 #define READ_SFR (BIT(14) | BIT(13))
154 #define READ_PRAM BIT(14)
155 #define READ_ROM BIT(13)
156 #define READ_RAM (0x00 << 13)
157 #define INT_MEM_WRITE_EN BIT(12)
158 #define EN_PATCH_RAM_TRAP_ADDR(x) BIT((x) + 7)
159 #define INT_MEM_DATA_M GENMASK(7, 0)
160 #define INT_MEM_DATA(x) (INT_MEM_DATA_M & (x))
162 /* Extended page GPIO register 13G */
163 #define MSCC_CLKOUT_CNTL 13
164 #define CLKOUT_ENABLE BIT(15)
165 #define CLKOUT_FREQ_MASK GENMASK(14, 13)
166 #define CLKOUT_FREQ_25M (0x0 << 13)
167 #define CLKOUT_FREQ_50M (0x1 << 13)
168 #define CLKOUT_FREQ_125M (0x2 << 13)
170 /* Extended page GPIO register 18G */
171 #define MSCC_PHY_PROC_CMD 18
172 #define PROC_CMD_NCOMPLETED BIT(15)
173 #define PROC_CMD_FAILED BIT(14)
174 #define PROC_CMD_SGMII_PORT(x) ((x) << 8)
175 #define PROC_CMD_FIBER_PORT(x) BIT(8 + (x) % 4)
176 #define PROC_CMD_QSGMII_PORT (BIT(11) | BIT(10))
177 #define PROC_CMD_RST_CONF_PORT BIT(7)
178 #define PROC_CMD_RECONF_PORT (0 << 7)
179 #define PROC_CMD_READ_MOD_WRITE_PORT BIT(6)
180 #define PROC_CMD_WRITE BIT(6)
181 #define PROC_CMD_READ (0 << 6)
182 #define PROC_CMD_FIBER_DISABLE BIT(5)
183 #define PROC_CMD_FIBER_100BASE_FX BIT(4)
184 #define PROC_CMD_FIBER_1000BASE_X (0 << 4)
185 #define PROC_CMD_SGMII_MAC (BIT(5) | BIT(4))
186 #define PROC_CMD_QSGMII_MAC BIT(5)
187 #define PROC_CMD_NO_MAC_CONF (0x00 << 4)
188 #define PROC_CMD_1588_DEFAULT_INIT BIT(4)
189 #define PROC_CMD_NOP GENMASK(3, 0)
190 #define PROC_CMD_PHY_INIT (BIT(3) | BIT(1))
191 #define PROC_CMD_CRC16 BIT(3)
192 #define PROC_CMD_FIBER_MEDIA_CONF BIT(0)
193 #define PROC_CMD_MCB_ACCESS_MAC_CONF (0x0000 << 0)
194 #define PROC_CMD_NCOMPLETED_TIMEOUT_MS 500
196 /* Extended page GPIO register 19G */
197 #define MSCC_PHY_MAC_CFG_FASTLINK 19
198 #define MAC_CFG_MASK GENMASK(15, 14)
199 #define MAC_CFG_SGMII (0x00 << 14)
200 #define MAC_CFG_QSGMII BIT(14)
203 #define MSCC_PHY_TEST_PAGE_5 5
205 #define MSCC_PHY_TEST_PAGE_8 8
206 #define TR_CLK_DISABLE BIT(15)
208 #define MSCC_PHY_TEST_PAGE_9 9
209 #define MSCC_PHY_TEST_PAGE_20 20
210 #define MSCC_PHY_TEST_PAGE_24 24
212 /* Token Ring Page 0x52B5 Registers */
213 #define MSCC_PHY_REG_TR_ADDR_16 16
214 #define MSCC_PHY_REG_TR_DATA_17 17
215 #define MSCC_PHY_REG_TR_DATA_18 18
217 /* Token Ring - Read Value in */
218 #define MSCC_PHY_TR_16_READ (0xA000)
219 /* Token Ring - Write Value out */
220 #define MSCC_PHY_TR_16_WRITE (0x8000)
222 /* Token Ring Registers */
223 #define MSCC_PHY_TR_LINKDETCTRL_POS (3)
224 #define MSCC_PHY_TR_LINKDETCTRL_WIDTH (2)
225 #define MSCC_PHY_TR_LINKDETCTRL_VAL (3)
226 #define MSCC_PHY_TR_LINKDETCTRL_MASK (0x0018)
227 #define MSCC_PHY_TR_LINKDETCTRL_ADDR (0x07F8)
229 #define MSCC_PHY_TR_VGATHRESH100_POS (0)
230 #define MSCC_PHY_TR_VGATHRESH100_WIDTH (7)
231 #define MSCC_PHY_TR_VGATHRESH100_VAL (0x0018)
232 #define MSCC_PHY_TR_VGATHRESH100_MASK (0x007f)
233 #define MSCC_PHY_TR_VGATHRESH100_ADDR (0x0FA4)
235 #define MSCC_PHY_TR_VGAGAIN10_U_POS (0)
236 #define MSCC_PHY_TR_VGAGAIN10_U_WIDTH (1)
237 #define MSCC_PHY_TR_VGAGAIN10_U_MASK (0x0001)
238 #define MSCC_PHY_TR_VGAGAIN10_U_VAL (0)
240 #define MSCC_PHY_TR_VGAGAIN10_L_POS (12)
241 #define MSCC_PHY_TR_VGAGAIN10_L_WIDTH (4)
242 #define MSCC_PHY_TR_VGAGAIN10_L_MASK (0xf000)
243 #define MSCC_PHY_TR_VGAGAIN10_L_VAL (0x0001)
244 #define MSCC_PHY_TR_VGAGAIN10_ADDR (0x0F92)
246 /* General Timeout Values */
247 #define MSCC_PHY_RESET_TIMEOUT (100)
248 #define MSCC_PHY_MICRO_TIMEOUT (500)
250 #define VSC8584_REVB 0x0001
251 #define MSCC_DEV_REV_MASK GENMASK(3, 0)
253 #define MSCC_VSC8574_REVB_INT8051_FW_START_ADDR 0x4000
254 #define MSCC_VSC8574_REVB_INT8051_FW_CRC 0x29e8
256 #define MSCC_VSC8584_REVB_INT8051_FW_START_ADDR 0xe800
257 #define MSCC_VSC8584_REVB_INT8051_FW_CRC 0xfb48
259 /* RGMII/GMII Clock Delay (Skew) Options */ enum vsc_phy_rgmii_skew {
260 VSC_PHY_RGMII_DELAY_200_PS,
261 VSC_PHY_RGMII_DELAY_800_PS,
262 VSC_PHY_RGMII_DELAY_1100_PS,
263 VSC_PHY_RGMII_DELAY_1700_PS,
264 VSC_PHY_RGMII_DELAY_2000_PS,
265 VSC_PHY_RGMII_DELAY_2300_PS,
266 VSC_PHY_RGMII_DELAY_2600_PS,
267 VSC_PHY_RGMII_DELAY_3400_PS,
270 /* MAC i/f Clock Edge Rage Control (Slew), See Reg27E2 */ enum
272 VSC_PHY_CLK_SLEW_RATE_0,
273 VSC_PHY_CLK_SLEW_RATE_1,
274 VSC_PHY_CLK_SLEW_RATE_2,
275 VSC_PHY_CLK_SLEW_RATE_3,
276 VSC_PHY_CLK_SLEW_RATE_4,
277 VSC_PHY_CLK_SLEW_RATE_5,
278 VSC_PHY_CLK_SLEW_RATE_6,
279 VSC_PHY_CLK_SLEW_RATE_7,
282 struct vsc85xx_priv {
283 int (*config_pre)(struct phy_device *phydev);
286 static void vsc8584_csr_write(struct mii_dev *bus, int phy0, u16 addr, u32 val)
288 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18,
290 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17,
291 val & GENMASK(15, 0));
292 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
293 MSCC_PHY_TR_16_WRITE | addr);
296 static int vsc8584_cmd(struct mii_dev *bus, int phy, u16 val)
298 unsigned long deadline;
301 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
304 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_PROC_CMD,
305 PROC_CMD_NCOMPLETED | val);
307 deadline = timer_get_us() + PROC_CMD_NCOMPLETED_TIMEOUT_MS * 1000;
309 reg_val = bus->read(bus, phy, MDIO_DEVAD_NONE,
311 } while (timer_get_us() <= deadline &&
312 (reg_val & PROC_CMD_NCOMPLETED) &&
313 !(reg_val & PROC_CMD_FAILED));
315 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
318 if (reg_val & PROC_CMD_FAILED)
320 if (reg_val & PROC_CMD_NCOMPLETED)
326 static int vsc8584_micro_deassert_reset(struct mii_dev *bus, int phy,
331 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
334 enable = RUN_FROM_INT_ROM | MICRO_CLK_EN | DW8051_CLK_EN;
335 release = MICRO_NSOFT_RESET | RUN_FROM_INT_ROM | DW8051_CLK_EN |
339 enable |= MICRO_PATCH_EN;
340 release |= MICRO_PATCH_EN;
342 /* Clear all patches */
343 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL,
348 * Enable 8051 Micro clock; CLEAR/SET patch present; disable PRAM clock
349 * override and addr. auto-incr; operate at 125 MHz
351 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_DW8051_CNTL_STATUS, enable);
352 /* Release 8051 Micro SW reset */
353 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_DW8051_CNTL_STATUS, release);
355 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
361 static int vsc8584_micro_assert_reset(struct mii_dev *bus, int phy)
366 ret = vsc8584_cmd(bus, phy, PROC_CMD_NOP);
370 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
373 reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL);
374 reg &= ~EN_PATCH_RAM_TRAP_ADDR(4);
375 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL, reg);
377 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_TRAP_ROM_ADDR(4), 0x005b);
378 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_PATCH_RAM_ADDR(4), 0x005b);
380 reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL);
381 reg |= EN_PATCH_RAM_TRAP_ADDR(4);
382 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL, reg);
384 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_PROC_CMD, PROC_CMD_NOP);
386 reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_DW8051_CNTL_STATUS);
387 reg &= ~MICRO_NSOFT_RESET;
388 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_DW8051_CNTL_STATUS, reg);
390 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_PROC_CMD,
391 PROC_CMD_MCB_ACCESS_MAC_CONF | PROC_CMD_SGMII_PORT(0) |
392 PROC_CMD_NO_MAC_CONF | PROC_CMD_READ);
394 reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL);
395 reg &= ~EN_PATCH_RAM_TRAP_ADDR(4);
396 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL, reg);
398 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
404 static const u8 fw_patch_vsc8574[] = {
405 0x46, 0x4a, 0x02, 0x43, 0x37, 0x02, 0x46, 0x26, 0x02, 0x46, 0x77, 0x02,
406 0x45, 0x60, 0x02, 0x45, 0xaf, 0xed, 0xff, 0xe5, 0xfc, 0x54, 0x38, 0x64,
407 0x20, 0x70, 0x08, 0x65, 0xff, 0x70, 0x04, 0xed, 0x44, 0x80, 0xff, 0x22,
408 0x8f, 0x19, 0x7b, 0xbb, 0x7d, 0x0e, 0x7f, 0x04, 0x12, 0x3d, 0xd7, 0xef,
409 0x4e, 0x60, 0x03, 0x02, 0x41, 0xf9, 0xe4, 0xf5, 0x1a, 0x74, 0x01, 0x7e,
410 0x00, 0xa8, 0x1a, 0x08, 0x80, 0x05, 0xc3, 0x33, 0xce, 0x33, 0xce, 0xd8,
411 0xf9, 0xff, 0xef, 0x55, 0x19, 0x70, 0x03, 0x02, 0x41, 0xed, 0x85, 0x1a,
412 0xfb, 0x7b, 0xbb, 0xe4, 0xfd, 0xff, 0x12, 0x3d, 0xd7, 0xef, 0x4e, 0x60,
413 0x03, 0x02, 0x41, 0xed, 0xe5, 0x1a, 0x54, 0x02, 0x75, 0x1d, 0x00, 0x25,
414 0xe0, 0x25, 0xe0, 0xf5, 0x1c, 0xe4, 0x78, 0xc5, 0xf6, 0xd2, 0x0a, 0x12,
415 0x41, 0xfa, 0x7b, 0xff, 0x7d, 0x12, 0x7f, 0x07, 0x12, 0x3d, 0xd7, 0xef,
416 0x4e, 0x60, 0x03, 0x02, 0x41, 0xe7, 0xc2, 0x0a, 0x74, 0xc7, 0x25, 0x1a,
417 0xf9, 0x74, 0xe7, 0x25, 0x1a, 0xf8, 0xe6, 0x27, 0xf5, 0x1b, 0xe5, 0x1d,
418 0x24, 0x5b, 0x12, 0x45, 0xea, 0x12, 0x3e, 0xda, 0x7b, 0xfc, 0x7d, 0x11,
419 0x7f, 0x07, 0x12, 0x3d, 0xd7, 0x78, 0xcc, 0xef, 0xf6, 0x78, 0xc1, 0xe6,
420 0xfe, 0xef, 0xd3, 0x9e, 0x40, 0x06, 0x78, 0xcc, 0xe6, 0x78, 0xc1, 0xf6,
421 0x12, 0x41, 0xfa, 0x7b, 0xec, 0x7d, 0x12, 0x7f, 0x07, 0x12, 0x3d, 0xd7,
422 0x78, 0xcb, 0xef, 0xf6, 0xbf, 0x07, 0x06, 0x78, 0xc3, 0x76, 0x1a, 0x80,
423 0x1f, 0x78, 0xc5, 0xe6, 0xff, 0x60, 0x0f, 0xc3, 0xe5, 0x1b, 0x9f, 0xff,
424 0x78, 0xcb, 0xe6, 0x85, 0x1b, 0xf0, 0xa4, 0x2f, 0x80, 0x07, 0x78, 0xcb,
425 0xe6, 0x85, 0x1b, 0xf0, 0xa4, 0x78, 0xc3, 0xf6, 0xe4, 0x78, 0xc2, 0xf6,
426 0x78, 0xc2, 0xe6, 0xff, 0xc3, 0x08, 0x96, 0x40, 0x03, 0x02, 0x41, 0xd1,
427 0xef, 0x54, 0x03, 0x60, 0x33, 0x14, 0x60, 0x46, 0x24, 0xfe, 0x60, 0x42,
428 0x04, 0x70, 0x4b, 0xef, 0x24, 0x02, 0xff, 0xe4, 0x33, 0xfe, 0xef, 0x78,
429 0x02, 0xce, 0xa2, 0xe7, 0x13, 0xce, 0x13, 0xd8, 0xf8, 0xff, 0xe5, 0x1d,
430 0x24, 0x5c, 0xcd, 0xe5, 0x1c, 0x34, 0xf0, 0xcd, 0x2f, 0xff, 0xed, 0x3e,
431 0xfe, 0x12, 0x46, 0x0d, 0x7d, 0x11, 0x80, 0x0b, 0x78, 0xc2, 0xe6, 0x70,
432 0x04, 0x7d, 0x11, 0x80, 0x02, 0x7d, 0x12, 0x7f, 0x07, 0x12, 0x3e, 0x9a,
433 0x8e, 0x1e, 0x8f, 0x1f, 0x80, 0x03, 0xe5, 0x1e, 0xff, 0x78, 0xc5, 0xe6,
434 0x06, 0x24, 0xcd, 0xf8, 0xa6, 0x07, 0x78, 0xc2, 0x06, 0xe6, 0xb4, 0x1a,
435 0x0a, 0xe5, 0x1d, 0x24, 0x5c, 0x12, 0x45, 0xea, 0x12, 0x3e, 0xda, 0x78,
436 0xc5, 0xe6, 0x65, 0x1b, 0x70, 0x82, 0x75, 0xdb, 0x20, 0x75, 0xdb, 0x28,
437 0x12, 0x46, 0x02, 0x12, 0x46, 0x02, 0xe5, 0x1a, 0x12, 0x45, 0xf5, 0xe5,
438 0x1a, 0xc3, 0x13, 0x12, 0x45, 0xf5, 0x78, 0xc5, 0x16, 0xe6, 0x24, 0xcd,
439 0xf8, 0xe6, 0xff, 0x7e, 0x08, 0x1e, 0xef, 0xa8, 0x06, 0x08, 0x80, 0x02,
440 0xc3, 0x13, 0xd8, 0xfc, 0xfd, 0xc4, 0x33, 0x54, 0xe0, 0xf5, 0xdb, 0xef,
441 0xa8, 0x06, 0x08, 0x80, 0x02, 0xc3, 0x13, 0xd8, 0xfc, 0xfd, 0xc4, 0x33,
442 0x54, 0xe0, 0x44, 0x08, 0xf5, 0xdb, 0xee, 0x70, 0xd8, 0x78, 0xc5, 0xe6,
443 0x70, 0xc8, 0x75, 0xdb, 0x10, 0x02, 0x40, 0xfd, 0x78, 0xc2, 0xe6, 0xc3,
444 0x94, 0x17, 0x50, 0x0e, 0xe5, 0x1d, 0x24, 0x62, 0x12, 0x42, 0x08, 0xe5,
445 0x1d, 0x24, 0x5c, 0x12, 0x42, 0x08, 0x20, 0x0a, 0x03, 0x02, 0x40, 0x76,
446 0x05, 0x1a, 0xe5, 0x1a, 0xc3, 0x94, 0x04, 0x50, 0x03, 0x02, 0x40, 0x3a,
447 0x22, 0xe5, 0x1d, 0x24, 0x5c, 0xff, 0xe5, 0x1c, 0x34, 0xf0, 0xfe, 0x12,
448 0x46, 0x0d, 0x22, 0xff, 0xe5, 0x1c, 0x34, 0xf0, 0xfe, 0x12, 0x46, 0x0d,
449 0x22, 0xe4, 0xf5, 0x19, 0x12, 0x46, 0x43, 0x20, 0xe7, 0x1e, 0x7b, 0xfe,
450 0x12, 0x42, 0xf9, 0xef, 0xc4, 0x33, 0x33, 0x54, 0xc0, 0xff, 0xc0, 0x07,
451 0x7b, 0x54, 0x12, 0x42, 0xf9, 0xd0, 0xe0, 0x4f, 0xff, 0x74, 0x2a, 0x25,
452 0x19, 0xf8, 0xa6, 0x07, 0x12, 0x46, 0x43, 0x20, 0xe7, 0x03, 0x02, 0x42,
453 0xdf, 0x54, 0x03, 0x64, 0x03, 0x70, 0x03, 0x02, 0x42, 0xcf, 0x7b, 0xcb,
454 0x12, 0x43, 0x2c, 0x8f, 0xfb, 0x7b, 0x30, 0x7d, 0x03, 0xe4, 0xff, 0x12,
455 0x3d, 0xd7, 0xc3, 0xef, 0x94, 0x02, 0xee, 0x94, 0x00, 0x50, 0x2a, 0x12,
456 0x42, 0xec, 0xef, 0x4e, 0x70, 0x23, 0x12, 0x43, 0x04, 0x60, 0x0a, 0x12,
457 0x43, 0x12, 0x70, 0x0c, 0x12, 0x43, 0x1f, 0x70, 0x07, 0x12, 0x46, 0x39,
458 0x7b, 0x03, 0x80, 0x07, 0x12, 0x46, 0x39, 0x12, 0x46, 0x43, 0xfb, 0x7a,
459 0x00, 0x7d, 0x54, 0x80, 0x3e, 0x12, 0x42, 0xec, 0xef, 0x4e, 0x70, 0x24,
460 0x12, 0x43, 0x04, 0x60, 0x0a, 0x12, 0x43, 0x12, 0x70, 0x0f, 0x12, 0x43,
461 0x1f, 0x70, 0x0a, 0x12, 0x46, 0x39, 0xe4, 0xfb, 0xfa, 0x7d, 0xee, 0x80,
462 0x1e, 0x12, 0x46, 0x39, 0x7b, 0x01, 0x7a, 0x00, 0x7d, 0xee, 0x80, 0x13,
463 0x12, 0x46, 0x39, 0x12, 0x46, 0x43, 0x54, 0x40, 0xfe, 0xc4, 0x13, 0x13,
464 0x54, 0x03, 0xfb, 0x7a, 0x00, 0x7d, 0xee, 0x12, 0x38, 0xbd, 0x7b, 0xff,
465 0x12, 0x43, 0x2c, 0xef, 0x4e, 0x70, 0x07, 0x74, 0x2a, 0x25, 0x19, 0xf8,
466 0xe4, 0xf6, 0x05, 0x19, 0xe5, 0x19, 0xc3, 0x94, 0x02, 0x50, 0x03, 0x02,
467 0x42, 0x15, 0x22, 0xe5, 0x19, 0x24, 0x17, 0xfd, 0x7b, 0x20, 0x7f, 0x04,
468 0x12, 0x3d, 0xd7, 0x22, 0xe5, 0x19, 0x24, 0x17, 0xfd, 0x7f, 0x04, 0x12,
469 0x3d, 0xd7, 0x22, 0x7b, 0x22, 0x7d, 0x18, 0x7f, 0x06, 0x12, 0x3d, 0xd7,
470 0xef, 0x64, 0x01, 0x4e, 0x22, 0x7d, 0x1c, 0xe4, 0xff, 0x12, 0x3e, 0x9a,
471 0xef, 0x54, 0x1b, 0x64, 0x0a, 0x22, 0x7b, 0xcc, 0x7d, 0x10, 0xff, 0x12,
472 0x3d, 0xd7, 0xef, 0x64, 0x01, 0x4e, 0x22, 0xe5, 0x19, 0x24, 0x17, 0xfd,
473 0x7f, 0x04, 0x12, 0x3d, 0xd7, 0x22, 0xd2, 0x08, 0x75, 0xfb, 0x03, 0xab,
474 0x7e, 0xaa, 0x7d, 0x7d, 0x19, 0x7f, 0x03, 0x12, 0x3e, 0xda, 0xe5, 0x7e,
475 0x54, 0x0f, 0x24, 0xf3, 0x60, 0x03, 0x02, 0x43, 0xe9, 0x12, 0x46, 0x5a,
476 0x12, 0x46, 0x61, 0xd8, 0xfb, 0xff, 0x20, 0xe2, 0x35, 0x13, 0x92, 0x0c,
477 0xef, 0xa2, 0xe1, 0x92, 0x0b, 0x30, 0x0c, 0x2a, 0xe4, 0xf5, 0x10, 0x7b,
478 0xfe, 0x12, 0x43, 0xff, 0xef, 0xc4, 0x33, 0x33, 0x54, 0xc0, 0xff, 0xc0,
479 0x07, 0x7b, 0x54, 0x12, 0x43, 0xff, 0xd0, 0xe0, 0x4f, 0xff, 0x74, 0x2a,
480 0x25, 0x10, 0xf8, 0xa6, 0x07, 0x05, 0x10, 0xe5, 0x10, 0xc3, 0x94, 0x02,
481 0x40, 0xd9, 0x12, 0x46, 0x5a, 0x12, 0x46, 0x61, 0xd8, 0xfb, 0x54, 0x05,
482 0x64, 0x04, 0x70, 0x27, 0x78, 0xc4, 0xe6, 0x78, 0xc6, 0xf6, 0xe5, 0x7d,
483 0xff, 0x33, 0x95, 0xe0, 0xef, 0x54, 0x0f, 0x78, 0xc4, 0xf6, 0x12, 0x44,
484 0x0a, 0x20, 0x0c, 0x0c, 0x12, 0x46, 0x5a, 0x12, 0x46, 0x61, 0xd8, 0xfb,
485 0x13, 0x92, 0x0d, 0x22, 0xc2, 0x0d, 0x22, 0x12, 0x46, 0x5a, 0x12, 0x46,
486 0x61, 0xd8, 0xfb, 0x54, 0x05, 0x64, 0x05, 0x70, 0x1e, 0x78, 0xc4, 0x7d,
487 0xb8, 0x12, 0x43, 0xf5, 0x78, 0xc1, 0x7d, 0x74, 0x12, 0x43, 0xf5, 0xe4,
488 0x78, 0xc1, 0xf6, 0x22, 0x7b, 0x01, 0x7a, 0x00, 0x7d, 0xee, 0x7f, 0x92,
489 0x12, 0x38, 0xbd, 0x22, 0xe6, 0xfb, 0x7a, 0x00, 0x7f, 0x92, 0x12, 0x38,
490 0xbd, 0x22, 0xe5, 0x10, 0x24, 0x17, 0xfd, 0x7f, 0x04, 0x12, 0x3d, 0xd7,
491 0x22, 0x78, 0xc1, 0xe6, 0xfb, 0x7a, 0x00, 0x7d, 0x74, 0x7f, 0x92, 0x12,
492 0x38, 0xbd, 0xe4, 0x78, 0xc1, 0xf6, 0xf5, 0x11, 0x74, 0x01, 0x7e, 0x00,
493 0xa8, 0x11, 0x08, 0x80, 0x05, 0xc3, 0x33, 0xce, 0x33, 0xce, 0xd8, 0xf9,
494 0xff, 0x78, 0xc4, 0xe6, 0xfd, 0xef, 0x5d, 0x60, 0x44, 0x85, 0x11, 0xfb,
495 0xe5, 0x11, 0x54, 0x02, 0x25, 0xe0, 0x25, 0xe0, 0xfe, 0xe4, 0x24, 0x5b,
496 0xfb, 0xee, 0x12, 0x45, 0xed, 0x12, 0x3e, 0xda, 0x7b, 0x40, 0x7d, 0x11,
497 0x7f, 0x07, 0x12, 0x3d, 0xd7, 0x74, 0xc7, 0x25, 0x11, 0xf8, 0xa6, 0x07,
498 0x7b, 0x11, 0x7d, 0x12, 0x7f, 0x07, 0x12, 0x3d, 0xd7, 0xef, 0x4e, 0x60,
499 0x09, 0x74, 0xe7, 0x25, 0x11, 0xf8, 0x76, 0x04, 0x80, 0x07, 0x74, 0xe7,
500 0x25, 0x11, 0xf8, 0x76, 0x0a, 0x05, 0x11, 0xe5, 0x11, 0xc3, 0x94, 0x04,
501 0x40, 0x9a, 0x78, 0xc6, 0xe6, 0x70, 0x15, 0x78, 0xc4, 0xe6, 0x60, 0x10,
502 0x75, 0xd9, 0x38, 0x75, 0xdb, 0x10, 0x7d, 0xfe, 0x12, 0x44, 0xb8, 0x7d,
503 0x76, 0x12, 0x44, 0xb8, 0x79, 0xc6, 0xe7, 0x78, 0xc4, 0x66, 0xff, 0x60,
504 0x03, 0x12, 0x40, 0x25, 0x78, 0xc4, 0xe6, 0x70, 0x09, 0xfb, 0xfa, 0x7d,
505 0xfe, 0x7f, 0x8e, 0x12, 0x38, 0xbd, 0x22, 0x7b, 0x01, 0x7a, 0x00, 0x7f,
506 0x8e, 0x12, 0x38, 0xbd, 0x22, 0xe4, 0xf5, 0xfb, 0x7d, 0x1c, 0xe4, 0xff,
507 0x12, 0x3e, 0x9a, 0xad, 0x07, 0xac, 0x06, 0xec, 0x54, 0xc0, 0xff, 0xed,
508 0x54, 0x3f, 0x4f, 0xf5, 0x20, 0x30, 0x06, 0x2c, 0x30, 0x01, 0x08, 0xa2,
509 0x04, 0x72, 0x03, 0x92, 0x07, 0x80, 0x21, 0x30, 0x04, 0x06, 0x7b, 0xcc,
510 0x7d, 0x11, 0x80, 0x0d, 0x30, 0x03, 0x06, 0x7b, 0xcc, 0x7d, 0x10, 0x80,
511 0x04, 0x7b, 0x66, 0x7d, 0x16, 0xe4, 0xff, 0x12, 0x3d, 0xd7, 0xee, 0x4f,
512 0x24, 0xff, 0x92, 0x07, 0xaf, 0xfb, 0x74, 0x26, 0x2f, 0xf8, 0xe6, 0xff,
513 0xa6, 0x20, 0x20, 0x07, 0x39, 0x8f, 0x20, 0x30, 0x07, 0x34, 0x30, 0x00,
514 0x31, 0x20, 0x04, 0x2e, 0x20, 0x03, 0x2b, 0xe4, 0xf5, 0xff, 0x75, 0xfc,
515 0xc2, 0xe5, 0xfc, 0x30, 0xe0, 0xfb, 0xaf, 0xfe, 0xef, 0x20, 0xe3, 0x1a,
516 0xae, 0xfd, 0x44, 0x08, 0xf5, 0xfe, 0x75, 0xfc, 0x80, 0xe5, 0xfc, 0x30,
517 0xe0, 0xfb, 0x8f, 0xfe, 0x8e, 0xfd, 0x75, 0xfc, 0x80, 0xe5, 0xfc, 0x30,
518 0xe0, 0xfb, 0x05, 0xfb, 0xaf, 0xfb, 0xef, 0xc3, 0x94, 0x04, 0x50, 0x03,
519 0x02, 0x44, 0xc5, 0xe4, 0xf5, 0xfb, 0x22, 0xe5, 0x7e, 0x54, 0x0f, 0x64,
520 0x01, 0x70, 0x23, 0xe5, 0x7e, 0x30, 0xe4, 0x1e, 0x90, 0x47, 0xd0, 0xe0,
521 0x44, 0x02, 0xf0, 0x54, 0xfb, 0xf0, 0x90, 0x47, 0xd4, 0xe0, 0x44, 0x04,
522 0xf0, 0x7b, 0x03, 0x7d, 0x5b, 0x7f, 0x5d, 0x12, 0x36, 0x29, 0x7b, 0x0e,
523 0x80, 0x1c, 0x90, 0x47, 0xd0, 0xe0, 0x54, 0xfd, 0xf0, 0x44, 0x04, 0xf0,
524 0x90, 0x47, 0xd4, 0xe0, 0x54, 0xfb, 0xf0, 0x7b, 0x02, 0x7d, 0x5b, 0x7f,
525 0x5d, 0x12, 0x36, 0x29, 0x7b, 0x06, 0x7d, 0x60, 0x7f, 0x63, 0x12, 0x36,
526 0x29, 0x22, 0xe5, 0x7e, 0x30, 0xe5, 0x35, 0x30, 0xe4, 0x0b, 0x7b, 0x02,
527 0x7d, 0x33, 0x7f, 0x35, 0x12, 0x36, 0x29, 0x80, 0x10, 0x7b, 0x01, 0x7d,
528 0x33, 0x7f, 0x35, 0x12, 0x36, 0x29, 0x90, 0x47, 0xd2, 0xe0, 0x44, 0x04,
529 0xf0, 0x90, 0x47, 0xd2, 0xe0, 0x54, 0xf7, 0xf0, 0x90, 0x47, 0xd1, 0xe0,
530 0x44, 0x10, 0xf0, 0x7b, 0x05, 0x7d, 0x84, 0x7f, 0x86, 0x12, 0x36, 0x29,
531 0x22, 0xfb, 0xe5, 0x1c, 0x34, 0xf0, 0xfa, 0x7d, 0x10, 0x7f, 0x07, 0x22,
532 0x54, 0x01, 0xc4, 0x33, 0x54, 0xe0, 0xf5, 0xdb, 0x44, 0x08, 0xf5, 0xdb,
533 0x22, 0xf5, 0xdb, 0x75, 0xdb, 0x08, 0xf5, 0xdb, 0x75, 0xdb, 0x08, 0x22,
534 0xab, 0x07, 0xaa, 0x06, 0x7d, 0x10, 0x7f, 0x07, 0x12, 0x3e, 0xda, 0x7b,
535 0xff, 0x7d, 0x10, 0x7f, 0x07, 0x12, 0x3d, 0xd7, 0xef, 0x4e, 0x60, 0xf3,
536 0x22, 0x12, 0x44, 0xc2, 0x30, 0x0c, 0x03, 0x12, 0x42, 0x12, 0x78, 0xc4,
537 0xe6, 0xff, 0x60, 0x03, 0x12, 0x40, 0x25, 0x22, 0xe5, 0x19, 0x24, 0x17,
538 0x54, 0x1f, 0x44, 0x80, 0xff, 0x22, 0x74, 0x2a, 0x25, 0x19, 0xf8, 0xe6,
539 0x22, 0x12, 0x46, 0x72, 0x12, 0x46, 0x68, 0x90, 0x47, 0xfa, 0xe0, 0x54,
540 0xf8, 0x44, 0x02, 0xf0, 0x22, 0xe5, 0x7e, 0xae, 0x7d, 0x78, 0x04, 0x22,
541 0xce, 0xa2, 0xe7, 0x13, 0xce, 0x13, 0x22, 0xe4, 0x78, 0xc4, 0xf6, 0xc2,
542 0x0d, 0x78, 0xc1, 0xf6, 0x22, 0xc2, 0x0c, 0xc2, 0x0b, 0x22, 0x22,
545 static const u8 fw_patch_vsc8584[] = {
546 0xe8, 0x59, 0x02, 0xe8, 0x12, 0x02, 0xe8, 0x42, 0x02, 0xe8, 0x5a, 0x02,
547 0xe8, 0x5b, 0x02, 0xe8, 0x5c, 0xe5, 0x69, 0x54, 0x0f, 0x24, 0xf7, 0x60,
548 0x27, 0x24, 0xfc, 0x60, 0x23, 0x24, 0x08, 0x70, 0x14, 0xe5, 0x69, 0xae,
549 0x68, 0x78, 0x04, 0xce, 0xa2, 0xe7, 0x13, 0xce, 0x13, 0xd8, 0xf8, 0x7e,
550 0x00, 0x54, 0x0f, 0x80, 0x00, 0x7b, 0x01, 0x7a, 0x00, 0x7d, 0xee, 0x7f,
551 0x92, 0x12, 0x50, 0xee, 0x22, 0xe4, 0xf5, 0x10, 0x85, 0x10, 0xfb, 0x7d,
552 0x1c, 0xe4, 0xff, 0x12, 0x59, 0xea, 0x05, 0x10, 0xe5, 0x10, 0xc3, 0x94,
553 0x04, 0x40, 0xed, 0x22, 0x22, 0x22, 0x22, 0x22,
556 static int vsc8584_get_fw_crc(struct mii_dev *bus, int phy, u16 start,
557 u16 *crc, const u8 *fw_patch, int fw_size)
561 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
564 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_VERIPHY_CNTL_2, start);
565 /* Add one byte to size for the one added by the patch_fw function */
566 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_VERIPHY_CNTL_3,
569 ret = vsc8584_cmd(bus, phy, PROC_CMD_CRC16);
573 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
576 *crc = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_VERIPHY_CNTL_2);
579 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
585 static int vsc8584_patch_fw(struct mii_dev *bus, int phy, const u8 *fw_patch,
590 ret = vsc8584_micro_assert_reset(bus, phy);
592 pr_err("%s: failed to assert reset of micro\n", __func__);
596 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
600 * Hold 8051 Micro in SW Reset, Enable auto incr address and patch clock
601 * Disable the 8051 Micro clock
603 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_DW8051_CNTL_STATUS,
604 RUN_FROM_INT_ROM | AUTOINC_ADDR | PATCH_RAM_CLK |
605 MICRO_CLK_EN | MICRO_CLK_DIVIDE(2));
606 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL, READ_PRAM |
607 INT_MEM_WRITE_EN | INT_MEM_DATA(2));
608 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_ADDR, 0x0000);
610 for (i = 0; i < fw_size; i++)
611 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL,
612 READ_PRAM | INT_MEM_WRITE_EN | fw_patch[i]);
614 /* Clear internal memory access */
615 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL, READ_RAM);
617 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
623 static bool vsc8574_is_serdes_init(struct mii_dev *bus, int phy)
628 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
631 reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_TRAP_ROM_ADDR(1));
632 if (reg != MSCC_TRAP_ROM_ADDR_SERDES_INIT) {
637 reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_PATCH_RAM_ADDR(1));
638 if (reg != MSCC_PATCH_RAM_ADDR_SERDES_INIT) {
643 reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL);
644 if (reg != EN_PATCH_RAM_TRAP_ADDR(1)) {
649 reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_DW8051_CNTL_STATUS);
650 if ((MICRO_NSOFT_RESET | RUN_FROM_INT_ROM | DW8051_CLK_EN |
651 MICRO_CLK_EN) != (reg & MSCC_DW8051_VLD_MASK)) {
659 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
665 static int vsc8574_config_pre_init(struct phy_device *phydev)
667 struct mii_dev *bus = phydev->bus;
668 u16 crc, reg, phy0, addr;
672 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
674 addr = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_EXT_PHY_CNTL_4);
675 addr >>= PHY_CNTL_4_ADDR_POS;
677 reg = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_ACTIPHY_CNTL);
678 if (reg & PHY_ADDR_REVERSED)
679 phy0 = phydev->addr + addr;
681 phy0 = phydev->addr - addr;
683 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
686 /* all writes below are broadcasted to all PHYs in the same package */
687 reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS);
688 reg |= SMI_BROADCAST_WR_EN;
689 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS, reg);
692 * The below register writes are tweaking analog and electrical
693 * configuration that were determined through characterization by PHY
694 * engineers. These don't mean anything more than "these are the best
697 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_PHY_CNTL_2, 0x0040);
699 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
702 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_20, 0x4320);
703 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_24, 0x0c00);
704 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_9, 0x18ca);
705 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_5, 0x1b20);
707 reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8);
708 reg |= TR_CLK_DISABLE;
709 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8, reg);
711 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
714 vsc8584_csr_write(bus, phy0, 0x0fae, 0x000401bd);
715 vsc8584_csr_write(bus, phy0, 0x0fac, 0x000f000f);
716 vsc8584_csr_write(bus, phy0, 0x17a0, 0x00a0f147);
717 vsc8584_csr_write(bus, phy0, 0x0fe4, 0x00052f54);
718 vsc8584_csr_write(bus, phy0, 0x1792, 0x0027303d);
719 vsc8584_csr_write(bus, phy0, 0x07fe, 0x00000704);
720 vsc8584_csr_write(bus, phy0, 0x0fe0, 0x00060150);
721 vsc8584_csr_write(bus, phy0, 0x0f82, 0x0012b00a);
722 vsc8584_csr_write(bus, phy0, 0x0f80, 0x00000d74);
723 vsc8584_csr_write(bus, phy0, 0x02e0, 0x00000012);
724 vsc8584_csr_write(bus, phy0, 0x03a2, 0x00050208);
725 vsc8584_csr_write(bus, phy0, 0x03b2, 0x00009186);
726 vsc8584_csr_write(bus, phy0, 0x0fb0, 0x000e3700);
727 vsc8584_csr_write(bus, phy0, 0x1688, 0x00049f81);
728 vsc8584_csr_write(bus, phy0, 0x0fd2, 0x0000ffff);
729 vsc8584_csr_write(bus, phy0, 0x168a, 0x00039fa2);
730 vsc8584_csr_write(bus, phy0, 0x1690, 0x0020640b);
731 vsc8584_csr_write(bus, phy0, 0x0258, 0x00002220);
732 vsc8584_csr_write(bus, phy0, 0x025a, 0x00002a20);
733 vsc8584_csr_write(bus, phy0, 0x025c, 0x00003060);
734 vsc8584_csr_write(bus, phy0, 0x025e, 0x00003fa0);
735 vsc8584_csr_write(bus, phy0, 0x03a6, 0x0000e0f0);
736 vsc8584_csr_write(bus, phy0, 0x0f92, 0x00001489);
737 vsc8584_csr_write(bus, phy0, 0x16a2, 0x00007000);
738 vsc8584_csr_write(bus, phy0, 0x16a6, 0x00071448);
739 vsc8584_csr_write(bus, phy0, 0x16a0, 0x00eeffdd);
740 vsc8584_csr_write(bus, phy0, 0x0fe8, 0x0091b06c);
741 vsc8584_csr_write(bus, phy0, 0x0fea, 0x00041600);
742 vsc8584_csr_write(bus, phy0, 0x16b0, 0x00eeff00);
743 vsc8584_csr_write(bus, phy0, 0x16b2, 0x00007000);
744 vsc8584_csr_write(bus, phy0, 0x16b4, 0x00000814);
745 vsc8584_csr_write(bus, phy0, 0x0f90, 0x00688980);
746 vsc8584_csr_write(bus, phy0, 0x03a4, 0x0000d8f0);
747 vsc8584_csr_write(bus, phy0, 0x0fc0, 0x00000400);
748 vsc8584_csr_write(bus, phy0, 0x07fa, 0x0050100f);
749 vsc8584_csr_write(bus, phy0, 0x0796, 0x00000003);
750 vsc8584_csr_write(bus, phy0, 0x07f8, 0x00c3ff98);
751 vsc8584_csr_write(bus, phy0, 0x0fa4, 0x0018292a);
752 vsc8584_csr_write(bus, phy0, 0x168c, 0x00d2c46f);
753 vsc8584_csr_write(bus, phy0, 0x17a2, 0x00000620);
754 vsc8584_csr_write(bus, phy0, 0x16a4, 0x0013132f);
755 vsc8584_csr_write(bus, phy0, 0x16a8, 0x00000000);
756 vsc8584_csr_write(bus, phy0, 0x0ffc, 0x00c0a028);
757 vsc8584_csr_write(bus, phy0, 0x0fec, 0x00901c09);
758 vsc8584_csr_write(bus, phy0, 0x0fee, 0x0004a6a1);
759 vsc8584_csr_write(bus, phy0, 0x0ffe, 0x00b01807);
761 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
764 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_CU_PMD_TX_CNTL, 0x028e);
766 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
769 vsc8584_csr_write(bus, phy0, 0x0486, 0x0008a518);
770 vsc8584_csr_write(bus, phy0, 0x0488, 0x006dc696);
771 vsc8584_csr_write(bus, phy0, 0x048a, 0x00000912);
772 vsc8584_csr_write(bus, phy0, 0x048e, 0x00000db6);
773 vsc8584_csr_write(bus, phy0, 0x049c, 0x00596596);
774 vsc8584_csr_write(bus, phy0, 0x049e, 0x00000514);
775 vsc8584_csr_write(bus, phy0, 0x04a2, 0x00410280);
776 vsc8584_csr_write(bus, phy0, 0x04a4, 0x00000000);
777 vsc8584_csr_write(bus, phy0, 0x04a6, 0x00000000);
778 vsc8584_csr_write(bus, phy0, 0x04a8, 0x00000000);
779 vsc8584_csr_write(bus, phy0, 0x04aa, 0x00000000);
780 vsc8584_csr_write(bus, phy0, 0x04ae, 0x007df7dd);
781 vsc8584_csr_write(bus, phy0, 0x04b0, 0x006d95d4);
782 vsc8584_csr_write(bus, phy0, 0x04b2, 0x00492410);
784 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
787 reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8);
788 reg &= ~TR_CLK_DISABLE;
789 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8, reg);
791 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
794 /* end of write broadcasting */
795 reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS);
796 reg &= ~SMI_BROADCAST_WR_EN;
797 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS, reg);
799 ret = vsc8584_get_fw_crc(bus, phy0,
800 MSCC_VSC8574_REVB_INT8051_FW_START_ADDR, &crc,
802 ARRAY_SIZE(fw_patch_vsc8574));
806 if (crc == MSCC_VSC8574_REVB_INT8051_FW_CRC) {
807 serdes_init = vsc8574_is_serdes_init(bus, phy0);
810 ret = vsc8584_micro_assert_reset(bus, phy0);
812 pr_err("failed to assert reset of micro\n");
817 pr_debug("FW CRC is not the expected one, patching FW\n");
821 if (vsc8584_patch_fw(bus, phy0, fw_patch_vsc8574,
822 ARRAY_SIZE(fw_patch_vsc8574)))
823 pr_warn("failed to patch FW, expect non-optimal device\n");
827 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
830 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_TRAP_ROM_ADDR(1),
831 MSCC_TRAP_ROM_ADDR_SERDES_INIT);
832 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PATCH_RAM_ADDR(1),
833 MSCC_PATCH_RAM_ADDR_SERDES_INIT);
835 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL,
836 EN_PATCH_RAM_TRAP_ADDR(1));
838 vsc8584_micro_deassert_reset(bus, phy0, false);
840 ret = vsc8584_get_fw_crc(bus, phy0,
841 MSCC_VSC8574_REVB_INT8051_FW_START_ADDR,
842 &crc, fw_patch_vsc8574,
843 ARRAY_SIZE(fw_patch_vsc8574));
847 if (crc != MSCC_VSC8574_REVB_INT8051_FW_CRC)
848 pr_warn("FW CRC after patching is not the expected one, expect non-optimal device\n");
851 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
854 ret = vsc8584_cmd(bus, phy0, PROC_CMD_1588_DEFAULT_INIT |
858 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
864 static int vsc8584_config_pre_init(struct phy_device *phydev)
866 struct mii_dev *bus = phydev->bus;
867 u16 reg, crc, phy0, addr;
870 if ((phydev->phy_id & MSCC_DEV_REV_MASK) != VSC8584_REVB) {
871 pr_warn("VSC8584 revA not officially supported, skipping firmware patching. Use at your own risk.\n");
875 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
877 addr = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_EXT_PHY_CNTL_4);
878 addr >>= PHY_CNTL_4_ADDR_POS;
880 reg = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_ACTIPHY_CNTL);
881 if (reg & PHY_ADDR_REVERSED)
882 phy0 = phydev->addr + addr;
884 phy0 = phydev->addr - addr;
886 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
889 /* all writes below are broadcasted to all PHYs in the same package */
890 reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS);
891 reg |= SMI_BROADCAST_WR_EN;
892 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS, reg);
895 * The below register writes are tweaking analog and electrical
896 * configuration that were determined through characterization by PHY
897 * engineers. These don't mean anything more than "these are the best
900 reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_BYPASS_CONTROL);
901 reg |= PARALLEL_DET_IGNORE_ADVERTISED;
902 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_BYPASS_CONTROL, reg);
904 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
907 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_SERDES_TX_CRC_ERR_CNT,
910 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
913 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_5, 0x1f20);
915 reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8);
916 reg |= TR_CLK_DISABLE;
917 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8, reg);
919 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
922 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16, 0xafa4);
924 reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18);
927 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18, reg);
929 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16, 0x8fa4);
931 vsc8584_csr_write(bus, phy0, 0x07fa, 0x0050100f);
932 vsc8584_csr_write(bus, phy0, 0x1688, 0x00049f81);
933 vsc8584_csr_write(bus, phy0, 0x0f90, 0x00688980);
934 vsc8584_csr_write(bus, phy0, 0x03a4, 0x0000d8f0);
935 vsc8584_csr_write(bus, phy0, 0x0fc0, 0x00000400);
936 vsc8584_csr_write(bus, phy0, 0x0f82, 0x0012b002);
937 vsc8584_csr_write(bus, phy0, 0x1686, 0x00000004);
938 vsc8584_csr_write(bus, phy0, 0x168c, 0x00d2c46f);
939 vsc8584_csr_write(bus, phy0, 0x17a2, 0x00000620);
940 vsc8584_csr_write(bus, phy0, 0x16a0, 0x00eeffdd);
941 vsc8584_csr_write(bus, phy0, 0x16a6, 0x00071448);
942 vsc8584_csr_write(bus, phy0, 0x16a4, 0x0013132f);
943 vsc8584_csr_write(bus, phy0, 0x16a8, 0x00000000);
944 vsc8584_csr_write(bus, phy0, 0x0ffc, 0x00c0a028);
945 vsc8584_csr_write(bus, phy0, 0x0fe8, 0x0091b06c);
946 vsc8584_csr_write(bus, phy0, 0x0fea, 0x00041600);
947 vsc8584_csr_write(bus, phy0, 0x0f80, 0x00fffaff);
948 vsc8584_csr_write(bus, phy0, 0x0fec, 0x00901809);
949 vsc8584_csr_write(bus, phy0, 0x0ffe, 0x00b01007);
950 vsc8584_csr_write(bus, phy0, 0x16b0, 0x00eeff00);
951 vsc8584_csr_write(bus, phy0, 0x16b2, 0x00007000);
952 vsc8584_csr_write(bus, phy0, 0x16b4, 0x00000814);
954 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
957 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_CU_PMD_TX_CNTL, 0x028e);
959 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
962 vsc8584_csr_write(bus, phy0, 0x0486, 0x0008a518);
963 vsc8584_csr_write(bus, phy0, 0x0488, 0x006dc696);
964 vsc8584_csr_write(bus, phy0, 0x048a, 0x00000912);
966 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
969 reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8);
970 reg &= ~TR_CLK_DISABLE;
971 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8, reg);
973 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
976 /* end of write broadcasting */
977 reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS);
978 reg &= ~SMI_BROADCAST_WR_EN;
979 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS, reg);
981 ret = vsc8584_get_fw_crc(bus, phy0,
982 MSCC_VSC8584_REVB_INT8051_FW_START_ADDR, &crc,
984 ARRAY_SIZE(fw_patch_vsc8584));
988 if (crc != MSCC_VSC8584_REVB_INT8051_FW_CRC) {
989 debug("FW CRC is not the expected one, patching FW...\n");
990 if (vsc8584_patch_fw(bus, phy0, fw_patch_vsc8584,
991 ARRAY_SIZE(fw_patch_vsc8584)))
992 pr_warn("failed to patch FW, expect non-optimal device\n");
995 vsc8584_micro_deassert_reset(bus, phy0, false);
997 ret = vsc8584_get_fw_crc(bus, phy0,
998 MSCC_VSC8584_REVB_INT8051_FW_START_ADDR, &crc,
1000 ARRAY_SIZE(fw_patch_vsc8584));
1004 if (crc != MSCC_VSC8584_REVB_INT8051_FW_CRC)
1005 pr_warn("FW CRC after patching is not the expected one, expect non-optimal device\n");
1007 ret = vsc8584_micro_assert_reset(bus, phy0);
1011 vsc8584_micro_deassert_reset(bus, phy0, true);
1014 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1020 static int mscc_vsc8531_vsc8541_init_scripts(struct phy_device *phydev)
1024 /* Set to Access Token Ring Registers */
1025 phy_write(phydev, MDIO_DEVAD_NONE,
1026 MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_TR);
1028 /* Update LinkDetectCtrl default to optimized values */
1029 /* Determined during Silicon Validation Testing */
1030 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
1031 (MSCC_PHY_TR_LINKDETCTRL_ADDR | MSCC_PHY_TR_16_READ));
1032 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17);
1033 reg_val = bitfield_replace(reg_val, MSCC_PHY_TR_LINKDETCTRL_POS,
1034 MSCC_PHY_TR_LINKDETCTRL_WIDTH,
1035 MSCC_PHY_TR_LINKDETCTRL_VAL);
1037 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17, reg_val);
1038 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
1039 (MSCC_PHY_TR_LINKDETCTRL_ADDR | MSCC_PHY_TR_16_WRITE));
1041 /* Update VgaThresh100 defaults to optimized values */
1042 /* Determined during Silicon Validation Testing */
1043 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
1044 (MSCC_PHY_TR_VGATHRESH100_ADDR | MSCC_PHY_TR_16_READ));
1046 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18);
1047 reg_val = bitfield_replace(reg_val, MSCC_PHY_TR_VGATHRESH100_POS,
1048 MSCC_PHY_TR_VGATHRESH100_WIDTH,
1049 MSCC_PHY_TR_VGATHRESH100_VAL);
1051 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18, reg_val);
1052 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
1053 (MSCC_PHY_TR_VGATHRESH100_ADDR | MSCC_PHY_TR_16_WRITE));
1055 /* Update VgaGain10 defaults to optimized values */
1056 /* Determined during Silicon Validation Testing */
1057 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
1058 (MSCC_PHY_TR_VGAGAIN10_ADDR | MSCC_PHY_TR_16_READ));
1060 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18);
1061 reg_val = bitfield_replace(reg_val, MSCC_PHY_TR_VGAGAIN10_U_POS,
1062 MSCC_PHY_TR_VGAGAIN10_U_WIDTH,
1063 MSCC_PHY_TR_VGAGAIN10_U_VAL);
1065 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18, reg_val);
1066 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17);
1067 reg_val = bitfield_replace(reg_val, MSCC_PHY_TR_VGAGAIN10_L_POS,
1068 MSCC_PHY_TR_VGAGAIN10_L_WIDTH,
1069 MSCC_PHY_TR_VGAGAIN10_L_VAL);
1071 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17, reg_val);
1072 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
1073 (MSCC_PHY_TR_VGAGAIN10_ADDR | MSCC_PHY_TR_16_WRITE));
1075 /* Set back to Access Standard Page Registers */
1076 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1082 static int mscc_parse_status(struct phy_device *phydev)
1087 mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_AUX_CNTRL_STAT_REG);
1089 if (mii_reg & MIIM_AUX_CNTRL_STAT_F_DUPLEX)
1090 phydev->duplex = DUPLEX_FULL;
1092 phydev->duplex = DUPLEX_HALF;
1094 speed = mii_reg & MIIM_AUX_CNTRL_STAT_SPEED_MASK;
1095 speed = speed >> MIIM_AUX_CNTRL_STAT_SPEED_POS;
1098 case MIIM_AUX_CNTRL_STAT_SPEED_1000M:
1099 phydev->speed = SPEED_1000;
1101 case MIIM_AUX_CNTRL_STAT_SPEED_100M:
1102 phydev->speed = SPEED_100;
1104 case MIIM_AUX_CNTRL_STAT_SPEED_10M:
1105 phydev->speed = SPEED_10;
1108 phydev->speed = SPEED_10;
1115 static int mscc_startup(struct phy_device *phydev)
1119 retval = genphy_update_link(phydev);
1124 return mscc_parse_status(phydev);
1127 static int mscc_phy_soft_reset(struct phy_device *phydev)
1130 u16 timeout = MSCC_PHY_RESET_TIMEOUT;
1133 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1136 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
1137 phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, (reg_val | BMCR_RESET));
1139 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
1141 while ((reg_val & BMCR_RESET) && (timeout > 0)) {
1142 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
1144 udelay(1000); /* 1 ms */
1148 printf("MSCC PHY Soft_Reset Error: mac i/f = 0x%x\n",
1156 static int vsc8531_vsc8541_mac_config(struct phy_device *phydev)
1162 /* For VSC8530/31 the only MAC modes are RMII/RGMII. */
1163 /* For VSC8540/41 the only MAC modes are (G)MII and RMII/RGMII. */
1164 /* Setup MAC Configuration */
1165 switch (phydev->interface) {
1166 case PHY_INTERFACE_MODE_MII:
1167 case PHY_INTERFACE_MODE_GMII:
1168 /* Set Reg23.12:11=0 */
1169 mac_if = MAC_IF_SELECTION_GMII;
1170 /* Set Reg20E2.11=1 */
1171 rx_clk_out = RX_CLK_OUT_DISABLE;
1174 case PHY_INTERFACE_MODE_RMII:
1175 /* Set Reg23.12:11=1 */
1176 mac_if = MAC_IF_SELECTION_RMII;
1177 /* Set Reg20E2.11=0 */
1178 rx_clk_out = RX_CLK_OUT_NORMAL;
1181 case PHY_INTERFACE_MODE_RGMII_TXID:
1182 case PHY_INTERFACE_MODE_RGMII_RXID:
1183 case PHY_INTERFACE_MODE_RGMII_ID:
1184 case PHY_INTERFACE_MODE_RGMII:
1185 /* Set Reg23.12:11=2 */
1186 mac_if = MAC_IF_SELECTION_RGMII;
1187 /* Set Reg20E2.11=0 */
1188 rx_clk_out = RX_CLK_OUT_NORMAL;
1192 printf("MSCC PHY - INVALID MAC i/f Config: mac i/f = 0x%x\n",
1197 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1200 reg_val = phy_read(phydev, MDIO_DEVAD_NONE,
1201 MSCC_PHY_EXT_PHY_CNTL_1_REG);
1202 /* Set MAC i/f bits Reg23.12:11 */
1203 reg_val = bitfield_replace(reg_val, MAC_IF_SELECTION_POS,
1204 MAC_IF_SELECTION_WIDTH, mac_if);
1205 /* Update Reg23.12:11 */
1206 phy_write(phydev, MDIO_DEVAD_NONE,
1207 MSCC_PHY_EXT_PHY_CNTL_1_REG, reg_val);
1208 /* Setup ExtPg_2 Register Access */
1209 phy_write(phydev, MDIO_DEVAD_NONE,
1210 MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_EXT2);
1212 reg_val = phy_read(phydev, MDIO_DEVAD_NONE,
1213 MSCC_PHY_RGMII_CNTL_REG);
1214 reg_val = bitfield_replace(reg_val, RX_CLK_OUT_POS,
1215 RX_CLK_OUT_WIDTH, rx_clk_out);
1216 /* Update Reg20E2.11 */
1217 phy_write(phydev, MDIO_DEVAD_NONE,
1218 MSCC_PHY_RGMII_CNTL_REG, reg_val);
1219 /* Before leaving - Change back to Std Page Register Access */
1220 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1226 static int vsc8531_vsc8541_clkout_config(struct phy_device *phydev)
1228 struct ofnode_phandle_args phandle_args;
1229 u32 clkout_rate = 0;
1233 retval = dev_read_phandle_with_args(phydev->dev, "phy-handle", NULL,
1234 0, 0, &phandle_args);
1236 clkout_rate = ofnode_read_u32_default(phandle_args.node,
1237 "vsc8531,clk-out-frequency", 0);
1239 switch (clkout_rate) {
1244 reg_val = CLKOUT_FREQ_25M | CLKOUT_ENABLE;
1247 reg_val = CLKOUT_FREQ_50M | CLKOUT_ENABLE;
1250 reg_val = CLKOUT_FREQ_125M | CLKOUT_ENABLE;
1253 printf("PHY 8530/31 invalid clkout rate %u\n",
1258 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1259 MSCC_PHY_PAGE_GPIO);
1260 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_CLKOUT_CNTL, reg_val);
1261 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1267 static int vsc8531_vsc8541_clk_skew_config(struct phy_device *phydev)
1269 enum vsc_phy_rgmii_skew rx_clk_skew = VSC_PHY_RGMII_DELAY_200_PS;
1270 enum vsc_phy_rgmii_skew tx_clk_skew = VSC_PHY_RGMII_DELAY_200_PS;
1273 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID ||
1274 phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
1275 rx_clk_skew = VSC_PHY_RGMII_DELAY_2000_PS;
1277 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID ||
1278 phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
1279 tx_clk_skew = VSC_PHY_RGMII_DELAY_2000_PS;
1281 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1282 MSCC_PHY_PAGE_EXT2);
1283 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG);
1285 /* Reg20E2 - Update RGMII RX_Clk Skews. */
1286 reg_val = bitfield_replace(reg_val, RGMII_RX_CLK_DELAY_POS,
1287 RGMII_RX_CLK_DELAY_WIDTH, rx_clk_skew);
1288 /* Reg20E2 - Update RGMII TX_Clk Skews. */
1289 reg_val = bitfield_replace(reg_val, RGMII_TX_CLK_DELAY_POS,
1290 RGMII_TX_CLK_DELAY_WIDTH, tx_clk_skew);
1292 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG, reg_val);
1293 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1299 static int vsc8531_config(struct phy_device *phydev)
1301 int retval = -EINVAL;
1304 enum vsc_phy_clk_slew edge_rate = VSC_PHY_CLK_SLEW_RATE_4;
1306 /* For VSC8530/31 and VSC8540/41 the init scripts are the same */
1307 mscc_vsc8531_vsc8541_init_scripts(phydev);
1309 /* For VSC8530/31 the only MAC modes are RMII/RGMII. */
1310 switch (phydev->interface) {
1311 case PHY_INTERFACE_MODE_RMII:
1312 case PHY_INTERFACE_MODE_RGMII:
1313 case PHY_INTERFACE_MODE_RGMII_TXID:
1314 case PHY_INTERFACE_MODE_RGMII_RXID:
1315 case PHY_INTERFACE_MODE_RGMII_ID:
1316 retval = vsc8531_vsc8541_mac_config(phydev);
1320 retval = mscc_phy_soft_reset(phydev);
1325 printf("PHY 8530/31 MAC i/f Config Error: mac i/f = 0x%x\n",
1329 /* Default RMII Clk Output to 0=OFF/1=ON */
1332 retval = vsc8531_vsc8541_clk_skew_config(phydev);
1336 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1337 MSCC_PHY_PAGE_EXT2);
1338 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL);
1339 /* Reg27E2 - Update Clk Slew Rate. */
1340 reg_val = bitfield_replace(reg_val, EDGE_RATE_CNTL_POS,
1341 EDGE_RATE_CNTL_WIDTH, edge_rate);
1342 /* Reg27E2 - Update RMII Clk Out. */
1343 reg_val = bitfield_replace(reg_val, RMII_CLK_OUT_ENABLE_POS,
1344 RMII_CLK_OUT_ENABLE_WIDTH, rmii_clk_out);
1345 /* Update Reg27E2 */
1346 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL, reg_val);
1347 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1350 /* Configure the clk output */
1351 retval = vsc8531_vsc8541_clkout_config(phydev);
1355 return genphy_config_aneg(phydev);
1358 static int vsc8541_config(struct phy_device *phydev)
1360 int retval = -EINVAL;
1363 enum vsc_phy_clk_slew edge_rate = VSC_PHY_CLK_SLEW_RATE_4;
1365 /* For VSC8530/31 and VSC8540/41 the init scripts are the same */
1366 mscc_vsc8531_vsc8541_init_scripts(phydev);
1368 /* For VSC8540/41 the only MAC modes are (G)MII and RMII/RGMII. */
1369 switch (phydev->interface) {
1370 case PHY_INTERFACE_MODE_MII:
1371 case PHY_INTERFACE_MODE_GMII:
1372 case PHY_INTERFACE_MODE_RMII:
1373 case PHY_INTERFACE_MODE_RGMII:
1374 retval = vsc8531_vsc8541_mac_config(phydev);
1378 retval = mscc_phy_soft_reset(phydev);
1383 printf("PHY 8541 MAC i/f config Error: mac i/f = 0x%x\n",
1387 /* Default RMII Clk Output to 0=OFF/1=ON */
1390 retval = vsc8531_vsc8541_clk_skew_config(phydev);
1394 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1395 MSCC_PHY_PAGE_EXT2);
1396 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL);
1397 /* Reg27E2 - Update Clk Slew Rate. */
1398 reg_val = bitfield_replace(reg_val, EDGE_RATE_CNTL_POS,
1399 EDGE_RATE_CNTL_WIDTH, edge_rate);
1400 /* Reg27E2 - Update RMII Clk Out. */
1401 reg_val = bitfield_replace(reg_val, RMII_CLK_OUT_ENABLE_POS,
1402 RMII_CLK_OUT_ENABLE_WIDTH, rmii_clk_out);
1403 /* Update Reg27E2 */
1404 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL, reg_val);
1405 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1408 /* Configure the clk output */
1409 retval = vsc8531_vsc8541_clkout_config(phydev);
1413 return genphy_config_aneg(phydev);
1416 static int vsc8584_config_init(struct phy_device *phydev)
1418 struct vsc85xx_priv *priv = phydev->priv;
1424 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1425 MSCC_PHY_PAGE_EXT1);
1426 addr = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_EXT_PHY_CNTL_4);
1427 addr >>= PHY_CNTL_4_ADDR_POS;
1429 ret = priv->config_pre(phydev);
1433 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1434 MSCC_PHY_PAGE_GPIO);
1436 if (phydev->interface == PHY_INTERFACE_MODE_QSGMII)
1437 val = MAC_CFG_QSGMII;
1439 val = MAC_CFG_SGMII;
1441 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_MAC_CFG_FASTLINK);
1442 reg_val &= ~MAC_CFG_MASK;
1444 ret = phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_MAC_CFG_FASTLINK,
1449 reg_val = PROC_CMD_MCB_ACCESS_MAC_CONF | PROC_CMD_RST_CONF_PORT |
1450 PROC_CMD_READ_MOD_WRITE_PORT;
1451 if (phydev->interface == PHY_INTERFACE_MODE_QSGMII)
1452 reg_val |= PROC_CMD_QSGMII_MAC;
1454 reg_val |= PROC_CMD_SGMII_MAC;
1456 ret = vsc8584_cmd(phydev->bus, phydev->addr, reg_val);
1462 /* Disable SerDes for 100Base-FX */
1463 ret = vsc8584_cmd(phydev->bus, phydev->addr, PROC_CMD_FIBER_MEDIA_CONF |
1464 PROC_CMD_FIBER_PORT(addr) | PROC_CMD_FIBER_DISABLE |
1465 PROC_CMD_READ_MOD_WRITE_PORT |
1466 PROC_CMD_RST_CONF_PORT | PROC_CMD_FIBER_100BASE_FX);
1470 /* Disable SerDes for 1000Base-X */
1471 ret = vsc8584_cmd(phydev->bus, phydev->addr, PROC_CMD_FIBER_MEDIA_CONF |
1472 PROC_CMD_FIBER_PORT(addr) | PROC_CMD_FIBER_DISABLE |
1473 PROC_CMD_READ_MOD_WRITE_PORT |
1474 PROC_CMD_RST_CONF_PORT | PROC_CMD_FIBER_1000BASE_X);
1478 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1480 reg_val = phy_read(phydev, MDIO_DEVAD_NONE,
1481 MSCC_PHY_EXT_PHY_CNTL_1_REG);
1482 reg_val &= ~(MEDIA_OP_MODE_MASK | VSC8584_MAC_IF_SELECTION_MASK);
1483 reg_val |= MEDIA_OP_MODE_COPPER |
1484 (VSC8584_MAC_IF_SELECTION_SGMII <<
1485 VSC8584_MAC_IF_SELECTION_POS);
1486 ret = phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_EXT_PHY_CNTL_1_REG,
1489 ret = mscc_phy_soft_reset(phydev);
1493 return genphy_config(phydev);
1496 static struct vsc85xx_priv vsc8574_priv = {
1497 .config_pre = vsc8574_config_pre_init,
1500 static int vsc8574_config(struct phy_device *phydev)
1502 phydev->priv = &vsc8574_priv;
1504 return vsc8584_config_init(phydev);
1507 static struct vsc85xx_priv vsc8584_priv = {
1508 .config_pre = vsc8584_config_pre_init,
1511 static int vsc8584_config(struct phy_device *phydev)
1513 phydev->priv = &vsc8584_priv;
1515 return vsc8584_config_init(phydev);
1518 static int vsc8502_config(struct phy_device *phydev)
1520 bool rgmii_rx_delay = false, rgmii_tx_delay = false;
1524 /* Assume nothing needs to be done for the default GMII/MII mode */
1525 if (!phy_interface_is_rgmii(phydev))
1528 /* Set Extended PHY Control 1 register to RGMII */
1529 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_EXT_PHY_CNTL_1_REG,
1532 /* Soft reset required after changing PHY mode from the default
1535 ret = mscc_phy_soft_reset(phydev);
1539 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID ||
1540 phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
1541 rgmii_rx_delay = true;
1542 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID ||
1543 phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
1544 rgmii_tx_delay = true;
1546 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1547 MSCC_PHY_PAGE_EXT2);
1550 reg |= VSC_PHY_RGMII_DELAY_2000_PS << RGMII_RX_CLK_DELAY_POS;
1552 reg |= VSC_PHY_RGMII_DELAY_2000_PS << RGMII_TX_CLK_DELAY_POS;
1554 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG, reg);
1556 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1562 U_BOOT_PHY_DRIVER(vsc8530) = {
1563 .name = "Microsemi VSC8530",
1564 .uid = PHY_ID_VSC8530,
1566 .features = PHY_BASIC_FEATURES,
1567 .config = &vsc8531_config,
1568 .startup = &mscc_startup,
1569 .shutdown = &genphy_shutdown,
1572 U_BOOT_PHY_DRIVER(vsc8531) = {
1573 .name = "Microsemi VSC8531",
1574 .uid = PHY_ID_VSC8531,
1576 .features = PHY_GBIT_FEATURES,
1577 .config = &vsc8531_config,
1578 .startup = &mscc_startup,
1579 .shutdown = &genphy_shutdown,
1582 U_BOOT_PHY_DRIVER(vsc8502) = {
1583 .name = "Microsemi VSC8502",
1584 .uid = PHY_ID_VSC8502,
1586 .features = PHY_GBIT_FEATURES,
1587 .config = &vsc8502_config,
1588 .startup = &mscc_startup,
1589 .shutdown = &genphy_shutdown,
1592 U_BOOT_PHY_DRIVER(vsc8540) = {
1593 .name = "Microsemi VSC8540",
1594 .uid = PHY_ID_VSC8540,
1596 .features = PHY_BASIC_FEATURES,
1597 .config = &vsc8541_config,
1598 .startup = &mscc_startup,
1599 .shutdown = &genphy_shutdown,
1602 U_BOOT_PHY_DRIVER(vsc8541) = {
1603 .name = "Microsemi VSC8541",
1604 .uid = PHY_ID_VSC8541,
1606 .features = PHY_GBIT_FEATURES,
1607 .config = &vsc8541_config,
1608 .startup = &mscc_startup,
1609 .shutdown = &genphy_shutdown,
1612 U_BOOT_PHY_DRIVER(vsc8574) = {
1613 .name = "Microsemi VSC8574",
1614 .uid = PHY_ID_VSC8574,
1616 .features = PHY_GBIT_FEATURES,
1617 .config = &vsc8574_config,
1618 .startup = &mscc_startup,
1619 .shutdown = &genphy_shutdown,
1622 U_BOOT_PHY_DRIVER(vsc8584) = {
1623 .name = "Microsemi VSC8584",
1624 .uid = PHY_ID_VSC8584,
1626 .features = PHY_GBIT_FEATURES,
1627 .config = &vsc8584_config,
1628 .startup = &mscc_startup,
1629 .shutdown = &genphy_shutdown,