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