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