blob: d1a643cf5a0ced833458b12f4be96e5bcf1e328b [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: MIT
John Haechtena5fd13a2016-12-09 22:15:17 +00002/*
3 * Microsemi PHY drivers
4 *
John Haechtena5fd13a2016-12-09 22:15:17 +00005 *
6 * Copyright (c) 2016 Microsemi Corporation
7 *
8 * Author: John Haechten
9 *
10 */
11
Simon Glassf7ae49f2020-05-10 11:40:05 -060012#include <log.h>
John Haechtena5fd13a2016-12-09 22:15:17 +000013#include <miiphy.h>
14#include <bitfield.h>
Quentin Schulz04087fc2018-10-31 11:20:37 +010015#include <time.h>
Simon Glasscd93d622020-05-10 11:40:13 -060016#include <linux/bitops.h>
Quentin Schulz04087fc2018-10-31 11:20:37 +010017#include <linux/delay.h>
John Haechtena5fd13a2016-12-09 22:15:17 +000018
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
Quentin Schulz05bbd672018-10-31 11:20:39 +010024#define PHY_ID_VSC8574 0x000704a0
Quentin Schulz04087fc2018-10-31 11:20:37 +010025#define PHY_ID_VSC8584 0x000707c0
John Haechtena5fd13a2016-12-09 22:15:17 +000026
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
Quentin Schulz04087fc2018-10-31 11:20:37 +010038/* 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
Quentin Schulz05bbd672018-10-31 11:20:39 +010046/* Std Page Register 24 */
47#define MSCC_PHY_EXT_PHY_CNTL_2 24
48
John Haechtena5fd13a2016-12-09 22:15:17 +000049/* 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)
Quentin Schulz04087fc2018-10-31 11:20:37 +010067#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
John Haechtena5fd13a2016-12-09 22:15:17 +000098
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
Quentin Schulz04087fc2018-10-31 11:20:37 +0100123/* 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)
Quentin Schulz05bbd672018-10-31 11:20:39 +0100136#define MSCC_DW8051_VLD_MASK 0xf1ff
Quentin Schulz04087fc2018-10-31 11:20:37 +0100137
138/* Extended page GPIO register 09G */
139#define MSCC_TRAP_ROM_ADDR(x) ((x) * 2 + 1)
Quentin Schulz05bbd672018-10-31 11:20:39 +0100140#define MSCC_TRAP_ROM_ADDR_SERDES_INIT 0x3eb7
Quentin Schulz04087fc2018-10-31 11:20:37 +0100141
142/* Extended page GPIO register 10G */
143#define MSCC_PATCH_RAM_ADDR(x) (((x) + 1) * 2)
Quentin Schulz05bbd672018-10-31 11:20:39 +0100144#define MSCC_PATCH_RAM_ADDR_SERDES_INIT 0x4012
Quentin Schulz04087fc2018-10-31 11:20:37 +0100145
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
Heiko Stuebner9a499b22020-06-09 15:37:39 +0200160/* 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
Quentin Schulz04087fc2018-10-31 11:20:37 +0100168/* 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)
Quentin Schulz05bbd672018-10-31 11:20:39 +0100186#define PROC_CMD_1588_DEFAULT_INIT BIT(4)
Quentin Schulz04087fc2018-10-31 11:20:37 +0100187#define PROC_CMD_NOP GENMASK(3, 0)
Quentin Schulz05bbd672018-10-31 11:20:39 +0100188#define PROC_CMD_PHY_INIT (BIT(3) | BIT(1))
Quentin Schulz04087fc2018-10-31 11:20:37 +0100189#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
Quentin Schulz05bbd672018-10-31 11:20:39 +0100206#define MSCC_PHY_TEST_PAGE_9 9
207#define MSCC_PHY_TEST_PAGE_20 20
208#define MSCC_PHY_TEST_PAGE_24 24
209
John Haechtena5fd13a2016-12-09 22:15:17 +0000210/* 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
Quentin Schulz04087fc2018-10-31 11:20:37 +0100248#define VSC8584_REVB 0x0001
249#define MSCC_DEV_REV_MASK GENMASK(3, 0)
250
Quentin Schulz05bbd672018-10-31 11:20:39 +0100251#define MSCC_VSC8574_REVB_INT8051_FW_START_ADDR 0x4000
252#define MSCC_VSC8574_REVB_INT8051_FW_CRC 0x29e8
253
Quentin Schulz04087fc2018-10-31 11:20:37 +0100254#define MSCC_VSC8584_REVB_INT8051_FW_START_ADDR 0xe800
255#define MSCC_VSC8584_REVB_INT8051_FW_CRC 0xfb48
256
John Haechtena5fd13a2016-12-09 22:15:17 +0000257/* 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
269vsc_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
Quentin Schulzb5bca652018-10-31 11:20:38 +0100280struct vsc85xx_priv {
281 int (*config_pre)(struct phy_device *phydev);
282};
283
Quentin Schulz04087fc2018-10-31 11:20:37 +0100284static 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
294static 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
324static 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
359static 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
Quentin Schulz05bbd672018-10-31 11:20:39 +0100402static 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
Quentin Schulz04087fc2018-10-31 11:20:37 +0100543static 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
554static 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
576out:
577 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
578 MSCC_PHY_PAGE_STD);
579
580 return ret;
581}
582
583static 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
Quentin Schulz05bbd672018-10-31 11:20:39 +0100621static 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
656out:
657 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
658 MSCC_PHY_PAGE_GPIO);
659
660 return ret;
661}
662
663static 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
855out:
856 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
857 MSCC_PHY_PAGE_STD);
858
859 return ret;
860}
861
Quentin Schulzb5bca652018-10-31 11:20:38 +0100862static int vsc8584_config_pre_init(struct phy_device *phydev)
Quentin Schulz04087fc2018-10-31 11:20:37 +0100863{
Quentin Schulzb5bca652018-10-31 11:20:38 +0100864 struct mii_dev *bus = phydev->bus;
865 u16 reg, crc, phy0, addr;
Quentin Schulz04087fc2018-10-31 11:20:37 +0100866 int ret;
867
Quentin Schulzb5bca652018-10-31 11:20:38 +0100868 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
Quentin Schulz04087fc2018-10-31 11:20:37 +0100884 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
1011out:
1012 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1013 MSCC_PHY_PAGE_STD);
1014
1015 return ret;
1016}
John Haechtena5fd13a2016-12-09 22:15:17 +00001017
1018static 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
1080static 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
1113static 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
1125static 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
1154static 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
Heiko Stuebnerd63c14c2020-06-09 15:37:40 +02001179 case PHY_INTERFACE_MODE_RGMII_TXID:
1180 case PHY_INTERFACE_MODE_RGMII_RXID:
1181 case PHY_INTERFACE_MODE_RGMII_ID:
John Haechtena5fd13a2016-12-09 22:15:17 +00001182 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
Heiko Stuebner9a499b22020-06-09 15:37:39 +02001224static 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
Heiko Stuebnerd63c14c2020-06-09 15:37:40 +02001265static 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
John Haechtena5fd13a2016-12-09 22:15:17 +00001297static int vsc8531_config(struct phy_device *phydev)
1298{
1299 int retval = -EINVAL;
1300 u16 reg_val;
1301 u16 rmii_clk_out;
John Haechtena5fd13a2016-12-09 22:15:17 +00001302 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:
Heiko Stuebnerd63c14c2020-06-09 15:37:40 +02001311 case PHY_INTERFACE_MODE_RGMII_TXID:
1312 case PHY_INTERFACE_MODE_RGMII_RXID:
1313 case PHY_INTERFACE_MODE_RGMII_ID:
John Haechtena5fd13a2016-12-09 22:15:17 +00001314 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
Heiko Stuebnerd63c14c2020-06-09 15:37:40 +02001330 retval = vsc8531_vsc8541_clk_skew_config(phydev);
1331 if (retval != 0)
1332 return retval;
1333
John Haechtena5fd13a2016-12-09 22:15:17 +00001334 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1335 MSCC_PHY_PAGE_EXT2);
John Haechtena5fd13a2016-12-09 22:15:17 +00001336 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
Heiko Stuebner9a499b22020-06-09 15:37:39 +02001348 /* Configure the clk output */
1349 retval = vsc8531_vsc8541_clkout_config(phydev);
1350 if (retval != 0)
1351 return retval;
1352
John Haechtena5fd13a2016-12-09 22:15:17 +00001353 return genphy_config_aneg(phydev);
1354}
1355
1356static int vsc8541_config(struct phy_device *phydev)
1357{
1358 int retval = -EINVAL;
1359 u16 reg_val;
1360 u16 rmii_clk_out;
John Haechtena5fd13a2016-12-09 22:15:17 +00001361 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
Heiko Stuebnerd63c14c2020-06-09 15:37:40 +02001388 retval = vsc8531_vsc8541_clk_skew_config(phydev);
1389 if (retval != 0)
1390 return retval;
1391
John Haechtena5fd13a2016-12-09 22:15:17 +00001392 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1393 MSCC_PHY_PAGE_EXT2);
John Haechtena5fd13a2016-12-09 22:15:17 +00001394 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
Heiko Stuebner9a499b22020-06-09 15:37:39 +02001406 /* Configure the clk output */
1407 retval = vsc8531_vsc8541_clkout_config(phydev);
1408 if (retval != 0)
1409 return retval;
1410
John Haechtena5fd13a2016-12-09 22:15:17 +00001411 return genphy_config_aneg(phydev);
1412}
1413
Quentin Schulzb5bca652018-10-31 11:20:38 +01001414static int vsc8584_config_init(struct phy_device *phydev)
Quentin Schulz04087fc2018-10-31 11:20:37 +01001415{
Quentin Schulzb5bca652018-10-31 11:20:38 +01001416 struct vsc85xx_priv *priv = phydev->priv;
Quentin Schulz04087fc2018-10-31 11:20:37 +01001417 int ret;
1418 u16 addr;
1419 u16 reg_val;
1420 u16 val;
Quentin Schulz04087fc2018-10-31 11:20:37 +01001421
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
Quentin Schulzb5bca652018-10-31 11:20:38 +01001427 ret = priv->config_pre(phydev);
1428 if (ret)
1429 return ret;
Quentin Schulz04087fc2018-10-31 11:20:37 +01001430
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
Quentin Schulz05bbd672018-10-31 11:20:39 +01001494static struct vsc85xx_priv vsc8574_priv = {
1495 .config_pre = vsc8574_config_pre_init,
1496};
1497
1498static int vsc8574_config(struct phy_device *phydev)
1499{
1500 phydev->priv = &vsc8574_priv;
1501
1502 return vsc8584_config_init(phydev);
1503}
1504
Quentin Schulzb5bca652018-10-31 11:20:38 +01001505static struct vsc85xx_priv vsc8584_priv = {
1506 .config_pre = vsc8584_config_pre_init,
1507};
1508
1509static int vsc8584_config(struct phy_device *phydev)
1510{
1511 phydev->priv = &vsc8584_priv;
1512
1513 return vsc8584_config_init(phydev);
1514}
1515
John Haechtena5fd13a2016-12-09 22:15:17 +00001516static 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
1526static 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
1536static 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
1546static 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
Quentin Schulz05bbd672018-10-31 11:20:39 +01001556static 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
Quentin Schulz04087fc2018-10-31 11:20:37 +01001566static 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
John Haechtena5fd13a2016-12-09 22:15:17 +00001576int 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);
Quentin Schulz05bbd672018-10-31 11:20:39 +01001582 phy_register(&VSC8574_driver);
Quentin Schulz04087fc2018-10-31 11:20:37 +01001583 phy_register(&VSC8584_driver);
John Haechtena5fd13a2016-12-09 22:15:17 +00001584
1585 return 0;
1586}