blob: c1b73c6348dbf0a07b340ac363f3f7562c93d195 [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 Schulzb5bca652018-10-31 11:20:38 +0100254struct vsc85xx_priv {
255 int (*config_pre)(struct phy_device *phydev);
256};
257
Quentin Schulz04087fc2018-10-31 11:20:37 +0100258static void vsc8584_csr_write(struct mii_dev *bus, int phy0, u16 addr, u32 val)
259{
260 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18,
261 val >> 16);
262 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17,
263 val & GENMASK(15, 0));
264 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
265 MSCC_PHY_TR_16_WRITE | addr);
266}
267
268static int vsc8584_cmd(struct mii_dev *bus, int phy, u16 val)
269{
270 unsigned long deadline;
271 u16 reg_val;
272
273 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
274 MSCC_PHY_PAGE_GPIO);
275
276 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_PROC_CMD,
277 PROC_CMD_NCOMPLETED | val);
278
279 deadline = timer_get_us() + PROC_CMD_NCOMPLETED_TIMEOUT_MS * 1000;
280 do {
281 reg_val = bus->read(bus, phy, MDIO_DEVAD_NONE,
282 MSCC_PHY_PROC_CMD);
283 } while (timer_get_us() <= deadline &&
284 (reg_val & PROC_CMD_NCOMPLETED) &&
285 !(reg_val & PROC_CMD_FAILED));
286
287 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
288 MSCC_PHY_PAGE_STD);
289
290 if (reg_val & PROC_CMD_FAILED)
291 return -EIO;
292 if (reg_val & PROC_CMD_NCOMPLETED)
293 return -ETIMEDOUT;
294
295 return 0;
296}
297
298static int vsc8584_micro_deassert_reset(struct mii_dev *bus, int phy,
299 bool patch_en)
300{
301 u32 enable, release;
302
303 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
304 MSCC_PHY_PAGE_GPIO);
305
306 enable = RUN_FROM_INT_ROM | MICRO_CLK_EN | DW8051_CLK_EN;
307 release = MICRO_NSOFT_RESET | RUN_FROM_INT_ROM | DW8051_CLK_EN |
308 MICRO_CLK_EN;
309
310 if (patch_en) {
311 enable |= MICRO_PATCH_EN;
312 release |= MICRO_PATCH_EN;
313
314 /* Clear all patches */
315 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL,
316 READ_RAM);
317 }
318
319 /*
320 * Enable 8051 Micro clock; CLEAR/SET patch present; disable PRAM clock
321 * override and addr. auto-incr; operate at 125 MHz
322 */
323 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_DW8051_CNTL_STATUS, enable);
324 /* Release 8051 Micro SW reset */
325 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_DW8051_CNTL_STATUS, release);
326
327 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
328 MSCC_PHY_PAGE_STD);
329
330 return 0;
331}
332
333static int vsc8584_micro_assert_reset(struct mii_dev *bus, int phy)
334{
335 int ret;
336 u16 reg;
337
338 ret = vsc8584_cmd(bus, phy, PROC_CMD_NOP);
339 if (ret)
340 return ret;
341
342 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
343 MSCC_PHY_PAGE_GPIO);
344
345 reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL);
346 reg &= ~EN_PATCH_RAM_TRAP_ADDR(4);
347 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL, reg);
348
349 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_TRAP_ROM_ADDR(4), 0x005b);
350 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_PATCH_RAM_ADDR(4), 0x005b);
351
352 reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL);
353 reg |= EN_PATCH_RAM_TRAP_ADDR(4);
354 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL, reg);
355
356 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_PROC_CMD, PROC_CMD_NOP);
357
358 reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_DW8051_CNTL_STATUS);
359 reg &= ~MICRO_NSOFT_RESET;
360 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_DW8051_CNTL_STATUS, reg);
361
362 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_PROC_CMD,
363 PROC_CMD_MCB_ACCESS_MAC_CONF | PROC_CMD_SGMII_PORT(0) |
364 PROC_CMD_NO_MAC_CONF | PROC_CMD_READ);
365
366 reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL);
367 reg &= ~EN_PATCH_RAM_TRAP_ADDR(4);
368 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL, reg);
369
370 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
371 MSCC_PHY_PAGE_STD);
372
373 return 0;
374}
375
376static const u8 fw_patch_vsc8584[] = {
377 0xe8, 0x59, 0x02, 0xe8, 0x12, 0x02, 0xe8, 0x42, 0x02, 0xe8, 0x5a, 0x02,
378 0xe8, 0x5b, 0x02, 0xe8, 0x5c, 0xe5, 0x69, 0x54, 0x0f, 0x24, 0xf7, 0x60,
379 0x27, 0x24, 0xfc, 0x60, 0x23, 0x24, 0x08, 0x70, 0x14, 0xe5, 0x69, 0xae,
380 0x68, 0x78, 0x04, 0xce, 0xa2, 0xe7, 0x13, 0xce, 0x13, 0xd8, 0xf8, 0x7e,
381 0x00, 0x54, 0x0f, 0x80, 0x00, 0x7b, 0x01, 0x7a, 0x00, 0x7d, 0xee, 0x7f,
382 0x92, 0x12, 0x50, 0xee, 0x22, 0xe4, 0xf5, 0x10, 0x85, 0x10, 0xfb, 0x7d,
383 0x1c, 0xe4, 0xff, 0x12, 0x59, 0xea, 0x05, 0x10, 0xe5, 0x10, 0xc3, 0x94,
384 0x04, 0x40, 0xed, 0x22, 0x22, 0x22, 0x22, 0x22,
385};
386
387static int vsc8584_get_fw_crc(struct mii_dev *bus, int phy, u16 start,
388 u16 *crc, const u8 *fw_patch, int fw_size)
389{
390 int ret;
391
392 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
393 MSCC_PHY_PAGE_EXT1);
394
395 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_VERIPHY_CNTL_2, start);
396 /* Add one byte to size for the one added by the patch_fw function */
397 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_VERIPHY_CNTL_3,
398 fw_size + 1);
399
400 ret = vsc8584_cmd(bus, phy, PROC_CMD_CRC16);
401 if (ret)
402 goto out;
403
404 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
405 MSCC_PHY_PAGE_EXT1);
406
407 *crc = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_VERIPHY_CNTL_2);
408
409out:
410 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
411 MSCC_PHY_PAGE_STD);
412
413 return ret;
414}
415
416static int vsc8584_patch_fw(struct mii_dev *bus, int phy, const u8 *fw_patch,
417 int fw_size)
418{
419 int i, ret;
420
421 ret = vsc8584_micro_assert_reset(bus, phy);
422 if (ret) {
423 pr_err("%s: failed to assert reset of micro\n", __func__);
424 return ret;
425 }
426
427 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
428 MSCC_PHY_PAGE_GPIO);
429
430 /*
431 * Hold 8051 Micro in SW Reset, Enable auto incr address and patch clock
432 * Disable the 8051 Micro clock
433 */
434 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_DW8051_CNTL_STATUS,
435 RUN_FROM_INT_ROM | AUTOINC_ADDR | PATCH_RAM_CLK |
436 MICRO_CLK_EN | MICRO_CLK_DIVIDE(2));
437 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL, READ_PRAM |
438 INT_MEM_WRITE_EN | INT_MEM_DATA(2));
439 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_ADDR, 0x0000);
440
441 for (i = 0; i < fw_size; i++)
442 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL,
443 READ_PRAM | INT_MEM_WRITE_EN | fw_patch[i]);
444
445 /* Clear internal memory access */
446 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL, READ_RAM);
447
448 bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
449 MSCC_PHY_PAGE_STD);
450
451 return 0;
452}
453
Quentin Schulzb5bca652018-10-31 11:20:38 +0100454static int vsc8584_config_pre_init(struct phy_device *phydev)
Quentin Schulz04087fc2018-10-31 11:20:37 +0100455{
Quentin Schulzb5bca652018-10-31 11:20:38 +0100456 struct mii_dev *bus = phydev->bus;
457 u16 reg, crc, phy0, addr;
Quentin Schulz04087fc2018-10-31 11:20:37 +0100458 int ret;
459
Quentin Schulzb5bca652018-10-31 11:20:38 +0100460 if ((phydev->phy_id & MSCC_DEV_REV_MASK) != VSC8584_REVB) {
461 pr_warn("VSC8584 revA not officially supported, skipping firmware patching. Use at your own risk.\n");
462 return 0;
463 }
464
465 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
466 MSCC_PHY_PAGE_EXT1);
467 addr = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_EXT_PHY_CNTL_4);
468 addr >>= PHY_CNTL_4_ADDR_POS;
469
470 reg = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_ACTIPHY_CNTL);
471 if (reg & PHY_ADDR_REVERSED)
472 phy0 = phydev->addr + addr;
473 else
474 phy0 = phydev->addr - addr;
475
Quentin Schulz04087fc2018-10-31 11:20:37 +0100476 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
477 MSCC_PHY_PAGE_STD);
478
479 /* all writes below are broadcasted to all PHYs in the same package */
480 reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS);
481 reg |= SMI_BROADCAST_WR_EN;
482 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS, reg);
483
484 /*
485 * The below register writes are tweaking analog and electrical
486 * configuration that were determined through characterization by PHY
487 * engineers. These don't mean anything more than "these are the best
488 * values".
489 */
490 reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_BYPASS_CONTROL);
491 reg |= PARALLEL_DET_IGNORE_ADVERTISED;
492 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_BYPASS_CONTROL, reg);
493
494 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
495 MSCC_PHY_PAGE_EXT3);
496
497 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_SERDES_TX_CRC_ERR_CNT,
498 0x2000);
499
500 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
501 MSCC_PHY_PAGE_TEST);
502
503 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_5, 0x1f20);
504
505 reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8);
506 reg |= TR_CLK_DISABLE;
507 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8, reg);
508
509 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
510 MSCC_PHY_PAGE_TR);
511
512 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16, 0xafa4);
513
514 reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18);
515 reg &= ~0x007f;
516 reg |= 0x0019;
517 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18, reg);
518
519 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16, 0x8fa4);
520
521 vsc8584_csr_write(bus, phy0, 0x07fa, 0x0050100f);
522 vsc8584_csr_write(bus, phy0, 0x1688, 0x00049f81);
523 vsc8584_csr_write(bus, phy0, 0x0f90, 0x00688980);
524 vsc8584_csr_write(bus, phy0, 0x03a4, 0x0000d8f0);
525 vsc8584_csr_write(bus, phy0, 0x0fc0, 0x00000400);
526 vsc8584_csr_write(bus, phy0, 0x0f82, 0x0012b002);
527 vsc8584_csr_write(bus, phy0, 0x1686, 0x00000004);
528 vsc8584_csr_write(bus, phy0, 0x168c, 0x00d2c46f);
529 vsc8584_csr_write(bus, phy0, 0x17a2, 0x00000620);
530 vsc8584_csr_write(bus, phy0, 0x16a0, 0x00eeffdd);
531 vsc8584_csr_write(bus, phy0, 0x16a6, 0x00071448);
532 vsc8584_csr_write(bus, phy0, 0x16a4, 0x0013132f);
533 vsc8584_csr_write(bus, phy0, 0x16a8, 0x00000000);
534 vsc8584_csr_write(bus, phy0, 0x0ffc, 0x00c0a028);
535 vsc8584_csr_write(bus, phy0, 0x0fe8, 0x0091b06c);
536 vsc8584_csr_write(bus, phy0, 0x0fea, 0x00041600);
537 vsc8584_csr_write(bus, phy0, 0x0f80, 0x00fffaff);
538 vsc8584_csr_write(bus, phy0, 0x0fec, 0x00901809);
539 vsc8584_csr_write(bus, phy0, 0x0ffe, 0x00b01007);
540 vsc8584_csr_write(bus, phy0, 0x16b0, 0x00eeff00);
541 vsc8584_csr_write(bus, phy0, 0x16b2, 0x00007000);
542 vsc8584_csr_write(bus, phy0, 0x16b4, 0x00000814);
543
544 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
545 MSCC_PHY_PAGE_EXT2);
546
547 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_CU_PMD_TX_CNTL, 0x028e);
548
549 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
550 MSCC_PHY_PAGE_TR);
551
552 vsc8584_csr_write(bus, phy0, 0x0486, 0x0008a518);
553 vsc8584_csr_write(bus, phy0, 0x0488, 0x006dc696);
554 vsc8584_csr_write(bus, phy0, 0x048a, 0x00000912);
555
556 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
557 MSCC_PHY_PAGE_TEST);
558
559 reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8);
560 reg &= ~TR_CLK_DISABLE;
561 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8, reg);
562
563 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
564 MSCC_PHY_PAGE_STD);
565
566 /* end of write broadcasting */
567 reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS);
568 reg &= ~SMI_BROADCAST_WR_EN;
569 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS, reg);
570
571 ret = vsc8584_get_fw_crc(bus, phy0,
572 MSCC_VSC8584_REVB_INT8051_FW_START_ADDR, &crc,
573 fw_patch_vsc8584,
574 ARRAY_SIZE(fw_patch_vsc8584));
575 if (ret)
576 goto out;
577
578 if (crc != MSCC_VSC8584_REVB_INT8051_FW_CRC) {
579 debug("FW CRC is not the expected one, patching FW...\n");
580 if (vsc8584_patch_fw(bus, phy0, fw_patch_vsc8584,
581 ARRAY_SIZE(fw_patch_vsc8584)))
582 pr_warn("failed to patch FW, expect non-optimal device\n");
583 }
584
585 vsc8584_micro_deassert_reset(bus, phy0, false);
586
587 ret = vsc8584_get_fw_crc(bus, phy0,
588 MSCC_VSC8584_REVB_INT8051_FW_START_ADDR, &crc,
589 fw_patch_vsc8584,
590 ARRAY_SIZE(fw_patch_vsc8584));
591 if (ret)
592 goto out;
593
594 if (crc != MSCC_VSC8584_REVB_INT8051_FW_CRC)
595 pr_warn("FW CRC after patching is not the expected one, expect non-optimal device\n");
596
597 ret = vsc8584_micro_assert_reset(bus, phy0);
598 if (ret)
599 goto out;
600
601 vsc8584_micro_deassert_reset(bus, phy0, true);
602
603out:
604 bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
605 MSCC_PHY_PAGE_STD);
606
607 return ret;
608}
John Haechtena5fd13a2016-12-09 22:15:17 +0000609
610static int mscc_vsc8531_vsc8541_init_scripts(struct phy_device *phydev)
611{
612 u16 reg_val;
613
614 /* Set to Access Token Ring Registers */
615 phy_write(phydev, MDIO_DEVAD_NONE,
616 MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_TR);
617
618 /* Update LinkDetectCtrl default to optimized values */
619 /* Determined during Silicon Validation Testing */
620 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
621 (MSCC_PHY_TR_LINKDETCTRL_ADDR | MSCC_PHY_TR_16_READ));
622 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17);
623 reg_val = bitfield_replace(reg_val, MSCC_PHY_TR_LINKDETCTRL_POS,
624 MSCC_PHY_TR_LINKDETCTRL_WIDTH,
625 MSCC_PHY_TR_LINKDETCTRL_VAL);
626
627 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17, reg_val);
628 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
629 (MSCC_PHY_TR_LINKDETCTRL_ADDR | MSCC_PHY_TR_16_WRITE));
630
631 /* Update VgaThresh100 defaults to optimized values */
632 /* Determined during Silicon Validation Testing */
633 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
634 (MSCC_PHY_TR_VGATHRESH100_ADDR | MSCC_PHY_TR_16_READ));
635
636 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18);
637 reg_val = bitfield_replace(reg_val, MSCC_PHY_TR_VGATHRESH100_POS,
638 MSCC_PHY_TR_VGATHRESH100_WIDTH,
639 MSCC_PHY_TR_VGATHRESH100_VAL);
640
641 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18, reg_val);
642 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
643 (MSCC_PHY_TR_VGATHRESH100_ADDR | MSCC_PHY_TR_16_WRITE));
644
645 /* Update VgaGain10 defaults to optimized values */
646 /* Determined during Silicon Validation Testing */
647 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
648 (MSCC_PHY_TR_VGAGAIN10_ADDR | MSCC_PHY_TR_16_READ));
649
650 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18);
651 reg_val = bitfield_replace(reg_val, MSCC_PHY_TR_VGAGAIN10_U_POS,
652 MSCC_PHY_TR_VGAGAIN10_U_WIDTH,
653 MSCC_PHY_TR_VGAGAIN10_U_VAL);
654
655 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18, reg_val);
656 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17);
657 reg_val = bitfield_replace(reg_val, MSCC_PHY_TR_VGAGAIN10_L_POS,
658 MSCC_PHY_TR_VGAGAIN10_L_WIDTH,
659 MSCC_PHY_TR_VGAGAIN10_L_VAL);
660
661 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17, reg_val);
662 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
663 (MSCC_PHY_TR_VGAGAIN10_ADDR | MSCC_PHY_TR_16_WRITE));
664
665 /* Set back to Access Standard Page Registers */
666 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
667 MSCC_PHY_PAGE_STD);
668
669 return 0;
670}
671
672static int mscc_parse_status(struct phy_device *phydev)
673{
674 u16 speed;
675 u16 mii_reg;
676
677 mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_AUX_CNTRL_STAT_REG);
678
679 if (mii_reg & MIIM_AUX_CNTRL_STAT_F_DUPLEX)
680 phydev->duplex = DUPLEX_FULL;
681 else
682 phydev->duplex = DUPLEX_HALF;
683
684 speed = mii_reg & MIIM_AUX_CNTRL_STAT_SPEED_MASK;
685 speed = speed >> MIIM_AUX_CNTRL_STAT_SPEED_POS;
686
687 switch (speed) {
688 case MIIM_AUX_CNTRL_STAT_SPEED_1000M:
689 phydev->speed = SPEED_1000;
690 break;
691 case MIIM_AUX_CNTRL_STAT_SPEED_100M:
692 phydev->speed = SPEED_100;
693 break;
694 case MIIM_AUX_CNTRL_STAT_SPEED_10M:
695 phydev->speed = SPEED_10;
696 break;
697 default:
698 phydev->speed = SPEED_10;
699 break;
700 }
701
702 return 0;
703}
704
705static int mscc_startup(struct phy_device *phydev)
706{
707 int retval;
708
709 retval = genphy_update_link(phydev);
710
711 if (retval)
712 return retval;
713
714 return mscc_parse_status(phydev);
715}
716
717static int mscc_phy_soft_reset(struct phy_device *phydev)
718{
719 int retval = 0;
720 u16 timeout = MSCC_PHY_RESET_TIMEOUT;
721 u16 reg_val = 0;
722
723 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
724 MSCC_PHY_PAGE_STD);
725
726 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
727 phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, (reg_val | BMCR_RESET));
728
729 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
730
731 while ((reg_val & BMCR_RESET) && (timeout > 0)) {
732 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
733 timeout--;
734 udelay(1000); /* 1 ms */
735 }
736
737 if (timeout == 0) {
738 printf("MSCC PHY Soft_Reset Error: mac i/f = 0x%x\n",
739 phydev->interface);
740 retval = -ETIME;
741 }
742
743 return retval;
744}
745
746static int vsc8531_vsc8541_mac_config(struct phy_device *phydev)
747{
748 u16 reg_val = 0;
749 u16 mac_if = 0;
750 u16 rx_clk_out = 0;
751
752 /* For VSC8530/31 the only MAC modes are RMII/RGMII. */
753 /* For VSC8540/41 the only MAC modes are (G)MII and RMII/RGMII. */
754 /* Setup MAC Configuration */
755 switch (phydev->interface) {
756 case PHY_INTERFACE_MODE_MII:
757 case PHY_INTERFACE_MODE_GMII:
758 /* Set Reg23.12:11=0 */
759 mac_if = MAC_IF_SELECTION_GMII;
760 /* Set Reg20E2.11=1 */
761 rx_clk_out = RX_CLK_OUT_DISABLE;
762 break;
763
764 case PHY_INTERFACE_MODE_RMII:
765 /* Set Reg23.12:11=1 */
766 mac_if = MAC_IF_SELECTION_RMII;
767 /* Set Reg20E2.11=0 */
768 rx_clk_out = RX_CLK_OUT_NORMAL;
769 break;
770
771 case PHY_INTERFACE_MODE_RGMII:
772 /* Set Reg23.12:11=2 */
773 mac_if = MAC_IF_SELECTION_RGMII;
774 /* Set Reg20E2.11=0 */
775 rx_clk_out = RX_CLK_OUT_NORMAL;
776 break;
777
778 default:
779 printf("MSCC PHY - INVALID MAC i/f Config: mac i/f = 0x%x\n",
780 phydev->interface);
781 return -EINVAL;
782 }
783
784 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
785 MSCC_PHY_PAGE_STD);
786
787 reg_val = phy_read(phydev, MDIO_DEVAD_NONE,
788 MSCC_PHY_EXT_PHY_CNTL_1_REG);
789 /* Set MAC i/f bits Reg23.12:11 */
790 reg_val = bitfield_replace(reg_val, MAC_IF_SELECTION_POS,
791 MAC_IF_SELECTION_WIDTH, mac_if);
792 /* Update Reg23.12:11 */
793 phy_write(phydev, MDIO_DEVAD_NONE,
794 MSCC_PHY_EXT_PHY_CNTL_1_REG, reg_val);
795 /* Setup ExtPg_2 Register Access */
796 phy_write(phydev, MDIO_DEVAD_NONE,
797 MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_EXT2);
798 /* Read Reg20E2 */
799 reg_val = phy_read(phydev, MDIO_DEVAD_NONE,
800 MSCC_PHY_RGMII_CNTL_REG);
801 reg_val = bitfield_replace(reg_val, RX_CLK_OUT_POS,
802 RX_CLK_OUT_WIDTH, rx_clk_out);
803 /* Update Reg20E2.11 */
804 phy_write(phydev, MDIO_DEVAD_NONE,
805 MSCC_PHY_RGMII_CNTL_REG, reg_val);
806 /* Before leaving - Change back to Std Page Register Access */
807 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
808 MSCC_PHY_PAGE_STD);
809
810 return 0;
811}
812
813static int vsc8531_config(struct phy_device *phydev)
814{
815 int retval = -EINVAL;
816 u16 reg_val;
817 u16 rmii_clk_out;
818 enum vsc_phy_rgmii_skew rx_clk_skew = VSC_PHY_RGMII_DELAY_1700_PS;
819 enum vsc_phy_rgmii_skew tx_clk_skew = VSC_PHY_RGMII_DELAY_800_PS;
820 enum vsc_phy_clk_slew edge_rate = VSC_PHY_CLK_SLEW_RATE_4;
821
822 /* For VSC8530/31 and VSC8540/41 the init scripts are the same */
823 mscc_vsc8531_vsc8541_init_scripts(phydev);
824
825 /* For VSC8530/31 the only MAC modes are RMII/RGMII. */
826 switch (phydev->interface) {
827 case PHY_INTERFACE_MODE_RMII:
828 case PHY_INTERFACE_MODE_RGMII:
829 retval = vsc8531_vsc8541_mac_config(phydev);
830 if (retval != 0)
831 return retval;
832
833 retval = mscc_phy_soft_reset(phydev);
834 if (retval != 0)
835 return retval;
836 break;
837 default:
838 printf("PHY 8530/31 MAC i/f Config Error: mac i/f = 0x%x\n",
839 phydev->interface);
840 return -EINVAL;
841 }
842 /* Default RMII Clk Output to 0=OFF/1=ON */
843 rmii_clk_out = 0;
844
845 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
846 MSCC_PHY_PAGE_EXT2);
847 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG);
848
849 /* Reg20E2 - Update RGMII RX_Clk Skews. */
850 reg_val = bitfield_replace(reg_val, RGMII_RX_CLK_DELAY_POS,
851 RGMII_RX_CLK_DELAY_WIDTH, rx_clk_skew);
852 /* Reg20E2 - Update RGMII TX_Clk Skews. */
853 reg_val = bitfield_replace(reg_val, RGMII_TX_CLK_DELAY_POS,
854 RGMII_TX_CLK_DELAY_WIDTH, tx_clk_skew);
855
856 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG, reg_val);
857
858 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL);
859 /* Reg27E2 - Update Clk Slew Rate. */
860 reg_val = bitfield_replace(reg_val, EDGE_RATE_CNTL_POS,
861 EDGE_RATE_CNTL_WIDTH, edge_rate);
862 /* Reg27E2 - Update RMII Clk Out. */
863 reg_val = bitfield_replace(reg_val, RMII_CLK_OUT_ENABLE_POS,
864 RMII_CLK_OUT_ENABLE_WIDTH, rmii_clk_out);
865 /* Update Reg27E2 */
866 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL, reg_val);
867 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
868 MSCC_PHY_PAGE_STD);
869
870 return genphy_config_aneg(phydev);
871}
872
873static int vsc8541_config(struct phy_device *phydev)
874{
875 int retval = -EINVAL;
876 u16 reg_val;
877 u16 rmii_clk_out;
878 enum vsc_phy_rgmii_skew rx_clk_skew = VSC_PHY_RGMII_DELAY_1700_PS;
879 enum vsc_phy_rgmii_skew tx_clk_skew = VSC_PHY_RGMII_DELAY_800_PS;
880 enum vsc_phy_clk_slew edge_rate = VSC_PHY_CLK_SLEW_RATE_4;
881
882 /* For VSC8530/31 and VSC8540/41 the init scripts are the same */
883 mscc_vsc8531_vsc8541_init_scripts(phydev);
884
885 /* For VSC8540/41 the only MAC modes are (G)MII and RMII/RGMII. */
886 switch (phydev->interface) {
887 case PHY_INTERFACE_MODE_MII:
888 case PHY_INTERFACE_MODE_GMII:
889 case PHY_INTERFACE_MODE_RMII:
890 case PHY_INTERFACE_MODE_RGMII:
891 retval = vsc8531_vsc8541_mac_config(phydev);
892 if (retval != 0)
893 return retval;
894
895 retval = mscc_phy_soft_reset(phydev);
896 if (retval != 0)
897 return retval;
898 break;
899 default:
900 printf("PHY 8541 MAC i/f config Error: mac i/f = 0x%x\n",
901 phydev->interface);
902 return -EINVAL;
903 }
904 /* Default RMII Clk Output to 0=OFF/1=ON */
905 rmii_clk_out = 0;
906
907 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
908 MSCC_PHY_PAGE_EXT2);
909 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG);
910 /* Reg20E2 - Update RGMII RX_Clk Skews. */
911 reg_val = bitfield_replace(reg_val, RGMII_RX_CLK_DELAY_POS,
912 RGMII_RX_CLK_DELAY_WIDTH, rx_clk_skew);
913 /* Reg20E2 - Update RGMII TX_Clk Skews. */
914 reg_val = bitfield_replace(reg_val, RGMII_TX_CLK_DELAY_POS,
915 RGMII_TX_CLK_DELAY_WIDTH, tx_clk_skew);
916 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG, reg_val);
917
918 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL);
919 /* Reg27E2 - Update Clk Slew Rate. */
920 reg_val = bitfield_replace(reg_val, EDGE_RATE_CNTL_POS,
921 EDGE_RATE_CNTL_WIDTH, edge_rate);
922 /* Reg27E2 - Update RMII Clk Out. */
923 reg_val = bitfield_replace(reg_val, RMII_CLK_OUT_ENABLE_POS,
924 RMII_CLK_OUT_ENABLE_WIDTH, rmii_clk_out);
925 /* Update Reg27E2 */
926 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL, reg_val);
927 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
928 MSCC_PHY_PAGE_STD);
929
930 return genphy_config_aneg(phydev);
931}
932
Quentin Schulzb5bca652018-10-31 11:20:38 +0100933static int vsc8584_config_init(struct phy_device *phydev)
Quentin Schulz04087fc2018-10-31 11:20:37 +0100934{
Quentin Schulzb5bca652018-10-31 11:20:38 +0100935 struct vsc85xx_priv *priv = phydev->priv;
Quentin Schulz04087fc2018-10-31 11:20:37 +0100936 int ret;
937 u16 addr;
938 u16 reg_val;
939 u16 val;
Quentin Schulz04087fc2018-10-31 11:20:37 +0100940
941 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
942 MSCC_PHY_PAGE_EXT1);
943 addr = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_EXT_PHY_CNTL_4);
944 addr >>= PHY_CNTL_4_ADDR_POS;
945
Quentin Schulzb5bca652018-10-31 11:20:38 +0100946 ret = priv->config_pre(phydev);
947 if (ret)
948 return ret;
Quentin Schulz04087fc2018-10-31 11:20:37 +0100949
950 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
951 MSCC_PHY_PAGE_GPIO);
952
953 if (phydev->interface == PHY_INTERFACE_MODE_QSGMII)
954 val = MAC_CFG_QSGMII;
955 else
956 val = MAC_CFG_SGMII;
957
958 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_MAC_CFG_FASTLINK);
959 reg_val &= ~MAC_CFG_MASK;
960 reg_val |= val;
961 ret = phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_MAC_CFG_FASTLINK,
962 reg_val);
963 if (ret)
964 return ret;
965
966 reg_val = PROC_CMD_MCB_ACCESS_MAC_CONF | PROC_CMD_RST_CONF_PORT |
967 PROC_CMD_READ_MOD_WRITE_PORT;
968 if (phydev->interface == PHY_INTERFACE_MODE_QSGMII)
969 reg_val |= PROC_CMD_QSGMII_MAC;
970 else
971 reg_val |= PROC_CMD_SGMII_MAC;
972
973 ret = vsc8584_cmd(phydev->bus, phydev->addr, reg_val);
974 if (ret)
975 return ret;
976
977 mdelay(10);
978
979 /* Disable SerDes for 100Base-FX */
980 ret = vsc8584_cmd(phydev->bus, phydev->addr, PROC_CMD_FIBER_MEDIA_CONF |
981 PROC_CMD_FIBER_PORT(addr) | PROC_CMD_FIBER_DISABLE |
982 PROC_CMD_READ_MOD_WRITE_PORT |
983 PROC_CMD_RST_CONF_PORT | PROC_CMD_FIBER_100BASE_FX);
984 if (ret)
985 return ret;
986
987 /* Disable SerDes for 1000Base-X */
988 ret = vsc8584_cmd(phydev->bus, phydev->addr, PROC_CMD_FIBER_MEDIA_CONF |
989 PROC_CMD_FIBER_PORT(addr) | PROC_CMD_FIBER_DISABLE |
990 PROC_CMD_READ_MOD_WRITE_PORT |
991 PROC_CMD_RST_CONF_PORT | PROC_CMD_FIBER_1000BASE_X);
992 if (ret)
993 return ret;
994
995 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
996 MSCC_PHY_PAGE_STD);
997 reg_val = phy_read(phydev, MDIO_DEVAD_NONE,
998 MSCC_PHY_EXT_PHY_CNTL_1_REG);
999 reg_val &= ~(MEDIA_OP_MODE_MASK | VSC8584_MAC_IF_SELECTION_MASK);
1000 reg_val |= MEDIA_OP_MODE_COPPER |
1001 (VSC8584_MAC_IF_SELECTION_SGMII <<
1002 VSC8584_MAC_IF_SELECTION_POS);
1003 ret = phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_EXT_PHY_CNTL_1_REG,
1004 reg_val);
1005
1006 ret = mscc_phy_soft_reset(phydev);
1007 if (ret != 0)
1008 return ret;
1009
1010 return genphy_config(phydev);
1011}
1012
Quentin Schulzb5bca652018-10-31 11:20:38 +01001013static struct vsc85xx_priv vsc8584_priv = {
1014 .config_pre = vsc8584_config_pre_init,
1015};
1016
1017static int vsc8584_config(struct phy_device *phydev)
1018{
1019 phydev->priv = &vsc8584_priv;
1020
1021 return vsc8584_config_init(phydev);
1022}
1023
John Haechtena5fd13a2016-12-09 22:15:17 +00001024static struct phy_driver VSC8530_driver = {
1025 .name = "Microsemi VSC8530",
1026 .uid = PHY_ID_VSC8530,
1027 .mask = 0x000ffff0,
1028 .features = PHY_BASIC_FEATURES,
1029 .config = &vsc8531_config,
1030 .startup = &mscc_startup,
1031 .shutdown = &genphy_shutdown,
1032};
1033
1034static struct phy_driver VSC8531_driver = {
1035 .name = "Microsemi VSC8531",
1036 .uid = PHY_ID_VSC8531,
1037 .mask = 0x000ffff0,
1038 .features = PHY_GBIT_FEATURES,
1039 .config = &vsc8531_config,
1040 .startup = &mscc_startup,
1041 .shutdown = &genphy_shutdown,
1042};
1043
1044static struct phy_driver VSC8540_driver = {
1045 .name = "Microsemi VSC8540",
1046 .uid = PHY_ID_VSC8540,
1047 .mask = 0x000ffff0,
1048 .features = PHY_BASIC_FEATURES,
1049 .config = &vsc8541_config,
1050 .startup = &mscc_startup,
1051 .shutdown = &genphy_shutdown,
1052};
1053
1054static struct phy_driver VSC8541_driver = {
1055 .name = "Microsemi VSC8541",
1056 .uid = PHY_ID_VSC8541,
1057 .mask = 0x000ffff0,
1058 .features = PHY_GBIT_FEATURES,
1059 .config = &vsc8541_config,
1060 .startup = &mscc_startup,
1061 .shutdown = &genphy_shutdown,
1062};
1063
Quentin Schulz04087fc2018-10-31 11:20:37 +01001064static struct phy_driver VSC8584_driver = {
1065 .name = "Microsemi VSC8584",
1066 .uid = PHY_ID_VSC8584,
1067 .mask = 0x000ffff0,
1068 .features = PHY_GBIT_FEATURES,
1069 .config = &vsc8584_config,
1070 .startup = &mscc_startup,
1071 .shutdown = &genphy_shutdown,
1072};
1073
John Haechtena5fd13a2016-12-09 22:15:17 +00001074int phy_mscc_init(void)
1075{
1076 phy_register(&VSC8530_driver);
1077 phy_register(&VSC8531_driver);
1078 phy_register(&VSC8540_driver);
1079 phy_register(&VSC8541_driver);
Quentin Schulz04087fc2018-10-31 11:20:37 +01001080 phy_register(&VSC8584_driver);
John Haechtena5fd13a2016-12-09 22:15:17 +00001081
1082 return 0;
1083}