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 <log.h>
13 #include <miiphy.h>
14 #include <bitfield.h>
15 #include <time.h>
16 #include <linux/bitops.h>
17 #include <linux/delay.h>
18 
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
26 
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 */
37 
38 /* Std Page Register 18 */
39 #define MSCC_PHY_BYPASS_CONTROL           18
40 #define PARALLEL_DET_IGNORE_ADVERTISED    BIT(3)
41 
42 /* Std Page Register 22 */
43 #define MSCC_PHY_EXT_CNTL_STATUS          22
44 #define SMI_BROADCAST_WR_EN              BIT(0)
45 
46 /* Std Page Register 24 */
47 #define MSCC_PHY_EXT_PHY_CNTL_2           24
48 
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)
58 
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
80 
81 /* Extended Page 1 Register 20E1 */
82 #define MSCC_PHY_ACTIPHY_CNTL		  20
83 #define PHY_ADDR_REVERSED		  BIT(9)
84 
85 /* Extended Page 1 Register 23E1 */
86 
87 #define MSCC_PHY_EXT_PHY_CNTL_4           23
88 #define PHY_CNTL_4_ADDR_POS		  11
89 
90 /* Extended Page 1 Register 25E1 */
91 #define MSCC_PHY_VERIPHY_CNTL_2		25
92 
93 /* Extended Page 1 Register 26E1 */
94 #define MSCC_PHY_VERIPHY_CNTL_3		26
95 
96 /* Extended Page 2 Register 16E2 */
97 #define MSCC_PHY_CU_PMD_TX_CNTL         16
98 
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)
113 
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)
122 
123 /* Extended Page 3 Register 22E3 */
124 #define MSCC_PHY_SERDES_TX_CRC_ERR_CNT	22
125 
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
137 
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
141 
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
145 
146 /* Extended page GPIO register 11G */
147 #define MSCC_INT_MEM_ADDR		11
148 
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))
159 
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)
167 
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
193 
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)
199 
200 /* Test Registers */
201 #define MSCC_PHY_TEST_PAGE_5		5
202 
203 #define MSCC_PHY_TEST_PAGE_8		8
204 #define TR_CLK_DISABLE			BIT(15)
205 
206 #define MSCC_PHY_TEST_PAGE_9		9
207 #define MSCC_PHY_TEST_PAGE_20		20
208 #define MSCC_PHY_TEST_PAGE_24		24
209 
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
214 
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)
219 
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)
226 
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)
232 
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)
237 
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)
243 
244 /* General Timeout Values */
245 #define MSCC_PHY_RESET_TIMEOUT		(100)
246 #define MSCC_PHY_MICRO_TIMEOUT		(500)
247 
248 #define VSC8584_REVB		0x0001
249 #define MSCC_DEV_REV_MASK	GENMASK(3, 0)
250 
251 #define MSCC_VSC8574_REVB_INT8051_FW_START_ADDR 0x4000
252 #define MSCC_VSC8574_REVB_INT8051_FW_CRC	0x29e8
253 
254 #define MSCC_VSC8584_REVB_INT8051_FW_START_ADDR	0xe800
255 #define MSCC_VSC8584_REVB_INT8051_FW_CRC	0xfb48
256 
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,
266 };
267 
268 /* MAC i/f Clock Edge Rage Control (Slew), See Reg27E2  */ enum
269 vsc_phy_clk_slew {
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,
278 };
279 
280 struct vsc85xx_priv {
281 	int (*config_pre)(struct phy_device *phydev);
282 };
283 
vsc8584_csr_write(struct mii_dev * bus,int phy0,u16 addr,u32 val)284 static void vsc8584_csr_write(struct mii_dev *bus, int phy0, u16 addr, u32 val)
285 {
286 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18,
287 		   val >> 16);
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);
292 }
293 
vsc8584_cmd(struct mii_dev * bus,int phy,u16 val)294 static int vsc8584_cmd(struct mii_dev *bus, int phy, u16 val)
295 {
296 	unsigned long deadline;
297 	u16 reg_val;
298 
299 	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
300 		   MSCC_PHY_PAGE_GPIO);
301 
302 	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_PROC_CMD,
303 		   PROC_CMD_NCOMPLETED | val);
304 
305 	deadline = timer_get_us() + PROC_CMD_NCOMPLETED_TIMEOUT_MS * 1000;
306 	do {
307 		reg_val = bus->read(bus, phy, MDIO_DEVAD_NONE,
308 				    MSCC_PHY_PROC_CMD);
309 	} while (timer_get_us() <= deadline &&
310 		 (reg_val & PROC_CMD_NCOMPLETED) &&
311 		 !(reg_val & PROC_CMD_FAILED));
312 
313 	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
314 		   MSCC_PHY_PAGE_STD);
315 
316 	if (reg_val & PROC_CMD_FAILED)
317 		return -EIO;
318 	if (reg_val & PROC_CMD_NCOMPLETED)
319 		return -ETIMEDOUT;
320 
321 	return 0;
322 }
323 
vsc8584_micro_deassert_reset(struct mii_dev * bus,int phy,bool patch_en)324 static int vsc8584_micro_deassert_reset(struct mii_dev *bus, int phy,
325 					bool patch_en)
326 {
327 	u32 enable, release;
328 
329 	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
330 		   MSCC_PHY_PAGE_GPIO);
331 
332 	enable = RUN_FROM_INT_ROM | MICRO_CLK_EN | DW8051_CLK_EN;
333 	release = MICRO_NSOFT_RESET | RUN_FROM_INT_ROM | DW8051_CLK_EN |
334 		MICRO_CLK_EN;
335 
336 	if (patch_en) {
337 		enable |= MICRO_PATCH_EN;
338 		release |= MICRO_PATCH_EN;
339 
340 		/* Clear all patches */
341 		bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL,
342 			   READ_RAM);
343 	}
344 
345 	/*
346 	 * Enable 8051 Micro clock; CLEAR/SET patch present; disable PRAM clock
347 	 * override and addr. auto-incr; operate at 125 MHz
348 	 */
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);
352 
353 	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
354 		   MSCC_PHY_PAGE_STD);
355 
356 	return 0;
357 }
358 
vsc8584_micro_assert_reset(struct mii_dev * bus,int phy)359 static int vsc8584_micro_assert_reset(struct mii_dev *bus, int phy)
360 {
361 	int ret;
362 	u16 reg;
363 
364 	ret = vsc8584_cmd(bus, phy, PROC_CMD_NOP);
365 	if (ret)
366 		return ret;
367 
368 	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
369 		   MSCC_PHY_PAGE_GPIO);
370 
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);
374 
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);
377 
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);
381 
382 	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_PROC_CMD, PROC_CMD_NOP);
383 
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);
387 
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);
391 
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);
395 
396 	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
397 		   MSCC_PHY_PAGE_STD);
398 
399 	return 0;
400 }
401 
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,
541 };
542 
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,
552 };
553 
vsc8584_get_fw_crc(struct mii_dev * bus,int phy,u16 start,u16 * crc,const u8 * fw_patch,int fw_size)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)
556 {
557 	int ret;
558 
559 	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
560 		   MSCC_PHY_PAGE_EXT1);
561 
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,
565 		   fw_size + 1);
566 
567 	ret = vsc8584_cmd(bus, phy, PROC_CMD_CRC16);
568 	if (ret)
569 		goto out;
570 
571 	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
572 		   MSCC_PHY_PAGE_EXT1);
573 
574 	*crc = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_VERIPHY_CNTL_2);
575 
576 out:
577 	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
578 		   MSCC_PHY_PAGE_STD);
579 
580 	return ret;
581 }
582 
vsc8584_patch_fw(struct mii_dev * bus,int phy,const u8 * fw_patch,int fw_size)583 static int vsc8584_patch_fw(struct mii_dev *bus, int phy, const u8 *fw_patch,
584 			    int fw_size)
585 {
586 	int i, ret;
587 
588 	ret = vsc8584_micro_assert_reset(bus, phy);
589 	if (ret) {
590 		pr_err("%s: failed to assert reset of micro\n", __func__);
591 		return ret;
592 	}
593 
594 	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
595 		   MSCC_PHY_PAGE_GPIO);
596 
597 	/*
598 	 * Hold 8051 Micro in SW Reset, Enable auto incr address and patch clock
599 	 * Disable the 8051 Micro clock
600 	 */
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);
607 
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]);
611 
612 	/* Clear internal memory access */
613 	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL, READ_RAM);
614 
615 	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
616 		   MSCC_PHY_PAGE_STD);
617 
618 	return 0;
619 }
620 
vsc8574_is_serdes_init(struct mii_dev * bus,int phy)621 static bool vsc8574_is_serdes_init(struct mii_dev *bus, int phy)
622 {
623 	u16 reg;
624 	bool ret;
625 
626 	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
627 		   MSCC_PHY_PAGE_GPIO);
628 
629 	reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_TRAP_ROM_ADDR(1));
630 	if (reg != MSCC_TRAP_ROM_ADDR_SERDES_INIT) {
631 		ret = false;
632 		goto out;
633 	}
634 
635 	reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_PATCH_RAM_ADDR(1));
636 	if (reg != MSCC_PATCH_RAM_ADDR_SERDES_INIT) {
637 		ret = false;
638 		goto out;
639 	}
640 
641 	reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL);
642 	if (reg != EN_PATCH_RAM_TRAP_ADDR(1)) {
643 		ret = false;
644 		goto out;
645 	}
646 
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)) {
650 		ret = false;
651 		goto out;
652 	}
653 
654 	ret = true;
655 
656 out:
657 	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
658 		   MSCC_PHY_PAGE_GPIO);
659 
660 	return ret;
661 }
662 
vsc8574_config_pre_init(struct phy_device * phydev)663 static int vsc8574_config_pre_init(struct phy_device *phydev)
664 {
665 	struct mii_dev *bus = phydev->bus;
666 	u16 crc, reg, phy0, addr;
667 	bool serdes_init;
668 	int ret;
669 
670 	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
671 		  MSCC_PHY_PAGE_EXT1);
672 	addr = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_EXT_PHY_CNTL_4);
673 	addr >>= PHY_CNTL_4_ADDR_POS;
674 
675 	reg = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_ACTIPHY_CNTL);
676 	if (reg & PHY_ADDR_REVERSED)
677 		phy0 = phydev->addr + addr;
678 	else
679 		phy0 = phydev->addr - addr;
680 
681 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
682 		   MSCC_PHY_PAGE_STD);
683 
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);
688 
689 	/*
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
693 	 * values".
694 	 */
695 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_PHY_CNTL_2, 0x0040);
696 
697 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
698 		   MSCC_PHY_PAGE_TEST);
699 
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);
704 
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);
708 
709 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
710 		   MSCC_PHY_PAGE_TR);
711 
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);
758 
759 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
760 			MSCC_PHY_PAGE_EXT2);
761 
762 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_CU_PMD_TX_CNTL, 0x028e);
763 
764 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
765 		   MSCC_PHY_PAGE_TR);
766 
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);
781 
782 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
783 		   MSCC_PHY_PAGE_TEST);
784 
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);
788 
789 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
790 			MSCC_PHY_PAGE_STD);
791 
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);
796 
797 	ret = vsc8584_get_fw_crc(bus, phy0,
798 				 MSCC_VSC8574_REVB_INT8051_FW_START_ADDR, &crc,
799 				 fw_patch_vsc8574,
800 				 ARRAY_SIZE(fw_patch_vsc8574));
801 	if (ret)
802 		goto out;
803 
804 	if (crc == MSCC_VSC8574_REVB_INT8051_FW_CRC) {
805 		serdes_init = vsc8574_is_serdes_init(bus, phy0);
806 
807 		if (!serdes_init) {
808 			ret = vsc8584_micro_assert_reset(bus, phy0);
809 			if (ret) {
810 				pr_err("failed to assert reset of micro\n");
811 				return ret;
812 			}
813 		}
814 	} else {
815 		pr_debug("FW CRC is not the expected one, patching FW\n");
816 
817 		serdes_init = false;
818 
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");
822 	}
823 
824 	if (!serdes_init) {
825 		bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
826 				MSCC_PHY_PAGE_GPIO);
827 
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);
832 
833 		bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL,
834 				EN_PATCH_RAM_TRAP_ADDR(1));
835 
836 		vsc8584_micro_deassert_reset(bus, phy0, false);
837 
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));
842 		if (ret)
843 			goto out;
844 
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");
847 	}
848 
849 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
850 		   MSCC_PHY_PAGE_GPIO);
851 
852 	ret = vsc8584_cmd(bus, phy0, PROC_CMD_1588_DEFAULT_INIT |
853 			  PROC_CMD_PHY_INIT);
854 
855 out:
856 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
857 			MSCC_PHY_PAGE_STD);
858 
859 	return ret;
860 }
861 
vsc8584_config_pre_init(struct phy_device * phydev)862 static int vsc8584_config_pre_init(struct phy_device *phydev)
863 {
864 	struct mii_dev *bus = phydev->bus;
865 	u16 reg, crc, phy0, addr;
866 	int ret;
867 
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");
870 		return 0;
871 	}
872 
873 	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
874 		  MSCC_PHY_PAGE_EXT1);
875 	addr = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_EXT_PHY_CNTL_4);
876 	addr >>= PHY_CNTL_4_ADDR_POS;
877 
878 	reg = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_ACTIPHY_CNTL);
879 	if (reg & PHY_ADDR_REVERSED)
880 		phy0 = phydev->addr + addr;
881 	else
882 		phy0 = phydev->addr - addr;
883 
884 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
885 		   MSCC_PHY_PAGE_STD);
886 
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);
891 
892 	/*
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
896 	 * values".
897 	 */
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);
901 
902 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
903 		   MSCC_PHY_PAGE_EXT3);
904 
905 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_SERDES_TX_CRC_ERR_CNT,
906 		   0x2000);
907 
908 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
909 		   MSCC_PHY_PAGE_TEST);
910 
911 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_5, 0x1f20);
912 
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);
916 
917 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
918 		   MSCC_PHY_PAGE_TR);
919 
920 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16, 0xafa4);
921 
922 	reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18);
923 	reg &= ~0x007f;
924 	reg |= 0x0019;
925 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18, reg);
926 
927 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16, 0x8fa4);
928 
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);
951 
952 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
953 		   MSCC_PHY_PAGE_EXT2);
954 
955 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_CU_PMD_TX_CNTL, 0x028e);
956 
957 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
958 		   MSCC_PHY_PAGE_TR);
959 
960 	vsc8584_csr_write(bus, phy0, 0x0486, 0x0008a518);
961 	vsc8584_csr_write(bus, phy0, 0x0488, 0x006dc696);
962 	vsc8584_csr_write(bus, phy0, 0x048a, 0x00000912);
963 
964 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
965 		   MSCC_PHY_PAGE_TEST);
966 
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);
970 
971 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
972 		   MSCC_PHY_PAGE_STD);
973 
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);
978 
979 	ret = vsc8584_get_fw_crc(bus, phy0,
980 				 MSCC_VSC8584_REVB_INT8051_FW_START_ADDR, &crc,
981 				 fw_patch_vsc8584,
982 				 ARRAY_SIZE(fw_patch_vsc8584));
983 	if (ret)
984 		goto out;
985 
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");
991 	}
992 
993 	vsc8584_micro_deassert_reset(bus, phy0, false);
994 
995 	ret = vsc8584_get_fw_crc(bus, phy0,
996 				 MSCC_VSC8584_REVB_INT8051_FW_START_ADDR, &crc,
997 				 fw_patch_vsc8584,
998 				 ARRAY_SIZE(fw_patch_vsc8584));
999 	if (ret)
1000 		goto out;
1001 
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");
1004 
1005 	ret = vsc8584_micro_assert_reset(bus, phy0);
1006 	if (ret)
1007 		goto out;
1008 
1009 	vsc8584_micro_deassert_reset(bus, phy0, true);
1010 
1011 out:
1012 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1013 		   MSCC_PHY_PAGE_STD);
1014 
1015 	return ret;
1016 }
1017 
mscc_vsc8531_vsc8541_init_scripts(struct phy_device * phydev)1018 static int mscc_vsc8531_vsc8541_init_scripts(struct phy_device *phydev)
1019 {
1020 	u16	reg_val;
1021 
1022 	/* Set to Access Token Ring Registers */
1023 	phy_write(phydev, MDIO_DEVAD_NONE,
1024 		  MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_TR);
1025 
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);
1034 
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));
1038 
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));
1043 
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);
1048 
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));
1052 
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));
1057 
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);
1062 
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);
1068 
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));
1072 
1073 	/* Set back to Access Standard Page Registers */
1074 	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1075 		  MSCC_PHY_PAGE_STD);
1076 
1077 	return 0;
1078 }
1079 
mscc_parse_status(struct phy_device * phydev)1080 static int mscc_parse_status(struct phy_device *phydev)
1081 {
1082 	u16 speed;
1083 	u16 mii_reg;
1084 
1085 	mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_AUX_CNTRL_STAT_REG);
1086 
1087 	if (mii_reg & MIIM_AUX_CNTRL_STAT_F_DUPLEX)
1088 		phydev->duplex = DUPLEX_FULL;
1089 	else
1090 		phydev->duplex = DUPLEX_HALF;
1091 
1092 	speed = mii_reg & MIIM_AUX_CNTRL_STAT_SPEED_MASK;
1093 	speed = speed >> MIIM_AUX_CNTRL_STAT_SPEED_POS;
1094 
1095 	switch (speed) {
1096 	case MIIM_AUX_CNTRL_STAT_SPEED_1000M:
1097 		phydev->speed = SPEED_1000;
1098 		break;
1099 	case MIIM_AUX_CNTRL_STAT_SPEED_100M:
1100 		phydev->speed = SPEED_100;
1101 		break;
1102 	case MIIM_AUX_CNTRL_STAT_SPEED_10M:
1103 		phydev->speed = SPEED_10;
1104 		break;
1105 	default:
1106 		phydev->speed = SPEED_10;
1107 		break;
1108 	}
1109 
1110 	return 0;
1111 }
1112 
mscc_startup(struct phy_device * phydev)1113 static int mscc_startup(struct phy_device *phydev)
1114 {
1115 	int retval;
1116 
1117 	retval = genphy_update_link(phydev);
1118 
1119 	if (retval)
1120 		return retval;
1121 
1122 	return mscc_parse_status(phydev);
1123 }
1124 
mscc_phy_soft_reset(struct phy_device * phydev)1125 static int mscc_phy_soft_reset(struct phy_device *phydev)
1126 {
1127 	int     retval = 0;
1128 	u16     timeout = MSCC_PHY_RESET_TIMEOUT;
1129 	u16     reg_val = 0;
1130 
1131 	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1132 		  MSCC_PHY_PAGE_STD);
1133 
1134 	reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
1135 	phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, (reg_val | BMCR_RESET));
1136 
1137 	reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
1138 
1139 	while ((reg_val & BMCR_RESET) && (timeout > 0)) {
1140 		reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
1141 		timeout--;
1142 		udelay(1000);   /* 1 ms */
1143 	}
1144 
1145 	if (timeout == 0) {
1146 		printf("MSCC PHY Soft_Reset Error: mac i/f = 0x%x\n",
1147 		       phydev->interface);
1148 		retval = -ETIME;
1149 	}
1150 
1151 	return retval;
1152 }
1153 
vsc8531_vsc8541_mac_config(struct phy_device * phydev)1154 static int vsc8531_vsc8541_mac_config(struct phy_device *phydev)
1155 {
1156 	u16	reg_val = 0;
1157 	u16	mac_if = 0;
1158 	u16	rx_clk_out = 0;
1159 
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;
1170 		break;
1171 
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;
1177 		break;
1178 
1179 	case PHY_INTERFACE_MODE_RGMII_TXID:
1180 	case PHY_INTERFACE_MODE_RGMII_RXID:
1181 	case PHY_INTERFACE_MODE_RGMII_ID:
1182 	case PHY_INTERFACE_MODE_RGMII:
1183 		/* Set Reg23.12:11=2 */
1184 		mac_if = MAC_IF_SELECTION_RGMII;
1185 		/* Set Reg20E2.11=0 */
1186 		rx_clk_out = RX_CLK_OUT_NORMAL;
1187 		break;
1188 
1189 	default:
1190 		printf("MSCC PHY - INVALID MAC i/f Config: mac i/f = 0x%x\n",
1191 		       phydev->interface);
1192 		return -EINVAL;
1193 	}
1194 
1195 	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1196 		  MSCC_PHY_PAGE_STD);
1197 
1198 	reg_val = phy_read(phydev, MDIO_DEVAD_NONE,
1199 			   MSCC_PHY_EXT_PHY_CNTL_1_REG);
1200 	/* Set MAC i/f bits Reg23.12:11 */
1201 	reg_val = bitfield_replace(reg_val, MAC_IF_SELECTION_POS,
1202 				   MAC_IF_SELECTION_WIDTH, mac_if);
1203 	/* Update Reg23.12:11 */
1204 	phy_write(phydev, MDIO_DEVAD_NONE,
1205 		  MSCC_PHY_EXT_PHY_CNTL_1_REG, reg_val);
1206 	/* Setup ExtPg_2 Register Access */
1207 	phy_write(phydev, MDIO_DEVAD_NONE,
1208 		  MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_EXT2);
1209 	/* Read Reg20E2 */
1210 	reg_val = phy_read(phydev, MDIO_DEVAD_NONE,
1211 			   MSCC_PHY_RGMII_CNTL_REG);
1212 	reg_val = bitfield_replace(reg_val, RX_CLK_OUT_POS,
1213 				   RX_CLK_OUT_WIDTH, rx_clk_out);
1214 	/* Update Reg20E2.11 */
1215 	phy_write(phydev, MDIO_DEVAD_NONE,
1216 		  MSCC_PHY_RGMII_CNTL_REG, reg_val);
1217 	/* Before leaving - Change back to Std Page Register Access */
1218 	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1219 		  MSCC_PHY_PAGE_STD);
1220 
1221 	return 0;
1222 }
1223 
vsc8531_vsc8541_clkout_config(struct phy_device * phydev)1224 static int vsc8531_vsc8541_clkout_config(struct phy_device *phydev)
1225 {
1226 	struct ofnode_phandle_args phandle_args;
1227 	u32 clkout_rate = 0;
1228 	u16 reg_val;
1229 	int retval;
1230 
1231 	retval = dev_read_phandle_with_args(phydev->dev, "phy-handle", NULL,
1232 					    0, 0, &phandle_args);
1233 	if (!retval)
1234 		clkout_rate = ofnode_read_u32_default(phandle_args.node,
1235 						"vsc8531,clk-out-frequency", 0);
1236 
1237 	switch (clkout_rate) {
1238 	case 0:
1239 		reg_val = 0;
1240 		break;
1241 	case 25000000:
1242 		reg_val = CLKOUT_FREQ_25M | CLKOUT_ENABLE;
1243 		break;
1244 	case 50000000:
1245 		reg_val = CLKOUT_FREQ_50M | CLKOUT_ENABLE;
1246 		break;
1247 	case 125000000:
1248 		reg_val = CLKOUT_FREQ_125M | CLKOUT_ENABLE;
1249 		break;
1250 	default:
1251 		printf("PHY 8530/31 invalid clkout rate %u\n",
1252 		       clkout_rate);
1253 		return -EINVAL;
1254 	}
1255 
1256 	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1257 		  MSCC_PHY_PAGE_GPIO);
1258 	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_CLKOUT_CNTL, reg_val);
1259 	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1260 		  MSCC_PHY_PAGE_STD);
1261 
1262 	return 0;
1263 }
1264 
vsc8531_vsc8541_clk_skew_config(struct phy_device * phydev)1265 static int vsc8531_vsc8541_clk_skew_config(struct phy_device *phydev)
1266 {
1267 	enum vsc_phy_rgmii_skew rx_clk_skew = VSC_PHY_RGMII_DELAY_200_PS;
1268 	enum vsc_phy_rgmii_skew tx_clk_skew = VSC_PHY_RGMII_DELAY_200_PS;
1269 	u16 reg_val;
1270 
1271 	if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID ||
1272 	    phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
1273 		rx_clk_skew = VSC_PHY_RGMII_DELAY_2000_PS;
1274 
1275 	if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID ||
1276 	    phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
1277 		tx_clk_skew = VSC_PHY_RGMII_DELAY_2000_PS;
1278 
1279 	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1280 		  MSCC_PHY_PAGE_EXT2);
1281 	reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG);
1282 
1283 	/* Reg20E2 - Update RGMII RX_Clk Skews. */
1284 	reg_val = bitfield_replace(reg_val, RGMII_RX_CLK_DELAY_POS,
1285 				   RGMII_RX_CLK_DELAY_WIDTH, rx_clk_skew);
1286 	/* Reg20E2 - Update RGMII TX_Clk Skews. */
1287 	reg_val = bitfield_replace(reg_val, RGMII_TX_CLK_DELAY_POS,
1288 				   RGMII_TX_CLK_DELAY_WIDTH, tx_clk_skew);
1289 
1290 	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG, reg_val);
1291 	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1292 		  MSCC_PHY_PAGE_STD);
1293 
1294 	return 0;
1295 }
1296 
vsc8531_config(struct phy_device * phydev)1297 static int vsc8531_config(struct phy_device *phydev)
1298 {
1299 	int  retval = -EINVAL;
1300 	u16  reg_val;
1301 	u16  rmii_clk_out;
1302 	enum vsc_phy_clk_slew    edge_rate = VSC_PHY_CLK_SLEW_RATE_4;
1303 
1304 	/* For VSC8530/31 and VSC8540/41 the init scripts are the same */
1305 	mscc_vsc8531_vsc8541_init_scripts(phydev);
1306 
1307 	/* For VSC8530/31 the only MAC modes are RMII/RGMII. */
1308 	switch (phydev->interface) {
1309 	case PHY_INTERFACE_MODE_RMII:
1310 	case PHY_INTERFACE_MODE_RGMII:
1311 	case PHY_INTERFACE_MODE_RGMII_TXID:
1312 	case PHY_INTERFACE_MODE_RGMII_RXID:
1313 	case PHY_INTERFACE_MODE_RGMII_ID:
1314 		retval = vsc8531_vsc8541_mac_config(phydev);
1315 		if (retval != 0)
1316 			return retval;
1317 
1318 		retval = mscc_phy_soft_reset(phydev);
1319 		if (retval != 0)
1320 			return retval;
1321 		break;
1322 	default:
1323 		printf("PHY 8530/31 MAC i/f Config Error: mac i/f = 0x%x\n",
1324 		       phydev->interface);
1325 		return -EINVAL;
1326 	}
1327 	/* Default RMII Clk Output to 0=OFF/1=ON  */
1328 	rmii_clk_out = 0;
1329 
1330 	retval = vsc8531_vsc8541_clk_skew_config(phydev);
1331 	if (retval != 0)
1332 		return retval;
1333 
1334 	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1335 		  MSCC_PHY_PAGE_EXT2);
1336 	reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL);
1337 	/* Reg27E2 - Update Clk Slew Rate. */
1338 	reg_val = bitfield_replace(reg_val, EDGE_RATE_CNTL_POS,
1339 				   EDGE_RATE_CNTL_WIDTH, edge_rate);
1340 	/* Reg27E2 - Update RMII Clk Out. */
1341 	reg_val = bitfield_replace(reg_val, RMII_CLK_OUT_ENABLE_POS,
1342 				   RMII_CLK_OUT_ENABLE_WIDTH, rmii_clk_out);
1343 	/* Update Reg27E2 */
1344 	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL, reg_val);
1345 	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1346 		  MSCC_PHY_PAGE_STD);
1347 
1348 	/* Configure the clk output */
1349 	retval = vsc8531_vsc8541_clkout_config(phydev);
1350 	if (retval != 0)
1351 		return retval;
1352 
1353 	return genphy_config_aneg(phydev);
1354 }
1355 
vsc8541_config(struct phy_device * phydev)1356 static int vsc8541_config(struct phy_device *phydev)
1357 {
1358 	int  retval = -EINVAL;
1359 	u16  reg_val;
1360 	u16  rmii_clk_out;
1361 	enum vsc_phy_clk_slew    edge_rate = VSC_PHY_CLK_SLEW_RATE_4;
1362 
1363 	/* For VSC8530/31 and VSC8540/41 the init scripts are the same */
1364 	mscc_vsc8531_vsc8541_init_scripts(phydev);
1365 
1366 	/* For VSC8540/41 the only MAC modes are (G)MII and RMII/RGMII. */
1367 	switch (phydev->interface) {
1368 	case PHY_INTERFACE_MODE_MII:
1369 	case PHY_INTERFACE_MODE_GMII:
1370 	case PHY_INTERFACE_MODE_RMII:
1371 	case PHY_INTERFACE_MODE_RGMII:
1372 		retval = vsc8531_vsc8541_mac_config(phydev);
1373 		if (retval != 0)
1374 			return retval;
1375 
1376 		retval = mscc_phy_soft_reset(phydev);
1377 		if (retval != 0)
1378 			return retval;
1379 		break;
1380 	default:
1381 		printf("PHY 8541 MAC i/f config Error: mac i/f = 0x%x\n",
1382 		       phydev->interface);
1383 		return -EINVAL;
1384 	}
1385 	/* Default RMII Clk Output to 0=OFF/1=ON  */
1386 	rmii_clk_out = 0;
1387 
1388 	retval = vsc8531_vsc8541_clk_skew_config(phydev);
1389 	if (retval != 0)
1390 		return retval;
1391 
1392 	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1393 		  MSCC_PHY_PAGE_EXT2);
1394 	reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL);
1395 	/* Reg27E2 - Update Clk Slew Rate. */
1396 	reg_val = bitfield_replace(reg_val, EDGE_RATE_CNTL_POS,
1397 				   EDGE_RATE_CNTL_WIDTH, edge_rate);
1398 	/* Reg27E2 - Update RMII Clk Out. */
1399 	reg_val = bitfield_replace(reg_val, RMII_CLK_OUT_ENABLE_POS,
1400 				   RMII_CLK_OUT_ENABLE_WIDTH, rmii_clk_out);
1401 	/* Update Reg27E2 */
1402 	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL, reg_val);
1403 	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1404 		  MSCC_PHY_PAGE_STD);
1405 
1406 	/* Configure the clk output */
1407 	retval = vsc8531_vsc8541_clkout_config(phydev);
1408 	if (retval != 0)
1409 		return retval;
1410 
1411 	return genphy_config_aneg(phydev);
1412 }
1413 
vsc8584_config_init(struct phy_device * phydev)1414 static int vsc8584_config_init(struct phy_device *phydev)
1415 {
1416 	struct vsc85xx_priv *priv = phydev->priv;
1417 	int ret;
1418 	u16 addr;
1419 	u16 reg_val;
1420 	u16 val;
1421 
1422 	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1423 		  MSCC_PHY_PAGE_EXT1);
1424 	addr = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_EXT_PHY_CNTL_4);
1425 	addr >>= PHY_CNTL_4_ADDR_POS;
1426 
1427 	ret = priv->config_pre(phydev);
1428 	if (ret)
1429 		return ret;
1430 
1431 	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1432 		  MSCC_PHY_PAGE_GPIO);
1433 
1434 	if (phydev->interface == PHY_INTERFACE_MODE_QSGMII)
1435 		val = MAC_CFG_QSGMII;
1436 	else
1437 		val = MAC_CFG_SGMII;
1438 
1439 	reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_MAC_CFG_FASTLINK);
1440 	reg_val &= ~MAC_CFG_MASK;
1441 	reg_val |= val;
1442 	ret = phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_MAC_CFG_FASTLINK,
1443 			reg_val);
1444 	if (ret)
1445 		return ret;
1446 
1447 	reg_val = PROC_CMD_MCB_ACCESS_MAC_CONF | PROC_CMD_RST_CONF_PORT |
1448 		PROC_CMD_READ_MOD_WRITE_PORT;
1449 	if (phydev->interface == PHY_INTERFACE_MODE_QSGMII)
1450 		reg_val |= PROC_CMD_QSGMII_MAC;
1451 	else
1452 		reg_val |= PROC_CMD_SGMII_MAC;
1453 
1454 	ret = vsc8584_cmd(phydev->bus, phydev->addr, reg_val);
1455 	if (ret)
1456 		return ret;
1457 
1458 	mdelay(10);
1459 
1460 	/* Disable SerDes for 100Base-FX */
1461 	ret = vsc8584_cmd(phydev->bus, phydev->addr, PROC_CMD_FIBER_MEDIA_CONF |
1462 			  PROC_CMD_FIBER_PORT(addr) | PROC_CMD_FIBER_DISABLE |
1463 			  PROC_CMD_READ_MOD_WRITE_PORT |
1464 			  PROC_CMD_RST_CONF_PORT | PROC_CMD_FIBER_100BASE_FX);
1465 	if (ret)
1466 		return ret;
1467 
1468 	/* Disable SerDes for 1000Base-X */
1469 	ret = vsc8584_cmd(phydev->bus, phydev->addr, PROC_CMD_FIBER_MEDIA_CONF |
1470 			  PROC_CMD_FIBER_PORT(addr) | PROC_CMD_FIBER_DISABLE |
1471 			  PROC_CMD_READ_MOD_WRITE_PORT |
1472 			  PROC_CMD_RST_CONF_PORT | PROC_CMD_FIBER_1000BASE_X);
1473 	if (ret)
1474 		return ret;
1475 
1476 	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1477 		  MSCC_PHY_PAGE_STD);
1478 	reg_val = phy_read(phydev, MDIO_DEVAD_NONE,
1479 			   MSCC_PHY_EXT_PHY_CNTL_1_REG);
1480 	reg_val &= ~(MEDIA_OP_MODE_MASK | VSC8584_MAC_IF_SELECTION_MASK);
1481 	reg_val |= MEDIA_OP_MODE_COPPER |
1482 		(VSC8584_MAC_IF_SELECTION_SGMII <<
1483 		 VSC8584_MAC_IF_SELECTION_POS);
1484 	ret = phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_EXT_PHY_CNTL_1_REG,
1485 			reg_val);
1486 
1487 	ret = mscc_phy_soft_reset(phydev);
1488 	if (ret != 0)
1489 		return ret;
1490 
1491 	return genphy_config(phydev);
1492 }
1493 
1494 static struct vsc85xx_priv vsc8574_priv = {
1495 	.config_pre = vsc8574_config_pre_init,
1496 };
1497 
vsc8574_config(struct phy_device * phydev)1498 static int vsc8574_config(struct phy_device *phydev)
1499 {
1500 	phydev->priv = &vsc8574_priv;
1501 
1502 	return vsc8584_config_init(phydev);
1503 }
1504 
1505 static struct vsc85xx_priv vsc8584_priv = {
1506 	.config_pre = vsc8584_config_pre_init,
1507 };
1508 
vsc8584_config(struct phy_device * phydev)1509 static int vsc8584_config(struct phy_device *phydev)
1510 {
1511 	phydev->priv = &vsc8584_priv;
1512 
1513 	return vsc8584_config_init(phydev);
1514 }
1515 
1516 static struct phy_driver VSC8530_driver = {
1517 	.name = "Microsemi VSC8530",
1518 	.uid = PHY_ID_VSC8530,
1519 	.mask = 0x000ffff0,
1520 	.features = PHY_BASIC_FEATURES,
1521 	.config = &vsc8531_config,
1522 	.startup = &mscc_startup,
1523 	.shutdown = &genphy_shutdown,
1524 };
1525 
1526 static struct phy_driver VSC8531_driver = {
1527 	.name = "Microsemi VSC8531",
1528 	.uid = PHY_ID_VSC8531,
1529 	.mask = 0x000ffff0,
1530 	.features = PHY_GBIT_FEATURES,
1531 	.config = &vsc8531_config,
1532 	.startup = &mscc_startup,
1533 	.shutdown = &genphy_shutdown,
1534 };
1535 
1536 static struct phy_driver VSC8540_driver = {
1537 	.name = "Microsemi VSC8540",
1538 	.uid = PHY_ID_VSC8540,
1539 	.mask = 0x000ffff0,
1540 	.features = PHY_BASIC_FEATURES,
1541 	.config = &vsc8541_config,
1542 	.startup = &mscc_startup,
1543 	.shutdown = &genphy_shutdown,
1544 };
1545 
1546 static struct phy_driver VSC8541_driver = {
1547 	.name = "Microsemi VSC8541",
1548 	.uid = PHY_ID_VSC8541,
1549 	.mask = 0x000ffff0,
1550 	.features = PHY_GBIT_FEATURES,
1551 	.config = &vsc8541_config,
1552 	.startup = &mscc_startup,
1553 	.shutdown = &genphy_shutdown,
1554 };
1555 
1556 static struct phy_driver VSC8574_driver = {
1557 	.name = "Microsemi VSC8574",
1558 	.uid = PHY_ID_VSC8574,
1559 	.mask = 0x000ffff0,
1560 	.features = PHY_GBIT_FEATURES,
1561 	.config = &vsc8574_config,
1562 	.startup = &mscc_startup,
1563 	.shutdown = &genphy_shutdown,
1564 };
1565 
1566 static struct phy_driver VSC8584_driver = {
1567 	.name = "Microsemi VSC8584",
1568 	.uid = PHY_ID_VSC8584,
1569 	.mask = 0x000ffff0,
1570 	.features = PHY_GBIT_FEATURES,
1571 	.config = &vsc8584_config,
1572 	.startup = &mscc_startup,
1573 	.shutdown = &genphy_shutdown,
1574 };
1575 
phy_mscc_init(void)1576 int phy_mscc_init(void)
1577 {
1578 	phy_register(&VSC8530_driver);
1579 	phy_register(&VSC8531_driver);
1580 	phy_register(&VSC8540_driver);
1581 	phy_register(&VSC8541_driver);
1582 	phy_register(&VSC8574_driver);
1583 	phy_register(&VSC8584_driver);
1584 
1585 	return 0;
1586 }
1587