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