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