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 13G */
161 #define MSCC_CLKOUT_CNTL 13
162 #define CLKOUT_ENABLE BIT(15)
163 #define CLKOUT_FREQ_MASK GENMASK(14, 13)
164 #define CLKOUT_FREQ_25M (0x0 << 13)
165 #define CLKOUT_FREQ_50M (0x1 << 13)
166 #define CLKOUT_FREQ_125M (0x2 << 13)
168 /* Extended page GPIO register 18G */
169 #define MSCC_PHY_PROC_CMD 18
170 #define PROC_CMD_NCOMPLETED BIT(15)
171 #define PROC_CMD_FAILED BIT(14)
172 #define PROC_CMD_SGMII_PORT(x) ((x) << 8)
173 #define PROC_CMD_FIBER_PORT(x) BIT(8 + (x) % 4)
174 #define PROC_CMD_QSGMII_PORT (BIT(11) | BIT(10))
175 #define PROC_CMD_RST_CONF_PORT BIT(7)
176 #define PROC_CMD_RECONF_PORT (0 << 7)
177 #define PROC_CMD_READ_MOD_WRITE_PORT BIT(6)
178 #define PROC_CMD_WRITE BIT(6)
179 #define PROC_CMD_READ (0 << 6)
180 #define PROC_CMD_FIBER_DISABLE BIT(5)
181 #define PROC_CMD_FIBER_100BASE_FX BIT(4)
182 #define PROC_CMD_FIBER_1000BASE_X (0 << 4)
183 #define PROC_CMD_SGMII_MAC (BIT(5) | BIT(4))
184 #define PROC_CMD_QSGMII_MAC BIT(5)
185 #define PROC_CMD_NO_MAC_CONF (0x00 << 4)
186 #define PROC_CMD_1588_DEFAULT_INIT BIT(4)
187 #define PROC_CMD_NOP GENMASK(3, 0)
188 #define PROC_CMD_PHY_INIT (BIT(3) | BIT(1))
189 #define PROC_CMD_CRC16 BIT(3)
190 #define PROC_CMD_FIBER_MEDIA_CONF BIT(0)
191 #define PROC_CMD_MCB_ACCESS_MAC_CONF (0x0000 << 0)
192 #define PROC_CMD_NCOMPLETED_TIMEOUT_MS 500
194 /* Extended page GPIO register 19G */
195 #define MSCC_PHY_MAC_CFG_FASTLINK 19
196 #define MAC_CFG_MASK GENMASK(15, 14)
197 #define MAC_CFG_SGMII (0x00 << 14)
198 #define MAC_CFG_QSGMII BIT(14)
201 #define MSCC_PHY_TEST_PAGE_5 5
203 #define MSCC_PHY_TEST_PAGE_8 8
204 #define TR_CLK_DISABLE BIT(15)
206 #define MSCC_PHY_TEST_PAGE_9 9
207 #define MSCC_PHY_TEST_PAGE_20 20
208 #define MSCC_PHY_TEST_PAGE_24 24
210 /* Token Ring Page 0x52B5 Registers */
211 #define MSCC_PHY_REG_TR_ADDR_16 16
212 #define MSCC_PHY_REG_TR_DATA_17 17
213 #define MSCC_PHY_REG_TR_DATA_18 18
215 /* Token Ring - Read Value in */
216 #define MSCC_PHY_TR_16_READ (0xA000)
217 /* Token Ring - Write Value out */
218 #define MSCC_PHY_TR_16_WRITE (0x8000)
220 /* Token Ring Registers */
221 #define MSCC_PHY_TR_LINKDETCTRL_POS (3)
222 #define MSCC_PHY_TR_LINKDETCTRL_WIDTH (2)
223 #define MSCC_PHY_TR_LINKDETCTRL_VAL (3)
224 #define MSCC_PHY_TR_LINKDETCTRL_MASK (0x0018)
225 #define MSCC_PHY_TR_LINKDETCTRL_ADDR (0x07F8)
227 #define MSCC_PHY_TR_VGATHRESH100_POS (0)
228 #define MSCC_PHY_TR_VGATHRESH100_WIDTH (7)
229 #define MSCC_PHY_TR_VGATHRESH100_VAL (0x0018)
230 #define MSCC_PHY_TR_VGATHRESH100_MASK (0x007f)
231 #define MSCC_PHY_TR_VGATHRESH100_ADDR (0x0FA4)
233 #define MSCC_PHY_TR_VGAGAIN10_U_POS (0)
234 #define MSCC_PHY_TR_VGAGAIN10_U_WIDTH (1)
235 #define MSCC_PHY_TR_VGAGAIN10_U_MASK (0x0001)
236 #define MSCC_PHY_TR_VGAGAIN10_U_VAL (0)
238 #define MSCC_PHY_TR_VGAGAIN10_L_POS (12)
239 #define MSCC_PHY_TR_VGAGAIN10_L_WIDTH (4)
240 #define MSCC_PHY_TR_VGAGAIN10_L_MASK (0xf000)
241 #define MSCC_PHY_TR_VGAGAIN10_L_VAL (0x0001)
242 #define MSCC_PHY_TR_VGAGAIN10_ADDR (0x0F92)
244 /* General Timeout Values */
245 #define MSCC_PHY_RESET_TIMEOUT (100)
246 #define MSCC_PHY_MICRO_TIMEOUT (500)
248 #define VSC8584_REVB 0x0001
249 #define MSCC_DEV_REV_MASK GENMASK(3, 0)
251 #define MSCC_VSC8574_REVB_INT8051_FW_START_ADDR 0x4000
252 #define MSCC_VSC8574_REVB_INT8051_FW_CRC 0x29e8
254 #define MSCC_VSC8584_REVB_INT8051_FW_START_ADDR 0xe800
255 #define MSCC_VSC8584_REVB_INT8051_FW_CRC 0xfb48
257 /* RGMII/GMII Clock Delay (Skew) Options */ enum vsc_phy_rgmii_skew {
258 VSC_PHY_RGMII_DELAY_200_PS,
259 VSC_PHY_RGMII_DELAY_800_PS,
260 VSC_PHY_RGMII_DELAY_1100_PS,
261 VSC_PHY_RGMII_DELAY_1700_PS,
262 VSC_PHY_RGMII_DELAY_2000_PS,
263 VSC_PHY_RGMII_DELAY_2300_PS,
264 VSC_PHY_RGMII_DELAY_2600_PS,
265 VSC_PHY_RGMII_DELAY_3400_PS,
268 /* MAC i/f Clock Edge Rage Control (Slew), See Reg27E2 */ enum
270 VSC_PHY_CLK_SLEW_RATE_0,
271 VSC_PHY_CLK_SLEW_RATE_1,
272 VSC_PHY_CLK_SLEW_RATE_2,
273 VSC_PHY_CLK_SLEW_RATE_3,
274 VSC_PHY_CLK_SLEW_RATE_4,
275 VSC_PHY_CLK_SLEW_RATE_5,
276 VSC_PHY_CLK_SLEW_RATE_6,
277 VSC_PHY_CLK_SLEW_RATE_7,
280 struct vsc85xx_priv {
281 int (*config_pre)(struct phy_device *phydev);
284 static void vsc8584_csr_write(struct mii_dev *bus, int phy0, u16 addr, u32 val)
286 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18,
288 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17,
289 val & GENMASK(15, 0));
290 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
291 MSCC_PHY_TR_16_WRITE | addr);
294 static int vsc8584_cmd(struct mii_dev *bus, int phy, u16 val)
296 unsigned long deadline;
299 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
302 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_PROC_CMD,
303 PROC_CMD_NCOMPLETED | val);
305 deadline = timer_get_us() + PROC_CMD_NCOMPLETED_TIMEOUT_MS * 1000;
307 reg_val = bus->read(bus, phy, MDIO_DEVAD_NONE,
309 } while (timer_get_us() <= deadline &&
310 (reg_val & PROC_CMD_NCOMPLETED) &&
311 !(reg_val & PROC_CMD_FAILED));
313 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
316 if (reg_val & PROC_CMD_FAILED)
318 if (reg_val & PROC_CMD_NCOMPLETED)
324 static int vsc8584_micro_deassert_reset(struct mii_dev *bus, int phy,
329 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
332 enable = RUN_FROM_INT_ROM | MICRO_CLK_EN | DW8051_CLK_EN;
333 release = MICRO_NSOFT_RESET | RUN_FROM_INT_ROM | DW8051_CLK_EN |
337 enable |= MICRO_PATCH_EN;
338 release |= MICRO_PATCH_EN;
340 /* Clear all patches */
341 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL,
346 * Enable 8051 Micro clock; CLEAR/SET patch present; disable PRAM clock
347 * override and addr. auto-incr; operate at 125 MHz
349 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_DW8051_CNTL_STATUS, enable);
350 /* Release 8051 Micro SW reset */
351 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_DW8051_CNTL_STATUS, release);
353 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
359 static int vsc8584_micro_assert_reset(struct mii_dev *bus, int phy)
364 ret = vsc8584_cmd(bus, phy, PROC_CMD_NOP);
368 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
371 reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL);
372 reg &= ~EN_PATCH_RAM_TRAP_ADDR(4);
373 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL, reg);
375 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_TRAP_ROM_ADDR(4), 0x005b);
376 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_PATCH_RAM_ADDR(4), 0x005b);
378 reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL);
379 reg |= EN_PATCH_RAM_TRAP_ADDR(4);
380 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL, reg);
382 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_PROC_CMD, PROC_CMD_NOP);
384 reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_DW8051_CNTL_STATUS);
385 reg &= ~MICRO_NSOFT_RESET;
386 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_DW8051_CNTL_STATUS, reg);
388 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_PROC_CMD,
389 PROC_CMD_MCB_ACCESS_MAC_CONF | PROC_CMD_SGMII_PORT(0) |
390 PROC_CMD_NO_MAC_CONF | PROC_CMD_READ);
392 reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL);
393 reg &= ~EN_PATCH_RAM_TRAP_ADDR(4);
394 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL, reg);
396 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
402 static const u8 fw_patch_vsc8574[] = {
403 0x46, 0x4a, 0x02, 0x43, 0x37, 0x02, 0x46, 0x26, 0x02, 0x46, 0x77, 0x02,
404 0x45, 0x60, 0x02, 0x45, 0xaf, 0xed, 0xff, 0xe5, 0xfc, 0x54, 0x38, 0x64,
405 0x20, 0x70, 0x08, 0x65, 0xff, 0x70, 0x04, 0xed, 0x44, 0x80, 0xff, 0x22,
406 0x8f, 0x19, 0x7b, 0xbb, 0x7d, 0x0e, 0x7f, 0x04, 0x12, 0x3d, 0xd7, 0xef,
407 0x4e, 0x60, 0x03, 0x02, 0x41, 0xf9, 0xe4, 0xf5, 0x1a, 0x74, 0x01, 0x7e,
408 0x00, 0xa8, 0x1a, 0x08, 0x80, 0x05, 0xc3, 0x33, 0xce, 0x33, 0xce, 0xd8,
409 0xf9, 0xff, 0xef, 0x55, 0x19, 0x70, 0x03, 0x02, 0x41, 0xed, 0x85, 0x1a,
410 0xfb, 0x7b, 0xbb, 0xe4, 0xfd, 0xff, 0x12, 0x3d, 0xd7, 0xef, 0x4e, 0x60,
411 0x03, 0x02, 0x41, 0xed, 0xe5, 0x1a, 0x54, 0x02, 0x75, 0x1d, 0x00, 0x25,
412 0xe0, 0x25, 0xe0, 0xf5, 0x1c, 0xe4, 0x78, 0xc5, 0xf6, 0xd2, 0x0a, 0x12,
413 0x41, 0xfa, 0x7b, 0xff, 0x7d, 0x12, 0x7f, 0x07, 0x12, 0x3d, 0xd7, 0xef,
414 0x4e, 0x60, 0x03, 0x02, 0x41, 0xe7, 0xc2, 0x0a, 0x74, 0xc7, 0x25, 0x1a,
415 0xf9, 0x74, 0xe7, 0x25, 0x1a, 0xf8, 0xe6, 0x27, 0xf5, 0x1b, 0xe5, 0x1d,
416 0x24, 0x5b, 0x12, 0x45, 0xea, 0x12, 0x3e, 0xda, 0x7b, 0xfc, 0x7d, 0x11,
417 0x7f, 0x07, 0x12, 0x3d, 0xd7, 0x78, 0xcc, 0xef, 0xf6, 0x78, 0xc1, 0xe6,
418 0xfe, 0xef, 0xd3, 0x9e, 0x40, 0x06, 0x78, 0xcc, 0xe6, 0x78, 0xc1, 0xf6,
419 0x12, 0x41, 0xfa, 0x7b, 0xec, 0x7d, 0x12, 0x7f, 0x07, 0x12, 0x3d, 0xd7,
420 0x78, 0xcb, 0xef, 0xf6, 0xbf, 0x07, 0x06, 0x78, 0xc3, 0x76, 0x1a, 0x80,
421 0x1f, 0x78, 0xc5, 0xe6, 0xff, 0x60, 0x0f, 0xc3, 0xe5, 0x1b, 0x9f, 0xff,
422 0x78, 0xcb, 0xe6, 0x85, 0x1b, 0xf0, 0xa4, 0x2f, 0x80, 0x07, 0x78, 0xcb,
423 0xe6, 0x85, 0x1b, 0xf0, 0xa4, 0x78, 0xc3, 0xf6, 0xe4, 0x78, 0xc2, 0xf6,
424 0x78, 0xc2, 0xe6, 0xff, 0xc3, 0x08, 0x96, 0x40, 0x03, 0x02, 0x41, 0xd1,
425 0xef, 0x54, 0x03, 0x60, 0x33, 0x14, 0x60, 0x46, 0x24, 0xfe, 0x60, 0x42,
426 0x04, 0x70, 0x4b, 0xef, 0x24, 0x02, 0xff, 0xe4, 0x33, 0xfe, 0xef, 0x78,
427 0x02, 0xce, 0xa2, 0xe7, 0x13, 0xce, 0x13, 0xd8, 0xf8, 0xff, 0xe5, 0x1d,
428 0x24, 0x5c, 0xcd, 0xe5, 0x1c, 0x34, 0xf0, 0xcd, 0x2f, 0xff, 0xed, 0x3e,
429 0xfe, 0x12, 0x46, 0x0d, 0x7d, 0x11, 0x80, 0x0b, 0x78, 0xc2, 0xe6, 0x70,
430 0x04, 0x7d, 0x11, 0x80, 0x02, 0x7d, 0x12, 0x7f, 0x07, 0x12, 0x3e, 0x9a,
431 0x8e, 0x1e, 0x8f, 0x1f, 0x80, 0x03, 0xe5, 0x1e, 0xff, 0x78, 0xc5, 0xe6,
432 0x06, 0x24, 0xcd, 0xf8, 0xa6, 0x07, 0x78, 0xc2, 0x06, 0xe6, 0xb4, 0x1a,
433 0x0a, 0xe5, 0x1d, 0x24, 0x5c, 0x12, 0x45, 0xea, 0x12, 0x3e, 0xda, 0x78,
434 0xc5, 0xe6, 0x65, 0x1b, 0x70, 0x82, 0x75, 0xdb, 0x20, 0x75, 0xdb, 0x28,
435 0x12, 0x46, 0x02, 0x12, 0x46, 0x02, 0xe5, 0x1a, 0x12, 0x45, 0xf5, 0xe5,
436 0x1a, 0xc3, 0x13, 0x12, 0x45, 0xf5, 0x78, 0xc5, 0x16, 0xe6, 0x24, 0xcd,
437 0xf8, 0xe6, 0xff, 0x7e, 0x08, 0x1e, 0xef, 0xa8, 0x06, 0x08, 0x80, 0x02,
438 0xc3, 0x13, 0xd8, 0xfc, 0xfd, 0xc4, 0x33, 0x54, 0xe0, 0xf5, 0xdb, 0xef,
439 0xa8, 0x06, 0x08, 0x80, 0x02, 0xc3, 0x13, 0xd8, 0xfc, 0xfd, 0xc4, 0x33,
440 0x54, 0xe0, 0x44, 0x08, 0xf5, 0xdb, 0xee, 0x70, 0xd8, 0x78, 0xc5, 0xe6,
441 0x70, 0xc8, 0x75, 0xdb, 0x10, 0x02, 0x40, 0xfd, 0x78, 0xc2, 0xe6, 0xc3,
442 0x94, 0x17, 0x50, 0x0e, 0xe5, 0x1d, 0x24, 0x62, 0x12, 0x42, 0x08, 0xe5,
443 0x1d, 0x24, 0x5c, 0x12, 0x42, 0x08, 0x20, 0x0a, 0x03, 0x02, 0x40, 0x76,
444 0x05, 0x1a, 0xe5, 0x1a, 0xc3, 0x94, 0x04, 0x50, 0x03, 0x02, 0x40, 0x3a,
445 0x22, 0xe5, 0x1d, 0x24, 0x5c, 0xff, 0xe5, 0x1c, 0x34, 0xf0, 0xfe, 0x12,
446 0x46, 0x0d, 0x22, 0xff, 0xe5, 0x1c, 0x34, 0xf0, 0xfe, 0x12, 0x46, 0x0d,
447 0x22, 0xe4, 0xf5, 0x19, 0x12, 0x46, 0x43, 0x20, 0xe7, 0x1e, 0x7b, 0xfe,
448 0x12, 0x42, 0xf9, 0xef, 0xc4, 0x33, 0x33, 0x54, 0xc0, 0xff, 0xc0, 0x07,
449 0x7b, 0x54, 0x12, 0x42, 0xf9, 0xd0, 0xe0, 0x4f, 0xff, 0x74, 0x2a, 0x25,
450 0x19, 0xf8, 0xa6, 0x07, 0x12, 0x46, 0x43, 0x20, 0xe7, 0x03, 0x02, 0x42,
451 0xdf, 0x54, 0x03, 0x64, 0x03, 0x70, 0x03, 0x02, 0x42, 0xcf, 0x7b, 0xcb,
452 0x12, 0x43, 0x2c, 0x8f, 0xfb, 0x7b, 0x30, 0x7d, 0x03, 0xe4, 0xff, 0x12,
453 0x3d, 0xd7, 0xc3, 0xef, 0x94, 0x02, 0xee, 0x94, 0x00, 0x50, 0x2a, 0x12,
454 0x42, 0xec, 0xef, 0x4e, 0x70, 0x23, 0x12, 0x43, 0x04, 0x60, 0x0a, 0x12,
455 0x43, 0x12, 0x70, 0x0c, 0x12, 0x43, 0x1f, 0x70, 0x07, 0x12, 0x46, 0x39,
456 0x7b, 0x03, 0x80, 0x07, 0x12, 0x46, 0x39, 0x12, 0x46, 0x43, 0xfb, 0x7a,
457 0x00, 0x7d, 0x54, 0x80, 0x3e, 0x12, 0x42, 0xec, 0xef, 0x4e, 0x70, 0x24,
458 0x12, 0x43, 0x04, 0x60, 0x0a, 0x12, 0x43, 0x12, 0x70, 0x0f, 0x12, 0x43,
459 0x1f, 0x70, 0x0a, 0x12, 0x46, 0x39, 0xe4, 0xfb, 0xfa, 0x7d, 0xee, 0x80,
460 0x1e, 0x12, 0x46, 0x39, 0x7b, 0x01, 0x7a, 0x00, 0x7d, 0xee, 0x80, 0x13,
461 0x12, 0x46, 0x39, 0x12, 0x46, 0x43, 0x54, 0x40, 0xfe, 0xc4, 0x13, 0x13,
462 0x54, 0x03, 0xfb, 0x7a, 0x00, 0x7d, 0xee, 0x12, 0x38, 0xbd, 0x7b, 0xff,
463 0x12, 0x43, 0x2c, 0xef, 0x4e, 0x70, 0x07, 0x74, 0x2a, 0x25, 0x19, 0xf8,
464 0xe4, 0xf6, 0x05, 0x19, 0xe5, 0x19, 0xc3, 0x94, 0x02, 0x50, 0x03, 0x02,
465 0x42, 0x15, 0x22, 0xe5, 0x19, 0x24, 0x17, 0xfd, 0x7b, 0x20, 0x7f, 0x04,
466 0x12, 0x3d, 0xd7, 0x22, 0xe5, 0x19, 0x24, 0x17, 0xfd, 0x7f, 0x04, 0x12,
467 0x3d, 0xd7, 0x22, 0x7b, 0x22, 0x7d, 0x18, 0x7f, 0x06, 0x12, 0x3d, 0xd7,
468 0xef, 0x64, 0x01, 0x4e, 0x22, 0x7d, 0x1c, 0xe4, 0xff, 0x12, 0x3e, 0x9a,
469 0xef, 0x54, 0x1b, 0x64, 0x0a, 0x22, 0x7b, 0xcc, 0x7d, 0x10, 0xff, 0x12,
470 0x3d, 0xd7, 0xef, 0x64, 0x01, 0x4e, 0x22, 0xe5, 0x19, 0x24, 0x17, 0xfd,
471 0x7f, 0x04, 0x12, 0x3d, 0xd7, 0x22, 0xd2, 0x08, 0x75, 0xfb, 0x03, 0xab,
472 0x7e, 0xaa, 0x7d, 0x7d, 0x19, 0x7f, 0x03, 0x12, 0x3e, 0xda, 0xe5, 0x7e,
473 0x54, 0x0f, 0x24, 0xf3, 0x60, 0x03, 0x02, 0x43, 0xe9, 0x12, 0x46, 0x5a,
474 0x12, 0x46, 0x61, 0xd8, 0xfb, 0xff, 0x20, 0xe2, 0x35, 0x13, 0x92, 0x0c,
475 0xef, 0xa2, 0xe1, 0x92, 0x0b, 0x30, 0x0c, 0x2a, 0xe4, 0xf5, 0x10, 0x7b,
476 0xfe, 0x12, 0x43, 0xff, 0xef, 0xc4, 0x33, 0x33, 0x54, 0xc0, 0xff, 0xc0,
477 0x07, 0x7b, 0x54, 0x12, 0x43, 0xff, 0xd0, 0xe0, 0x4f, 0xff, 0x74, 0x2a,
478 0x25, 0x10, 0xf8, 0xa6, 0x07, 0x05, 0x10, 0xe5, 0x10, 0xc3, 0x94, 0x02,
479 0x40, 0xd9, 0x12, 0x46, 0x5a, 0x12, 0x46, 0x61, 0xd8, 0xfb, 0x54, 0x05,
480 0x64, 0x04, 0x70, 0x27, 0x78, 0xc4, 0xe6, 0x78, 0xc6, 0xf6, 0xe5, 0x7d,
481 0xff, 0x33, 0x95, 0xe0, 0xef, 0x54, 0x0f, 0x78, 0xc4, 0xf6, 0x12, 0x44,
482 0x0a, 0x20, 0x0c, 0x0c, 0x12, 0x46, 0x5a, 0x12, 0x46, 0x61, 0xd8, 0xfb,
483 0x13, 0x92, 0x0d, 0x22, 0xc2, 0x0d, 0x22, 0x12, 0x46, 0x5a, 0x12, 0x46,
484 0x61, 0xd8, 0xfb, 0x54, 0x05, 0x64, 0x05, 0x70, 0x1e, 0x78, 0xc4, 0x7d,
485 0xb8, 0x12, 0x43, 0xf5, 0x78, 0xc1, 0x7d, 0x74, 0x12, 0x43, 0xf5, 0xe4,
486 0x78, 0xc1, 0xf6, 0x22, 0x7b, 0x01, 0x7a, 0x00, 0x7d, 0xee, 0x7f, 0x92,
487 0x12, 0x38, 0xbd, 0x22, 0xe6, 0xfb, 0x7a, 0x00, 0x7f, 0x92, 0x12, 0x38,
488 0xbd, 0x22, 0xe5, 0x10, 0x24, 0x17, 0xfd, 0x7f, 0x04, 0x12, 0x3d, 0xd7,
489 0x22, 0x78, 0xc1, 0xe6, 0xfb, 0x7a, 0x00, 0x7d, 0x74, 0x7f, 0x92, 0x12,
490 0x38, 0xbd, 0xe4, 0x78, 0xc1, 0xf6, 0xf5, 0x11, 0x74, 0x01, 0x7e, 0x00,
491 0xa8, 0x11, 0x08, 0x80, 0x05, 0xc3, 0x33, 0xce, 0x33, 0xce, 0xd8, 0xf9,
492 0xff, 0x78, 0xc4, 0xe6, 0xfd, 0xef, 0x5d, 0x60, 0x44, 0x85, 0x11, 0xfb,
493 0xe5, 0x11, 0x54, 0x02, 0x25, 0xe0, 0x25, 0xe0, 0xfe, 0xe4, 0x24, 0x5b,
494 0xfb, 0xee, 0x12, 0x45, 0xed, 0x12, 0x3e, 0xda, 0x7b, 0x40, 0x7d, 0x11,
495 0x7f, 0x07, 0x12, 0x3d, 0xd7, 0x74, 0xc7, 0x25, 0x11, 0xf8, 0xa6, 0x07,
496 0x7b, 0x11, 0x7d, 0x12, 0x7f, 0x07, 0x12, 0x3d, 0xd7, 0xef, 0x4e, 0x60,
497 0x09, 0x74, 0xe7, 0x25, 0x11, 0xf8, 0x76, 0x04, 0x80, 0x07, 0x74, 0xe7,
498 0x25, 0x11, 0xf8, 0x76, 0x0a, 0x05, 0x11, 0xe5, 0x11, 0xc3, 0x94, 0x04,
499 0x40, 0x9a, 0x78, 0xc6, 0xe6, 0x70, 0x15, 0x78, 0xc4, 0xe6, 0x60, 0x10,
500 0x75, 0xd9, 0x38, 0x75, 0xdb, 0x10, 0x7d, 0xfe, 0x12, 0x44, 0xb8, 0x7d,
501 0x76, 0x12, 0x44, 0xb8, 0x79, 0xc6, 0xe7, 0x78, 0xc4, 0x66, 0xff, 0x60,
502 0x03, 0x12, 0x40, 0x25, 0x78, 0xc4, 0xe6, 0x70, 0x09, 0xfb, 0xfa, 0x7d,
503 0xfe, 0x7f, 0x8e, 0x12, 0x38, 0xbd, 0x22, 0x7b, 0x01, 0x7a, 0x00, 0x7f,
504 0x8e, 0x12, 0x38, 0xbd, 0x22, 0xe4, 0xf5, 0xfb, 0x7d, 0x1c, 0xe4, 0xff,
505 0x12, 0x3e, 0x9a, 0xad, 0x07, 0xac, 0x06, 0xec, 0x54, 0xc0, 0xff, 0xed,
506 0x54, 0x3f, 0x4f, 0xf5, 0x20, 0x30, 0x06, 0x2c, 0x30, 0x01, 0x08, 0xa2,
507 0x04, 0x72, 0x03, 0x92, 0x07, 0x80, 0x21, 0x30, 0x04, 0x06, 0x7b, 0xcc,
508 0x7d, 0x11, 0x80, 0x0d, 0x30, 0x03, 0x06, 0x7b, 0xcc, 0x7d, 0x10, 0x80,
509 0x04, 0x7b, 0x66, 0x7d, 0x16, 0xe4, 0xff, 0x12, 0x3d, 0xd7, 0xee, 0x4f,
510 0x24, 0xff, 0x92, 0x07, 0xaf, 0xfb, 0x74, 0x26, 0x2f, 0xf8, 0xe6, 0xff,
511 0xa6, 0x20, 0x20, 0x07, 0x39, 0x8f, 0x20, 0x30, 0x07, 0x34, 0x30, 0x00,
512 0x31, 0x20, 0x04, 0x2e, 0x20, 0x03, 0x2b, 0xe4, 0xf5, 0xff, 0x75, 0xfc,
513 0xc2, 0xe5, 0xfc, 0x30, 0xe0, 0xfb, 0xaf, 0xfe, 0xef, 0x20, 0xe3, 0x1a,
514 0xae, 0xfd, 0x44, 0x08, 0xf5, 0xfe, 0x75, 0xfc, 0x80, 0xe5, 0xfc, 0x30,
515 0xe0, 0xfb, 0x8f, 0xfe, 0x8e, 0xfd, 0x75, 0xfc, 0x80, 0xe5, 0xfc, 0x30,
516 0xe0, 0xfb, 0x05, 0xfb, 0xaf, 0xfb, 0xef, 0xc3, 0x94, 0x04, 0x50, 0x03,
517 0x02, 0x44, 0xc5, 0xe4, 0xf5, 0xfb, 0x22, 0xe5, 0x7e, 0x54, 0x0f, 0x64,
518 0x01, 0x70, 0x23, 0xe5, 0x7e, 0x30, 0xe4, 0x1e, 0x90, 0x47, 0xd0, 0xe0,
519 0x44, 0x02, 0xf0, 0x54, 0xfb, 0xf0, 0x90, 0x47, 0xd4, 0xe0, 0x44, 0x04,
520 0xf0, 0x7b, 0x03, 0x7d, 0x5b, 0x7f, 0x5d, 0x12, 0x36, 0x29, 0x7b, 0x0e,
521 0x80, 0x1c, 0x90, 0x47, 0xd0, 0xe0, 0x54, 0xfd, 0xf0, 0x44, 0x04, 0xf0,
522 0x90, 0x47, 0xd4, 0xe0, 0x54, 0xfb, 0xf0, 0x7b, 0x02, 0x7d, 0x5b, 0x7f,
523 0x5d, 0x12, 0x36, 0x29, 0x7b, 0x06, 0x7d, 0x60, 0x7f, 0x63, 0x12, 0x36,
524 0x29, 0x22, 0xe5, 0x7e, 0x30, 0xe5, 0x35, 0x30, 0xe4, 0x0b, 0x7b, 0x02,
525 0x7d, 0x33, 0x7f, 0x35, 0x12, 0x36, 0x29, 0x80, 0x10, 0x7b, 0x01, 0x7d,
526 0x33, 0x7f, 0x35, 0x12, 0x36, 0x29, 0x90, 0x47, 0xd2, 0xe0, 0x44, 0x04,
527 0xf0, 0x90, 0x47, 0xd2, 0xe0, 0x54, 0xf7, 0xf0, 0x90, 0x47, 0xd1, 0xe0,
528 0x44, 0x10, 0xf0, 0x7b, 0x05, 0x7d, 0x84, 0x7f, 0x86, 0x12, 0x36, 0x29,
529 0x22, 0xfb, 0xe5, 0x1c, 0x34, 0xf0, 0xfa, 0x7d, 0x10, 0x7f, 0x07, 0x22,
530 0x54, 0x01, 0xc4, 0x33, 0x54, 0xe0, 0xf5, 0xdb, 0x44, 0x08, 0xf5, 0xdb,
531 0x22, 0xf5, 0xdb, 0x75, 0xdb, 0x08, 0xf5, 0xdb, 0x75, 0xdb, 0x08, 0x22,
532 0xab, 0x07, 0xaa, 0x06, 0x7d, 0x10, 0x7f, 0x07, 0x12, 0x3e, 0xda, 0x7b,
533 0xff, 0x7d, 0x10, 0x7f, 0x07, 0x12, 0x3d, 0xd7, 0xef, 0x4e, 0x60, 0xf3,
534 0x22, 0x12, 0x44, 0xc2, 0x30, 0x0c, 0x03, 0x12, 0x42, 0x12, 0x78, 0xc4,
535 0xe6, 0xff, 0x60, 0x03, 0x12, 0x40, 0x25, 0x22, 0xe5, 0x19, 0x24, 0x17,
536 0x54, 0x1f, 0x44, 0x80, 0xff, 0x22, 0x74, 0x2a, 0x25, 0x19, 0xf8, 0xe6,
537 0x22, 0x12, 0x46, 0x72, 0x12, 0x46, 0x68, 0x90, 0x47, 0xfa, 0xe0, 0x54,
538 0xf8, 0x44, 0x02, 0xf0, 0x22, 0xe5, 0x7e, 0xae, 0x7d, 0x78, 0x04, 0x22,
539 0xce, 0xa2, 0xe7, 0x13, 0xce, 0x13, 0x22, 0xe4, 0x78, 0xc4, 0xf6, 0xc2,
540 0x0d, 0x78, 0xc1, 0xf6, 0x22, 0xc2, 0x0c, 0xc2, 0x0b, 0x22, 0x22,
543 static const u8 fw_patch_vsc8584[] = {
544 0xe8, 0x59, 0x02, 0xe8, 0x12, 0x02, 0xe8, 0x42, 0x02, 0xe8, 0x5a, 0x02,
545 0xe8, 0x5b, 0x02, 0xe8, 0x5c, 0xe5, 0x69, 0x54, 0x0f, 0x24, 0xf7, 0x60,
546 0x27, 0x24, 0xfc, 0x60, 0x23, 0x24, 0x08, 0x70, 0x14, 0xe5, 0x69, 0xae,
547 0x68, 0x78, 0x04, 0xce, 0xa2, 0xe7, 0x13, 0xce, 0x13, 0xd8, 0xf8, 0x7e,
548 0x00, 0x54, 0x0f, 0x80, 0x00, 0x7b, 0x01, 0x7a, 0x00, 0x7d, 0xee, 0x7f,
549 0x92, 0x12, 0x50, 0xee, 0x22, 0xe4, 0xf5, 0x10, 0x85, 0x10, 0xfb, 0x7d,
550 0x1c, 0xe4, 0xff, 0x12, 0x59, 0xea, 0x05, 0x10, 0xe5, 0x10, 0xc3, 0x94,
551 0x04, 0x40, 0xed, 0x22, 0x22, 0x22, 0x22, 0x22,
554 static int vsc8584_get_fw_crc(struct mii_dev *bus, int phy, u16 start,
555 u16 *crc, const u8 *fw_patch, int fw_size)
559 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
562 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_VERIPHY_CNTL_2, start);
563 /* Add one byte to size for the one added by the patch_fw function */
564 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_VERIPHY_CNTL_3,
567 ret = vsc8584_cmd(bus, phy, PROC_CMD_CRC16);
571 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
574 *crc = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_VERIPHY_CNTL_2);
577 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
583 static int vsc8584_patch_fw(struct mii_dev *bus, int phy, const u8 *fw_patch,
588 ret = vsc8584_micro_assert_reset(bus, phy);
590 pr_err("%s: failed to assert reset of micro\n", __func__);
594 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
598 * Hold 8051 Micro in SW Reset, Enable auto incr address and patch clock
599 * Disable the 8051 Micro clock
601 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_DW8051_CNTL_STATUS,
602 RUN_FROM_INT_ROM | AUTOINC_ADDR | PATCH_RAM_CLK |
603 MICRO_CLK_EN | MICRO_CLK_DIVIDE(2));
604 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL, READ_PRAM |
605 INT_MEM_WRITE_EN | INT_MEM_DATA(2));
606 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_ADDR, 0x0000);
608 for (i = 0; i < fw_size; i++)
609 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL,
610 READ_PRAM | INT_MEM_WRITE_EN | fw_patch[i]);
612 /* Clear internal memory access */
613 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL, READ_RAM);
615 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
621 static bool vsc8574_is_serdes_init(struct mii_dev *bus, int phy)
626 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
629 reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_TRAP_ROM_ADDR(1));
630 if (reg != MSCC_TRAP_ROM_ADDR_SERDES_INIT) {
635 reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_PATCH_RAM_ADDR(1));
636 if (reg != MSCC_PATCH_RAM_ADDR_SERDES_INIT) {
641 reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL);
642 if (reg != EN_PATCH_RAM_TRAP_ADDR(1)) {
647 reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_DW8051_CNTL_STATUS);
648 if ((MICRO_NSOFT_RESET | RUN_FROM_INT_ROM | DW8051_CLK_EN |
649 MICRO_CLK_EN) != (reg & MSCC_DW8051_VLD_MASK)) {
657 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
663 static int vsc8574_config_pre_init(struct phy_device *phydev)
665 struct mii_dev *bus = phydev->bus;
666 u16 crc, reg, phy0, addr;
670 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
672 addr = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_EXT_PHY_CNTL_4);
673 addr >>= PHY_CNTL_4_ADDR_POS;
675 reg = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_ACTIPHY_CNTL);
676 if (reg & PHY_ADDR_REVERSED)
677 phy0 = phydev->addr + addr;
679 phy0 = phydev->addr - addr;
681 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
684 /* all writes below are broadcasted to all PHYs in the same package */
685 reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS);
686 reg |= SMI_BROADCAST_WR_EN;
687 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS, reg);
690 * The below register writes are tweaking analog and electrical
691 * configuration that were determined through characterization by PHY
692 * engineers. These don't mean anything more than "these are the best
695 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_PHY_CNTL_2, 0x0040);
697 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
700 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_20, 0x4320);
701 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_24, 0x0c00);
702 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_9, 0x18ca);
703 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_5, 0x1b20);
705 reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8);
706 reg |= TR_CLK_DISABLE;
707 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8, reg);
709 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
712 vsc8584_csr_write(bus, phy0, 0x0fae, 0x000401bd);
713 vsc8584_csr_write(bus, phy0, 0x0fac, 0x000f000f);
714 vsc8584_csr_write(bus, phy0, 0x17a0, 0x00a0f147);
715 vsc8584_csr_write(bus, phy0, 0x0fe4, 0x00052f54);
716 vsc8584_csr_write(bus, phy0, 0x1792, 0x0027303d);
717 vsc8584_csr_write(bus, phy0, 0x07fe, 0x00000704);
718 vsc8584_csr_write(bus, phy0, 0x0fe0, 0x00060150);
719 vsc8584_csr_write(bus, phy0, 0x0f82, 0x0012b00a);
720 vsc8584_csr_write(bus, phy0, 0x0f80, 0x00000d74);
721 vsc8584_csr_write(bus, phy0, 0x02e0, 0x00000012);
722 vsc8584_csr_write(bus, phy0, 0x03a2, 0x00050208);
723 vsc8584_csr_write(bus, phy0, 0x03b2, 0x00009186);
724 vsc8584_csr_write(bus, phy0, 0x0fb0, 0x000e3700);
725 vsc8584_csr_write(bus, phy0, 0x1688, 0x00049f81);
726 vsc8584_csr_write(bus, phy0, 0x0fd2, 0x0000ffff);
727 vsc8584_csr_write(bus, phy0, 0x168a, 0x00039fa2);
728 vsc8584_csr_write(bus, phy0, 0x1690, 0x0020640b);
729 vsc8584_csr_write(bus, phy0, 0x0258, 0x00002220);
730 vsc8584_csr_write(bus, phy0, 0x025a, 0x00002a20);
731 vsc8584_csr_write(bus, phy0, 0x025c, 0x00003060);
732 vsc8584_csr_write(bus, phy0, 0x025e, 0x00003fa0);
733 vsc8584_csr_write(bus, phy0, 0x03a6, 0x0000e0f0);
734 vsc8584_csr_write(bus, phy0, 0x0f92, 0x00001489);
735 vsc8584_csr_write(bus, phy0, 0x16a2, 0x00007000);
736 vsc8584_csr_write(bus, phy0, 0x16a6, 0x00071448);
737 vsc8584_csr_write(bus, phy0, 0x16a0, 0x00eeffdd);
738 vsc8584_csr_write(bus, phy0, 0x0fe8, 0x0091b06c);
739 vsc8584_csr_write(bus, phy0, 0x0fea, 0x00041600);
740 vsc8584_csr_write(bus, phy0, 0x16b0, 0x00eeff00);
741 vsc8584_csr_write(bus, phy0, 0x16b2, 0x00007000);
742 vsc8584_csr_write(bus, phy0, 0x16b4, 0x00000814);
743 vsc8584_csr_write(bus, phy0, 0x0f90, 0x00688980);
744 vsc8584_csr_write(bus, phy0, 0x03a4, 0x0000d8f0);
745 vsc8584_csr_write(bus, phy0, 0x0fc0, 0x00000400);
746 vsc8584_csr_write(bus, phy0, 0x07fa, 0x0050100f);
747 vsc8584_csr_write(bus, phy0, 0x0796, 0x00000003);
748 vsc8584_csr_write(bus, phy0, 0x07f8, 0x00c3ff98);
749 vsc8584_csr_write(bus, phy0, 0x0fa4, 0x0018292a);
750 vsc8584_csr_write(bus, phy0, 0x168c, 0x00d2c46f);
751 vsc8584_csr_write(bus, phy0, 0x17a2, 0x00000620);
752 vsc8584_csr_write(bus, phy0, 0x16a4, 0x0013132f);
753 vsc8584_csr_write(bus, phy0, 0x16a8, 0x00000000);
754 vsc8584_csr_write(bus, phy0, 0x0ffc, 0x00c0a028);
755 vsc8584_csr_write(bus, phy0, 0x0fec, 0x00901c09);
756 vsc8584_csr_write(bus, phy0, 0x0fee, 0x0004a6a1);
757 vsc8584_csr_write(bus, phy0, 0x0ffe, 0x00b01807);
759 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
762 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_CU_PMD_TX_CNTL, 0x028e);
764 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
767 vsc8584_csr_write(bus, phy0, 0x0486, 0x0008a518);
768 vsc8584_csr_write(bus, phy0, 0x0488, 0x006dc696);
769 vsc8584_csr_write(bus, phy0, 0x048a, 0x00000912);
770 vsc8584_csr_write(bus, phy0, 0x048e, 0x00000db6);
771 vsc8584_csr_write(bus, phy0, 0x049c, 0x00596596);
772 vsc8584_csr_write(bus, phy0, 0x049e, 0x00000514);
773 vsc8584_csr_write(bus, phy0, 0x04a2, 0x00410280);
774 vsc8584_csr_write(bus, phy0, 0x04a4, 0x00000000);
775 vsc8584_csr_write(bus, phy0, 0x04a6, 0x00000000);
776 vsc8584_csr_write(bus, phy0, 0x04a8, 0x00000000);
777 vsc8584_csr_write(bus, phy0, 0x04aa, 0x00000000);
778 vsc8584_csr_write(bus, phy0, 0x04ae, 0x007df7dd);
779 vsc8584_csr_write(bus, phy0, 0x04b0, 0x006d95d4);
780 vsc8584_csr_write(bus, phy0, 0x04b2, 0x00492410);
782 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
785 reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8);
786 reg &= ~TR_CLK_DISABLE;
787 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8, reg);
789 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
792 /* end of write broadcasting */
793 reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS);
794 reg &= ~SMI_BROADCAST_WR_EN;
795 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS, reg);
797 ret = vsc8584_get_fw_crc(bus, phy0,
798 MSCC_VSC8574_REVB_INT8051_FW_START_ADDR, &crc,
800 ARRAY_SIZE(fw_patch_vsc8574));
804 if (crc == MSCC_VSC8574_REVB_INT8051_FW_CRC) {
805 serdes_init = vsc8574_is_serdes_init(bus, phy0);
808 ret = vsc8584_micro_assert_reset(bus, phy0);
810 pr_err("failed to assert reset of micro\n");
815 pr_debug("FW CRC is not the expected one, patching FW\n");
819 if (vsc8584_patch_fw(bus, phy0, fw_patch_vsc8574,
820 ARRAY_SIZE(fw_patch_vsc8574)))
821 pr_warn("failed to patch FW, expect non-optimal device\n");
825 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
828 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_TRAP_ROM_ADDR(1),
829 MSCC_TRAP_ROM_ADDR_SERDES_INIT);
830 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PATCH_RAM_ADDR(1),
831 MSCC_PATCH_RAM_ADDR_SERDES_INIT);
833 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL,
834 EN_PATCH_RAM_TRAP_ADDR(1));
836 vsc8584_micro_deassert_reset(bus, phy0, false);
838 ret = vsc8584_get_fw_crc(bus, phy0,
839 MSCC_VSC8574_REVB_INT8051_FW_START_ADDR,
840 &crc, fw_patch_vsc8574,
841 ARRAY_SIZE(fw_patch_vsc8574));
845 if (crc != MSCC_VSC8574_REVB_INT8051_FW_CRC)
846 pr_warn("FW CRC after patching is not the expected one, expect non-optimal device\n");
849 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
852 ret = vsc8584_cmd(bus, phy0, PROC_CMD_1588_DEFAULT_INIT |
856 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
862 static int vsc8584_config_pre_init(struct phy_device *phydev)
864 struct mii_dev *bus = phydev->bus;
865 u16 reg, crc, phy0, addr;
868 if ((phydev->phy_id & MSCC_DEV_REV_MASK) != VSC8584_REVB) {
869 pr_warn("VSC8584 revA not officially supported, skipping firmware patching. Use at your own risk.\n");
873 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
875 addr = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_EXT_PHY_CNTL_4);
876 addr >>= PHY_CNTL_4_ADDR_POS;
878 reg = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_ACTIPHY_CNTL);
879 if (reg & PHY_ADDR_REVERSED)
880 phy0 = phydev->addr + addr;
882 phy0 = phydev->addr - addr;
884 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
887 /* all writes below are broadcasted to all PHYs in the same package */
888 reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS);
889 reg |= SMI_BROADCAST_WR_EN;
890 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS, reg);
893 * The below register writes are tweaking analog and electrical
894 * configuration that were determined through characterization by PHY
895 * engineers. These don't mean anything more than "these are the best
898 reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_BYPASS_CONTROL);
899 reg |= PARALLEL_DET_IGNORE_ADVERTISED;
900 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_BYPASS_CONTROL, reg);
902 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
905 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_SERDES_TX_CRC_ERR_CNT,
908 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
911 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_5, 0x1f20);
913 reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8);
914 reg |= TR_CLK_DISABLE;
915 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8, reg);
917 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
920 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16, 0xafa4);
922 reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18);
925 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18, reg);
927 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16, 0x8fa4);
929 vsc8584_csr_write(bus, phy0, 0x07fa, 0x0050100f);
930 vsc8584_csr_write(bus, phy0, 0x1688, 0x00049f81);
931 vsc8584_csr_write(bus, phy0, 0x0f90, 0x00688980);
932 vsc8584_csr_write(bus, phy0, 0x03a4, 0x0000d8f0);
933 vsc8584_csr_write(bus, phy0, 0x0fc0, 0x00000400);
934 vsc8584_csr_write(bus, phy0, 0x0f82, 0x0012b002);
935 vsc8584_csr_write(bus, phy0, 0x1686, 0x00000004);
936 vsc8584_csr_write(bus, phy0, 0x168c, 0x00d2c46f);
937 vsc8584_csr_write(bus, phy0, 0x17a2, 0x00000620);
938 vsc8584_csr_write(bus, phy0, 0x16a0, 0x00eeffdd);
939 vsc8584_csr_write(bus, phy0, 0x16a6, 0x00071448);
940 vsc8584_csr_write(bus, phy0, 0x16a4, 0x0013132f);
941 vsc8584_csr_write(bus, phy0, 0x16a8, 0x00000000);
942 vsc8584_csr_write(bus, phy0, 0x0ffc, 0x00c0a028);
943 vsc8584_csr_write(bus, phy0, 0x0fe8, 0x0091b06c);
944 vsc8584_csr_write(bus, phy0, 0x0fea, 0x00041600);
945 vsc8584_csr_write(bus, phy0, 0x0f80, 0x00fffaff);
946 vsc8584_csr_write(bus, phy0, 0x0fec, 0x00901809);
947 vsc8584_csr_write(bus, phy0, 0x0ffe, 0x00b01007);
948 vsc8584_csr_write(bus, phy0, 0x16b0, 0x00eeff00);
949 vsc8584_csr_write(bus, phy0, 0x16b2, 0x00007000);
950 vsc8584_csr_write(bus, phy0, 0x16b4, 0x00000814);
952 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
955 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_CU_PMD_TX_CNTL, 0x028e);
957 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
960 vsc8584_csr_write(bus, phy0, 0x0486, 0x0008a518);
961 vsc8584_csr_write(bus, phy0, 0x0488, 0x006dc696);
962 vsc8584_csr_write(bus, phy0, 0x048a, 0x00000912);
964 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
967 reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8);
968 reg &= ~TR_CLK_DISABLE;
969 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8, reg);
971 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
974 /* end of write broadcasting */
975 reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS);
976 reg &= ~SMI_BROADCAST_WR_EN;
977 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS, reg);
979 ret = vsc8584_get_fw_crc(bus, phy0,
980 MSCC_VSC8584_REVB_INT8051_FW_START_ADDR, &crc,
982 ARRAY_SIZE(fw_patch_vsc8584));
986 if (crc != MSCC_VSC8584_REVB_INT8051_FW_CRC) {
987 debug("FW CRC is not the expected one, patching FW...\n");
988 if (vsc8584_patch_fw(bus, phy0, fw_patch_vsc8584,
989 ARRAY_SIZE(fw_patch_vsc8584)))
990 pr_warn("failed to patch FW, expect non-optimal device\n");
993 vsc8584_micro_deassert_reset(bus, phy0, false);
995 ret = vsc8584_get_fw_crc(bus, phy0,
996 MSCC_VSC8584_REVB_INT8051_FW_START_ADDR, &crc,
998 ARRAY_SIZE(fw_patch_vsc8584));
1002 if (crc != MSCC_VSC8584_REVB_INT8051_FW_CRC)
1003 pr_warn("FW CRC after patching is not the expected one, expect non-optimal device\n");
1005 ret = vsc8584_micro_assert_reset(bus, phy0);
1009 vsc8584_micro_deassert_reset(bus, phy0, true);
1012 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1018 static int mscc_vsc8531_vsc8541_init_scripts(struct phy_device *phydev)
1022 /* Set to Access Token Ring Registers */
1023 phy_write(phydev, MDIO_DEVAD_NONE,
1024 MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_TR);
1026 /* Update LinkDetectCtrl default to optimized values */
1027 /* Determined during Silicon Validation Testing */
1028 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
1029 (MSCC_PHY_TR_LINKDETCTRL_ADDR | MSCC_PHY_TR_16_READ));
1030 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17);
1031 reg_val = bitfield_replace(reg_val, MSCC_PHY_TR_LINKDETCTRL_POS,
1032 MSCC_PHY_TR_LINKDETCTRL_WIDTH,
1033 MSCC_PHY_TR_LINKDETCTRL_VAL);
1035 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17, reg_val);
1036 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
1037 (MSCC_PHY_TR_LINKDETCTRL_ADDR | MSCC_PHY_TR_16_WRITE));
1039 /* Update VgaThresh100 defaults to optimized values */
1040 /* Determined during Silicon Validation Testing */
1041 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
1042 (MSCC_PHY_TR_VGATHRESH100_ADDR | MSCC_PHY_TR_16_READ));
1044 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18);
1045 reg_val = bitfield_replace(reg_val, MSCC_PHY_TR_VGATHRESH100_POS,
1046 MSCC_PHY_TR_VGATHRESH100_WIDTH,
1047 MSCC_PHY_TR_VGATHRESH100_VAL);
1049 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18, reg_val);
1050 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
1051 (MSCC_PHY_TR_VGATHRESH100_ADDR | MSCC_PHY_TR_16_WRITE));
1053 /* Update VgaGain10 defaults to optimized values */
1054 /* Determined during Silicon Validation Testing */
1055 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
1056 (MSCC_PHY_TR_VGAGAIN10_ADDR | MSCC_PHY_TR_16_READ));
1058 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18);
1059 reg_val = bitfield_replace(reg_val, MSCC_PHY_TR_VGAGAIN10_U_POS,
1060 MSCC_PHY_TR_VGAGAIN10_U_WIDTH,
1061 MSCC_PHY_TR_VGAGAIN10_U_VAL);
1063 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18, reg_val);
1064 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17);
1065 reg_val = bitfield_replace(reg_val, MSCC_PHY_TR_VGAGAIN10_L_POS,
1066 MSCC_PHY_TR_VGAGAIN10_L_WIDTH,
1067 MSCC_PHY_TR_VGAGAIN10_L_VAL);
1069 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17, reg_val);
1070 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
1071 (MSCC_PHY_TR_VGAGAIN10_ADDR | MSCC_PHY_TR_16_WRITE));
1073 /* Set back to Access Standard Page Registers */
1074 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1080 static int mscc_parse_status(struct phy_device *phydev)
1085 mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_AUX_CNTRL_STAT_REG);
1087 if (mii_reg & MIIM_AUX_CNTRL_STAT_F_DUPLEX)
1088 phydev->duplex = DUPLEX_FULL;
1090 phydev->duplex = DUPLEX_HALF;
1092 speed = mii_reg & MIIM_AUX_CNTRL_STAT_SPEED_MASK;
1093 speed = speed >> MIIM_AUX_CNTRL_STAT_SPEED_POS;
1096 case MIIM_AUX_CNTRL_STAT_SPEED_1000M:
1097 phydev->speed = SPEED_1000;
1099 case MIIM_AUX_CNTRL_STAT_SPEED_100M:
1100 phydev->speed = SPEED_100;
1102 case MIIM_AUX_CNTRL_STAT_SPEED_10M:
1103 phydev->speed = SPEED_10;
1106 phydev->speed = SPEED_10;
1113 static int mscc_startup(struct phy_device *phydev)
1117 retval = genphy_update_link(phydev);
1122 return mscc_parse_status(phydev);
1125 static int mscc_phy_soft_reset(struct phy_device *phydev)
1128 u16 timeout = MSCC_PHY_RESET_TIMEOUT;
1131 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1134 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
1135 phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, (reg_val | BMCR_RESET));
1137 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
1139 while ((reg_val & BMCR_RESET) && (timeout > 0)) {
1140 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
1142 udelay(1000); /* 1 ms */
1146 printf("MSCC PHY Soft_Reset Error: mac i/f = 0x%x\n",
1154 static int vsc8531_vsc8541_mac_config(struct phy_device *phydev)
1160 /* For VSC8530/31 the only MAC modes are RMII/RGMII. */
1161 /* For VSC8540/41 the only MAC modes are (G)MII and RMII/RGMII. */
1162 /* Setup MAC Configuration */
1163 switch (phydev->interface) {
1164 case PHY_INTERFACE_MODE_MII:
1165 case PHY_INTERFACE_MODE_GMII:
1166 /* Set Reg23.12:11=0 */
1167 mac_if = MAC_IF_SELECTION_GMII;
1168 /* Set Reg20E2.11=1 */
1169 rx_clk_out = RX_CLK_OUT_DISABLE;
1172 case PHY_INTERFACE_MODE_RMII:
1173 /* Set Reg23.12:11=1 */
1174 mac_if = MAC_IF_SELECTION_RMII;
1175 /* Set Reg20E2.11=0 */
1176 rx_clk_out = RX_CLK_OUT_NORMAL;
1179 case PHY_INTERFACE_MODE_RGMII:
1180 /* Set Reg23.12:11=2 */
1181 mac_if = MAC_IF_SELECTION_RGMII;
1182 /* Set Reg20E2.11=0 */
1183 rx_clk_out = RX_CLK_OUT_NORMAL;
1187 printf("MSCC PHY - INVALID MAC i/f Config: mac i/f = 0x%x\n",
1192 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1195 reg_val = phy_read(phydev, MDIO_DEVAD_NONE,
1196 MSCC_PHY_EXT_PHY_CNTL_1_REG);
1197 /* Set MAC i/f bits Reg23.12:11 */
1198 reg_val = bitfield_replace(reg_val, MAC_IF_SELECTION_POS,
1199 MAC_IF_SELECTION_WIDTH, mac_if);
1200 /* Update Reg23.12:11 */
1201 phy_write(phydev, MDIO_DEVAD_NONE,
1202 MSCC_PHY_EXT_PHY_CNTL_1_REG, reg_val);
1203 /* Setup ExtPg_2 Register Access */
1204 phy_write(phydev, MDIO_DEVAD_NONE,
1205 MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_EXT2);
1207 reg_val = phy_read(phydev, MDIO_DEVAD_NONE,
1208 MSCC_PHY_RGMII_CNTL_REG);
1209 reg_val = bitfield_replace(reg_val, RX_CLK_OUT_POS,
1210 RX_CLK_OUT_WIDTH, rx_clk_out);
1211 /* Update Reg20E2.11 */
1212 phy_write(phydev, MDIO_DEVAD_NONE,
1213 MSCC_PHY_RGMII_CNTL_REG, reg_val);
1214 /* Before leaving - Change back to Std Page Register Access */
1215 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1221 static int vsc8531_vsc8541_clkout_config(struct phy_device *phydev)
1223 struct ofnode_phandle_args phandle_args;
1224 u32 clkout_rate = 0;
1228 retval = dev_read_phandle_with_args(phydev->dev, "phy-handle", NULL,
1229 0, 0, &phandle_args);
1231 clkout_rate = ofnode_read_u32_default(phandle_args.node,
1232 "vsc8531,clk-out-frequency", 0);
1234 switch (clkout_rate) {
1239 reg_val = CLKOUT_FREQ_25M | CLKOUT_ENABLE;
1242 reg_val = CLKOUT_FREQ_50M | CLKOUT_ENABLE;
1245 reg_val = CLKOUT_FREQ_125M | CLKOUT_ENABLE;
1248 printf("PHY 8530/31 invalid clkout rate %u\n",
1253 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1254 MSCC_PHY_PAGE_GPIO);
1255 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_CLKOUT_CNTL, reg_val);
1256 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1262 static int vsc8531_config(struct phy_device *phydev)
1264 int retval = -EINVAL;
1267 enum vsc_phy_rgmii_skew rx_clk_skew = VSC_PHY_RGMII_DELAY_1700_PS;
1268 enum vsc_phy_rgmii_skew tx_clk_skew = VSC_PHY_RGMII_DELAY_800_PS;
1269 enum vsc_phy_clk_slew edge_rate = VSC_PHY_CLK_SLEW_RATE_4;
1271 /* For VSC8530/31 and VSC8540/41 the init scripts are the same */
1272 mscc_vsc8531_vsc8541_init_scripts(phydev);
1274 /* For VSC8530/31 the only MAC modes are RMII/RGMII. */
1275 switch (phydev->interface) {
1276 case PHY_INTERFACE_MODE_RMII:
1277 case PHY_INTERFACE_MODE_RGMII:
1278 retval = vsc8531_vsc8541_mac_config(phydev);
1282 retval = mscc_phy_soft_reset(phydev);
1287 printf("PHY 8530/31 MAC i/f Config Error: mac i/f = 0x%x\n",
1291 /* Default RMII Clk Output to 0=OFF/1=ON */
1294 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1295 MSCC_PHY_PAGE_EXT2);
1296 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG);
1298 /* Reg20E2 - Update RGMII RX_Clk Skews. */
1299 reg_val = bitfield_replace(reg_val, RGMII_RX_CLK_DELAY_POS,
1300 RGMII_RX_CLK_DELAY_WIDTH, rx_clk_skew);
1301 /* Reg20E2 - Update RGMII TX_Clk Skews. */
1302 reg_val = bitfield_replace(reg_val, RGMII_TX_CLK_DELAY_POS,
1303 RGMII_TX_CLK_DELAY_WIDTH, tx_clk_skew);
1305 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG, reg_val);
1307 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL);
1308 /* Reg27E2 - Update Clk Slew Rate. */
1309 reg_val = bitfield_replace(reg_val, EDGE_RATE_CNTL_POS,
1310 EDGE_RATE_CNTL_WIDTH, edge_rate);
1311 /* Reg27E2 - Update RMII Clk Out. */
1312 reg_val = bitfield_replace(reg_val, RMII_CLK_OUT_ENABLE_POS,
1313 RMII_CLK_OUT_ENABLE_WIDTH, rmii_clk_out);
1314 /* Update Reg27E2 */
1315 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL, reg_val);
1316 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1319 /* Configure the clk output */
1320 retval = vsc8531_vsc8541_clkout_config(phydev);
1324 return genphy_config_aneg(phydev);
1327 static int vsc8541_config(struct phy_device *phydev)
1329 int retval = -EINVAL;
1332 enum vsc_phy_rgmii_skew rx_clk_skew = VSC_PHY_RGMII_DELAY_1700_PS;
1333 enum vsc_phy_rgmii_skew tx_clk_skew = VSC_PHY_RGMII_DELAY_800_PS;
1334 enum vsc_phy_clk_slew edge_rate = VSC_PHY_CLK_SLEW_RATE_4;
1336 /* For VSC8530/31 and VSC8540/41 the init scripts are the same */
1337 mscc_vsc8531_vsc8541_init_scripts(phydev);
1339 /* For VSC8540/41 the only MAC modes are (G)MII and RMII/RGMII. */
1340 switch (phydev->interface) {
1341 case PHY_INTERFACE_MODE_MII:
1342 case PHY_INTERFACE_MODE_GMII:
1343 case PHY_INTERFACE_MODE_RMII:
1344 case PHY_INTERFACE_MODE_RGMII:
1345 retval = vsc8531_vsc8541_mac_config(phydev);
1349 retval = mscc_phy_soft_reset(phydev);
1354 printf("PHY 8541 MAC i/f config Error: mac i/f = 0x%x\n",
1358 /* Default RMII Clk Output to 0=OFF/1=ON */
1361 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1362 MSCC_PHY_PAGE_EXT2);
1363 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG);
1364 /* Reg20E2 - Update RGMII RX_Clk Skews. */
1365 reg_val = bitfield_replace(reg_val, RGMII_RX_CLK_DELAY_POS,
1366 RGMII_RX_CLK_DELAY_WIDTH, rx_clk_skew);
1367 /* Reg20E2 - Update RGMII TX_Clk Skews. */
1368 reg_val = bitfield_replace(reg_val, RGMII_TX_CLK_DELAY_POS,
1369 RGMII_TX_CLK_DELAY_WIDTH, tx_clk_skew);
1370 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG, reg_val);
1372 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL);
1373 /* Reg27E2 - Update Clk Slew Rate. */
1374 reg_val = bitfield_replace(reg_val, EDGE_RATE_CNTL_POS,
1375 EDGE_RATE_CNTL_WIDTH, edge_rate);
1376 /* Reg27E2 - Update RMII Clk Out. */
1377 reg_val = bitfield_replace(reg_val, RMII_CLK_OUT_ENABLE_POS,
1378 RMII_CLK_OUT_ENABLE_WIDTH, rmii_clk_out);
1379 /* Update Reg27E2 */
1380 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL, reg_val);
1381 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1384 /* Configure the clk output */
1385 retval = vsc8531_vsc8541_clkout_config(phydev);
1389 return genphy_config_aneg(phydev);
1392 static int vsc8584_config_init(struct phy_device *phydev)
1394 struct vsc85xx_priv *priv = phydev->priv;
1400 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1401 MSCC_PHY_PAGE_EXT1);
1402 addr = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_EXT_PHY_CNTL_4);
1403 addr >>= PHY_CNTL_4_ADDR_POS;
1405 ret = priv->config_pre(phydev);
1409 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1410 MSCC_PHY_PAGE_GPIO);
1412 if (phydev->interface == PHY_INTERFACE_MODE_QSGMII)
1413 val = MAC_CFG_QSGMII;
1415 val = MAC_CFG_SGMII;
1417 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_MAC_CFG_FASTLINK);
1418 reg_val &= ~MAC_CFG_MASK;
1420 ret = phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_MAC_CFG_FASTLINK,
1425 reg_val = PROC_CMD_MCB_ACCESS_MAC_CONF | PROC_CMD_RST_CONF_PORT |
1426 PROC_CMD_READ_MOD_WRITE_PORT;
1427 if (phydev->interface == PHY_INTERFACE_MODE_QSGMII)
1428 reg_val |= PROC_CMD_QSGMII_MAC;
1430 reg_val |= PROC_CMD_SGMII_MAC;
1432 ret = vsc8584_cmd(phydev->bus, phydev->addr, reg_val);
1438 /* Disable SerDes for 100Base-FX */
1439 ret = vsc8584_cmd(phydev->bus, phydev->addr, PROC_CMD_FIBER_MEDIA_CONF |
1440 PROC_CMD_FIBER_PORT(addr) | PROC_CMD_FIBER_DISABLE |
1441 PROC_CMD_READ_MOD_WRITE_PORT |
1442 PROC_CMD_RST_CONF_PORT | PROC_CMD_FIBER_100BASE_FX);
1446 /* Disable SerDes for 1000Base-X */
1447 ret = vsc8584_cmd(phydev->bus, phydev->addr, PROC_CMD_FIBER_MEDIA_CONF |
1448 PROC_CMD_FIBER_PORT(addr) | PROC_CMD_FIBER_DISABLE |
1449 PROC_CMD_READ_MOD_WRITE_PORT |
1450 PROC_CMD_RST_CONF_PORT | PROC_CMD_FIBER_1000BASE_X);
1454 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1456 reg_val = phy_read(phydev, MDIO_DEVAD_NONE,
1457 MSCC_PHY_EXT_PHY_CNTL_1_REG);
1458 reg_val &= ~(MEDIA_OP_MODE_MASK | VSC8584_MAC_IF_SELECTION_MASK);
1459 reg_val |= MEDIA_OP_MODE_COPPER |
1460 (VSC8584_MAC_IF_SELECTION_SGMII <<
1461 VSC8584_MAC_IF_SELECTION_POS);
1462 ret = phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_EXT_PHY_CNTL_1_REG,
1465 ret = mscc_phy_soft_reset(phydev);
1469 return genphy_config(phydev);
1472 static struct vsc85xx_priv vsc8574_priv = {
1473 .config_pre = vsc8574_config_pre_init,
1476 static int vsc8574_config(struct phy_device *phydev)
1478 phydev->priv = &vsc8574_priv;
1480 return vsc8584_config_init(phydev);
1483 static struct vsc85xx_priv vsc8584_priv = {
1484 .config_pre = vsc8584_config_pre_init,
1487 static int vsc8584_config(struct phy_device *phydev)
1489 phydev->priv = &vsc8584_priv;
1491 return vsc8584_config_init(phydev);
1494 static struct phy_driver VSC8530_driver = {
1495 .name = "Microsemi VSC8530",
1496 .uid = PHY_ID_VSC8530,
1498 .features = PHY_BASIC_FEATURES,
1499 .config = &vsc8531_config,
1500 .startup = &mscc_startup,
1501 .shutdown = &genphy_shutdown,
1504 static struct phy_driver VSC8531_driver = {
1505 .name = "Microsemi VSC8531",
1506 .uid = PHY_ID_VSC8531,
1508 .features = PHY_GBIT_FEATURES,
1509 .config = &vsc8531_config,
1510 .startup = &mscc_startup,
1511 .shutdown = &genphy_shutdown,
1514 static struct phy_driver VSC8540_driver = {
1515 .name = "Microsemi VSC8540",
1516 .uid = PHY_ID_VSC8540,
1518 .features = PHY_BASIC_FEATURES,
1519 .config = &vsc8541_config,
1520 .startup = &mscc_startup,
1521 .shutdown = &genphy_shutdown,
1524 static struct phy_driver VSC8541_driver = {
1525 .name = "Microsemi VSC8541",
1526 .uid = PHY_ID_VSC8541,
1528 .features = PHY_GBIT_FEATURES,
1529 .config = &vsc8541_config,
1530 .startup = &mscc_startup,
1531 .shutdown = &genphy_shutdown,
1534 static struct phy_driver VSC8574_driver = {
1535 .name = "Microsemi VSC8574",
1536 .uid = PHY_ID_VSC8574,
1538 .features = PHY_GBIT_FEATURES,
1539 .config = &vsc8574_config,
1540 .startup = &mscc_startup,
1541 .shutdown = &genphy_shutdown,
1544 static struct phy_driver VSC8584_driver = {
1545 .name = "Microsemi VSC8584",
1546 .uid = PHY_ID_VSC8584,
1548 .features = PHY_GBIT_FEATURES,
1549 .config = &vsc8584_config,
1550 .startup = &mscc_startup,
1551 .shutdown = &genphy_shutdown,
1554 int phy_mscc_init(void)
1556 phy_register(&VSC8530_driver);
1557 phy_register(&VSC8531_driver);
1558 phy_register(&VSC8540_driver);
1559 phy_register(&VSC8541_driver);
1560 phy_register(&VSC8574_driver);
1561 phy_register(&VSC8584_driver);