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