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