blob: 86d882dd08887fdbe46ba4f62f9071ec43e1008c [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: MIT
John Haechtena5fd13a2016-12-09 22:15:17 +00002/*
3 * Microsemi PHY drivers
4 *
John Haechtena5fd13a2016-12-09 22:15:17 +00005 *
6 * Copyright (c) 2016 Microsemi Corporation
7 *
8 * Author: John Haechten
9 *
10 */
11
12#include <miiphy.h>
13#include <bitfield.h>
Quentin Schulz04087fc2018-10-31 11:20:37 +010014#include <time.h>
15#include <linux/delay.h>
John Haechtena5fd13a2016-12-09 22:15:17 +000016
17/* Microsemi PHY ID's */
18#define PHY_ID_VSC8530 0x00070560
19#define PHY_ID_VSC8531 0x00070570
20#define PHY_ID_VSC8540 0x00070760
21#define PHY_ID_VSC8541 0x00070770
Quentin Schulz04087fc2018-10-31 11:20:37 +010022#define PHY_ID_VSC8584 0x000707c0
John Haechtena5fd13a2016-12-09 22:15:17 +000023
24/* Microsemi VSC85xx PHY Register Pages */
25#define MSCC_EXT_PAGE_ACCESS 31 /* Page Access Register */
26#define MSCC_PHY_PAGE_STD 0x0000 /* Standard registers */
27#define MSCC_PHY_PAGE_EXT1 0x0001 /* Extended registers - page 1 */
28#define MSCC_PHY_PAGE_EXT2 0x0002 /* Extended registers - page 2 */
29#define MSCC_PHY_PAGE_EXT3 0x0003 /* Extended registers - page 3 */
30#define MSCC_PHY_PAGE_EXT4 0x0004 /* Extended registers - page 4 */
31#define MSCC_PHY_PAGE_GPIO 0x0010 /* GPIO registers */
32#define MSCC_PHY_PAGE_TEST 0x2A30 /* TEST Page registers */
33#define MSCC_PHY_PAGE_TR 0x52B5 /* Token Ring Page registers */
34
Quentin Schulz04087fc2018-10-31 11:20:37 +010035/* Std Page Register 18 */
36#define MSCC_PHY_BYPASS_CONTROL 18
37#define PARALLEL_DET_IGNORE_ADVERTISED BIT(3)
38
39/* Std Page Register 22 */
40#define MSCC_PHY_EXT_CNTL_STATUS 22
41#define SMI_BROADCAST_WR_EN BIT(0)
42
John Haechtena5fd13a2016-12-09 22:15:17 +000043/* Std Page Register 28 - PHY AUX Control/Status */
44#define MIIM_AUX_CNTRL_STAT_REG 28
45#define MIIM_AUX_CNTRL_STAT_ACTIPHY_TO (0x0004)
46#define MIIM_AUX_CNTRL_STAT_F_DUPLEX (0x0020)
47#define MIIM_AUX_CNTRL_STAT_SPEED_MASK (0x0018)
48#define MIIM_AUX_CNTRL_STAT_SPEED_POS (3)
49#define MIIM_AUX_CNTRL_STAT_SPEED_10M (0x0)
50#define MIIM_AUX_CNTRL_STAT_SPEED_100M (0x1)
51#define MIIM_AUX_CNTRL_STAT_SPEED_1000M (0x2)
52
53/* Std Page Register 23 - Extended PHY CTRL_1 */
54#define MSCC_PHY_EXT_PHY_CNTL_1_REG 23
55#define MAC_IF_SELECTION_MASK (0x1800)
56#define MAC_IF_SELECTION_GMII (0)
57#define MAC_IF_SELECTION_RMII (1)
58#define MAC_IF_SELECTION_RGMII (2)
59#define MAC_IF_SELECTION_POS (11)
60#define MAC_IF_SELECTION_WIDTH (2)
Quentin Schulz04087fc2018-10-31 11:20:37 +010061#define VSC8584_MAC_IF_SELECTION_MASK BIT(12)
62#define VSC8584_MAC_IF_SELECTION_SGMII 0
63#define VSC8584_MAC_IF_SELECTION_1000BASEX 1
64#define VSC8584_MAC_IF_SELECTION_POS 12
65#define MEDIA_OP_MODE_MASK GENMASK(10, 8)
66#define MEDIA_OP_MODE_COPPER 0
67#define MEDIA_OP_MODE_SERDES 1
68#define MEDIA_OP_MODE_1000BASEX 2
69#define MEDIA_OP_MODE_100BASEFX 3
70#define MEDIA_OP_MODE_AMS_COPPER_SERDES 5
71#define MEDIA_OP_MODE_AMS_COPPER_1000BASEX 6
72#define MEDIA_OP_MODE_AMS_COPPER_100BASEFX 7
73#define MEDIA_OP_MODE_POS 8
74
75/* Extended Page 1 Register 20E1 */
76#define MSCC_PHY_ACTIPHY_CNTL 20
77#define PHY_ADDR_REVERSED BIT(9)
78
79/* Extended Page 1 Register 23E1 */
80
81#define MSCC_PHY_EXT_PHY_CNTL_4 23
82#define PHY_CNTL_4_ADDR_POS 11
83
84/* Extended Page 1 Register 25E1 */
85#define MSCC_PHY_VERIPHY_CNTL_2 25
86
87/* Extended Page 1 Register 26E1 */
88#define MSCC_PHY_VERIPHY_CNTL_3 26
89
90/* Extended Page 2 Register 16E2 */
91#define MSCC_PHY_CU_PMD_TX_CNTL 16
John Haechtena5fd13a2016-12-09 22:15:17 +000092
93/* Extended Page 2 Register 20E2 */
94#define MSCC_PHY_RGMII_CNTL_REG 20
95#define VSC_FAST_LINK_FAIL2_ENA_MASK (0x8000)
96#define RX_CLK_OUT_MASK (0x0800)
97#define RX_CLK_OUT_POS (11)
98#define RX_CLK_OUT_WIDTH (1)
99#define RX_CLK_OUT_NORMAL (0)
100#define RX_CLK_OUT_DISABLE (1)
101#define RGMII_RX_CLK_DELAY_POS (4)
102#define RGMII_RX_CLK_DELAY_WIDTH (3)
103#define RGMII_RX_CLK_DELAY_MASK (0x0070)
104#define RGMII_TX_CLK_DELAY_POS (0)
105#define RGMII_TX_CLK_DELAY_WIDTH (3)
106#define RGMII_TX_CLK_DELAY_MASK (0x0007)
107
108/* Extended Page 2 Register 27E2 */
109#define MSCC_PHY_WOL_MAC_CONTROL 27
110#define EDGE_RATE_CNTL_POS (5)
111#define EDGE_RATE_CNTL_WIDTH (3)
112#define EDGE_RATE_CNTL_MASK (0x00E0)
113#define RMII_CLK_OUT_ENABLE_POS (4)
114#define RMII_CLK_OUT_ENABLE_WIDTH (1)
115#define RMII_CLK_OUT_ENABLE_MASK (0x10)
116
Quentin Schulz04087fc2018-10-31 11:20:37 +0100117/* Extended Page 3 Register 22E3 */
118#define MSCC_PHY_SERDES_TX_CRC_ERR_CNT 22
119
120/* Extended page GPIO register 00G */
121#define MSCC_DW8051_CNTL_STATUS 0
122#define MICRO_NSOFT_RESET BIT(15)
123#define RUN_FROM_INT_ROM BIT(14)
124#define AUTOINC_ADDR BIT(13)
125#define PATCH_RAM_CLK BIT(12)
126#define MICRO_PATCH_EN BIT(7)
127#define DW8051_CLK_EN BIT(4)
128#define MICRO_CLK_EN BIT(3)
129#define MICRO_CLK_DIVIDE(x) ((x) >> 1)
130
131/* Extended page GPIO register 09G */
132#define MSCC_TRAP_ROM_ADDR(x) ((x) * 2 + 1)
133
134/* Extended page GPIO register 10G */
135#define MSCC_PATCH_RAM_ADDR(x) (((x) + 1) * 2)
136
137/* Extended page GPIO register 11G */
138#define MSCC_INT_MEM_ADDR 11
139
140/* Extended page GPIO register 12G */
141#define MSCC_INT_MEM_CNTL 12
142#define READ_SFR (BIT(14) | BIT(13))
143#define READ_PRAM BIT(14)
144#define READ_ROM BIT(13)
145#define READ_RAM (0x00 << 13)
146#define INT_MEM_WRITE_EN BIT(12)
147#define EN_PATCH_RAM_TRAP_ADDR(x) BIT((x) + 7)
148#define INT_MEM_DATA_M GENMASK(7, 0)
149#define INT_MEM_DATA(x) (INT_MEM_DATA_M & (x))
150
151/* Extended page GPIO register 18G */
152#define MSCC_PHY_PROC_CMD 18
153#define PROC_CMD_NCOMPLETED BIT(15)
154#define PROC_CMD_FAILED BIT(14)
155#define PROC_CMD_SGMII_PORT(x) ((x) << 8)
156#define PROC_CMD_FIBER_PORT(x) BIT(8 + (x) % 4)
157#define PROC_CMD_QSGMII_PORT (BIT(11) | BIT(10))
158#define PROC_CMD_RST_CONF_PORT BIT(7)
159#define PROC_CMD_RECONF_PORT (0 << 7)
160#define PROC_CMD_READ_MOD_WRITE_PORT BIT(6)
161#define PROC_CMD_WRITE BIT(6)
162#define PROC_CMD_READ (0 << 6)
163#define PROC_CMD_FIBER_DISABLE BIT(5)
164#define PROC_CMD_FIBER_100BASE_FX BIT(4)
165#define PROC_CMD_FIBER_1000BASE_X (0 << 4)
166#define PROC_CMD_SGMII_MAC (BIT(5) | BIT(4))
167#define PROC_CMD_QSGMII_MAC BIT(5)
168#define PROC_CMD_NO_MAC_CONF (0x00 << 4)
169#define PROC_CMD_NOP GENMASK(3, 0)
170#define PROC_CMD_CRC16 BIT(3)
171#define PROC_CMD_FIBER_MEDIA_CONF BIT(0)
172#define PROC_CMD_MCB_ACCESS_MAC_CONF (0x0000 << 0)
173#define PROC_CMD_NCOMPLETED_TIMEOUT_MS 500
174
175/* Extended page GPIO register 19G */
176#define MSCC_PHY_MAC_CFG_FASTLINK 19
177#define MAC_CFG_MASK GENMASK(15, 14)
178#define MAC_CFG_SGMII (0x00 << 14)
179#define MAC_CFG_QSGMII BIT(14)
180
181/* Test Registers */
182#define MSCC_PHY_TEST_PAGE_5 5
183
184#define MSCC_PHY_TEST_PAGE_8 8
185#define TR_CLK_DISABLE BIT(15)
186
John Haechtena5fd13a2016-12-09 22:15:17 +0000187/* Token Ring Page 0x52B5 Registers */
188#define MSCC_PHY_REG_TR_ADDR_16 16
189#define MSCC_PHY_REG_TR_DATA_17 17
190#define MSCC_PHY_REG_TR_DATA_18 18
191
192/* Token Ring - Read Value in */
193#define MSCC_PHY_TR_16_READ (0xA000)
194/* Token Ring - Write Value out */
195#define MSCC_PHY_TR_16_WRITE (0x8000)
196
197/* Token Ring Registers */
198#define MSCC_PHY_TR_LINKDETCTRL_POS (3)
199#define MSCC_PHY_TR_LINKDETCTRL_WIDTH (2)
200#define MSCC_PHY_TR_LINKDETCTRL_VAL (3)
201#define MSCC_PHY_TR_LINKDETCTRL_MASK (0x0018)
202#define MSCC_PHY_TR_LINKDETCTRL_ADDR (0x07F8)
203
204#define MSCC_PHY_TR_VGATHRESH100_POS (0)
205#define MSCC_PHY_TR_VGATHRESH100_WIDTH (7)
206#define MSCC_PHY_TR_VGATHRESH100_VAL (0x0018)
207#define MSCC_PHY_TR_VGATHRESH100_MASK (0x007f)
208#define MSCC_PHY_TR_VGATHRESH100_ADDR (0x0FA4)
209
210#define MSCC_PHY_TR_VGAGAIN10_U_POS (0)
211#define MSCC_PHY_TR_VGAGAIN10_U_WIDTH (1)
212#define MSCC_PHY_TR_VGAGAIN10_U_MASK (0x0001)
213#define MSCC_PHY_TR_VGAGAIN10_U_VAL (0)
214
215#define MSCC_PHY_TR_VGAGAIN10_L_POS (12)
216#define MSCC_PHY_TR_VGAGAIN10_L_WIDTH (4)
217#define MSCC_PHY_TR_VGAGAIN10_L_MASK (0xf000)
218#define MSCC_PHY_TR_VGAGAIN10_L_VAL (0x0001)
219#define MSCC_PHY_TR_VGAGAIN10_ADDR (0x0F92)
220
221/* General Timeout Values */
222#define MSCC_PHY_RESET_TIMEOUT (100)
223#define MSCC_PHY_MICRO_TIMEOUT (500)
224
Quentin Schulz04087fc2018-10-31 11:20:37 +0100225#define VSC8584_REVB 0x0001
226#define MSCC_DEV_REV_MASK GENMASK(3, 0)
227
228#define MSCC_VSC8584_REVB_INT8051_FW_START_ADDR 0xe800
229#define MSCC_VSC8584_REVB_INT8051_FW_CRC 0xfb48
230
John Haechtena5fd13a2016-12-09 22:15:17 +0000231/* RGMII/GMII Clock Delay (Skew) Options */ enum vsc_phy_rgmii_skew {
232 VSC_PHY_RGMII_DELAY_200_PS,
233 VSC_PHY_RGMII_DELAY_800_PS,
234 VSC_PHY_RGMII_DELAY_1100_PS,
235 VSC_PHY_RGMII_DELAY_1700_PS,
236 VSC_PHY_RGMII_DELAY_2000_PS,
237 VSC_PHY_RGMII_DELAY_2300_PS,
238 VSC_PHY_RGMII_DELAY_2600_PS,
239 VSC_PHY_RGMII_DELAY_3400_PS,
240};
241
242/* MAC i/f Clock Edge Rage Control (Slew), See Reg27E2 */ enum
243vsc_phy_clk_slew {
244 VSC_PHY_CLK_SLEW_RATE_0,
245 VSC_PHY_CLK_SLEW_RATE_1,
246 VSC_PHY_CLK_SLEW_RATE_2,
247 VSC_PHY_CLK_SLEW_RATE_3,
248 VSC_PHY_CLK_SLEW_RATE_4,
249 VSC_PHY_CLK_SLEW_RATE_5,
250 VSC_PHY_CLK_SLEW_RATE_6,
251 VSC_PHY_CLK_SLEW_RATE_7,
252};
253
Quentin Schulz04087fc2018-10-31 11:20:37 +0100254static void vsc8584_csr_write(struct mii_dev *bus, int phy0, u16 addr, u32 val)
255{
256 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18,
257 val >> 16);
258 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17,
259 val & GENMASK(15, 0));
260 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
261 MSCC_PHY_TR_16_WRITE | addr);
262}
263
264static int vsc8584_cmd(struct mii_dev *bus, int phy, u16 val)
265{
266 unsigned long deadline;
267 u16 reg_val;
268
269 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
270 MSCC_PHY_PAGE_GPIO);
271
272 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_PROC_CMD,
273 PROC_CMD_NCOMPLETED | val);
274
275 deadline = timer_get_us() + PROC_CMD_NCOMPLETED_TIMEOUT_MS * 1000;
276 do {
277 reg_val = bus->read(bus, phy, MDIO_DEVAD_NONE,
278 MSCC_PHY_PROC_CMD);
279 } while (timer_get_us() <= deadline &&
280 (reg_val & PROC_CMD_NCOMPLETED) &&
281 !(reg_val & PROC_CMD_FAILED));
282
283 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
284 MSCC_PHY_PAGE_STD);
285
286 if (reg_val & PROC_CMD_FAILED)
287 return -EIO;
288 if (reg_val & PROC_CMD_NCOMPLETED)
289 return -ETIMEDOUT;
290
291 return 0;
292}
293
294static int vsc8584_micro_deassert_reset(struct mii_dev *bus, int phy,
295 bool patch_en)
296{
297 u32 enable, release;
298
299 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
300 MSCC_PHY_PAGE_GPIO);
301
302 enable = RUN_FROM_INT_ROM | MICRO_CLK_EN | DW8051_CLK_EN;
303 release = MICRO_NSOFT_RESET | RUN_FROM_INT_ROM | DW8051_CLK_EN |
304 MICRO_CLK_EN;
305
306 if (patch_en) {
307 enable |= MICRO_PATCH_EN;
308 release |= MICRO_PATCH_EN;
309
310 /* Clear all patches */
311 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL,
312 READ_RAM);
313 }
314
315 /*
316 * Enable 8051 Micro clock; CLEAR/SET patch present; disable PRAM clock
317 * override and addr. auto-incr; operate at 125 MHz
318 */
319 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_DW8051_CNTL_STATUS, enable);
320 /* Release 8051 Micro SW reset */
321 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_DW8051_CNTL_STATUS, release);
322
323 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
324 MSCC_PHY_PAGE_STD);
325
326 return 0;
327}
328
329static int vsc8584_micro_assert_reset(struct mii_dev *bus, int phy)
330{
331 int ret;
332 u16 reg;
333
334 ret = vsc8584_cmd(bus, phy, PROC_CMD_NOP);
335 if (ret)
336 return ret;
337
338 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
339 MSCC_PHY_PAGE_GPIO);
340
341 reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL);
342 reg &= ~EN_PATCH_RAM_TRAP_ADDR(4);
343 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL, reg);
344
345 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_TRAP_ROM_ADDR(4), 0x005b);
346 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_PATCH_RAM_ADDR(4), 0x005b);
347
348 reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL);
349 reg |= EN_PATCH_RAM_TRAP_ADDR(4);
350 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL, reg);
351
352 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_PROC_CMD, PROC_CMD_NOP);
353
354 reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_DW8051_CNTL_STATUS);
355 reg &= ~MICRO_NSOFT_RESET;
356 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_DW8051_CNTL_STATUS, reg);
357
358 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_PROC_CMD,
359 PROC_CMD_MCB_ACCESS_MAC_CONF | PROC_CMD_SGMII_PORT(0) |
360 PROC_CMD_NO_MAC_CONF | PROC_CMD_READ);
361
362 reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL);
363 reg &= ~EN_PATCH_RAM_TRAP_ADDR(4);
364 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL, reg);
365
366 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
367 MSCC_PHY_PAGE_STD);
368
369 return 0;
370}
371
372static const u8 fw_patch_vsc8584[] = {
373 0xe8, 0x59, 0x02, 0xe8, 0x12, 0x02, 0xe8, 0x42, 0x02, 0xe8, 0x5a, 0x02,
374 0xe8, 0x5b, 0x02, 0xe8, 0x5c, 0xe5, 0x69, 0x54, 0x0f, 0x24, 0xf7, 0x60,
375 0x27, 0x24, 0xfc, 0x60, 0x23, 0x24, 0x08, 0x70, 0x14, 0xe5, 0x69, 0xae,
376 0x68, 0x78, 0x04, 0xce, 0xa2, 0xe7, 0x13, 0xce, 0x13, 0xd8, 0xf8, 0x7e,
377 0x00, 0x54, 0x0f, 0x80, 0x00, 0x7b, 0x01, 0x7a, 0x00, 0x7d, 0xee, 0x7f,
378 0x92, 0x12, 0x50, 0xee, 0x22, 0xe4, 0xf5, 0x10, 0x85, 0x10, 0xfb, 0x7d,
379 0x1c, 0xe4, 0xff, 0x12, 0x59, 0xea, 0x05, 0x10, 0xe5, 0x10, 0xc3, 0x94,
380 0x04, 0x40, 0xed, 0x22, 0x22, 0x22, 0x22, 0x22,
381};
382
383static int vsc8584_get_fw_crc(struct mii_dev *bus, int phy, u16 start,
384 u16 *crc, const u8 *fw_patch, int fw_size)
385{
386 int ret;
387
388 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
389 MSCC_PHY_PAGE_EXT1);
390
391 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_VERIPHY_CNTL_2, start);
392 /* Add one byte to size for the one added by the patch_fw function */
393 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_VERIPHY_CNTL_3,
394 fw_size + 1);
395
396 ret = vsc8584_cmd(bus, phy, PROC_CMD_CRC16);
397 if (ret)
398 goto out;
399
400 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
401 MSCC_PHY_PAGE_EXT1);
402
403 *crc = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_VERIPHY_CNTL_2);
404
405out:
406 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
407 MSCC_PHY_PAGE_STD);
408
409 return ret;
410}
411
412static int vsc8584_patch_fw(struct mii_dev *bus, int phy, const u8 *fw_patch,
413 int fw_size)
414{
415 int i, ret;
416
417 ret = vsc8584_micro_assert_reset(bus, phy);
418 if (ret) {
419 pr_err("%s: failed to assert reset of micro\n", __func__);
420 return ret;
421 }
422
423 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
424 MSCC_PHY_PAGE_GPIO);
425
426 /*
427 * Hold 8051 Micro in SW Reset, Enable auto incr address and patch clock
428 * Disable the 8051 Micro clock
429 */
430 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_DW8051_CNTL_STATUS,
431 RUN_FROM_INT_ROM | AUTOINC_ADDR | PATCH_RAM_CLK |
432 MICRO_CLK_EN | MICRO_CLK_DIVIDE(2));
433 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL, READ_PRAM |
434 INT_MEM_WRITE_EN | INT_MEM_DATA(2));
435 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_ADDR, 0x0000);
436
437 for (i = 0; i < fw_size; i++)
438 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL,
439 READ_PRAM | INT_MEM_WRITE_EN | fw_patch[i]);
440
441 /* Clear internal memory access */
442 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL, READ_RAM);
443
444 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
445 MSCC_PHY_PAGE_STD);
446
447 return 0;
448}
449
450static int vsc8584_config_pre_init(struct mii_dev *bus, int phy0)
451{
452 u16 reg, crc;
453 int ret;
454
455 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
456 MSCC_PHY_PAGE_STD);
457
458 /* all writes below are broadcasted to all PHYs in the same package */
459 reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS);
460 reg |= SMI_BROADCAST_WR_EN;
461 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS, reg);
462
463 /*
464 * The below register writes are tweaking analog and electrical
465 * configuration that were determined through characterization by PHY
466 * engineers. These don't mean anything more than "these are the best
467 * values".
468 */
469 reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_BYPASS_CONTROL);
470 reg |= PARALLEL_DET_IGNORE_ADVERTISED;
471 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_BYPASS_CONTROL, reg);
472
473 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
474 MSCC_PHY_PAGE_EXT3);
475
476 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_SERDES_TX_CRC_ERR_CNT,
477 0x2000);
478
479 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
480 MSCC_PHY_PAGE_TEST);
481
482 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_5, 0x1f20);
483
484 reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8);
485 reg |= TR_CLK_DISABLE;
486 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8, reg);
487
488 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
489 MSCC_PHY_PAGE_TR);
490
491 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16, 0xafa4);
492
493 reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18);
494 reg &= ~0x007f;
495 reg |= 0x0019;
496 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18, reg);
497
498 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16, 0x8fa4);
499
500 vsc8584_csr_write(bus, phy0, 0x07fa, 0x0050100f);
501 vsc8584_csr_write(bus, phy0, 0x1688, 0x00049f81);
502 vsc8584_csr_write(bus, phy0, 0x0f90, 0x00688980);
503 vsc8584_csr_write(bus, phy0, 0x03a4, 0x0000d8f0);
504 vsc8584_csr_write(bus, phy0, 0x0fc0, 0x00000400);
505 vsc8584_csr_write(bus, phy0, 0x0f82, 0x0012b002);
506 vsc8584_csr_write(bus, phy0, 0x1686, 0x00000004);
507 vsc8584_csr_write(bus, phy0, 0x168c, 0x00d2c46f);
508 vsc8584_csr_write(bus, phy0, 0x17a2, 0x00000620);
509 vsc8584_csr_write(bus, phy0, 0x16a0, 0x00eeffdd);
510 vsc8584_csr_write(bus, phy0, 0x16a6, 0x00071448);
511 vsc8584_csr_write(bus, phy0, 0x16a4, 0x0013132f);
512 vsc8584_csr_write(bus, phy0, 0x16a8, 0x00000000);
513 vsc8584_csr_write(bus, phy0, 0x0ffc, 0x00c0a028);
514 vsc8584_csr_write(bus, phy0, 0x0fe8, 0x0091b06c);
515 vsc8584_csr_write(bus, phy0, 0x0fea, 0x00041600);
516 vsc8584_csr_write(bus, phy0, 0x0f80, 0x00fffaff);
517 vsc8584_csr_write(bus, phy0, 0x0fec, 0x00901809);
518 vsc8584_csr_write(bus, phy0, 0x0ffe, 0x00b01007);
519 vsc8584_csr_write(bus, phy0, 0x16b0, 0x00eeff00);
520 vsc8584_csr_write(bus, phy0, 0x16b2, 0x00007000);
521 vsc8584_csr_write(bus, phy0, 0x16b4, 0x00000814);
522
523 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
524 MSCC_PHY_PAGE_EXT2);
525
526 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_CU_PMD_TX_CNTL, 0x028e);
527
528 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
529 MSCC_PHY_PAGE_TR);
530
531 vsc8584_csr_write(bus, phy0, 0x0486, 0x0008a518);
532 vsc8584_csr_write(bus, phy0, 0x0488, 0x006dc696);
533 vsc8584_csr_write(bus, phy0, 0x048a, 0x00000912);
534
535 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
536 MSCC_PHY_PAGE_TEST);
537
538 reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8);
539 reg &= ~TR_CLK_DISABLE;
540 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8, reg);
541
542 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
543 MSCC_PHY_PAGE_STD);
544
545 /* end of write broadcasting */
546 reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS);
547 reg &= ~SMI_BROADCAST_WR_EN;
548 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS, reg);
549
550 ret = vsc8584_get_fw_crc(bus, phy0,
551 MSCC_VSC8584_REVB_INT8051_FW_START_ADDR, &crc,
552 fw_patch_vsc8584,
553 ARRAY_SIZE(fw_patch_vsc8584));
554 if (ret)
555 goto out;
556
557 if (crc != MSCC_VSC8584_REVB_INT8051_FW_CRC) {
558 debug("FW CRC is not the expected one, patching FW...\n");
559 if (vsc8584_patch_fw(bus, phy0, fw_patch_vsc8584,
560 ARRAY_SIZE(fw_patch_vsc8584)))
561 pr_warn("failed to patch FW, expect non-optimal device\n");
562 }
563
564 vsc8584_micro_deassert_reset(bus, phy0, false);
565
566 ret = vsc8584_get_fw_crc(bus, phy0,
567 MSCC_VSC8584_REVB_INT8051_FW_START_ADDR, &crc,
568 fw_patch_vsc8584,
569 ARRAY_SIZE(fw_patch_vsc8584));
570 if (ret)
571 goto out;
572
573 if (crc != MSCC_VSC8584_REVB_INT8051_FW_CRC)
574 pr_warn("FW CRC after patching is not the expected one, expect non-optimal device\n");
575
576 ret = vsc8584_micro_assert_reset(bus, phy0);
577 if (ret)
578 goto out;
579
580 vsc8584_micro_deassert_reset(bus, phy0, true);
581
582out:
583 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
584 MSCC_PHY_PAGE_STD);
585
586 return ret;
587}
John Haechtena5fd13a2016-12-09 22:15:17 +0000588
589static int mscc_vsc8531_vsc8541_init_scripts(struct phy_device *phydev)
590{
591 u16 reg_val;
592
593 /* Set to Access Token Ring Registers */
594 phy_write(phydev, MDIO_DEVAD_NONE,
595 MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_TR);
596
597 /* Update LinkDetectCtrl default to optimized values */
598 /* Determined during Silicon Validation Testing */
599 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
600 (MSCC_PHY_TR_LINKDETCTRL_ADDR | MSCC_PHY_TR_16_READ));
601 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17);
602 reg_val = bitfield_replace(reg_val, MSCC_PHY_TR_LINKDETCTRL_POS,
603 MSCC_PHY_TR_LINKDETCTRL_WIDTH,
604 MSCC_PHY_TR_LINKDETCTRL_VAL);
605
606 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17, reg_val);
607 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
608 (MSCC_PHY_TR_LINKDETCTRL_ADDR | MSCC_PHY_TR_16_WRITE));
609
610 /* Update VgaThresh100 defaults to optimized values */
611 /* Determined during Silicon Validation Testing */
612 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
613 (MSCC_PHY_TR_VGATHRESH100_ADDR | MSCC_PHY_TR_16_READ));
614
615 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18);
616 reg_val = bitfield_replace(reg_val, MSCC_PHY_TR_VGATHRESH100_POS,
617 MSCC_PHY_TR_VGATHRESH100_WIDTH,
618 MSCC_PHY_TR_VGATHRESH100_VAL);
619
620 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18, reg_val);
621 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
622 (MSCC_PHY_TR_VGATHRESH100_ADDR | MSCC_PHY_TR_16_WRITE));
623
624 /* Update VgaGain10 defaults to optimized values */
625 /* Determined during Silicon Validation Testing */
626 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
627 (MSCC_PHY_TR_VGAGAIN10_ADDR | MSCC_PHY_TR_16_READ));
628
629 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18);
630 reg_val = bitfield_replace(reg_val, MSCC_PHY_TR_VGAGAIN10_U_POS,
631 MSCC_PHY_TR_VGAGAIN10_U_WIDTH,
632 MSCC_PHY_TR_VGAGAIN10_U_VAL);
633
634 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18, reg_val);
635 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17);
636 reg_val = bitfield_replace(reg_val, MSCC_PHY_TR_VGAGAIN10_L_POS,
637 MSCC_PHY_TR_VGAGAIN10_L_WIDTH,
638 MSCC_PHY_TR_VGAGAIN10_L_VAL);
639
640 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17, reg_val);
641 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
642 (MSCC_PHY_TR_VGAGAIN10_ADDR | MSCC_PHY_TR_16_WRITE));
643
644 /* Set back to Access Standard Page Registers */
645 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
646 MSCC_PHY_PAGE_STD);
647
648 return 0;
649}
650
651static int mscc_parse_status(struct phy_device *phydev)
652{
653 u16 speed;
654 u16 mii_reg;
655
656 mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_AUX_CNTRL_STAT_REG);
657
658 if (mii_reg & MIIM_AUX_CNTRL_STAT_F_DUPLEX)
659 phydev->duplex = DUPLEX_FULL;
660 else
661 phydev->duplex = DUPLEX_HALF;
662
663 speed = mii_reg & MIIM_AUX_CNTRL_STAT_SPEED_MASK;
664 speed = speed >> MIIM_AUX_CNTRL_STAT_SPEED_POS;
665
666 switch (speed) {
667 case MIIM_AUX_CNTRL_STAT_SPEED_1000M:
668 phydev->speed = SPEED_1000;
669 break;
670 case MIIM_AUX_CNTRL_STAT_SPEED_100M:
671 phydev->speed = SPEED_100;
672 break;
673 case MIIM_AUX_CNTRL_STAT_SPEED_10M:
674 phydev->speed = SPEED_10;
675 break;
676 default:
677 phydev->speed = SPEED_10;
678 break;
679 }
680
681 return 0;
682}
683
684static int mscc_startup(struct phy_device *phydev)
685{
686 int retval;
687
688 retval = genphy_update_link(phydev);
689
690 if (retval)
691 return retval;
692
693 return mscc_parse_status(phydev);
694}
695
696static int mscc_phy_soft_reset(struct phy_device *phydev)
697{
698 int retval = 0;
699 u16 timeout = MSCC_PHY_RESET_TIMEOUT;
700 u16 reg_val = 0;
701
702 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
703 MSCC_PHY_PAGE_STD);
704
705 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
706 phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, (reg_val | BMCR_RESET));
707
708 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
709
710 while ((reg_val & BMCR_RESET) && (timeout > 0)) {
711 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
712 timeout--;
713 udelay(1000); /* 1 ms */
714 }
715
716 if (timeout == 0) {
717 printf("MSCC PHY Soft_Reset Error: mac i/f = 0x%x\n",
718 phydev->interface);
719 retval = -ETIME;
720 }
721
722 return retval;
723}
724
725static int vsc8531_vsc8541_mac_config(struct phy_device *phydev)
726{
727 u16 reg_val = 0;
728 u16 mac_if = 0;
729 u16 rx_clk_out = 0;
730
731 /* For VSC8530/31 the only MAC modes are RMII/RGMII. */
732 /* For VSC8540/41 the only MAC modes are (G)MII and RMII/RGMII. */
733 /* Setup MAC Configuration */
734 switch (phydev->interface) {
735 case PHY_INTERFACE_MODE_MII:
736 case PHY_INTERFACE_MODE_GMII:
737 /* Set Reg23.12:11=0 */
738 mac_if = MAC_IF_SELECTION_GMII;
739 /* Set Reg20E2.11=1 */
740 rx_clk_out = RX_CLK_OUT_DISABLE;
741 break;
742
743 case PHY_INTERFACE_MODE_RMII:
744 /* Set Reg23.12:11=1 */
745 mac_if = MAC_IF_SELECTION_RMII;
746 /* Set Reg20E2.11=0 */
747 rx_clk_out = RX_CLK_OUT_NORMAL;
748 break;
749
750 case PHY_INTERFACE_MODE_RGMII:
751 /* Set Reg23.12:11=2 */
752 mac_if = MAC_IF_SELECTION_RGMII;
753 /* Set Reg20E2.11=0 */
754 rx_clk_out = RX_CLK_OUT_NORMAL;
755 break;
756
757 default:
758 printf("MSCC PHY - INVALID MAC i/f Config: mac i/f = 0x%x\n",
759 phydev->interface);
760 return -EINVAL;
761 }
762
763 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
764 MSCC_PHY_PAGE_STD);
765
766 reg_val = phy_read(phydev, MDIO_DEVAD_NONE,
767 MSCC_PHY_EXT_PHY_CNTL_1_REG);
768 /* Set MAC i/f bits Reg23.12:11 */
769 reg_val = bitfield_replace(reg_val, MAC_IF_SELECTION_POS,
770 MAC_IF_SELECTION_WIDTH, mac_if);
771 /* Update Reg23.12:11 */
772 phy_write(phydev, MDIO_DEVAD_NONE,
773 MSCC_PHY_EXT_PHY_CNTL_1_REG, reg_val);
774 /* Setup ExtPg_2 Register Access */
775 phy_write(phydev, MDIO_DEVAD_NONE,
776 MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_EXT2);
777 /* Read Reg20E2 */
778 reg_val = phy_read(phydev, MDIO_DEVAD_NONE,
779 MSCC_PHY_RGMII_CNTL_REG);
780 reg_val = bitfield_replace(reg_val, RX_CLK_OUT_POS,
781 RX_CLK_OUT_WIDTH, rx_clk_out);
782 /* Update Reg20E2.11 */
783 phy_write(phydev, MDIO_DEVAD_NONE,
784 MSCC_PHY_RGMII_CNTL_REG, reg_val);
785 /* Before leaving - Change back to Std Page Register Access */
786 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
787 MSCC_PHY_PAGE_STD);
788
789 return 0;
790}
791
792static int vsc8531_config(struct phy_device *phydev)
793{
794 int retval = -EINVAL;
795 u16 reg_val;
796 u16 rmii_clk_out;
797 enum vsc_phy_rgmii_skew rx_clk_skew = VSC_PHY_RGMII_DELAY_1700_PS;
798 enum vsc_phy_rgmii_skew tx_clk_skew = VSC_PHY_RGMII_DELAY_800_PS;
799 enum vsc_phy_clk_slew edge_rate = VSC_PHY_CLK_SLEW_RATE_4;
800
801 /* For VSC8530/31 and VSC8540/41 the init scripts are the same */
802 mscc_vsc8531_vsc8541_init_scripts(phydev);
803
804 /* For VSC8530/31 the only MAC modes are RMII/RGMII. */
805 switch (phydev->interface) {
806 case PHY_INTERFACE_MODE_RMII:
807 case PHY_INTERFACE_MODE_RGMII:
808 retval = vsc8531_vsc8541_mac_config(phydev);
809 if (retval != 0)
810 return retval;
811
812 retval = mscc_phy_soft_reset(phydev);
813 if (retval != 0)
814 return retval;
815 break;
816 default:
817 printf("PHY 8530/31 MAC i/f Config Error: mac i/f = 0x%x\n",
818 phydev->interface);
819 return -EINVAL;
820 }
821 /* Default RMII Clk Output to 0=OFF/1=ON */
822 rmii_clk_out = 0;
823
824 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
825 MSCC_PHY_PAGE_EXT2);
826 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG);
827
828 /* Reg20E2 - Update RGMII RX_Clk Skews. */
829 reg_val = bitfield_replace(reg_val, RGMII_RX_CLK_DELAY_POS,
830 RGMII_RX_CLK_DELAY_WIDTH, rx_clk_skew);
831 /* Reg20E2 - Update RGMII TX_Clk Skews. */
832 reg_val = bitfield_replace(reg_val, RGMII_TX_CLK_DELAY_POS,
833 RGMII_TX_CLK_DELAY_WIDTH, tx_clk_skew);
834
835 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG, reg_val);
836
837 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL);
838 /* Reg27E2 - Update Clk Slew Rate. */
839 reg_val = bitfield_replace(reg_val, EDGE_RATE_CNTL_POS,
840 EDGE_RATE_CNTL_WIDTH, edge_rate);
841 /* Reg27E2 - Update RMII Clk Out. */
842 reg_val = bitfield_replace(reg_val, RMII_CLK_OUT_ENABLE_POS,
843 RMII_CLK_OUT_ENABLE_WIDTH, rmii_clk_out);
844 /* Update Reg27E2 */
845 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL, reg_val);
846 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
847 MSCC_PHY_PAGE_STD);
848
849 return genphy_config_aneg(phydev);
850}
851
852static int vsc8541_config(struct phy_device *phydev)
853{
854 int retval = -EINVAL;
855 u16 reg_val;
856 u16 rmii_clk_out;
857 enum vsc_phy_rgmii_skew rx_clk_skew = VSC_PHY_RGMII_DELAY_1700_PS;
858 enum vsc_phy_rgmii_skew tx_clk_skew = VSC_PHY_RGMII_DELAY_800_PS;
859 enum vsc_phy_clk_slew edge_rate = VSC_PHY_CLK_SLEW_RATE_4;
860
861 /* For VSC8530/31 and VSC8540/41 the init scripts are the same */
862 mscc_vsc8531_vsc8541_init_scripts(phydev);
863
864 /* For VSC8540/41 the only MAC modes are (G)MII and RMII/RGMII. */
865 switch (phydev->interface) {
866 case PHY_INTERFACE_MODE_MII:
867 case PHY_INTERFACE_MODE_GMII:
868 case PHY_INTERFACE_MODE_RMII:
869 case PHY_INTERFACE_MODE_RGMII:
870 retval = vsc8531_vsc8541_mac_config(phydev);
871 if (retval != 0)
872 return retval;
873
874 retval = mscc_phy_soft_reset(phydev);
875 if (retval != 0)
876 return retval;
877 break;
878 default:
879 printf("PHY 8541 MAC i/f config Error: mac i/f = 0x%x\n",
880 phydev->interface);
881 return -EINVAL;
882 }
883 /* Default RMII Clk Output to 0=OFF/1=ON */
884 rmii_clk_out = 0;
885
886 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
887 MSCC_PHY_PAGE_EXT2);
888 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG);
889 /* Reg20E2 - Update RGMII RX_Clk Skews. */
890 reg_val = bitfield_replace(reg_val, RGMII_RX_CLK_DELAY_POS,
891 RGMII_RX_CLK_DELAY_WIDTH, rx_clk_skew);
892 /* Reg20E2 - Update RGMII TX_Clk Skews. */
893 reg_val = bitfield_replace(reg_val, RGMII_TX_CLK_DELAY_POS,
894 RGMII_TX_CLK_DELAY_WIDTH, tx_clk_skew);
895 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG, reg_val);
896
897 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL);
898 /* Reg27E2 - Update Clk Slew Rate. */
899 reg_val = bitfield_replace(reg_val, EDGE_RATE_CNTL_POS,
900 EDGE_RATE_CNTL_WIDTH, edge_rate);
901 /* Reg27E2 - Update RMII Clk Out. */
902 reg_val = bitfield_replace(reg_val, RMII_CLK_OUT_ENABLE_POS,
903 RMII_CLK_OUT_ENABLE_WIDTH, rmii_clk_out);
904 /* Update Reg27E2 */
905 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL, reg_val);
906 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
907 MSCC_PHY_PAGE_STD);
908
909 return genphy_config_aneg(phydev);
910}
911
Quentin Schulz04087fc2018-10-31 11:20:37 +0100912static int vsc8584_config(struct phy_device *phydev)
913{
914 int ret;
915 u16 addr;
916 u16 reg_val;
917 u16 val;
918 u16 base_addr;
919
920 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
921 MSCC_PHY_PAGE_EXT1);
922 addr = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_EXT_PHY_CNTL_4);
923 addr >>= PHY_CNTL_4_ADDR_POS;
924
925 val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_ACTIPHY_CNTL);
926 if (val & PHY_ADDR_REVERSED)
927 base_addr = phydev->addr + addr;
928 else
929 base_addr = phydev->addr - addr;
930
931 if ((phydev->phy_id & MSCC_DEV_REV_MASK) != VSC8584_REVB) {
932 pr_warn("VSC8584 revA not officially supported, skipping firmware patching. Use at your own risk.\n");
933 } else {
934 ret = vsc8584_config_pre_init(phydev->bus, base_addr);
935 if (ret)
936 return ret;
937 }
938
939 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
940 MSCC_PHY_PAGE_GPIO);
941
942 if (phydev->interface == PHY_INTERFACE_MODE_QSGMII)
943 val = MAC_CFG_QSGMII;
944 else
945 val = MAC_CFG_SGMII;
946
947 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_MAC_CFG_FASTLINK);
948 reg_val &= ~MAC_CFG_MASK;
949 reg_val |= val;
950 ret = phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_MAC_CFG_FASTLINK,
951 reg_val);
952 if (ret)
953 return ret;
954
955 reg_val = PROC_CMD_MCB_ACCESS_MAC_CONF | PROC_CMD_RST_CONF_PORT |
956 PROC_CMD_READ_MOD_WRITE_PORT;
957 if (phydev->interface == PHY_INTERFACE_MODE_QSGMII)
958 reg_val |= PROC_CMD_QSGMII_MAC;
959 else
960 reg_val |= PROC_CMD_SGMII_MAC;
961
962 ret = vsc8584_cmd(phydev->bus, phydev->addr, reg_val);
963 if (ret)
964 return ret;
965
966 mdelay(10);
967
968 /* Disable SerDes for 100Base-FX */
969 ret = vsc8584_cmd(phydev->bus, phydev->addr, PROC_CMD_FIBER_MEDIA_CONF |
970 PROC_CMD_FIBER_PORT(addr) | PROC_CMD_FIBER_DISABLE |
971 PROC_CMD_READ_MOD_WRITE_PORT |
972 PROC_CMD_RST_CONF_PORT | PROC_CMD_FIBER_100BASE_FX);
973 if (ret)
974 return ret;
975
976 /* Disable SerDes for 1000Base-X */
977 ret = vsc8584_cmd(phydev->bus, phydev->addr, PROC_CMD_FIBER_MEDIA_CONF |
978 PROC_CMD_FIBER_PORT(addr) | PROC_CMD_FIBER_DISABLE |
979 PROC_CMD_READ_MOD_WRITE_PORT |
980 PROC_CMD_RST_CONF_PORT | PROC_CMD_FIBER_1000BASE_X);
981 if (ret)
982 return ret;
983
984 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
985 MSCC_PHY_PAGE_STD);
986 reg_val = phy_read(phydev, MDIO_DEVAD_NONE,
987 MSCC_PHY_EXT_PHY_CNTL_1_REG);
988 reg_val &= ~(MEDIA_OP_MODE_MASK | VSC8584_MAC_IF_SELECTION_MASK);
989 reg_val |= MEDIA_OP_MODE_COPPER |
990 (VSC8584_MAC_IF_SELECTION_SGMII <<
991 VSC8584_MAC_IF_SELECTION_POS);
992 ret = phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_EXT_PHY_CNTL_1_REG,
993 reg_val);
994
995 ret = mscc_phy_soft_reset(phydev);
996 if (ret != 0)
997 return ret;
998
999 return genphy_config(phydev);
1000}
1001
John Haechtena5fd13a2016-12-09 22:15:17 +00001002static struct phy_driver VSC8530_driver = {
1003 .name = "Microsemi VSC8530",
1004 .uid = PHY_ID_VSC8530,
1005 .mask = 0x000ffff0,
1006 .features = PHY_BASIC_FEATURES,
1007 .config = &vsc8531_config,
1008 .startup = &mscc_startup,
1009 .shutdown = &genphy_shutdown,
1010};
1011
1012static struct phy_driver VSC8531_driver = {
1013 .name = "Microsemi VSC8531",
1014 .uid = PHY_ID_VSC8531,
1015 .mask = 0x000ffff0,
1016 .features = PHY_GBIT_FEATURES,
1017 .config = &vsc8531_config,
1018 .startup = &mscc_startup,
1019 .shutdown = &genphy_shutdown,
1020};
1021
1022static struct phy_driver VSC8540_driver = {
1023 .name = "Microsemi VSC8540",
1024 .uid = PHY_ID_VSC8540,
1025 .mask = 0x000ffff0,
1026 .features = PHY_BASIC_FEATURES,
1027 .config = &vsc8541_config,
1028 .startup = &mscc_startup,
1029 .shutdown = &genphy_shutdown,
1030};
1031
1032static struct phy_driver VSC8541_driver = {
1033 .name = "Microsemi VSC8541",
1034 .uid = PHY_ID_VSC8541,
1035 .mask = 0x000ffff0,
1036 .features = PHY_GBIT_FEATURES,
1037 .config = &vsc8541_config,
1038 .startup = &mscc_startup,
1039 .shutdown = &genphy_shutdown,
1040};
1041
Quentin Schulz04087fc2018-10-31 11:20:37 +01001042static struct phy_driver VSC8584_driver = {
1043 .name = "Microsemi VSC8584",
1044 .uid = PHY_ID_VSC8584,
1045 .mask = 0x000ffff0,
1046 .features = PHY_GBIT_FEATURES,
1047 .config = &vsc8584_config,
1048 .startup = &mscc_startup,
1049 .shutdown = &genphy_shutdown,
1050};
1051
John Haechtena5fd13a2016-12-09 22:15:17 +00001052int phy_mscc_init(void)
1053{
1054 phy_register(&VSC8530_driver);
1055 phy_register(&VSC8531_driver);
1056 phy_register(&VSC8540_driver);
1057 phy_register(&VSC8541_driver);
Quentin Schulz04087fc2018-10-31 11:20:37 +01001058 phy_register(&VSC8584_driver);
John Haechtena5fd13a2016-12-09 22:15:17 +00001059
1060 return 0;
1061}