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