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