treewide: remove redundant IS_ERR() before error code check
[linux/fpc-iii.git] / drivers / net / phy / mscc.c
blob937ac7da278944c3d9c39cd5b16a879ea116b2b6
1 // SPDX-License-Identifier: (GPL-2.0 OR MIT)
2 /*
3 * Driver for Microsemi VSC85xx PHYs
5 * Author: Nagaraju Lakkaraju
6 * License: Dual MIT/GPL
7 * Copyright (c) 2016 Microsemi Corporation
8 */
10 #include <linux/firmware.h>
11 #include <linux/jiffies.h>
12 #include <linux/kernel.h>
13 #include <linux/module.h>
14 #include <linux/mdio.h>
15 #include <linux/mii.h>
16 #include <linux/phy.h>
17 #include <linux/of.h>
18 #include <linux/netdevice.h>
19 #include <dt-bindings/net/mscc-phy-vsc8531.h>
21 #include <linux/scatterlist.h>
22 #include <crypto/skcipher.h>
24 #if IS_ENABLED(CONFIG_MACSEC)
25 #include <net/macsec.h>
26 #endif
28 #include "mscc_macsec.h"
29 #include "mscc_mac.h"
30 #include "mscc_fc_buffer.h"
32 enum rgmii_rx_clock_delay {
33 RGMII_RX_CLK_DELAY_0_2_NS = 0,
34 RGMII_RX_CLK_DELAY_0_8_NS = 1,
35 RGMII_RX_CLK_DELAY_1_1_NS = 2,
36 RGMII_RX_CLK_DELAY_1_7_NS = 3,
37 RGMII_RX_CLK_DELAY_2_0_NS = 4,
38 RGMII_RX_CLK_DELAY_2_3_NS = 5,
39 RGMII_RX_CLK_DELAY_2_6_NS = 6,
40 RGMII_RX_CLK_DELAY_3_4_NS = 7
43 /* Microsemi VSC85xx PHY registers */
44 /* IEEE 802. Std Registers */
45 #define MSCC_PHY_BYPASS_CONTROL 18
46 #define DISABLE_HP_AUTO_MDIX_MASK 0x0080
47 #define DISABLE_PAIR_SWAP_CORR_MASK 0x0020
48 #define DISABLE_POLARITY_CORR_MASK 0x0010
49 #define PARALLEL_DET_IGNORE_ADVERTISED 0x0008
51 #define MSCC_PHY_EXT_CNTL_STATUS 22
52 #define SMI_BROADCAST_WR_EN 0x0001
54 #define MSCC_PHY_ERR_RX_CNT 19
55 #define MSCC_PHY_ERR_FALSE_CARRIER_CNT 20
56 #define MSCC_PHY_ERR_LINK_DISCONNECT_CNT 21
57 #define ERR_CNT_MASK GENMASK(7, 0)
59 #define MSCC_PHY_EXT_PHY_CNTL_1 23
60 #define MAC_IF_SELECTION_MASK 0x1800
61 #define MAC_IF_SELECTION_GMII 0
62 #define MAC_IF_SELECTION_RMII 1
63 #define MAC_IF_SELECTION_RGMII 2
64 #define MAC_IF_SELECTION_POS 11
65 #define VSC8584_MAC_IF_SELECTION_MASK 0x1000
66 #define VSC8584_MAC_IF_SELECTION_SGMII 0
67 #define VSC8584_MAC_IF_SELECTION_1000BASEX 1
68 #define VSC8584_MAC_IF_SELECTION_POS 12
69 #define FAR_END_LOOPBACK_MODE_MASK 0x0008
70 #define MEDIA_OP_MODE_MASK 0x0700
71 #define MEDIA_OP_MODE_COPPER 0
72 #define MEDIA_OP_MODE_SERDES 1
73 #define MEDIA_OP_MODE_1000BASEX 2
74 #define MEDIA_OP_MODE_100BASEFX 3
75 #define MEDIA_OP_MODE_AMS_COPPER_SERDES 5
76 #define MEDIA_OP_MODE_AMS_COPPER_1000BASEX 6
77 #define MEDIA_OP_MODE_AMS_COPPER_100BASEFX 7
78 #define MEDIA_OP_MODE_POS 8
80 #define MSCC_PHY_EXT_PHY_CNTL_2 24
82 #define MII_VSC85XX_INT_MASK 25
83 #define MII_VSC85XX_INT_MASK_MASK 0xa020
84 #define MII_VSC85XX_INT_MASK_WOL 0x0040
85 #define MII_VSC85XX_INT_STATUS 26
87 #define MSCC_PHY_WOL_MAC_CONTROL 27
88 #define EDGE_RATE_CNTL_POS 5
89 #define EDGE_RATE_CNTL_MASK 0x00E0
91 #define MSCC_PHY_DEV_AUX_CNTL 28
92 #define HP_AUTO_MDIX_X_OVER_IND_MASK 0x2000
94 #define MSCC_PHY_LED_MODE_SEL 29
95 #define LED_MODE_SEL_POS(x) ((x) * 4)
96 #define LED_MODE_SEL_MASK(x) (GENMASK(3, 0) << LED_MODE_SEL_POS(x))
97 #define LED_MODE_SEL(x, mode) (((mode) << LED_MODE_SEL_POS(x)) & LED_MODE_SEL_MASK(x))
99 #define MSCC_EXT_PAGE_CSR_CNTL_17 17
100 #define MSCC_EXT_PAGE_CSR_CNTL_18 18
102 #define MSCC_EXT_PAGE_CSR_CNTL_19 19
103 #define MSCC_PHY_CSR_CNTL_19_REG_ADDR(x) (x)
104 #define MSCC_PHY_CSR_CNTL_19_TARGET(x) ((x) << 12)
105 #define MSCC_PHY_CSR_CNTL_19_READ BIT(14)
106 #define MSCC_PHY_CSR_CNTL_19_CMD BIT(15)
108 #define MSCC_EXT_PAGE_CSR_CNTL_20 20
109 #define MSCC_PHY_CSR_CNTL_20_TARGET(x) (x)
111 #define PHY_MCB_TARGET 0x07
112 #define PHY_MCB_S6G_WRITE BIT(31)
113 #define PHY_MCB_S6G_READ BIT(30)
115 #define PHY_S6G_PLL5G_CFG0 0x06
116 #define PHY_S6G_LCPLL_CFG 0x11
117 #define PHY_S6G_PLL_CFG 0x2b
118 #define PHY_S6G_COMMON_CFG 0x2c
119 #define PHY_S6G_GPC_CFG 0x2e
120 #define PHY_S6G_MISC_CFG 0x3b
121 #define PHY_MCB_S6G_CFG 0x3f
122 #define PHY_S6G_DFT_CFG2 0x3e
123 #define PHY_S6G_PLL_STATUS 0x31
124 #define PHY_S6G_IB_STATUS0 0x2f
126 #define PHY_S6G_SYS_RST_POS 31
127 #define PHY_S6G_ENA_LANE_POS 18
128 #define PHY_S6G_ENA_LOOP_POS 8
129 #define PHY_S6G_QRATE_POS 6
130 #define PHY_S6G_IF_MODE_POS 4
131 #define PHY_S6G_PLL_ENA_OFFS_POS 21
132 #define PHY_S6G_PLL_FSM_CTRL_DATA_POS 8
133 #define PHY_S6G_PLL_FSM_ENA_POS 7
135 #define MSCC_EXT_PAGE_MACSEC_17 17
136 #define MSCC_EXT_PAGE_MACSEC_18 18
138 #define MSCC_EXT_PAGE_MACSEC_19 19
139 #define MSCC_PHY_MACSEC_19_REG_ADDR(x) (x)
140 #define MSCC_PHY_MACSEC_19_TARGET(x) ((x) << 12)
141 #define MSCC_PHY_MACSEC_19_READ BIT(14)
142 #define MSCC_PHY_MACSEC_19_CMD BIT(15)
144 #define MSCC_EXT_PAGE_MACSEC_20 20
145 #define MSCC_PHY_MACSEC_20_TARGET(x) (x)
146 enum macsec_bank {
147 FC_BUFFER = 0x04,
148 HOST_MAC = 0x05,
149 LINE_MAC = 0x06,
150 IP_1588 = 0x0e,
151 MACSEC_INGR = 0x38,
152 MACSEC_EGR = 0x3c,
155 #define MSCC_EXT_PAGE_ACCESS 31
156 #define MSCC_PHY_PAGE_STANDARD 0x0000 /* Standard registers */
157 #define MSCC_PHY_PAGE_EXTENDED 0x0001 /* Extended registers */
158 #define MSCC_PHY_PAGE_EXTENDED_2 0x0002 /* Extended reg - page 2 */
159 #define MSCC_PHY_PAGE_EXTENDED_3 0x0003 /* Extended reg - page 3 */
160 #define MSCC_PHY_PAGE_EXTENDED_4 0x0004 /* Extended reg - page 4 */
161 #define MSCC_PHY_PAGE_CSR_CNTL MSCC_PHY_PAGE_EXTENDED_4
162 #define MSCC_PHY_PAGE_MACSEC MSCC_PHY_PAGE_EXTENDED_4
163 /* Extended reg - GPIO; this is a bank of registers that are shared for all PHYs
164 * in the same package.
166 #define MSCC_PHY_PAGE_EXTENDED_GPIO 0x0010 /* Extended reg - GPIO */
167 #define MSCC_PHY_PAGE_TEST 0x2a30 /* Test reg */
168 #define MSCC_PHY_PAGE_TR 0x52b5 /* Token ring registers */
170 /* Extended Page 1 Registers */
171 #define MSCC_PHY_CU_MEDIA_CRC_VALID_CNT 18
172 #define VALID_CRC_CNT_CRC_MASK GENMASK(13, 0)
174 #define MSCC_PHY_EXT_MODE_CNTL 19
175 #define FORCE_MDI_CROSSOVER_MASK 0x000C
176 #define FORCE_MDI_CROSSOVER_MDIX 0x000C
177 #define FORCE_MDI_CROSSOVER_MDI 0x0008
179 #define MSCC_PHY_ACTIPHY_CNTL 20
180 #define PHY_ADDR_REVERSED 0x0200
181 #define DOWNSHIFT_CNTL_MASK 0x001C
182 #define DOWNSHIFT_EN 0x0010
183 #define DOWNSHIFT_CNTL_POS 2
185 #define MSCC_PHY_EXT_PHY_CNTL_4 23
186 #define PHY_CNTL_4_ADDR_POS 11
188 #define MSCC_PHY_VERIPHY_CNTL_2 25
190 #define MSCC_PHY_VERIPHY_CNTL_3 26
192 /* Extended Page 2 Registers */
193 #define MSCC_PHY_CU_PMD_TX_CNTL 16
195 #define MSCC_PHY_RGMII_CNTL 20
196 #define RGMII_RX_CLK_DELAY_MASK 0x0070
197 #define RGMII_RX_CLK_DELAY_POS 4
199 #define MSCC_PHY_WOL_LOWER_MAC_ADDR 21
200 #define MSCC_PHY_WOL_MID_MAC_ADDR 22
201 #define MSCC_PHY_WOL_UPPER_MAC_ADDR 23
202 #define MSCC_PHY_WOL_LOWER_PASSWD 24
203 #define MSCC_PHY_WOL_MID_PASSWD 25
204 #define MSCC_PHY_WOL_UPPER_PASSWD 26
206 #define MSCC_PHY_WOL_MAC_CONTROL 27
207 #define SECURE_ON_ENABLE 0x8000
208 #define SECURE_ON_PASSWD_LEN_4 0x4000
210 #define MSCC_PHY_EXTENDED_INT 28
211 #define MSCC_PHY_EXTENDED_INT_MS_EGR BIT(9)
213 /* Extended Page 3 Registers */
214 #define MSCC_PHY_SERDES_TX_VALID_CNT 21
215 #define MSCC_PHY_SERDES_TX_CRC_ERR_CNT 22
216 #define MSCC_PHY_SERDES_RX_VALID_CNT 28
217 #define MSCC_PHY_SERDES_RX_CRC_ERR_CNT 29
219 /* Extended page GPIO Registers */
220 #define MSCC_DW8051_CNTL_STATUS 0
221 #define MICRO_NSOFT_RESET 0x8000
222 #define RUN_FROM_INT_ROM 0x4000
223 #define AUTOINC_ADDR 0x2000
224 #define PATCH_RAM_CLK 0x1000
225 #define MICRO_PATCH_EN 0x0080
226 #define DW8051_CLK_EN 0x0010
227 #define MICRO_CLK_EN 0x0008
228 #define MICRO_CLK_DIVIDE(x) ((x) >> 1)
229 #define MSCC_DW8051_VLD_MASK 0xf1ff
231 /* x Address in range 1-4 */
232 #define MSCC_TRAP_ROM_ADDR(x) ((x) * 2 + 1)
233 #define MSCC_PATCH_RAM_ADDR(x) (((x) + 1) * 2)
234 #define MSCC_INT_MEM_ADDR 11
236 #define MSCC_INT_MEM_CNTL 12
237 #define READ_SFR 0x6000
238 #define READ_PRAM 0x4000
239 #define READ_ROM 0x2000
240 #define READ_RAM 0x0000
241 #define INT_MEM_WRITE_EN 0x1000
242 #define EN_PATCH_RAM_TRAP_ADDR(x) (0x0100 << ((x) - 1))
243 #define INT_MEM_DATA_M 0x00ff
244 #define INT_MEM_DATA(x) (INT_MEM_DATA_M & (x))
246 #define MSCC_PHY_PROC_CMD 18
247 #define PROC_CMD_NCOMPLETED 0x8000
248 #define PROC_CMD_FAILED 0x4000
249 #define PROC_CMD_SGMII_PORT(x) ((x) << 8)
250 #define PROC_CMD_FIBER_PORT(x) (0x0100 << (x) % 4)
251 #define PROC_CMD_QSGMII_PORT 0x0c00
252 #define PROC_CMD_RST_CONF_PORT 0x0080
253 #define PROC_CMD_RECONF_PORT 0x0000
254 #define PROC_CMD_READ_MOD_WRITE_PORT 0x0040
255 #define PROC_CMD_WRITE 0x0040
256 #define PROC_CMD_READ 0x0000
257 #define PROC_CMD_FIBER_DISABLE 0x0020
258 #define PROC_CMD_FIBER_100BASE_FX 0x0010
259 #define PROC_CMD_FIBER_1000BASE_X 0x0000
260 #define PROC_CMD_SGMII_MAC 0x0030
261 #define PROC_CMD_QSGMII_MAC 0x0020
262 #define PROC_CMD_NO_MAC_CONF 0x0000
263 #define PROC_CMD_1588_DEFAULT_INIT 0x0010
264 #define PROC_CMD_NOP 0x000f
265 #define PROC_CMD_PHY_INIT 0x000a
266 #define PROC_CMD_CRC16 0x0008
267 #define PROC_CMD_FIBER_MEDIA_CONF 0x0001
268 #define PROC_CMD_MCB_ACCESS_MAC_CONF 0x0000
269 #define PROC_CMD_NCOMPLETED_TIMEOUT_MS 500
271 #define MSCC_PHY_MAC_CFG_FASTLINK 19
272 #define MAC_CFG_MASK 0xc000
273 #define MAC_CFG_SGMII 0x0000
274 #define MAC_CFG_QSGMII 0x4000
276 /* Test page Registers */
277 #define MSCC_PHY_TEST_PAGE_5 5
278 #define MSCC_PHY_TEST_PAGE_8 8
279 #define MSCC_PHY_TEST_PAGE_9 9
280 #define MSCC_PHY_TEST_PAGE_20 20
281 #define MSCC_PHY_TEST_PAGE_24 24
283 /* Token ring page Registers */
284 #define MSCC_PHY_TR_CNTL 16
285 #define TR_WRITE 0x8000
286 #define TR_ADDR(x) (0x7fff & (x))
287 #define MSCC_PHY_TR_LSB 17
288 #define MSCC_PHY_TR_MSB 18
290 /* Microsemi PHY ID's
291 * Code assumes lowest nibble is 0
293 #define PHY_ID_VSC8504 0x000704c0
294 #define PHY_ID_VSC8514 0x00070670
295 #define PHY_ID_VSC8530 0x00070560
296 #define PHY_ID_VSC8531 0x00070570
297 #define PHY_ID_VSC8540 0x00070760
298 #define PHY_ID_VSC8541 0x00070770
299 #define PHY_ID_VSC8552 0x000704e0
300 #define PHY_ID_VSC856X 0x000707e0
301 #define PHY_ID_VSC8572 0x000704d0
302 #define PHY_ID_VSC8574 0x000704a0
303 #define PHY_ID_VSC8575 0x000707d0
304 #define PHY_ID_VSC8582 0x000707b0
305 #define PHY_ID_VSC8584 0x000707c0
307 #define MSCC_VDDMAC_1500 1500
308 #define MSCC_VDDMAC_1800 1800
309 #define MSCC_VDDMAC_2500 2500
310 #define MSCC_VDDMAC_3300 3300
312 #define DOWNSHIFT_COUNT_MAX 5
314 #define MAX_LEDS 4
316 #define VSC8584_SUPP_LED_MODES (BIT(VSC8531_LINK_ACTIVITY) | \
317 BIT(VSC8531_LINK_1000_ACTIVITY) | \
318 BIT(VSC8531_LINK_100_ACTIVITY) | \
319 BIT(VSC8531_LINK_10_ACTIVITY) | \
320 BIT(VSC8531_LINK_100_1000_ACTIVITY) | \
321 BIT(VSC8531_LINK_10_1000_ACTIVITY) | \
322 BIT(VSC8531_LINK_10_100_ACTIVITY) | \
323 BIT(VSC8584_LINK_100FX_1000X_ACTIVITY) | \
324 BIT(VSC8531_DUPLEX_COLLISION) | \
325 BIT(VSC8531_COLLISION) | \
326 BIT(VSC8531_ACTIVITY) | \
327 BIT(VSC8584_100FX_1000X_ACTIVITY) | \
328 BIT(VSC8531_AUTONEG_FAULT) | \
329 BIT(VSC8531_SERIAL_MODE) | \
330 BIT(VSC8531_FORCE_LED_OFF) | \
331 BIT(VSC8531_FORCE_LED_ON))
333 #define VSC85XX_SUPP_LED_MODES (BIT(VSC8531_LINK_ACTIVITY) | \
334 BIT(VSC8531_LINK_1000_ACTIVITY) | \
335 BIT(VSC8531_LINK_100_ACTIVITY) | \
336 BIT(VSC8531_LINK_10_ACTIVITY) | \
337 BIT(VSC8531_LINK_100_1000_ACTIVITY) | \
338 BIT(VSC8531_LINK_10_1000_ACTIVITY) | \
339 BIT(VSC8531_LINK_10_100_ACTIVITY) | \
340 BIT(VSC8531_DUPLEX_COLLISION) | \
341 BIT(VSC8531_COLLISION) | \
342 BIT(VSC8531_ACTIVITY) | \
343 BIT(VSC8531_AUTONEG_FAULT) | \
344 BIT(VSC8531_SERIAL_MODE) | \
345 BIT(VSC8531_FORCE_LED_OFF) | \
346 BIT(VSC8531_FORCE_LED_ON))
348 #define MSCC_VSC8584_REVB_INT8051_FW "mscc_vsc8584_revb_int8051_fb48.bin"
349 #define MSCC_VSC8584_REVB_INT8051_FW_START_ADDR 0xe800
350 #define MSCC_VSC8584_REVB_INT8051_FW_CRC 0xfb48
352 #define MSCC_VSC8574_REVB_INT8051_FW "mscc_vsc8574_revb_int8051_29e8.bin"
353 #define MSCC_VSC8574_REVB_INT8051_FW_START_ADDR 0x4000
354 #define MSCC_VSC8574_REVB_INT8051_FW_CRC 0x29e8
356 #define VSC8584_REVB 0x0001
357 #define MSCC_DEV_REV_MASK GENMASK(3, 0)
359 struct reg_val {
360 u16 reg;
361 u32 val;
364 struct vsc85xx_hw_stat {
365 const char *string;
366 u8 reg;
367 u16 page;
368 u16 mask;
371 static const struct vsc85xx_hw_stat vsc85xx_hw_stats[] = {
373 .string = "phy_receive_errors",
374 .reg = MSCC_PHY_ERR_RX_CNT,
375 .page = MSCC_PHY_PAGE_STANDARD,
376 .mask = ERR_CNT_MASK,
377 }, {
378 .string = "phy_false_carrier",
379 .reg = MSCC_PHY_ERR_FALSE_CARRIER_CNT,
380 .page = MSCC_PHY_PAGE_STANDARD,
381 .mask = ERR_CNT_MASK,
382 }, {
383 .string = "phy_cu_media_link_disconnect",
384 .reg = MSCC_PHY_ERR_LINK_DISCONNECT_CNT,
385 .page = MSCC_PHY_PAGE_STANDARD,
386 .mask = ERR_CNT_MASK,
387 }, {
388 .string = "phy_cu_media_crc_good_count",
389 .reg = MSCC_PHY_CU_MEDIA_CRC_VALID_CNT,
390 .page = MSCC_PHY_PAGE_EXTENDED,
391 .mask = VALID_CRC_CNT_CRC_MASK,
392 }, {
393 .string = "phy_cu_media_crc_error_count",
394 .reg = MSCC_PHY_EXT_PHY_CNTL_4,
395 .page = MSCC_PHY_PAGE_EXTENDED,
396 .mask = ERR_CNT_MASK,
400 static const struct vsc85xx_hw_stat vsc8584_hw_stats[] = {
402 .string = "phy_receive_errors",
403 .reg = MSCC_PHY_ERR_RX_CNT,
404 .page = MSCC_PHY_PAGE_STANDARD,
405 .mask = ERR_CNT_MASK,
406 }, {
407 .string = "phy_false_carrier",
408 .reg = MSCC_PHY_ERR_FALSE_CARRIER_CNT,
409 .page = MSCC_PHY_PAGE_STANDARD,
410 .mask = ERR_CNT_MASK,
411 }, {
412 .string = "phy_cu_media_link_disconnect",
413 .reg = MSCC_PHY_ERR_LINK_DISCONNECT_CNT,
414 .page = MSCC_PHY_PAGE_STANDARD,
415 .mask = ERR_CNT_MASK,
416 }, {
417 .string = "phy_cu_media_crc_good_count",
418 .reg = MSCC_PHY_CU_MEDIA_CRC_VALID_CNT,
419 .page = MSCC_PHY_PAGE_EXTENDED,
420 .mask = VALID_CRC_CNT_CRC_MASK,
421 }, {
422 .string = "phy_cu_media_crc_error_count",
423 .reg = MSCC_PHY_EXT_PHY_CNTL_4,
424 .page = MSCC_PHY_PAGE_EXTENDED,
425 .mask = ERR_CNT_MASK,
426 }, {
427 .string = "phy_serdes_tx_good_pkt_count",
428 .reg = MSCC_PHY_SERDES_TX_VALID_CNT,
429 .page = MSCC_PHY_PAGE_EXTENDED_3,
430 .mask = VALID_CRC_CNT_CRC_MASK,
431 }, {
432 .string = "phy_serdes_tx_bad_crc_count",
433 .reg = MSCC_PHY_SERDES_TX_CRC_ERR_CNT,
434 .page = MSCC_PHY_PAGE_EXTENDED_3,
435 .mask = ERR_CNT_MASK,
436 }, {
437 .string = "phy_serdes_rx_good_pkt_count",
438 .reg = MSCC_PHY_SERDES_RX_VALID_CNT,
439 .page = MSCC_PHY_PAGE_EXTENDED_3,
440 .mask = VALID_CRC_CNT_CRC_MASK,
441 }, {
442 .string = "phy_serdes_rx_bad_crc_count",
443 .reg = MSCC_PHY_SERDES_RX_CRC_ERR_CNT,
444 .page = MSCC_PHY_PAGE_EXTENDED_3,
445 .mask = ERR_CNT_MASK,
449 #if IS_ENABLED(CONFIG_MACSEC)
450 struct macsec_flow {
451 struct list_head list;
452 enum mscc_macsec_destination_ports port;
453 enum macsec_bank bank;
454 u32 index;
455 int assoc_num;
456 bool has_transformation;
458 /* Highest takes precedence [0..15] */
459 u8 priority;
461 u8 key[MACSEC_KEYID_LEN];
463 union {
464 struct macsec_rx_sa *rx_sa;
465 struct macsec_tx_sa *tx_sa;
468 /* Matching */
469 struct {
470 u8 sci:1;
471 u8 tagged:1;
472 u8 untagged:1;
473 u8 etype:1;
474 } match;
476 u16 etype;
478 /* Action */
479 struct {
480 u8 bypass:1;
481 u8 drop:1;
482 } action;
485 #endif
487 struct vsc8531_private {
488 int rate_magic;
489 u16 supp_led_modes;
490 u32 leds_mode[MAX_LEDS];
491 u8 nleds;
492 const struct vsc85xx_hw_stat *hw_stats;
493 u64 *stats;
494 int nstats;
495 bool pkg_init;
496 /* For multiple port PHYs; the MDIO address of the base PHY in the
497 * package.
499 unsigned int base_addr;
501 #if IS_ENABLED(CONFIG_MACSEC)
502 /* MACsec fields:
503 * - One SecY per device (enforced at the s/w implementation level)
504 * - macsec_flows: list of h/w flows
505 * - ingr_flows: bitmap of ingress flows
506 * - egr_flows: bitmap of egress flows
508 struct macsec_secy *secy;
509 struct list_head macsec_flows;
510 unsigned long ingr_flows;
511 unsigned long egr_flows;
512 #endif
515 #ifdef CONFIG_OF_MDIO
516 struct vsc8531_edge_rate_table {
517 u32 vddmac;
518 u32 slowdown[8];
521 static const struct vsc8531_edge_rate_table edge_table[] = {
522 {MSCC_VDDMAC_3300, { 0, 2, 4, 7, 10, 17, 29, 53} },
523 {MSCC_VDDMAC_2500, { 0, 3, 6, 10, 14, 23, 37, 63} },
524 {MSCC_VDDMAC_1800, { 0, 5, 9, 16, 23, 35, 52, 76} },
525 {MSCC_VDDMAC_1500, { 0, 6, 14, 21, 29, 42, 58, 77} },
527 #endif /* CONFIG_OF_MDIO */
529 static int vsc85xx_phy_read_page(struct phy_device *phydev)
531 return __phy_read(phydev, MSCC_EXT_PAGE_ACCESS);
534 static int vsc85xx_phy_write_page(struct phy_device *phydev, int page)
536 return __phy_write(phydev, MSCC_EXT_PAGE_ACCESS, page);
539 static int vsc85xx_get_sset_count(struct phy_device *phydev)
541 struct vsc8531_private *priv = phydev->priv;
543 if (!priv)
544 return 0;
546 return priv->nstats;
549 static void vsc85xx_get_strings(struct phy_device *phydev, u8 *data)
551 struct vsc8531_private *priv = phydev->priv;
552 int i;
554 if (!priv)
555 return;
557 for (i = 0; i < priv->nstats; i++)
558 strlcpy(data + i * ETH_GSTRING_LEN, priv->hw_stats[i].string,
559 ETH_GSTRING_LEN);
562 static u64 vsc85xx_get_stat(struct phy_device *phydev, int i)
564 struct vsc8531_private *priv = phydev->priv;
565 int val;
567 val = phy_read_paged(phydev, priv->hw_stats[i].page,
568 priv->hw_stats[i].reg);
569 if (val < 0)
570 return U64_MAX;
572 val = val & priv->hw_stats[i].mask;
573 priv->stats[i] += val;
575 return priv->stats[i];
578 static void vsc85xx_get_stats(struct phy_device *phydev,
579 struct ethtool_stats *stats, u64 *data)
581 struct vsc8531_private *priv = phydev->priv;
582 int i;
584 if (!priv)
585 return;
587 for (i = 0; i < priv->nstats; i++)
588 data[i] = vsc85xx_get_stat(phydev, i);
591 static int vsc85xx_led_cntl_set(struct phy_device *phydev,
592 u8 led_num,
593 u8 mode)
595 int rc;
596 u16 reg_val;
598 mutex_lock(&phydev->lock);
599 reg_val = phy_read(phydev, MSCC_PHY_LED_MODE_SEL);
600 reg_val &= ~LED_MODE_SEL_MASK(led_num);
601 reg_val |= LED_MODE_SEL(led_num, (u16)mode);
602 rc = phy_write(phydev, MSCC_PHY_LED_MODE_SEL, reg_val);
603 mutex_unlock(&phydev->lock);
605 return rc;
608 static int vsc85xx_mdix_get(struct phy_device *phydev, u8 *mdix)
610 u16 reg_val;
612 reg_val = phy_read(phydev, MSCC_PHY_DEV_AUX_CNTL);
613 if (reg_val & HP_AUTO_MDIX_X_OVER_IND_MASK)
614 *mdix = ETH_TP_MDI_X;
615 else
616 *mdix = ETH_TP_MDI;
618 return 0;
621 static int vsc85xx_mdix_set(struct phy_device *phydev, u8 mdix)
623 int rc;
624 u16 reg_val;
626 reg_val = phy_read(phydev, MSCC_PHY_BYPASS_CONTROL);
627 if (mdix == ETH_TP_MDI || mdix == ETH_TP_MDI_X) {
628 reg_val |= (DISABLE_PAIR_SWAP_CORR_MASK |
629 DISABLE_POLARITY_CORR_MASK |
630 DISABLE_HP_AUTO_MDIX_MASK);
631 } else {
632 reg_val &= ~(DISABLE_PAIR_SWAP_CORR_MASK |
633 DISABLE_POLARITY_CORR_MASK |
634 DISABLE_HP_AUTO_MDIX_MASK);
636 rc = phy_write(phydev, MSCC_PHY_BYPASS_CONTROL, reg_val);
637 if (rc)
638 return rc;
640 reg_val = 0;
642 if (mdix == ETH_TP_MDI)
643 reg_val = FORCE_MDI_CROSSOVER_MDI;
644 else if (mdix == ETH_TP_MDI_X)
645 reg_val = FORCE_MDI_CROSSOVER_MDIX;
647 rc = phy_modify_paged(phydev, MSCC_PHY_PAGE_EXTENDED,
648 MSCC_PHY_EXT_MODE_CNTL, FORCE_MDI_CROSSOVER_MASK,
649 reg_val);
650 if (rc < 0)
651 return rc;
653 return genphy_restart_aneg(phydev);
656 static int vsc85xx_downshift_get(struct phy_device *phydev, u8 *count)
658 int reg_val;
660 reg_val = phy_read_paged(phydev, MSCC_PHY_PAGE_EXTENDED,
661 MSCC_PHY_ACTIPHY_CNTL);
662 if (reg_val < 0)
663 return reg_val;
665 reg_val &= DOWNSHIFT_CNTL_MASK;
666 if (!(reg_val & DOWNSHIFT_EN))
667 *count = DOWNSHIFT_DEV_DISABLE;
668 else
669 *count = ((reg_val & ~DOWNSHIFT_EN) >> DOWNSHIFT_CNTL_POS) + 2;
671 return 0;
674 static int vsc85xx_downshift_set(struct phy_device *phydev, u8 count)
676 if (count == DOWNSHIFT_DEV_DEFAULT_COUNT) {
677 /* Default downshift count 3 (i.e. Bit3:2 = 0b01) */
678 count = ((1 << DOWNSHIFT_CNTL_POS) | DOWNSHIFT_EN);
679 } else if (count > DOWNSHIFT_COUNT_MAX || count == 1) {
680 phydev_err(phydev, "Downshift count should be 2,3,4 or 5\n");
681 return -ERANGE;
682 } else if (count) {
683 /* Downshift count is either 2,3,4 or 5 */
684 count = (((count - 2) << DOWNSHIFT_CNTL_POS) | DOWNSHIFT_EN);
687 return phy_modify_paged(phydev, MSCC_PHY_PAGE_EXTENDED,
688 MSCC_PHY_ACTIPHY_CNTL, DOWNSHIFT_CNTL_MASK,
689 count);
692 static int vsc85xx_wol_set(struct phy_device *phydev,
693 struct ethtool_wolinfo *wol)
695 int rc;
696 u16 reg_val;
697 u8 i;
698 u16 pwd[3] = {0, 0, 0};
699 struct ethtool_wolinfo *wol_conf = wol;
700 u8 *mac_addr = phydev->attached_dev->dev_addr;
702 mutex_lock(&phydev->lock);
703 rc = phy_select_page(phydev, MSCC_PHY_PAGE_EXTENDED_2);
704 if (rc < 0) {
705 rc = phy_restore_page(phydev, rc, rc);
706 goto out_unlock;
709 if (wol->wolopts & WAKE_MAGIC) {
710 /* Store the device address for the magic packet */
711 for (i = 0; i < ARRAY_SIZE(pwd); i++)
712 pwd[i] = mac_addr[5 - (i * 2 + 1)] << 8 |
713 mac_addr[5 - i * 2];
714 __phy_write(phydev, MSCC_PHY_WOL_LOWER_MAC_ADDR, pwd[0]);
715 __phy_write(phydev, MSCC_PHY_WOL_MID_MAC_ADDR, pwd[1]);
716 __phy_write(phydev, MSCC_PHY_WOL_UPPER_MAC_ADDR, pwd[2]);
717 } else {
718 __phy_write(phydev, MSCC_PHY_WOL_LOWER_MAC_ADDR, 0);
719 __phy_write(phydev, MSCC_PHY_WOL_MID_MAC_ADDR, 0);
720 __phy_write(phydev, MSCC_PHY_WOL_UPPER_MAC_ADDR, 0);
723 if (wol_conf->wolopts & WAKE_MAGICSECURE) {
724 for (i = 0; i < ARRAY_SIZE(pwd); i++)
725 pwd[i] = wol_conf->sopass[5 - (i * 2 + 1)] << 8 |
726 wol_conf->sopass[5 - i * 2];
727 __phy_write(phydev, MSCC_PHY_WOL_LOWER_PASSWD, pwd[0]);
728 __phy_write(phydev, MSCC_PHY_WOL_MID_PASSWD, pwd[1]);
729 __phy_write(phydev, MSCC_PHY_WOL_UPPER_PASSWD, pwd[2]);
730 } else {
731 __phy_write(phydev, MSCC_PHY_WOL_LOWER_PASSWD, 0);
732 __phy_write(phydev, MSCC_PHY_WOL_MID_PASSWD, 0);
733 __phy_write(phydev, MSCC_PHY_WOL_UPPER_PASSWD, 0);
736 reg_val = __phy_read(phydev, MSCC_PHY_WOL_MAC_CONTROL);
737 if (wol_conf->wolopts & WAKE_MAGICSECURE)
738 reg_val |= SECURE_ON_ENABLE;
739 else
740 reg_val &= ~SECURE_ON_ENABLE;
741 __phy_write(phydev, MSCC_PHY_WOL_MAC_CONTROL, reg_val);
743 rc = phy_restore_page(phydev, rc, rc > 0 ? 0 : rc);
744 if (rc < 0)
745 goto out_unlock;
747 if (wol->wolopts & WAKE_MAGIC) {
748 /* Enable the WOL interrupt */
749 reg_val = phy_read(phydev, MII_VSC85XX_INT_MASK);
750 reg_val |= MII_VSC85XX_INT_MASK_WOL;
751 rc = phy_write(phydev, MII_VSC85XX_INT_MASK, reg_val);
752 if (rc)
753 goto out_unlock;
754 } else {
755 /* Disable the WOL interrupt */
756 reg_val = phy_read(phydev, MII_VSC85XX_INT_MASK);
757 reg_val &= (~MII_VSC85XX_INT_MASK_WOL);
758 rc = phy_write(phydev, MII_VSC85XX_INT_MASK, reg_val);
759 if (rc)
760 goto out_unlock;
762 /* Clear WOL iterrupt status */
763 reg_val = phy_read(phydev, MII_VSC85XX_INT_STATUS);
765 out_unlock:
766 mutex_unlock(&phydev->lock);
768 return rc;
771 static void vsc85xx_wol_get(struct phy_device *phydev,
772 struct ethtool_wolinfo *wol)
774 int rc;
775 u16 reg_val;
776 u8 i;
777 u16 pwd[3] = {0, 0, 0};
778 struct ethtool_wolinfo *wol_conf = wol;
780 mutex_lock(&phydev->lock);
781 rc = phy_select_page(phydev, MSCC_PHY_PAGE_EXTENDED_2);
782 if (rc < 0)
783 goto out_unlock;
785 reg_val = __phy_read(phydev, MSCC_PHY_WOL_MAC_CONTROL);
786 if (reg_val & SECURE_ON_ENABLE)
787 wol_conf->wolopts |= WAKE_MAGICSECURE;
788 if (wol_conf->wolopts & WAKE_MAGICSECURE) {
789 pwd[0] = __phy_read(phydev, MSCC_PHY_WOL_LOWER_PASSWD);
790 pwd[1] = __phy_read(phydev, MSCC_PHY_WOL_MID_PASSWD);
791 pwd[2] = __phy_read(phydev, MSCC_PHY_WOL_UPPER_PASSWD);
792 for (i = 0; i < ARRAY_SIZE(pwd); i++) {
793 wol_conf->sopass[5 - i * 2] = pwd[i] & 0x00ff;
794 wol_conf->sopass[5 - (i * 2 + 1)] = (pwd[i] & 0xff00)
795 >> 8;
799 out_unlock:
800 phy_restore_page(phydev, rc, rc > 0 ? 0 : rc);
801 mutex_unlock(&phydev->lock);
804 #ifdef CONFIG_OF_MDIO
805 static int vsc85xx_edge_rate_magic_get(struct phy_device *phydev)
807 u32 vdd, sd;
808 int i, j;
809 struct device *dev = &phydev->mdio.dev;
810 struct device_node *of_node = dev->of_node;
811 u8 sd_array_size = ARRAY_SIZE(edge_table[0].slowdown);
813 if (!of_node)
814 return -ENODEV;
816 if (of_property_read_u32(of_node, "vsc8531,vddmac", &vdd))
817 vdd = MSCC_VDDMAC_3300;
819 if (of_property_read_u32(of_node, "vsc8531,edge-slowdown", &sd))
820 sd = 0;
822 for (i = 0; i < ARRAY_SIZE(edge_table); i++)
823 if (edge_table[i].vddmac == vdd)
824 for (j = 0; j < sd_array_size; j++)
825 if (edge_table[i].slowdown[j] == sd)
826 return (sd_array_size - j - 1);
828 return -EINVAL;
831 static int vsc85xx_dt_led_mode_get(struct phy_device *phydev,
832 char *led,
833 u32 default_mode)
835 struct vsc8531_private *priv = phydev->priv;
836 struct device *dev = &phydev->mdio.dev;
837 struct device_node *of_node = dev->of_node;
838 u32 led_mode;
839 int err;
841 if (!of_node)
842 return -ENODEV;
844 led_mode = default_mode;
845 err = of_property_read_u32(of_node, led, &led_mode);
846 if (!err && !(BIT(led_mode) & priv->supp_led_modes)) {
847 phydev_err(phydev, "DT %s invalid\n", led);
848 return -EINVAL;
851 return led_mode;
854 #else
855 static int vsc85xx_edge_rate_magic_get(struct phy_device *phydev)
857 return 0;
860 static int vsc85xx_dt_led_mode_get(struct phy_device *phydev,
861 char *led,
862 u8 default_mode)
864 return default_mode;
866 #endif /* CONFIG_OF_MDIO */
868 static int vsc85xx_dt_led_modes_get(struct phy_device *phydev,
869 u32 *default_mode)
871 struct vsc8531_private *priv = phydev->priv;
872 char led_dt_prop[28];
873 int i, ret;
875 for (i = 0; i < priv->nleds; i++) {
876 ret = sprintf(led_dt_prop, "vsc8531,led-%d-mode", i);
877 if (ret < 0)
878 return ret;
880 ret = vsc85xx_dt_led_mode_get(phydev, led_dt_prop,
881 default_mode[i]);
882 if (ret < 0)
883 return ret;
884 priv->leds_mode[i] = ret;
887 return 0;
890 static int vsc85xx_edge_rate_cntl_set(struct phy_device *phydev, u8 edge_rate)
892 int rc;
894 mutex_lock(&phydev->lock);
895 rc = phy_modify_paged(phydev, MSCC_PHY_PAGE_EXTENDED_2,
896 MSCC_PHY_WOL_MAC_CONTROL, EDGE_RATE_CNTL_MASK,
897 edge_rate << EDGE_RATE_CNTL_POS);
898 mutex_unlock(&phydev->lock);
900 return rc;
903 static int vsc85xx_mac_if_set(struct phy_device *phydev,
904 phy_interface_t interface)
906 int rc;
907 u16 reg_val;
909 mutex_lock(&phydev->lock);
910 reg_val = phy_read(phydev, MSCC_PHY_EXT_PHY_CNTL_1);
911 reg_val &= ~(MAC_IF_SELECTION_MASK);
912 switch (interface) {
913 case PHY_INTERFACE_MODE_RGMII:
914 reg_val |= (MAC_IF_SELECTION_RGMII << MAC_IF_SELECTION_POS);
915 break;
916 case PHY_INTERFACE_MODE_RMII:
917 reg_val |= (MAC_IF_SELECTION_RMII << MAC_IF_SELECTION_POS);
918 break;
919 case PHY_INTERFACE_MODE_MII:
920 case PHY_INTERFACE_MODE_GMII:
921 reg_val |= (MAC_IF_SELECTION_GMII << MAC_IF_SELECTION_POS);
922 break;
923 default:
924 rc = -EINVAL;
925 goto out_unlock;
927 rc = phy_write(phydev, MSCC_PHY_EXT_PHY_CNTL_1, reg_val);
928 if (rc)
929 goto out_unlock;
931 rc = genphy_soft_reset(phydev);
933 out_unlock:
934 mutex_unlock(&phydev->lock);
936 return rc;
939 static int vsc85xx_default_config(struct phy_device *phydev)
941 int rc;
942 u16 reg_val;
944 phydev->mdix_ctrl = ETH_TP_MDI_AUTO;
945 mutex_lock(&phydev->lock);
947 reg_val = RGMII_RX_CLK_DELAY_1_1_NS << RGMII_RX_CLK_DELAY_POS;
949 rc = phy_modify_paged(phydev, MSCC_PHY_PAGE_EXTENDED_2,
950 MSCC_PHY_RGMII_CNTL, RGMII_RX_CLK_DELAY_MASK,
951 reg_val);
953 mutex_unlock(&phydev->lock);
955 return rc;
958 static int vsc85xx_get_tunable(struct phy_device *phydev,
959 struct ethtool_tunable *tuna, void *data)
961 switch (tuna->id) {
962 case ETHTOOL_PHY_DOWNSHIFT:
963 return vsc85xx_downshift_get(phydev, (u8 *)data);
964 default:
965 return -EINVAL;
969 static int vsc85xx_set_tunable(struct phy_device *phydev,
970 struct ethtool_tunable *tuna,
971 const void *data)
973 switch (tuna->id) {
974 case ETHTOOL_PHY_DOWNSHIFT:
975 return vsc85xx_downshift_set(phydev, *(u8 *)data);
976 default:
977 return -EINVAL;
981 /* mdiobus lock should be locked when using this function */
982 static void vsc85xx_tr_write(struct phy_device *phydev, u16 addr, u32 val)
984 __phy_write(phydev, MSCC_PHY_TR_MSB, val >> 16);
985 __phy_write(phydev, MSCC_PHY_TR_LSB, val & GENMASK(15, 0));
986 __phy_write(phydev, MSCC_PHY_TR_CNTL, TR_WRITE | TR_ADDR(addr));
989 static int vsc8531_pre_init_seq_set(struct phy_device *phydev)
991 int rc;
992 static const struct reg_val init_seq[] = {
993 {0x0f90, 0x00688980},
994 {0x0696, 0x00000003},
995 {0x07fa, 0x0050100f},
996 {0x1686, 0x00000004},
998 unsigned int i;
999 int oldpage;
1001 rc = phy_modify_paged(phydev, MSCC_PHY_PAGE_STANDARD,
1002 MSCC_PHY_EXT_CNTL_STATUS, SMI_BROADCAST_WR_EN,
1003 SMI_BROADCAST_WR_EN);
1004 if (rc < 0)
1005 return rc;
1006 rc = phy_modify_paged(phydev, MSCC_PHY_PAGE_TEST,
1007 MSCC_PHY_TEST_PAGE_24, 0, 0x0400);
1008 if (rc < 0)
1009 return rc;
1010 rc = phy_modify_paged(phydev, MSCC_PHY_PAGE_TEST,
1011 MSCC_PHY_TEST_PAGE_5, 0x0a00, 0x0e00);
1012 if (rc < 0)
1013 return rc;
1014 rc = phy_modify_paged(phydev, MSCC_PHY_PAGE_TEST,
1015 MSCC_PHY_TEST_PAGE_8, 0x8000, 0x8000);
1016 if (rc < 0)
1017 return rc;
1019 mutex_lock(&phydev->lock);
1020 oldpage = phy_select_page(phydev, MSCC_PHY_PAGE_TR);
1021 if (oldpage < 0)
1022 goto out_unlock;
1024 for (i = 0; i < ARRAY_SIZE(init_seq); i++)
1025 vsc85xx_tr_write(phydev, init_seq[i].reg, init_seq[i].val);
1027 out_unlock:
1028 oldpage = phy_restore_page(phydev, oldpage, oldpage);
1029 mutex_unlock(&phydev->lock);
1031 return oldpage;
1034 static int vsc85xx_eee_init_seq_set(struct phy_device *phydev)
1036 static const struct reg_val init_eee[] = {
1037 {0x0f82, 0x0012b00a},
1038 {0x1686, 0x00000004},
1039 {0x168c, 0x00d2c46f},
1040 {0x17a2, 0x00000620},
1041 {0x16a0, 0x00eeffdd},
1042 {0x16a6, 0x00071448},
1043 {0x16a4, 0x0013132f},
1044 {0x16a8, 0x00000000},
1045 {0x0ffc, 0x00c0a028},
1046 {0x0fe8, 0x0091b06c},
1047 {0x0fea, 0x00041600},
1048 {0x0f80, 0x00000af4},
1049 {0x0fec, 0x00901809},
1050 {0x0fee, 0x0000a6a1},
1051 {0x0ffe, 0x00b01007},
1052 {0x16b0, 0x00eeff00},
1053 {0x16b2, 0x00007000},
1054 {0x16b4, 0x00000814},
1056 unsigned int i;
1057 int oldpage;
1059 mutex_lock(&phydev->lock);
1060 oldpage = phy_select_page(phydev, MSCC_PHY_PAGE_TR);
1061 if (oldpage < 0)
1062 goto out_unlock;
1064 for (i = 0; i < ARRAY_SIZE(init_eee); i++)
1065 vsc85xx_tr_write(phydev, init_eee[i].reg, init_eee[i].val);
1067 out_unlock:
1068 oldpage = phy_restore_page(phydev, oldpage, oldpage);
1069 mutex_unlock(&phydev->lock);
1071 return oldpage;
1074 /* phydev->bus->mdio_lock should be locked when using this function */
1075 static int phy_base_write(struct phy_device *phydev, u32 regnum, u16 val)
1077 struct vsc8531_private *priv = phydev->priv;
1079 if (unlikely(!mutex_is_locked(&phydev->mdio.bus->mdio_lock))) {
1080 dev_err(&phydev->mdio.dev, "MDIO bus lock not held!\n");
1081 dump_stack();
1084 return __mdiobus_write(phydev->mdio.bus, priv->base_addr, regnum, val);
1087 /* phydev->bus->mdio_lock should be locked when using this function */
1088 static int phy_base_read(struct phy_device *phydev, u32 regnum)
1090 struct vsc8531_private *priv = phydev->priv;
1092 if (unlikely(!mutex_is_locked(&phydev->mdio.bus->mdio_lock))) {
1093 dev_err(&phydev->mdio.dev, "MDIO bus lock not held!\n");
1094 dump_stack();
1097 return __mdiobus_read(phydev->mdio.bus, priv->base_addr, regnum);
1100 /* bus->mdio_lock should be locked when using this function */
1101 static void vsc8584_csr_write(struct phy_device *phydev, u16 addr, u32 val)
1103 phy_base_write(phydev, MSCC_PHY_TR_MSB, val >> 16);
1104 phy_base_write(phydev, MSCC_PHY_TR_LSB, val & GENMASK(15, 0));
1105 phy_base_write(phydev, MSCC_PHY_TR_CNTL, TR_WRITE | TR_ADDR(addr));
1108 /* bus->mdio_lock should be locked when using this function */
1109 static int vsc8584_cmd(struct phy_device *phydev, u16 val)
1111 unsigned long deadline;
1112 u16 reg_val;
1114 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS,
1115 MSCC_PHY_PAGE_EXTENDED_GPIO);
1117 phy_base_write(phydev, MSCC_PHY_PROC_CMD, PROC_CMD_NCOMPLETED | val);
1119 deadline = jiffies + msecs_to_jiffies(PROC_CMD_NCOMPLETED_TIMEOUT_MS);
1120 do {
1121 reg_val = phy_base_read(phydev, MSCC_PHY_PROC_CMD);
1122 } while (time_before(jiffies, deadline) &&
1123 (reg_val & PROC_CMD_NCOMPLETED) &&
1124 !(reg_val & PROC_CMD_FAILED));
1126 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
1128 if (reg_val & PROC_CMD_FAILED)
1129 return -EIO;
1131 if (reg_val & PROC_CMD_NCOMPLETED)
1132 return -ETIMEDOUT;
1134 return 0;
1137 /* bus->mdio_lock should be locked when using this function */
1138 static int vsc8584_micro_deassert_reset(struct phy_device *phydev,
1139 bool patch_en)
1141 u32 enable, release;
1143 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS,
1144 MSCC_PHY_PAGE_EXTENDED_GPIO);
1146 enable = RUN_FROM_INT_ROM | MICRO_CLK_EN | DW8051_CLK_EN;
1147 release = MICRO_NSOFT_RESET | RUN_FROM_INT_ROM | DW8051_CLK_EN |
1148 MICRO_CLK_EN;
1150 if (patch_en) {
1151 enable |= MICRO_PATCH_EN;
1152 release |= MICRO_PATCH_EN;
1154 /* Clear all patches */
1155 phy_base_write(phydev, MSCC_INT_MEM_CNTL, READ_RAM);
1158 /* Enable 8051 Micro clock; CLEAR/SET patch present; disable PRAM clock
1159 * override and addr. auto-incr; operate at 125 MHz
1161 phy_base_write(phydev, MSCC_DW8051_CNTL_STATUS, enable);
1162 /* Release 8051 Micro SW reset */
1163 phy_base_write(phydev, MSCC_DW8051_CNTL_STATUS, release);
1165 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
1167 return 0;
1170 /* bus->mdio_lock should be locked when using this function */
1171 static int vsc8584_micro_assert_reset(struct phy_device *phydev)
1173 int ret;
1174 u16 reg;
1176 ret = vsc8584_cmd(phydev, PROC_CMD_NOP);
1177 if (ret)
1178 return ret;
1180 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS,
1181 MSCC_PHY_PAGE_EXTENDED_GPIO);
1183 reg = phy_base_read(phydev, MSCC_INT_MEM_CNTL);
1184 reg &= ~EN_PATCH_RAM_TRAP_ADDR(4);
1185 phy_base_write(phydev, MSCC_INT_MEM_CNTL, reg);
1187 phy_base_write(phydev, MSCC_TRAP_ROM_ADDR(4), 0x005b);
1188 phy_base_write(phydev, MSCC_PATCH_RAM_ADDR(4), 0x005b);
1190 reg = phy_base_read(phydev, MSCC_INT_MEM_CNTL);
1191 reg |= EN_PATCH_RAM_TRAP_ADDR(4);
1192 phy_base_write(phydev, MSCC_INT_MEM_CNTL, reg);
1194 phy_base_write(phydev, MSCC_PHY_PROC_CMD, PROC_CMD_NOP);
1196 reg = phy_base_read(phydev, MSCC_DW8051_CNTL_STATUS);
1197 reg &= ~MICRO_NSOFT_RESET;
1198 phy_base_write(phydev, MSCC_DW8051_CNTL_STATUS, reg);
1200 phy_base_write(phydev, MSCC_PHY_PROC_CMD, PROC_CMD_MCB_ACCESS_MAC_CONF |
1201 PROC_CMD_SGMII_PORT(0) | PROC_CMD_NO_MAC_CONF |
1202 PROC_CMD_READ);
1204 reg = phy_base_read(phydev, MSCC_INT_MEM_CNTL);
1205 reg &= ~EN_PATCH_RAM_TRAP_ADDR(4);
1206 phy_base_write(phydev, MSCC_INT_MEM_CNTL, reg);
1208 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
1210 return 0;
1213 /* bus->mdio_lock should be locked when using this function */
1214 static int vsc8584_get_fw_crc(struct phy_device *phydev, u16 start, u16 size,
1215 u16 *crc)
1217 int ret;
1219 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_EXTENDED);
1221 phy_base_write(phydev, MSCC_PHY_VERIPHY_CNTL_2, start);
1222 phy_base_write(phydev, MSCC_PHY_VERIPHY_CNTL_3, size);
1224 /* Start Micro command */
1225 ret = vsc8584_cmd(phydev, PROC_CMD_CRC16);
1226 if (ret)
1227 goto out;
1229 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_EXTENDED);
1231 *crc = phy_base_read(phydev, MSCC_PHY_VERIPHY_CNTL_2);
1233 out:
1234 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
1236 return ret;
1239 /* bus->mdio_lock should be locked when using this function */
1240 static int vsc8584_patch_fw(struct phy_device *phydev,
1241 const struct firmware *fw)
1243 int i, ret;
1245 ret = vsc8584_micro_assert_reset(phydev);
1246 if (ret) {
1247 dev_err(&phydev->mdio.dev,
1248 "%s: failed to assert reset of micro\n", __func__);
1249 return ret;
1252 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS,
1253 MSCC_PHY_PAGE_EXTENDED_GPIO);
1255 /* Hold 8051 Micro in SW Reset, Enable auto incr address and patch clock
1256 * Disable the 8051 Micro clock
1258 phy_base_write(phydev, MSCC_DW8051_CNTL_STATUS, RUN_FROM_INT_ROM |
1259 AUTOINC_ADDR | PATCH_RAM_CLK | MICRO_CLK_EN |
1260 MICRO_CLK_DIVIDE(2));
1261 phy_base_write(phydev, MSCC_INT_MEM_CNTL, READ_PRAM | INT_MEM_WRITE_EN |
1262 INT_MEM_DATA(2));
1263 phy_base_write(phydev, MSCC_INT_MEM_ADDR, 0x0000);
1265 for (i = 0; i < fw->size; i++)
1266 phy_base_write(phydev, MSCC_INT_MEM_CNTL, READ_PRAM |
1267 INT_MEM_WRITE_EN | fw->data[i]);
1269 /* Clear internal memory access */
1270 phy_base_write(phydev, MSCC_INT_MEM_CNTL, READ_RAM);
1272 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
1274 return 0;
1277 /* bus->mdio_lock should be locked when using this function */
1278 static bool vsc8574_is_serdes_init(struct phy_device *phydev)
1280 u16 reg;
1281 bool ret;
1283 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS,
1284 MSCC_PHY_PAGE_EXTENDED_GPIO);
1286 reg = phy_base_read(phydev, MSCC_TRAP_ROM_ADDR(1));
1287 if (reg != 0x3eb7) {
1288 ret = false;
1289 goto out;
1292 reg = phy_base_read(phydev, MSCC_PATCH_RAM_ADDR(1));
1293 if (reg != 0x4012) {
1294 ret = false;
1295 goto out;
1298 reg = phy_base_read(phydev, MSCC_INT_MEM_CNTL);
1299 if (reg != EN_PATCH_RAM_TRAP_ADDR(1)) {
1300 ret = false;
1301 goto out;
1304 reg = phy_base_read(phydev, MSCC_DW8051_CNTL_STATUS);
1305 if ((MICRO_NSOFT_RESET | RUN_FROM_INT_ROM | DW8051_CLK_EN |
1306 MICRO_CLK_EN) != (reg & MSCC_DW8051_VLD_MASK)) {
1307 ret = false;
1308 goto out;
1311 ret = true;
1312 out:
1313 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
1315 return ret;
1318 /* bus->mdio_lock should be locked when using this function */
1319 static int vsc8574_config_pre_init(struct phy_device *phydev)
1321 static const struct reg_val pre_init1[] = {
1322 {0x0fae, 0x000401bd},
1323 {0x0fac, 0x000f000f},
1324 {0x17a0, 0x00a0f147},
1325 {0x0fe4, 0x00052f54},
1326 {0x1792, 0x0027303d},
1327 {0x07fe, 0x00000704},
1328 {0x0fe0, 0x00060150},
1329 {0x0f82, 0x0012b00a},
1330 {0x0f80, 0x00000d74},
1331 {0x02e0, 0x00000012},
1332 {0x03a2, 0x00050208},
1333 {0x03b2, 0x00009186},
1334 {0x0fb0, 0x000e3700},
1335 {0x1688, 0x00049f81},
1336 {0x0fd2, 0x0000ffff},
1337 {0x168a, 0x00039fa2},
1338 {0x1690, 0x0020640b},
1339 {0x0258, 0x00002220},
1340 {0x025a, 0x00002a20},
1341 {0x025c, 0x00003060},
1342 {0x025e, 0x00003fa0},
1343 {0x03a6, 0x0000e0f0},
1344 {0x0f92, 0x00001489},
1345 {0x16a2, 0x00007000},
1346 {0x16a6, 0x00071448},
1347 {0x16a0, 0x00eeffdd},
1348 {0x0fe8, 0x0091b06c},
1349 {0x0fea, 0x00041600},
1350 {0x16b0, 0x00eeff00},
1351 {0x16b2, 0x00007000},
1352 {0x16b4, 0x00000814},
1353 {0x0f90, 0x00688980},
1354 {0x03a4, 0x0000d8f0},
1355 {0x0fc0, 0x00000400},
1356 {0x07fa, 0x0050100f},
1357 {0x0796, 0x00000003},
1358 {0x07f8, 0x00c3ff98},
1359 {0x0fa4, 0x0018292a},
1360 {0x168c, 0x00d2c46f},
1361 {0x17a2, 0x00000620},
1362 {0x16a4, 0x0013132f},
1363 {0x16a8, 0x00000000},
1364 {0x0ffc, 0x00c0a028},
1365 {0x0fec, 0x00901c09},
1366 {0x0fee, 0x0004a6a1},
1367 {0x0ffe, 0x00b01807},
1369 static const struct reg_val pre_init2[] = {
1370 {0x0486, 0x0008a518},
1371 {0x0488, 0x006dc696},
1372 {0x048a, 0x00000912},
1373 {0x048e, 0x00000db6},
1374 {0x049c, 0x00596596},
1375 {0x049e, 0x00000514},
1376 {0x04a2, 0x00410280},
1377 {0x04a4, 0x00000000},
1378 {0x04a6, 0x00000000},
1379 {0x04a8, 0x00000000},
1380 {0x04aa, 0x00000000},
1381 {0x04ae, 0x007df7dd},
1382 {0x04b0, 0x006d95d4},
1383 {0x04b2, 0x00492410},
1385 struct device *dev = &phydev->mdio.dev;
1386 const struct firmware *fw;
1387 unsigned int i;
1388 u16 crc, reg;
1389 bool serdes_init;
1390 int ret;
1392 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
1394 /* all writes below are broadcasted to all PHYs in the same package */
1395 reg = phy_base_read(phydev, MSCC_PHY_EXT_CNTL_STATUS);
1396 reg |= SMI_BROADCAST_WR_EN;
1397 phy_base_write(phydev, MSCC_PHY_EXT_CNTL_STATUS, reg);
1399 phy_base_write(phydev, MII_VSC85XX_INT_MASK, 0);
1401 /* The below register writes are tweaking analog and electrical
1402 * configuration that were determined through characterization by PHY
1403 * engineers. These don't mean anything more than "these are the best
1404 * values".
1406 phy_base_write(phydev, MSCC_PHY_EXT_PHY_CNTL_2, 0x0040);
1408 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_TEST);
1410 phy_base_write(phydev, MSCC_PHY_TEST_PAGE_20, 0x4320);
1411 phy_base_write(phydev, MSCC_PHY_TEST_PAGE_24, 0x0c00);
1412 phy_base_write(phydev, MSCC_PHY_TEST_PAGE_9, 0x18ca);
1413 phy_base_write(phydev, MSCC_PHY_TEST_PAGE_5, 0x1b20);
1415 reg = phy_base_read(phydev, MSCC_PHY_TEST_PAGE_8);
1416 reg |= 0x8000;
1417 phy_base_write(phydev, MSCC_PHY_TEST_PAGE_8, reg);
1419 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_TR);
1421 for (i = 0; i < ARRAY_SIZE(pre_init1); i++)
1422 vsc8584_csr_write(phydev, pre_init1[i].reg, pre_init1[i].val);
1424 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_EXTENDED_2);
1426 phy_base_write(phydev, MSCC_PHY_CU_PMD_TX_CNTL, 0x028e);
1428 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_TR);
1430 for (i = 0; i < ARRAY_SIZE(pre_init2); i++)
1431 vsc8584_csr_write(phydev, pre_init2[i].reg, pre_init2[i].val);
1433 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_TEST);
1435 reg = phy_base_read(phydev, MSCC_PHY_TEST_PAGE_8);
1436 reg &= ~0x8000;
1437 phy_base_write(phydev, MSCC_PHY_TEST_PAGE_8, reg);
1439 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
1441 /* end of write broadcasting */
1442 reg = phy_base_read(phydev, MSCC_PHY_EXT_CNTL_STATUS);
1443 reg &= ~SMI_BROADCAST_WR_EN;
1444 phy_base_write(phydev, MSCC_PHY_EXT_CNTL_STATUS, reg);
1446 ret = request_firmware(&fw, MSCC_VSC8574_REVB_INT8051_FW, dev);
1447 if (ret) {
1448 dev_err(dev, "failed to load firmware %s, ret: %d\n",
1449 MSCC_VSC8574_REVB_INT8051_FW, ret);
1450 return ret;
1453 /* Add one byte to size for the one added by the patch_fw function */
1454 ret = vsc8584_get_fw_crc(phydev,
1455 MSCC_VSC8574_REVB_INT8051_FW_START_ADDR,
1456 fw->size + 1, &crc);
1457 if (ret)
1458 goto out;
1460 if (crc == MSCC_VSC8574_REVB_INT8051_FW_CRC) {
1461 serdes_init = vsc8574_is_serdes_init(phydev);
1463 if (!serdes_init) {
1464 ret = vsc8584_micro_assert_reset(phydev);
1465 if (ret) {
1466 dev_err(dev,
1467 "%s: failed to assert reset of micro\n",
1468 __func__);
1469 goto out;
1472 } else {
1473 dev_dbg(dev, "FW CRC is not the expected one, patching FW\n");
1475 serdes_init = false;
1477 if (vsc8584_patch_fw(phydev, fw))
1478 dev_warn(dev,
1479 "failed to patch FW, expect non-optimal device\n");
1482 if (!serdes_init) {
1483 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS,
1484 MSCC_PHY_PAGE_EXTENDED_GPIO);
1486 phy_base_write(phydev, MSCC_TRAP_ROM_ADDR(1), 0x3eb7);
1487 phy_base_write(phydev, MSCC_PATCH_RAM_ADDR(1), 0x4012);
1488 phy_base_write(phydev, MSCC_INT_MEM_CNTL,
1489 EN_PATCH_RAM_TRAP_ADDR(1));
1491 vsc8584_micro_deassert_reset(phydev, false);
1493 /* Add one byte to size for the one added by the patch_fw
1494 * function
1496 ret = vsc8584_get_fw_crc(phydev,
1497 MSCC_VSC8574_REVB_INT8051_FW_START_ADDR,
1498 fw->size + 1, &crc);
1499 if (ret)
1500 goto out;
1502 if (crc != MSCC_VSC8574_REVB_INT8051_FW_CRC)
1503 dev_warn(dev,
1504 "FW CRC after patching is not the expected one, expect non-optimal device\n");
1507 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS,
1508 MSCC_PHY_PAGE_EXTENDED_GPIO);
1510 ret = vsc8584_cmd(phydev, PROC_CMD_1588_DEFAULT_INIT |
1511 PROC_CMD_PHY_INIT);
1513 out:
1514 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
1516 release_firmware(fw);
1518 return ret;
1521 /* bus->mdio_lock should be locked when using this function */
1522 static int vsc8584_config_pre_init(struct phy_device *phydev)
1524 static const struct reg_val pre_init1[] = {
1525 {0x07fa, 0x0050100f},
1526 {0x1688, 0x00049f81},
1527 {0x0f90, 0x00688980},
1528 {0x03a4, 0x0000d8f0},
1529 {0x0fc0, 0x00000400},
1530 {0x0f82, 0x0012b002},
1531 {0x1686, 0x00000004},
1532 {0x168c, 0x00d2c46f},
1533 {0x17a2, 0x00000620},
1534 {0x16a0, 0x00eeffdd},
1535 {0x16a6, 0x00071448},
1536 {0x16a4, 0x0013132f},
1537 {0x16a8, 0x00000000},
1538 {0x0ffc, 0x00c0a028},
1539 {0x0fe8, 0x0091b06c},
1540 {0x0fea, 0x00041600},
1541 {0x0f80, 0x00fffaff},
1542 {0x0fec, 0x00901809},
1543 {0x0ffe, 0x00b01007},
1544 {0x16b0, 0x00eeff00},
1545 {0x16b2, 0x00007000},
1546 {0x16b4, 0x00000814},
1548 static const struct reg_val pre_init2[] = {
1549 {0x0486, 0x0008a518},
1550 {0x0488, 0x006dc696},
1551 {0x048a, 0x00000912},
1553 const struct firmware *fw;
1554 struct device *dev = &phydev->mdio.dev;
1555 unsigned int i;
1556 u16 crc, reg;
1557 int ret;
1559 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
1561 /* all writes below are broadcasted to all PHYs in the same package */
1562 reg = phy_base_read(phydev, MSCC_PHY_EXT_CNTL_STATUS);
1563 reg |= SMI_BROADCAST_WR_EN;
1564 phy_base_write(phydev, MSCC_PHY_EXT_CNTL_STATUS, reg);
1566 phy_base_write(phydev, MII_VSC85XX_INT_MASK, 0);
1568 reg = phy_base_read(phydev, MSCC_PHY_BYPASS_CONTROL);
1569 reg |= PARALLEL_DET_IGNORE_ADVERTISED;
1570 phy_base_write(phydev, MSCC_PHY_BYPASS_CONTROL, reg);
1572 /* The below register writes are tweaking analog and electrical
1573 * configuration that were determined through characterization by PHY
1574 * engineers. These don't mean anything more than "these are the best
1575 * values".
1577 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_EXTENDED_3);
1579 phy_base_write(phydev, MSCC_PHY_SERDES_TX_CRC_ERR_CNT, 0x2000);
1581 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_TEST);
1583 phy_base_write(phydev, MSCC_PHY_TEST_PAGE_5, 0x1f20);
1585 reg = phy_base_read(phydev, MSCC_PHY_TEST_PAGE_8);
1586 reg |= 0x8000;
1587 phy_base_write(phydev, MSCC_PHY_TEST_PAGE_8, reg);
1589 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_TR);
1591 phy_base_write(phydev, MSCC_PHY_TR_CNTL, TR_WRITE | TR_ADDR(0x2fa4));
1593 reg = phy_base_read(phydev, MSCC_PHY_TR_MSB);
1594 reg &= ~0x007f;
1595 reg |= 0x0019;
1596 phy_base_write(phydev, MSCC_PHY_TR_MSB, reg);
1598 phy_base_write(phydev, MSCC_PHY_TR_CNTL, TR_WRITE | TR_ADDR(0x0fa4));
1600 for (i = 0; i < ARRAY_SIZE(pre_init1); i++)
1601 vsc8584_csr_write(phydev, pre_init1[i].reg, pre_init1[i].val);
1603 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_EXTENDED_2);
1605 phy_base_write(phydev, MSCC_PHY_CU_PMD_TX_CNTL, 0x028e);
1607 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_TR);
1609 for (i = 0; i < ARRAY_SIZE(pre_init2); i++)
1610 vsc8584_csr_write(phydev, pre_init2[i].reg, pre_init2[i].val);
1612 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_TEST);
1614 reg = phy_base_read(phydev, MSCC_PHY_TEST_PAGE_8);
1615 reg &= ~0x8000;
1616 phy_base_write(phydev, MSCC_PHY_TEST_PAGE_8, reg);
1618 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
1620 /* end of write broadcasting */
1621 reg = phy_base_read(phydev, MSCC_PHY_EXT_CNTL_STATUS);
1622 reg &= ~SMI_BROADCAST_WR_EN;
1623 phy_base_write(phydev, MSCC_PHY_EXT_CNTL_STATUS, reg);
1625 ret = request_firmware(&fw, MSCC_VSC8584_REVB_INT8051_FW, dev);
1626 if (ret) {
1627 dev_err(dev, "failed to load firmware %s, ret: %d\n",
1628 MSCC_VSC8584_REVB_INT8051_FW, ret);
1629 return ret;
1632 /* Add one byte to size for the one added by the patch_fw function */
1633 ret = vsc8584_get_fw_crc(phydev,
1634 MSCC_VSC8584_REVB_INT8051_FW_START_ADDR,
1635 fw->size + 1, &crc);
1636 if (ret)
1637 goto out;
1639 if (crc != MSCC_VSC8584_REVB_INT8051_FW_CRC) {
1640 dev_dbg(dev, "FW CRC is not the expected one, patching FW\n");
1641 if (vsc8584_patch_fw(phydev, fw))
1642 dev_warn(dev,
1643 "failed to patch FW, expect non-optimal device\n");
1646 vsc8584_micro_deassert_reset(phydev, false);
1648 /* Add one byte to size for the one added by the patch_fw function */
1649 ret = vsc8584_get_fw_crc(phydev,
1650 MSCC_VSC8584_REVB_INT8051_FW_START_ADDR,
1651 fw->size + 1, &crc);
1652 if (ret)
1653 goto out;
1655 if (crc != MSCC_VSC8584_REVB_INT8051_FW_CRC)
1656 dev_warn(dev,
1657 "FW CRC after patching is not the expected one, expect non-optimal device\n");
1659 ret = vsc8584_micro_assert_reset(phydev);
1660 if (ret)
1661 goto out;
1663 vsc8584_micro_deassert_reset(phydev, true);
1665 out:
1666 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
1668 release_firmware(fw);
1670 return ret;
1673 #if IS_ENABLED(CONFIG_MACSEC)
1674 static u32 vsc8584_macsec_phy_read(struct phy_device *phydev,
1675 enum macsec_bank bank, u32 reg)
1677 u32 val, val_l = 0, val_h = 0;
1678 unsigned long deadline;
1679 int rc;
1681 rc = phy_select_page(phydev, MSCC_PHY_PAGE_MACSEC);
1682 if (rc < 0)
1683 goto failed;
1685 __phy_write(phydev, MSCC_EXT_PAGE_MACSEC_20,
1686 MSCC_PHY_MACSEC_20_TARGET(bank >> 2));
1688 if (bank >> 2 == 0x1)
1689 /* non-MACsec access */
1690 bank &= 0x3;
1691 else
1692 bank = 0;
1694 __phy_write(phydev, MSCC_EXT_PAGE_MACSEC_19,
1695 MSCC_PHY_MACSEC_19_CMD | MSCC_PHY_MACSEC_19_READ |
1696 MSCC_PHY_MACSEC_19_REG_ADDR(reg) |
1697 MSCC_PHY_MACSEC_19_TARGET(bank));
1699 deadline = jiffies + msecs_to_jiffies(PROC_CMD_NCOMPLETED_TIMEOUT_MS);
1700 do {
1701 val = __phy_read(phydev, MSCC_EXT_PAGE_MACSEC_19);
1702 } while (time_before(jiffies, deadline) && !(val & MSCC_PHY_MACSEC_19_CMD));
1704 val_l = __phy_read(phydev, MSCC_EXT_PAGE_MACSEC_17);
1705 val_h = __phy_read(phydev, MSCC_EXT_PAGE_MACSEC_18);
1707 failed:
1708 phy_restore_page(phydev, rc, rc);
1710 return (val_h << 16) | val_l;
1713 static void vsc8584_macsec_phy_write(struct phy_device *phydev,
1714 enum macsec_bank bank, u32 reg, u32 val)
1716 unsigned long deadline;
1717 int rc;
1719 rc = phy_select_page(phydev, MSCC_PHY_PAGE_MACSEC);
1720 if (rc < 0)
1721 goto failed;
1723 __phy_write(phydev, MSCC_EXT_PAGE_MACSEC_20,
1724 MSCC_PHY_MACSEC_20_TARGET(bank >> 2));
1726 if ((bank >> 2 == 0x1) || (bank >> 2 == 0x3))
1727 bank &= 0x3;
1728 else
1729 /* MACsec access */
1730 bank = 0;
1732 __phy_write(phydev, MSCC_EXT_PAGE_MACSEC_17, (u16)val);
1733 __phy_write(phydev, MSCC_EXT_PAGE_MACSEC_18, (u16)(val >> 16));
1735 __phy_write(phydev, MSCC_EXT_PAGE_MACSEC_19,
1736 MSCC_PHY_MACSEC_19_CMD | MSCC_PHY_MACSEC_19_REG_ADDR(reg) |
1737 MSCC_PHY_MACSEC_19_TARGET(bank));
1739 deadline = jiffies + msecs_to_jiffies(PROC_CMD_NCOMPLETED_TIMEOUT_MS);
1740 do {
1741 val = __phy_read(phydev, MSCC_EXT_PAGE_MACSEC_19);
1742 } while (time_before(jiffies, deadline) && !(val & MSCC_PHY_MACSEC_19_CMD));
1744 failed:
1745 phy_restore_page(phydev, rc, rc);
1748 static void vsc8584_macsec_classification(struct phy_device *phydev,
1749 enum macsec_bank bank)
1751 /* enable VLAN tag parsing */
1752 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_CP_TAG,
1753 MSCC_MS_SAM_CP_TAG_PARSE_STAG |
1754 MSCC_MS_SAM_CP_TAG_PARSE_QTAG |
1755 MSCC_MS_SAM_CP_TAG_PARSE_QINQ);
1758 static void vsc8584_macsec_flow_default_action(struct phy_device *phydev,
1759 enum macsec_bank bank,
1760 bool block)
1762 u32 port = (bank == MACSEC_INGR) ?
1763 MSCC_MS_PORT_UNCONTROLLED : MSCC_MS_PORT_COMMON;
1764 u32 action = MSCC_MS_FLOW_BYPASS;
1766 if (block)
1767 action = MSCC_MS_FLOW_DROP;
1769 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_NM_FLOW_NCP,
1770 /* MACsec untagged */
1771 MSCC_MS_SAM_NM_FLOW_NCP_UNTAGGED_FLOW_TYPE(action) |
1772 MSCC_MS_SAM_NM_FLOW_NCP_UNTAGGED_DROP_ACTION(MSCC_MS_ACTION_DROP) |
1773 MSCC_MS_SAM_NM_FLOW_NCP_UNTAGGED_DEST_PORT(port) |
1774 /* MACsec tagged */
1775 MSCC_MS_SAM_NM_FLOW_NCP_TAGGED_FLOW_TYPE(action) |
1776 MSCC_MS_SAM_NM_FLOW_NCP_TAGGED_DROP_ACTION(MSCC_MS_ACTION_DROP) |
1777 MSCC_MS_SAM_NM_FLOW_NCP_TAGGED_DEST_PORT(port) |
1778 /* Bad tag */
1779 MSCC_MS_SAM_NM_FLOW_NCP_BADTAG_FLOW_TYPE(action) |
1780 MSCC_MS_SAM_NM_FLOW_NCP_BADTAG_DROP_ACTION(MSCC_MS_ACTION_DROP) |
1781 MSCC_MS_SAM_NM_FLOW_NCP_BADTAG_DEST_PORT(port) |
1782 /* Kay tag */
1783 MSCC_MS_SAM_NM_FLOW_NCP_KAY_FLOW_TYPE(action) |
1784 MSCC_MS_SAM_NM_FLOW_NCP_KAY_DROP_ACTION(MSCC_MS_ACTION_DROP) |
1785 MSCC_MS_SAM_NM_FLOW_NCP_KAY_DEST_PORT(port));
1786 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_NM_FLOW_CP,
1787 /* MACsec untagged */
1788 MSCC_MS_SAM_NM_FLOW_NCP_UNTAGGED_FLOW_TYPE(action) |
1789 MSCC_MS_SAM_NM_FLOW_CP_UNTAGGED_DROP_ACTION(MSCC_MS_ACTION_DROP) |
1790 MSCC_MS_SAM_NM_FLOW_CP_UNTAGGED_DEST_PORT(port) |
1791 /* MACsec tagged */
1792 MSCC_MS_SAM_NM_FLOW_NCP_TAGGED_FLOW_TYPE(action) |
1793 MSCC_MS_SAM_NM_FLOW_CP_TAGGED_DROP_ACTION(MSCC_MS_ACTION_DROP) |
1794 MSCC_MS_SAM_NM_FLOW_CP_TAGGED_DEST_PORT(port) |
1795 /* Bad tag */
1796 MSCC_MS_SAM_NM_FLOW_NCP_BADTAG_FLOW_TYPE(action) |
1797 MSCC_MS_SAM_NM_FLOW_CP_BADTAG_DROP_ACTION(MSCC_MS_ACTION_DROP) |
1798 MSCC_MS_SAM_NM_FLOW_CP_BADTAG_DEST_PORT(port) |
1799 /* Kay tag */
1800 MSCC_MS_SAM_NM_FLOW_NCP_KAY_FLOW_TYPE(action) |
1801 MSCC_MS_SAM_NM_FLOW_CP_KAY_DROP_ACTION(MSCC_MS_ACTION_DROP) |
1802 MSCC_MS_SAM_NM_FLOW_CP_KAY_DEST_PORT(port));
1805 static void vsc8584_macsec_integrity_checks(struct phy_device *phydev,
1806 enum macsec_bank bank)
1808 u32 val;
1810 if (bank != MACSEC_INGR)
1811 return;
1813 /* Set default rules to pass unmatched frames */
1814 val = vsc8584_macsec_phy_read(phydev, bank,
1815 MSCC_MS_PARAMS2_IG_CC_CONTROL);
1816 val |= MSCC_MS_PARAMS2_IG_CC_CONTROL_NON_MATCH_CTRL_ACT |
1817 MSCC_MS_PARAMS2_IG_CC_CONTROL_NON_MATCH_ACT;
1818 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_PARAMS2_IG_CC_CONTROL,
1819 val);
1821 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_PARAMS2_IG_CP_TAG,
1822 MSCC_MS_PARAMS2_IG_CP_TAG_PARSE_STAG |
1823 MSCC_MS_PARAMS2_IG_CP_TAG_PARSE_QTAG |
1824 MSCC_MS_PARAMS2_IG_CP_TAG_PARSE_QINQ);
1827 static void vsc8584_macsec_block_init(struct phy_device *phydev,
1828 enum macsec_bank bank)
1830 u32 val;
1831 int i;
1833 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_ENA_CFG,
1834 MSCC_MS_ENA_CFG_SW_RST |
1835 MSCC_MS_ENA_CFG_MACSEC_BYPASS_ENA);
1837 /* Set the MACsec block out of s/w reset and enable clocks */
1838 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_ENA_CFG,
1839 MSCC_MS_ENA_CFG_CLK_ENA);
1841 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_STATUS_CONTEXT_CTRL,
1842 bank == MACSEC_INGR ? 0xe5880214 : 0xe5880218);
1843 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_MISC_CONTROL,
1844 MSCC_MS_MISC_CONTROL_MC_LATENCY_FIX(bank == MACSEC_INGR ? 57 : 40) |
1845 MSCC_MS_MISC_CONTROL_XFORM_REC_SIZE(bank == MACSEC_INGR ? 1 : 2));
1847 /* Clear the counters */
1848 val = vsc8584_macsec_phy_read(phydev, bank, MSCC_MS_COUNT_CONTROL);
1849 val |= MSCC_MS_COUNT_CONTROL_AUTO_CNTR_RESET;
1850 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_COUNT_CONTROL, val);
1852 /* Enable octet increment mode */
1853 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_PP_CTRL,
1854 MSCC_MS_PP_CTRL_MACSEC_OCTET_INCR_MODE);
1856 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_BLOCK_CTX_UPDATE, 0x3);
1858 val = vsc8584_macsec_phy_read(phydev, bank, MSCC_MS_COUNT_CONTROL);
1859 val |= MSCC_MS_COUNT_CONTROL_RESET_ALL;
1860 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_COUNT_CONTROL, val);
1862 /* Set the MTU */
1863 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_NON_VLAN_MTU_CHECK,
1864 MSCC_MS_NON_VLAN_MTU_CHECK_NV_MTU_COMPARE(32761) |
1865 MSCC_MS_NON_VLAN_MTU_CHECK_NV_MTU_COMP_DROP);
1867 for (i = 0; i < 8; i++)
1868 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_VLAN_MTU_CHECK(i),
1869 MSCC_MS_VLAN_MTU_CHECK_MTU_COMPARE(32761) |
1870 MSCC_MS_VLAN_MTU_CHECK_MTU_COMP_DROP);
1872 if (bank == MACSEC_EGR) {
1873 val = vsc8584_macsec_phy_read(phydev, bank, MSCC_MS_INTR_CTRL_STATUS);
1874 val &= ~MSCC_MS_INTR_CTRL_STATUS_INTR_ENABLE_M;
1875 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_INTR_CTRL_STATUS, val);
1877 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_FC_CFG,
1878 MSCC_MS_FC_CFG_FCBUF_ENA |
1879 MSCC_MS_FC_CFG_LOW_THRESH(0x1) |
1880 MSCC_MS_FC_CFG_HIGH_THRESH(0x4) |
1881 MSCC_MS_FC_CFG_LOW_BYTES_VAL(0x4) |
1882 MSCC_MS_FC_CFG_HIGH_BYTES_VAL(0x6));
1885 vsc8584_macsec_classification(phydev, bank);
1886 vsc8584_macsec_flow_default_action(phydev, bank, false);
1887 vsc8584_macsec_integrity_checks(phydev, bank);
1889 /* Enable the MACsec block */
1890 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_ENA_CFG,
1891 MSCC_MS_ENA_CFG_CLK_ENA |
1892 MSCC_MS_ENA_CFG_MACSEC_ENA |
1893 MSCC_MS_ENA_CFG_MACSEC_SPEED_MODE(0x5));
1896 static void vsc8584_macsec_mac_init(struct phy_device *phydev,
1897 enum macsec_bank bank)
1899 u32 val;
1900 int i;
1902 /* Clear host & line stats */
1903 for (i = 0; i < 36; i++)
1904 vsc8584_macsec_phy_write(phydev, bank, 0x1c + i, 0);
1906 val = vsc8584_macsec_phy_read(phydev, bank,
1907 MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL);
1908 val &= ~MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL_PAUSE_MODE_M;
1909 val |= MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL_PAUSE_MODE(2) |
1910 MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL_PAUSE_VALUE(0xffff);
1911 vsc8584_macsec_phy_write(phydev, bank,
1912 MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL, val);
1914 val = vsc8584_macsec_phy_read(phydev, bank,
1915 MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL_2);
1916 val |= 0xffff;
1917 vsc8584_macsec_phy_write(phydev, bank,
1918 MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL_2, val);
1920 val = vsc8584_macsec_phy_read(phydev, bank,
1921 MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL);
1922 if (bank == HOST_MAC)
1923 val |= MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL_PAUSE_TIMER_ENA |
1924 MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL_PAUSE_FRAME_DROP_ENA;
1925 else
1926 val |= MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL_PAUSE_REACT_ENA |
1927 MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL_PAUSE_FRAME_DROP_ENA |
1928 MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL_PAUSE_MODE |
1929 MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL_EARLY_PAUSE_DETECT_ENA;
1930 vsc8584_macsec_phy_write(phydev, bank,
1931 MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL, val);
1933 vsc8584_macsec_phy_write(phydev, bank, MSCC_MAC_CFG_PKTINF_CFG,
1934 MSCC_MAC_CFG_PKTINF_CFG_STRIP_FCS_ENA |
1935 MSCC_MAC_CFG_PKTINF_CFG_INSERT_FCS_ENA |
1936 MSCC_MAC_CFG_PKTINF_CFG_LPI_RELAY_ENA |
1937 MSCC_MAC_CFG_PKTINF_CFG_STRIP_PREAMBLE_ENA |
1938 MSCC_MAC_CFG_PKTINF_CFG_INSERT_PREAMBLE_ENA |
1939 (bank == HOST_MAC ?
1940 MSCC_MAC_CFG_PKTINF_CFG_ENABLE_TX_PADDING : 0));
1942 val = vsc8584_macsec_phy_read(phydev, bank, MSCC_MAC_CFG_MODE_CFG);
1943 val &= ~MSCC_MAC_CFG_MODE_CFG_DISABLE_DIC;
1944 vsc8584_macsec_phy_write(phydev, bank, MSCC_MAC_CFG_MODE_CFG, val);
1946 val = vsc8584_macsec_phy_read(phydev, bank, MSCC_MAC_CFG_MAXLEN_CFG);
1947 val &= ~MSCC_MAC_CFG_MAXLEN_CFG_MAX_LEN_M;
1948 val |= MSCC_MAC_CFG_MAXLEN_CFG_MAX_LEN(10240);
1949 vsc8584_macsec_phy_write(phydev, bank, MSCC_MAC_CFG_MAXLEN_CFG, val);
1951 vsc8584_macsec_phy_write(phydev, bank, MSCC_MAC_CFG_ADV_CHK_CFG,
1952 MSCC_MAC_CFG_ADV_CHK_CFG_SFD_CHK_ENA |
1953 MSCC_MAC_CFG_ADV_CHK_CFG_PRM_CHK_ENA |
1954 MSCC_MAC_CFG_ADV_CHK_CFG_OOR_ERR_ENA |
1955 MSCC_MAC_CFG_ADV_CHK_CFG_INR_ERR_ENA);
1957 val = vsc8584_macsec_phy_read(phydev, bank, MSCC_MAC_CFG_LFS_CFG);
1958 val &= ~MSCC_MAC_CFG_LFS_CFG_LFS_MODE_ENA;
1959 vsc8584_macsec_phy_write(phydev, bank, MSCC_MAC_CFG_LFS_CFG, val);
1961 vsc8584_macsec_phy_write(phydev, bank, MSCC_MAC_CFG_ENA_CFG,
1962 MSCC_MAC_CFG_ENA_CFG_RX_CLK_ENA |
1963 MSCC_MAC_CFG_ENA_CFG_TX_CLK_ENA |
1964 MSCC_MAC_CFG_ENA_CFG_RX_ENA |
1965 MSCC_MAC_CFG_ENA_CFG_TX_ENA);
1968 /* Must be called with mdio_lock taken */
1969 static int vsc8584_macsec_init(struct phy_device *phydev)
1971 u32 val;
1973 vsc8584_macsec_block_init(phydev, MACSEC_INGR);
1974 vsc8584_macsec_block_init(phydev, MACSEC_EGR);
1975 vsc8584_macsec_mac_init(phydev, HOST_MAC);
1976 vsc8584_macsec_mac_init(phydev, LINE_MAC);
1978 vsc8584_macsec_phy_write(phydev, FC_BUFFER,
1979 MSCC_FCBUF_FC_READ_THRESH_CFG,
1980 MSCC_FCBUF_FC_READ_THRESH_CFG_TX_THRESH(4) |
1981 MSCC_FCBUF_FC_READ_THRESH_CFG_RX_THRESH(5));
1983 val = vsc8584_macsec_phy_read(phydev, FC_BUFFER, MSCC_FCBUF_MODE_CFG);
1984 val |= MSCC_FCBUF_MODE_CFG_PAUSE_GEN_ENA |
1985 MSCC_FCBUF_MODE_CFG_RX_PPM_RATE_ADAPT_ENA |
1986 MSCC_FCBUF_MODE_CFG_TX_PPM_RATE_ADAPT_ENA;
1987 vsc8584_macsec_phy_write(phydev, FC_BUFFER, MSCC_FCBUF_MODE_CFG, val);
1989 vsc8584_macsec_phy_write(phydev, FC_BUFFER, MSCC_FCBUF_PPM_RATE_ADAPT_THRESH_CFG,
1990 MSCC_FCBUF_PPM_RATE_ADAPT_THRESH_CFG_TX_THRESH(8) |
1991 MSCC_FCBUF_PPM_RATE_ADAPT_THRESH_CFG_TX_OFFSET(9));
1993 val = vsc8584_macsec_phy_read(phydev, FC_BUFFER,
1994 MSCC_FCBUF_TX_DATA_QUEUE_CFG);
1995 val &= ~(MSCC_FCBUF_TX_DATA_QUEUE_CFG_START_M |
1996 MSCC_FCBUF_TX_DATA_QUEUE_CFG_END_M);
1997 val |= MSCC_FCBUF_TX_DATA_QUEUE_CFG_START(0) |
1998 MSCC_FCBUF_TX_DATA_QUEUE_CFG_END(5119);
1999 vsc8584_macsec_phy_write(phydev, FC_BUFFER,
2000 MSCC_FCBUF_TX_DATA_QUEUE_CFG, val);
2002 val = vsc8584_macsec_phy_read(phydev, FC_BUFFER, MSCC_FCBUF_ENA_CFG);
2003 val |= MSCC_FCBUF_ENA_CFG_TX_ENA | MSCC_FCBUF_ENA_CFG_RX_ENA;
2004 vsc8584_macsec_phy_write(phydev, FC_BUFFER, MSCC_FCBUF_ENA_CFG, val);
2006 val = vsc8584_macsec_phy_read(phydev, IP_1588,
2007 MSCC_PROC_0_IP_1588_TOP_CFG_STAT_MODE_CTL);
2008 val &= ~MSCC_PROC_0_IP_1588_TOP_CFG_STAT_MODE_CTL_PROTOCOL_MODE_M;
2009 val |= MSCC_PROC_0_IP_1588_TOP_CFG_STAT_MODE_CTL_PROTOCOL_MODE(4);
2010 vsc8584_macsec_phy_write(phydev, IP_1588,
2011 MSCC_PROC_0_IP_1588_TOP_CFG_STAT_MODE_CTL, val);
2013 return 0;
2016 static void vsc8584_macsec_flow(struct phy_device *phydev,
2017 struct macsec_flow *flow)
2019 struct vsc8531_private *priv = phydev->priv;
2020 enum macsec_bank bank = flow->bank;
2021 u32 val, match = 0, mask = 0, action = 0, idx = flow->index;
2023 if (flow->match.tagged)
2024 match |= MSCC_MS_SAM_MISC_MATCH_TAGGED;
2025 if (flow->match.untagged)
2026 match |= MSCC_MS_SAM_MISC_MATCH_UNTAGGED;
2028 if (bank == MACSEC_INGR && flow->assoc_num >= 0) {
2029 match |= MSCC_MS_SAM_MISC_MATCH_AN(flow->assoc_num);
2030 mask |= MSCC_MS_SAM_MASK_AN_MASK(0x3);
2033 if (bank == MACSEC_INGR && flow->match.sci && flow->rx_sa->sc->sci) {
2034 match |= MSCC_MS_SAM_MISC_MATCH_TCI(BIT(3));
2035 mask |= MSCC_MS_SAM_MASK_TCI_MASK(BIT(3)) |
2036 MSCC_MS_SAM_MASK_SCI_MASK;
2038 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_MATCH_SCI_LO(idx),
2039 lower_32_bits(flow->rx_sa->sc->sci));
2040 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_MATCH_SCI_HI(idx),
2041 upper_32_bits(flow->rx_sa->sc->sci));
2044 if (flow->match.etype) {
2045 mask |= MSCC_MS_SAM_MASK_MAC_ETYPE_MASK;
2047 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_MAC_SA_MATCH_HI(idx),
2048 MSCC_MS_SAM_MAC_SA_MATCH_HI_ETYPE(htons(flow->etype)));
2051 match |= MSCC_MS_SAM_MISC_MATCH_PRIORITY(flow->priority);
2053 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_MISC_MATCH(idx), match);
2054 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_MASK(idx), mask);
2056 /* Action for matching packets */
2057 if (flow->action.drop)
2058 action = MSCC_MS_FLOW_DROP;
2059 else if (flow->action.bypass || flow->port == MSCC_MS_PORT_UNCONTROLLED)
2060 action = MSCC_MS_FLOW_BYPASS;
2061 else
2062 action = (bank == MACSEC_INGR) ?
2063 MSCC_MS_FLOW_INGRESS : MSCC_MS_FLOW_EGRESS;
2065 val = MSCC_MS_SAM_FLOW_CTRL_FLOW_TYPE(action) |
2066 MSCC_MS_SAM_FLOW_CTRL_DROP_ACTION(MSCC_MS_ACTION_DROP) |
2067 MSCC_MS_SAM_FLOW_CTRL_DEST_PORT(flow->port);
2069 if (action == MSCC_MS_FLOW_BYPASS)
2070 goto write_ctrl;
2072 if (bank == MACSEC_INGR) {
2073 if (priv->secy->replay_protect)
2074 val |= MSCC_MS_SAM_FLOW_CTRL_REPLAY_PROTECT;
2075 if (priv->secy->validate_frames == MACSEC_VALIDATE_STRICT)
2076 val |= MSCC_MS_SAM_FLOW_CTRL_VALIDATE_FRAMES(MSCC_MS_VALIDATE_STRICT);
2077 else if (priv->secy->validate_frames == MACSEC_VALIDATE_CHECK)
2078 val |= MSCC_MS_SAM_FLOW_CTRL_VALIDATE_FRAMES(MSCC_MS_VALIDATE_CHECK);
2079 } else if (bank == MACSEC_EGR) {
2080 if (priv->secy->protect_frames)
2081 val |= MSCC_MS_SAM_FLOW_CTRL_PROTECT_FRAME;
2082 if (priv->secy->tx_sc.encrypt)
2083 val |= MSCC_MS_SAM_FLOW_CTRL_CONF_PROTECT;
2084 if (priv->secy->tx_sc.send_sci)
2085 val |= MSCC_MS_SAM_FLOW_CTRL_INCLUDE_SCI;
2088 write_ctrl:
2089 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_FLOW_CTRL(idx), val);
2092 static struct macsec_flow *vsc8584_macsec_find_flow(struct macsec_context *ctx,
2093 enum macsec_bank bank)
2095 struct vsc8531_private *priv = ctx->phydev->priv;
2096 struct macsec_flow *pos, *tmp;
2098 list_for_each_entry_safe(pos, tmp, &priv->macsec_flows, list)
2099 if (pos->assoc_num == ctx->sa.assoc_num && pos->bank == bank)
2100 return pos;
2102 return ERR_PTR(-ENOENT);
2105 static void vsc8584_macsec_flow_enable(struct phy_device *phydev,
2106 struct macsec_flow *flow)
2108 enum macsec_bank bank = flow->bank;
2109 u32 val, idx = flow->index;
2111 if ((flow->bank == MACSEC_INGR && flow->rx_sa && !flow->rx_sa->active) ||
2112 (flow->bank == MACSEC_EGR && flow->tx_sa && !flow->tx_sa->active))
2113 return;
2115 /* Enable */
2116 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_ENTRY_SET1, BIT(idx));
2118 /* Set in-use */
2119 val = vsc8584_macsec_phy_read(phydev, bank, MSCC_MS_SAM_FLOW_CTRL(idx));
2120 val |= MSCC_MS_SAM_FLOW_CTRL_SA_IN_USE;
2121 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_FLOW_CTRL(idx), val);
2124 static void vsc8584_macsec_flow_disable(struct phy_device *phydev,
2125 struct macsec_flow *flow)
2127 enum macsec_bank bank = flow->bank;
2128 u32 val, idx = flow->index;
2130 /* Disable */
2131 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_ENTRY_CLEAR1, BIT(idx));
2133 /* Clear in-use */
2134 val = vsc8584_macsec_phy_read(phydev, bank, MSCC_MS_SAM_FLOW_CTRL(idx));
2135 val &= ~MSCC_MS_SAM_FLOW_CTRL_SA_IN_USE;
2136 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_FLOW_CTRL(idx), val);
2139 static u32 vsc8584_macsec_flow_context_id(struct macsec_flow *flow)
2141 if (flow->bank == MACSEC_INGR)
2142 return flow->index + MSCC_MS_MAX_FLOWS;
2144 return flow->index;
2147 /* Derive the AES key to get a key for the hash autentication */
2148 static int vsc8584_macsec_derive_key(const u8 key[MACSEC_KEYID_LEN],
2149 u16 key_len, u8 hkey[16])
2151 struct crypto_skcipher *tfm = crypto_alloc_skcipher("ecb(aes)", 0, 0);
2152 struct skcipher_request *req = NULL;
2153 struct scatterlist src, dst;
2154 DECLARE_CRYPTO_WAIT(wait);
2155 u32 input[4] = {0};
2156 int ret;
2158 if (IS_ERR(tfm))
2159 return PTR_ERR(tfm);
2161 req = skcipher_request_alloc(tfm, GFP_KERNEL);
2162 if (!req) {
2163 ret = -ENOMEM;
2164 goto out;
2167 skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
2168 CRYPTO_TFM_REQ_MAY_SLEEP, crypto_req_done,
2169 &wait);
2170 ret = crypto_skcipher_setkey(tfm, key, key_len);
2171 if (ret < 0)
2172 goto out;
2174 sg_init_one(&src, input, 16);
2175 sg_init_one(&dst, hkey, 16);
2176 skcipher_request_set_crypt(req, &src, &dst, 16, NULL);
2178 ret = crypto_wait_req(crypto_skcipher_encrypt(req), &wait);
2180 out:
2181 skcipher_request_free(req);
2182 crypto_free_skcipher(tfm);
2183 return ret;
2186 static int vsc8584_macsec_transformation(struct phy_device *phydev,
2187 struct macsec_flow *flow)
2189 struct vsc8531_private *priv = phydev->priv;
2190 enum macsec_bank bank = flow->bank;
2191 int i, ret, index = flow->index;
2192 u32 rec = 0, control = 0;
2193 u8 hkey[16];
2194 sci_t sci;
2196 ret = vsc8584_macsec_derive_key(flow->key, priv->secy->key_len, hkey);
2197 if (ret)
2198 return ret;
2200 switch (priv->secy->key_len) {
2201 case 16:
2202 control |= CONTROL_CRYPTO_ALG(CTRYPTO_ALG_AES_CTR_128);
2203 break;
2204 case 32:
2205 control |= CONTROL_CRYPTO_ALG(CTRYPTO_ALG_AES_CTR_256);
2206 break;
2207 default:
2208 return -EINVAL;
2211 control |= (bank == MACSEC_EGR) ?
2212 (CONTROL_TYPE_EGRESS | CONTROL_AN(priv->secy->tx_sc.encoding_sa)) :
2213 (CONTROL_TYPE_INGRESS | CONTROL_SEQ_MASK);
2215 control |= CONTROL_UPDATE_SEQ | CONTROL_ENCRYPT_AUTH | CONTROL_KEY_IN_CTX |
2216 CONTROL_IV0 | CONTROL_IV1 | CONTROL_IV_IN_SEQ |
2217 CONTROL_DIGEST_TYPE(0x2) | CONTROL_SEQ_TYPE(0x1) |
2218 CONTROL_AUTH_ALG(AUTH_ALG_AES_GHAS) | CONTROL_CONTEXT_ID;
2220 /* Set the control word */
2221 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_XFORM_REC(index, rec++),
2222 control);
2224 /* Set the context ID. Must be unique. */
2225 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_XFORM_REC(index, rec++),
2226 vsc8584_macsec_flow_context_id(flow));
2228 /* Set the encryption/decryption key */
2229 for (i = 0; i < priv->secy->key_len / sizeof(u32); i++)
2230 vsc8584_macsec_phy_write(phydev, bank,
2231 MSCC_MS_XFORM_REC(index, rec++),
2232 ((u32 *)flow->key)[i]);
2234 /* Set the authentication key */
2235 for (i = 0; i < 4; i++)
2236 vsc8584_macsec_phy_write(phydev, bank,
2237 MSCC_MS_XFORM_REC(index, rec++),
2238 ((u32 *)hkey)[i]);
2240 /* Initial sequence number */
2241 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_XFORM_REC(index, rec++),
2242 bank == MACSEC_INGR ?
2243 flow->rx_sa->next_pn : flow->tx_sa->next_pn);
2245 if (bank == MACSEC_INGR)
2246 /* Set the mask (replay window size) */
2247 vsc8584_macsec_phy_write(phydev, bank,
2248 MSCC_MS_XFORM_REC(index, rec++),
2249 priv->secy->replay_window);
2251 /* Set the input vectors */
2252 sci = bank == MACSEC_INGR ? flow->rx_sa->sc->sci : priv->secy->sci;
2253 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_XFORM_REC(index, rec++),
2254 lower_32_bits(sci));
2255 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_XFORM_REC(index, rec++),
2256 upper_32_bits(sci));
2258 while (rec < 20)
2259 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_XFORM_REC(index, rec++),
2262 flow->has_transformation = true;
2263 return 0;
2266 static struct macsec_flow *vsc8584_macsec_alloc_flow(struct vsc8531_private *priv,
2267 enum macsec_bank bank)
2269 unsigned long *bitmap = bank == MACSEC_INGR ?
2270 &priv->ingr_flows : &priv->egr_flows;
2271 struct macsec_flow *flow;
2272 int index;
2274 index = find_first_zero_bit(bitmap, MSCC_MS_MAX_FLOWS);
2276 if (index == MSCC_MS_MAX_FLOWS)
2277 return ERR_PTR(-ENOMEM);
2279 flow = kzalloc(sizeof(*flow), GFP_KERNEL);
2280 if (!flow)
2281 return ERR_PTR(-ENOMEM);
2283 set_bit(index, bitmap);
2284 flow->index = index;
2285 flow->bank = bank;
2286 flow->priority = 8;
2287 flow->assoc_num = -1;
2289 list_add_tail(&flow->list, &priv->macsec_flows);
2290 return flow;
2293 static void vsc8584_macsec_free_flow(struct vsc8531_private *priv,
2294 struct macsec_flow *flow)
2296 unsigned long *bitmap = flow->bank == MACSEC_INGR ?
2297 &priv->ingr_flows : &priv->egr_flows;
2299 list_del(&flow->list);
2300 clear_bit(flow->index, bitmap);
2301 kfree(flow);
2304 static int vsc8584_macsec_add_flow(struct phy_device *phydev,
2305 struct macsec_flow *flow, bool update)
2307 int ret;
2309 flow->port = MSCC_MS_PORT_CONTROLLED;
2310 vsc8584_macsec_flow(phydev, flow);
2312 if (update)
2313 return 0;
2315 ret = vsc8584_macsec_transformation(phydev, flow);
2316 if (ret) {
2317 vsc8584_macsec_free_flow(phydev->priv, flow);
2318 return ret;
2321 return 0;
2324 static int vsc8584_macsec_default_flows(struct phy_device *phydev)
2326 struct macsec_flow *flow;
2328 /* Add a rule to let the MKA traffic go through, ingress */
2329 flow = vsc8584_macsec_alloc_flow(phydev->priv, MACSEC_INGR);
2330 if (IS_ERR(flow))
2331 return PTR_ERR(flow);
2333 flow->priority = 15;
2334 flow->port = MSCC_MS_PORT_UNCONTROLLED;
2335 flow->match.tagged = 1;
2336 flow->match.untagged = 1;
2337 flow->match.etype = 1;
2338 flow->etype = ETH_P_PAE;
2339 flow->action.bypass = 1;
2341 vsc8584_macsec_flow(phydev, flow);
2342 vsc8584_macsec_flow_enable(phydev, flow);
2344 /* Add a rule to let the MKA traffic go through, egress */
2345 flow = vsc8584_macsec_alloc_flow(phydev->priv, MACSEC_EGR);
2346 if (IS_ERR(flow))
2347 return PTR_ERR(flow);
2349 flow->priority = 15;
2350 flow->port = MSCC_MS_PORT_COMMON;
2351 flow->match.untagged = 1;
2352 flow->match.etype = 1;
2353 flow->etype = ETH_P_PAE;
2354 flow->action.bypass = 1;
2356 vsc8584_macsec_flow(phydev, flow);
2357 vsc8584_macsec_flow_enable(phydev, flow);
2359 return 0;
2362 static void vsc8584_macsec_del_flow(struct phy_device *phydev,
2363 struct macsec_flow *flow)
2365 vsc8584_macsec_flow_disable(phydev, flow);
2366 vsc8584_macsec_free_flow(phydev->priv, flow);
2369 static int __vsc8584_macsec_add_rxsa(struct macsec_context *ctx,
2370 struct macsec_flow *flow, bool update)
2372 struct phy_device *phydev = ctx->phydev;
2373 struct vsc8531_private *priv = phydev->priv;
2375 if (!flow) {
2376 flow = vsc8584_macsec_alloc_flow(priv, MACSEC_INGR);
2377 if (IS_ERR(flow))
2378 return PTR_ERR(flow);
2380 memcpy(flow->key, ctx->sa.key, priv->secy->key_len);
2383 flow->assoc_num = ctx->sa.assoc_num;
2384 flow->rx_sa = ctx->sa.rx_sa;
2386 /* Always match tagged packets on ingress */
2387 flow->match.tagged = 1;
2388 flow->match.sci = 1;
2390 if (priv->secy->validate_frames != MACSEC_VALIDATE_DISABLED)
2391 flow->match.untagged = 1;
2393 return vsc8584_macsec_add_flow(phydev, flow, update);
2396 static int __vsc8584_macsec_add_txsa(struct macsec_context *ctx,
2397 struct macsec_flow *flow, bool update)
2399 struct phy_device *phydev = ctx->phydev;
2400 struct vsc8531_private *priv = phydev->priv;
2402 if (!flow) {
2403 flow = vsc8584_macsec_alloc_flow(priv, MACSEC_EGR);
2404 if (IS_ERR(flow))
2405 return PTR_ERR(flow);
2407 memcpy(flow->key, ctx->sa.key, priv->secy->key_len);
2410 flow->assoc_num = ctx->sa.assoc_num;
2411 flow->tx_sa = ctx->sa.tx_sa;
2413 /* Always match untagged packets on egress */
2414 flow->match.untagged = 1;
2416 return vsc8584_macsec_add_flow(phydev, flow, update);
2419 static int vsc8584_macsec_dev_open(struct macsec_context *ctx)
2421 struct vsc8531_private *priv = ctx->phydev->priv;
2422 struct macsec_flow *flow, *tmp;
2424 /* No operation to perform before the commit step */
2425 if (ctx->prepare)
2426 return 0;
2428 list_for_each_entry_safe(flow, tmp, &priv->macsec_flows, list)
2429 vsc8584_macsec_flow_enable(ctx->phydev, flow);
2431 return 0;
2434 static int vsc8584_macsec_dev_stop(struct macsec_context *ctx)
2436 struct vsc8531_private *priv = ctx->phydev->priv;
2437 struct macsec_flow *flow, *tmp;
2439 /* No operation to perform before the commit step */
2440 if (ctx->prepare)
2441 return 0;
2443 list_for_each_entry_safe(flow, tmp, &priv->macsec_flows, list)
2444 vsc8584_macsec_flow_disable(ctx->phydev, flow);
2446 return 0;
2449 static int vsc8584_macsec_add_secy(struct macsec_context *ctx)
2451 struct vsc8531_private *priv = ctx->phydev->priv;
2452 struct macsec_secy *secy = ctx->secy;
2454 if (ctx->prepare) {
2455 if (priv->secy)
2456 return -EEXIST;
2458 return 0;
2461 priv->secy = secy;
2463 vsc8584_macsec_flow_default_action(ctx->phydev, MACSEC_EGR,
2464 secy->validate_frames != MACSEC_VALIDATE_DISABLED);
2465 vsc8584_macsec_flow_default_action(ctx->phydev, MACSEC_INGR,
2466 secy->validate_frames != MACSEC_VALIDATE_DISABLED);
2468 return vsc8584_macsec_default_flows(ctx->phydev);
2471 static int vsc8584_macsec_del_secy(struct macsec_context *ctx)
2473 struct vsc8531_private *priv = ctx->phydev->priv;
2474 struct macsec_flow *flow, *tmp;
2476 /* No operation to perform before the commit step */
2477 if (ctx->prepare)
2478 return 0;
2480 list_for_each_entry_safe(flow, tmp, &priv->macsec_flows, list)
2481 vsc8584_macsec_del_flow(ctx->phydev, flow);
2483 vsc8584_macsec_flow_default_action(ctx->phydev, MACSEC_EGR, false);
2484 vsc8584_macsec_flow_default_action(ctx->phydev, MACSEC_INGR, false);
2486 priv->secy = NULL;
2487 return 0;
2490 static int vsc8584_macsec_upd_secy(struct macsec_context *ctx)
2492 /* No operation to perform before the commit step */
2493 if (ctx->prepare)
2494 return 0;
2496 vsc8584_macsec_del_secy(ctx);
2497 return vsc8584_macsec_add_secy(ctx);
2500 static int vsc8584_macsec_add_rxsc(struct macsec_context *ctx)
2502 /* Nothing to do */
2503 return 0;
2506 static int vsc8584_macsec_upd_rxsc(struct macsec_context *ctx)
2508 return -EOPNOTSUPP;
2511 static int vsc8584_macsec_del_rxsc(struct macsec_context *ctx)
2513 struct vsc8531_private *priv = ctx->phydev->priv;
2514 struct macsec_flow *flow, *tmp;
2516 /* No operation to perform before the commit step */
2517 if (ctx->prepare)
2518 return 0;
2520 list_for_each_entry_safe(flow, tmp, &priv->macsec_flows, list) {
2521 if (flow->bank == MACSEC_INGR && flow->rx_sa &&
2522 flow->rx_sa->sc->sci == ctx->rx_sc->sci)
2523 vsc8584_macsec_del_flow(ctx->phydev, flow);
2526 return 0;
2529 static int vsc8584_macsec_add_rxsa(struct macsec_context *ctx)
2531 struct macsec_flow *flow = NULL;
2533 if (ctx->prepare)
2534 return __vsc8584_macsec_add_rxsa(ctx, flow, false);
2536 flow = vsc8584_macsec_find_flow(ctx, MACSEC_INGR);
2537 if (IS_ERR(flow))
2538 return PTR_ERR(flow);
2540 vsc8584_macsec_flow_enable(ctx->phydev, flow);
2541 return 0;
2544 static int vsc8584_macsec_upd_rxsa(struct macsec_context *ctx)
2546 struct macsec_flow *flow;
2548 flow = vsc8584_macsec_find_flow(ctx, MACSEC_INGR);
2549 if (IS_ERR(flow))
2550 return PTR_ERR(flow);
2552 if (ctx->prepare) {
2553 /* Make sure the flow is disabled before updating it */
2554 vsc8584_macsec_flow_disable(ctx->phydev, flow);
2556 return __vsc8584_macsec_add_rxsa(ctx, flow, true);
2559 vsc8584_macsec_flow_enable(ctx->phydev, flow);
2560 return 0;
2563 static int vsc8584_macsec_del_rxsa(struct macsec_context *ctx)
2565 struct macsec_flow *flow;
2567 flow = vsc8584_macsec_find_flow(ctx, MACSEC_INGR);
2569 if (IS_ERR(flow))
2570 return PTR_ERR(flow);
2571 if (ctx->prepare)
2572 return 0;
2574 vsc8584_macsec_del_flow(ctx->phydev, flow);
2575 return 0;
2578 static int vsc8584_macsec_add_txsa(struct macsec_context *ctx)
2580 struct macsec_flow *flow = NULL;
2582 if (ctx->prepare)
2583 return __vsc8584_macsec_add_txsa(ctx, flow, false);
2585 flow = vsc8584_macsec_find_flow(ctx, MACSEC_EGR);
2586 if (IS_ERR(flow))
2587 return PTR_ERR(flow);
2589 vsc8584_macsec_flow_enable(ctx->phydev, flow);
2590 return 0;
2593 static int vsc8584_macsec_upd_txsa(struct macsec_context *ctx)
2595 struct macsec_flow *flow;
2597 flow = vsc8584_macsec_find_flow(ctx, MACSEC_EGR);
2598 if (IS_ERR(flow))
2599 return PTR_ERR(flow);
2601 if (ctx->prepare) {
2602 /* Make sure the flow is disabled before updating it */
2603 vsc8584_macsec_flow_disable(ctx->phydev, flow);
2605 return __vsc8584_macsec_add_txsa(ctx, flow, true);
2608 vsc8584_macsec_flow_enable(ctx->phydev, flow);
2609 return 0;
2612 static int vsc8584_macsec_del_txsa(struct macsec_context *ctx)
2614 struct macsec_flow *flow;
2616 flow = vsc8584_macsec_find_flow(ctx, MACSEC_EGR);
2618 if (IS_ERR(flow))
2619 return PTR_ERR(flow);
2620 if (ctx->prepare)
2621 return 0;
2623 vsc8584_macsec_del_flow(ctx->phydev, flow);
2624 return 0;
2627 static struct macsec_ops vsc8584_macsec_ops = {
2628 .mdo_dev_open = vsc8584_macsec_dev_open,
2629 .mdo_dev_stop = vsc8584_macsec_dev_stop,
2630 .mdo_add_secy = vsc8584_macsec_add_secy,
2631 .mdo_upd_secy = vsc8584_macsec_upd_secy,
2632 .mdo_del_secy = vsc8584_macsec_del_secy,
2633 .mdo_add_rxsc = vsc8584_macsec_add_rxsc,
2634 .mdo_upd_rxsc = vsc8584_macsec_upd_rxsc,
2635 .mdo_del_rxsc = vsc8584_macsec_del_rxsc,
2636 .mdo_add_rxsa = vsc8584_macsec_add_rxsa,
2637 .mdo_upd_rxsa = vsc8584_macsec_upd_rxsa,
2638 .mdo_del_rxsa = vsc8584_macsec_del_rxsa,
2639 .mdo_add_txsa = vsc8584_macsec_add_txsa,
2640 .mdo_upd_txsa = vsc8584_macsec_upd_txsa,
2641 .mdo_del_txsa = vsc8584_macsec_del_txsa,
2643 #endif /* CONFIG_MACSEC */
2645 /* Check if one PHY has already done the init of the parts common to all PHYs
2646 * in the Quad PHY package.
2648 static bool vsc8584_is_pkg_init(struct phy_device *phydev, bool reversed)
2650 struct mdio_device **map = phydev->mdio.bus->mdio_map;
2651 struct vsc8531_private *vsc8531;
2652 struct phy_device *phy;
2653 int i, addr;
2655 /* VSC8584 is a Quad PHY */
2656 for (i = 0; i < 4; i++) {
2657 vsc8531 = phydev->priv;
2659 if (reversed)
2660 addr = vsc8531->base_addr - i;
2661 else
2662 addr = vsc8531->base_addr + i;
2664 if (!map[addr])
2665 continue;
2667 phy = container_of(map[addr], struct phy_device, mdio);
2669 if ((phy->phy_id & phydev->drv->phy_id_mask) !=
2670 (phydev->drv->phy_id & phydev->drv->phy_id_mask))
2671 continue;
2673 vsc8531 = phy->priv;
2675 if (vsc8531 && vsc8531->pkg_init)
2676 return true;
2679 return false;
2682 static int vsc8584_config_init(struct phy_device *phydev)
2684 struct vsc8531_private *vsc8531 = phydev->priv;
2685 u16 addr, val;
2686 int ret, i;
2688 phydev->mdix_ctrl = ETH_TP_MDI_AUTO;
2690 mutex_lock(&phydev->mdio.bus->mdio_lock);
2692 __mdiobus_write(phydev->mdio.bus, phydev->mdio.addr,
2693 MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_EXTENDED);
2694 addr = __mdiobus_read(phydev->mdio.bus, phydev->mdio.addr,
2695 MSCC_PHY_EXT_PHY_CNTL_4);
2696 addr >>= PHY_CNTL_4_ADDR_POS;
2698 val = __mdiobus_read(phydev->mdio.bus, phydev->mdio.addr,
2699 MSCC_PHY_ACTIPHY_CNTL);
2700 if (val & PHY_ADDR_REVERSED)
2701 vsc8531->base_addr = phydev->mdio.addr + addr;
2702 else
2703 vsc8531->base_addr = phydev->mdio.addr - addr;
2705 /* Some parts of the init sequence are identical for every PHY in the
2706 * package. Some parts are modifying the GPIO register bank which is a
2707 * set of registers that are affecting all PHYs, a few resetting the
2708 * microprocessor common to all PHYs. The CRC check responsible of the
2709 * checking the firmware within the 8051 microprocessor can only be
2710 * accessed via the PHY whose internal address in the package is 0.
2711 * All PHYs' interrupts mask register has to be zeroed before enabling
2712 * any PHY's interrupt in this register.
2713 * For all these reasons, we need to do the init sequence once and only
2714 * once whatever is the first PHY in the package that is initialized and
2715 * do the correct init sequence for all PHYs that are package-critical
2716 * in this pre-init function.
2718 if (!vsc8584_is_pkg_init(phydev, val & PHY_ADDR_REVERSED ? 1 : 0)) {
2719 /* The following switch statement assumes that the lowest
2720 * nibble of the phy_id_mask is always 0. This works because
2721 * the lowest nibble of the PHY_ID's below are also 0.
2723 WARN_ON(phydev->drv->phy_id_mask & 0xf);
2725 switch (phydev->phy_id & phydev->drv->phy_id_mask) {
2726 case PHY_ID_VSC8504:
2727 case PHY_ID_VSC8552:
2728 case PHY_ID_VSC8572:
2729 case PHY_ID_VSC8574:
2730 ret = vsc8574_config_pre_init(phydev);
2731 break;
2732 case PHY_ID_VSC856X:
2733 case PHY_ID_VSC8575:
2734 case PHY_ID_VSC8582:
2735 case PHY_ID_VSC8584:
2736 ret = vsc8584_config_pre_init(phydev);
2737 break;
2738 default:
2739 ret = -EINVAL;
2740 break;
2743 if (ret)
2744 goto err;
2747 vsc8531->pkg_init = true;
2749 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS,
2750 MSCC_PHY_PAGE_EXTENDED_GPIO);
2752 val = phy_base_read(phydev, MSCC_PHY_MAC_CFG_FASTLINK);
2753 val &= ~MAC_CFG_MASK;
2754 if (phydev->interface == PHY_INTERFACE_MODE_QSGMII)
2755 val |= MAC_CFG_QSGMII;
2756 else
2757 val |= MAC_CFG_SGMII;
2759 ret = phy_base_write(phydev, MSCC_PHY_MAC_CFG_FASTLINK, val);
2760 if (ret)
2761 goto err;
2763 val = PROC_CMD_MCB_ACCESS_MAC_CONF | PROC_CMD_RST_CONF_PORT |
2764 PROC_CMD_READ_MOD_WRITE_PORT;
2765 if (phydev->interface == PHY_INTERFACE_MODE_QSGMII)
2766 val |= PROC_CMD_QSGMII_MAC;
2767 else
2768 val |= PROC_CMD_SGMII_MAC;
2770 ret = vsc8584_cmd(phydev, val);
2771 if (ret)
2772 goto err;
2774 usleep_range(10000, 20000);
2776 /* Disable SerDes for 100Base-FX */
2777 ret = vsc8584_cmd(phydev, PROC_CMD_FIBER_MEDIA_CONF |
2778 PROC_CMD_FIBER_PORT(addr) | PROC_CMD_FIBER_DISABLE |
2779 PROC_CMD_READ_MOD_WRITE_PORT |
2780 PROC_CMD_RST_CONF_PORT | PROC_CMD_FIBER_100BASE_FX);
2781 if (ret)
2782 goto err;
2784 /* Disable SerDes for 1000Base-X */
2785 ret = vsc8584_cmd(phydev, PROC_CMD_FIBER_MEDIA_CONF |
2786 PROC_CMD_FIBER_PORT(addr) | PROC_CMD_FIBER_DISABLE |
2787 PROC_CMD_READ_MOD_WRITE_PORT |
2788 PROC_CMD_RST_CONF_PORT | PROC_CMD_FIBER_1000BASE_X);
2789 if (ret)
2790 goto err;
2792 mutex_unlock(&phydev->mdio.bus->mdio_lock);
2794 #if IS_ENABLED(CONFIG_MACSEC)
2795 /* MACsec */
2796 switch (phydev->phy_id & phydev->drv->phy_id_mask) {
2797 case PHY_ID_VSC856X:
2798 case PHY_ID_VSC8575:
2799 case PHY_ID_VSC8582:
2800 case PHY_ID_VSC8584:
2801 INIT_LIST_HEAD(&vsc8531->macsec_flows);
2802 vsc8531->secy = NULL;
2804 phydev->macsec_ops = &vsc8584_macsec_ops;
2806 ret = vsc8584_macsec_init(phydev);
2807 if (ret)
2808 goto err;
2810 #endif
2812 phy_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
2814 val = phy_read(phydev, MSCC_PHY_EXT_PHY_CNTL_1);
2815 val &= ~(MEDIA_OP_MODE_MASK | VSC8584_MAC_IF_SELECTION_MASK);
2816 val |= MEDIA_OP_MODE_COPPER | (VSC8584_MAC_IF_SELECTION_SGMII <<
2817 VSC8584_MAC_IF_SELECTION_POS);
2818 ret = phy_write(phydev, MSCC_PHY_EXT_PHY_CNTL_1, val);
2820 ret = genphy_soft_reset(phydev);
2821 if (ret)
2822 return ret;
2824 for (i = 0; i < vsc8531->nleds; i++) {
2825 ret = vsc85xx_led_cntl_set(phydev, i, vsc8531->leds_mode[i]);
2826 if (ret)
2827 return ret;
2830 return 0;
2832 err:
2833 mutex_unlock(&phydev->mdio.bus->mdio_lock);
2834 return ret;
2837 static int vsc8584_handle_interrupt(struct phy_device *phydev)
2839 #if IS_ENABLED(CONFIG_MACSEC)
2840 struct vsc8531_private *priv = phydev->priv;
2841 struct macsec_flow *flow, *tmp;
2842 u32 cause, rec;
2844 /* Check MACsec PN rollover */
2845 cause = vsc8584_macsec_phy_read(phydev, MACSEC_EGR,
2846 MSCC_MS_INTR_CTRL_STATUS);
2847 cause &= MSCC_MS_INTR_CTRL_STATUS_INTR_CLR_STATUS_M;
2848 if (!(cause & MACSEC_INTR_CTRL_STATUS_ROLLOVER))
2849 goto skip_rollover;
2851 rec = 6 + priv->secy->key_len / sizeof(u32);
2852 list_for_each_entry_safe(flow, tmp, &priv->macsec_flows, list) {
2853 u32 val;
2855 if (flow->bank != MACSEC_EGR || !flow->has_transformation)
2856 continue;
2858 val = vsc8584_macsec_phy_read(phydev, MACSEC_EGR,
2859 MSCC_MS_XFORM_REC(flow->index, rec));
2860 if (val == 0xffffffff) {
2861 vsc8584_macsec_flow_disable(phydev, flow);
2862 macsec_pn_wrapped(priv->secy, flow->tx_sa);
2863 break;
2867 skip_rollover:
2868 #endif
2870 phy_mac_interrupt(phydev);
2871 return 0;
2874 static int vsc85xx_config_init(struct phy_device *phydev)
2876 int rc, i, phy_id;
2877 struct vsc8531_private *vsc8531 = phydev->priv;
2879 rc = vsc85xx_default_config(phydev);
2880 if (rc)
2881 return rc;
2883 rc = vsc85xx_mac_if_set(phydev, phydev->interface);
2884 if (rc)
2885 return rc;
2887 rc = vsc85xx_edge_rate_cntl_set(phydev, vsc8531->rate_magic);
2888 if (rc)
2889 return rc;
2891 phy_id = phydev->drv->phy_id & phydev->drv->phy_id_mask;
2892 if (PHY_ID_VSC8531 == phy_id || PHY_ID_VSC8541 == phy_id ||
2893 PHY_ID_VSC8530 == phy_id || PHY_ID_VSC8540 == phy_id) {
2894 rc = vsc8531_pre_init_seq_set(phydev);
2895 if (rc)
2896 return rc;
2899 rc = vsc85xx_eee_init_seq_set(phydev);
2900 if (rc)
2901 return rc;
2903 for (i = 0; i < vsc8531->nleds; i++) {
2904 rc = vsc85xx_led_cntl_set(phydev, i, vsc8531->leds_mode[i]);
2905 if (rc)
2906 return rc;
2909 return 0;
2912 static int vsc8584_did_interrupt(struct phy_device *phydev)
2914 int rc = 0;
2916 if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
2917 rc = phy_read(phydev, MII_VSC85XX_INT_STATUS);
2919 return (rc < 0) ? 0 : rc & MII_VSC85XX_INT_MASK_MASK;
2922 static int vsc8514_config_pre_init(struct phy_device *phydev)
2924 /* These are the settings to override the silicon default
2925 * values to handle hardware performance of PHY. They
2926 * are set at Power-On state and remain until PHY Reset.
2928 static const struct reg_val pre_init1[] = {
2929 {0x0f90, 0x00688980},
2930 {0x0786, 0x00000003},
2931 {0x07fa, 0x0050100f},
2932 {0x0f82, 0x0012b002},
2933 {0x1686, 0x00000004},
2934 {0x168c, 0x00d2c46f},
2935 {0x17a2, 0x00000620},
2936 {0x16a0, 0x00eeffdd},
2937 {0x16a6, 0x00071448},
2938 {0x16a4, 0x0013132f},
2939 {0x16a8, 0x00000000},
2940 {0x0ffc, 0x00c0a028},
2941 {0x0fe8, 0x0091b06c},
2942 {0x0fea, 0x00041600},
2943 {0x0f80, 0x00fffaff},
2944 {0x0fec, 0x00901809},
2945 {0x0ffe, 0x00b01007},
2946 {0x16b0, 0x00eeff00},
2947 {0x16b2, 0x00007000},
2948 {0x16b4, 0x00000814},
2950 unsigned int i;
2951 u16 reg;
2953 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
2955 /* all writes below are broadcasted to all PHYs in the same package */
2956 reg = phy_base_read(phydev, MSCC_PHY_EXT_CNTL_STATUS);
2957 reg |= SMI_BROADCAST_WR_EN;
2958 phy_base_write(phydev, MSCC_PHY_EXT_CNTL_STATUS, reg);
2960 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_TEST);
2962 reg = phy_base_read(phydev, MSCC_PHY_TEST_PAGE_8);
2963 reg |= BIT(15);
2964 phy_base_write(phydev, MSCC_PHY_TEST_PAGE_8, reg);
2966 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_TR);
2968 for (i = 0; i < ARRAY_SIZE(pre_init1); i++)
2969 vsc8584_csr_write(phydev, pre_init1[i].reg, pre_init1[i].val);
2971 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_TEST);
2973 reg = phy_base_read(phydev, MSCC_PHY_TEST_PAGE_8);
2974 reg &= ~BIT(15);
2975 phy_base_write(phydev, MSCC_PHY_TEST_PAGE_8, reg);
2977 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
2979 reg = phy_base_read(phydev, MSCC_PHY_EXT_CNTL_STATUS);
2980 reg &= ~SMI_BROADCAST_WR_EN;
2981 phy_base_write(phydev, MSCC_PHY_EXT_CNTL_STATUS, reg);
2983 return 0;
2986 static u32 vsc85xx_csr_ctrl_phy_read(struct phy_device *phydev,
2987 u32 target, u32 reg)
2989 unsigned long deadline;
2990 u32 val, val_l, val_h;
2992 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_CSR_CNTL);
2994 /* CSR registers are grouped under different Target IDs.
2995 * 6-bit Target_ID is split between MSCC_EXT_PAGE_CSR_CNTL_20 and
2996 * MSCC_EXT_PAGE_CSR_CNTL_19 registers.
2997 * Target_ID[5:2] maps to bits[3:0] of MSCC_EXT_PAGE_CSR_CNTL_20
2998 * and Target_ID[1:0] maps to bits[13:12] of MSCC_EXT_PAGE_CSR_CNTL_19.
3001 /* Setup the Target ID */
3002 phy_base_write(phydev, MSCC_EXT_PAGE_CSR_CNTL_20,
3003 MSCC_PHY_CSR_CNTL_20_TARGET(target >> 2));
3005 /* Trigger CSR Action - Read into the CSR's */
3006 phy_base_write(phydev, MSCC_EXT_PAGE_CSR_CNTL_19,
3007 MSCC_PHY_CSR_CNTL_19_CMD | MSCC_PHY_CSR_CNTL_19_READ |
3008 MSCC_PHY_CSR_CNTL_19_REG_ADDR(reg) |
3009 MSCC_PHY_CSR_CNTL_19_TARGET(target & 0x3));
3011 /* Wait for register access*/
3012 deadline = jiffies + msecs_to_jiffies(PROC_CMD_NCOMPLETED_TIMEOUT_MS);
3013 do {
3014 usleep_range(500, 1000);
3015 val = phy_base_read(phydev, MSCC_EXT_PAGE_CSR_CNTL_19);
3016 } while (time_before(jiffies, deadline) &&
3017 !(val & MSCC_PHY_CSR_CNTL_19_CMD));
3019 if (!(val & MSCC_PHY_CSR_CNTL_19_CMD))
3020 return 0xffffffff;
3022 /* Read the Least Significant Word (LSW) (17) */
3023 val_l = phy_base_read(phydev, MSCC_EXT_PAGE_CSR_CNTL_17);
3025 /* Read the Most Significant Word (MSW) (18) */
3026 val_h = phy_base_read(phydev, MSCC_EXT_PAGE_CSR_CNTL_18);
3028 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS,
3029 MSCC_PHY_PAGE_STANDARD);
3031 return (val_h << 16) | val_l;
3034 static int vsc85xx_csr_ctrl_phy_write(struct phy_device *phydev,
3035 u32 target, u32 reg, u32 val)
3037 unsigned long deadline;
3039 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_CSR_CNTL);
3041 /* CSR registers are grouped under different Target IDs.
3042 * 6-bit Target_ID is split between MSCC_EXT_PAGE_CSR_CNTL_20 and
3043 * MSCC_EXT_PAGE_CSR_CNTL_19 registers.
3044 * Target_ID[5:2] maps to bits[3:0] of MSCC_EXT_PAGE_CSR_CNTL_20
3045 * and Target_ID[1:0] maps to bits[13:12] of MSCC_EXT_PAGE_CSR_CNTL_19.
3048 /* Setup the Target ID */
3049 phy_base_write(phydev, MSCC_EXT_PAGE_CSR_CNTL_20,
3050 MSCC_PHY_CSR_CNTL_20_TARGET(target >> 2));
3052 /* Write the Least Significant Word (LSW) (17) */
3053 phy_base_write(phydev, MSCC_EXT_PAGE_CSR_CNTL_17, (u16)val);
3055 /* Write the Most Significant Word (MSW) (18) */
3056 phy_base_write(phydev, MSCC_EXT_PAGE_CSR_CNTL_18, (u16)(val >> 16));
3058 /* Trigger CSR Action - Write into the CSR's */
3059 phy_base_write(phydev, MSCC_EXT_PAGE_CSR_CNTL_19,
3060 MSCC_PHY_CSR_CNTL_19_CMD |
3061 MSCC_PHY_CSR_CNTL_19_REG_ADDR(reg) |
3062 MSCC_PHY_CSR_CNTL_19_TARGET(target & 0x3));
3064 /* Wait for register access */
3065 deadline = jiffies + msecs_to_jiffies(PROC_CMD_NCOMPLETED_TIMEOUT_MS);
3066 do {
3067 usleep_range(500, 1000);
3068 val = phy_base_read(phydev, MSCC_EXT_PAGE_CSR_CNTL_19);
3069 } while (time_before(jiffies, deadline) &&
3070 !(val & MSCC_PHY_CSR_CNTL_19_CMD));
3072 if (!(val & MSCC_PHY_CSR_CNTL_19_CMD))
3073 return -ETIMEDOUT;
3075 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS,
3076 MSCC_PHY_PAGE_STANDARD);
3078 return 0;
3081 static int __phy_write_mcb_s6g(struct phy_device *phydev, u32 reg, u8 mcb,
3082 u32 op)
3084 unsigned long deadline;
3085 u32 val;
3086 int ret;
3088 ret = vsc85xx_csr_ctrl_phy_write(phydev, PHY_MCB_TARGET, reg,
3089 op | (1 << mcb));
3090 if (ret)
3091 return -EINVAL;
3093 deadline = jiffies + msecs_to_jiffies(PROC_CMD_NCOMPLETED_TIMEOUT_MS);
3094 do {
3095 usleep_range(500, 1000);
3096 val = vsc85xx_csr_ctrl_phy_read(phydev, PHY_MCB_TARGET, reg);
3098 if (val == 0xffffffff)
3099 return -EIO;
3101 } while (time_before(jiffies, deadline) && (val & op));
3103 if (val & op)
3104 return -ETIMEDOUT;
3106 return 0;
3109 /* Trigger a read to the spcified MCB */
3110 static int phy_update_mcb_s6g(struct phy_device *phydev, u32 reg, u8 mcb)
3112 return __phy_write_mcb_s6g(phydev, reg, mcb, PHY_MCB_S6G_READ);
3115 /* Trigger a write to the spcified MCB */
3116 static int phy_commit_mcb_s6g(struct phy_device *phydev, u32 reg, u8 mcb)
3118 return __phy_write_mcb_s6g(phydev, reg, mcb, PHY_MCB_S6G_WRITE);
3121 static int vsc8514_config_init(struct phy_device *phydev)
3123 struct vsc8531_private *vsc8531 = phydev->priv;
3124 unsigned long deadline;
3125 u16 val, addr;
3126 int ret, i;
3127 u32 reg;
3129 phydev->mdix_ctrl = ETH_TP_MDI_AUTO;
3131 mutex_lock(&phydev->mdio.bus->mdio_lock);
3133 __phy_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_EXTENDED);
3135 addr = __phy_read(phydev, MSCC_PHY_EXT_PHY_CNTL_4);
3136 addr >>= PHY_CNTL_4_ADDR_POS;
3138 val = __phy_read(phydev, MSCC_PHY_ACTIPHY_CNTL);
3140 if (val & PHY_ADDR_REVERSED)
3141 vsc8531->base_addr = phydev->mdio.addr + addr;
3142 else
3143 vsc8531->base_addr = phydev->mdio.addr - addr;
3145 /* Some parts of the init sequence are identical for every PHY in the
3146 * package. Some parts are modifying the GPIO register bank which is a
3147 * set of registers that are affecting all PHYs, a few resetting the
3148 * microprocessor common to all PHYs.
3149 * All PHYs' interrupts mask register has to be zeroed before enabling
3150 * any PHY's interrupt in this register.
3151 * For all these reasons, we need to do the init sequence once and only
3152 * once whatever is the first PHY in the package that is initialized and
3153 * do the correct init sequence for all PHYs that are package-critical
3154 * in this pre-init function.
3156 if (!vsc8584_is_pkg_init(phydev, val & PHY_ADDR_REVERSED ? 1 : 0))
3157 vsc8514_config_pre_init(phydev);
3159 vsc8531->pkg_init = true;
3161 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS,
3162 MSCC_PHY_PAGE_EXTENDED_GPIO);
3164 val = phy_base_read(phydev, MSCC_PHY_MAC_CFG_FASTLINK);
3166 val &= ~MAC_CFG_MASK;
3167 val |= MAC_CFG_QSGMII;
3168 ret = phy_base_write(phydev, MSCC_PHY_MAC_CFG_FASTLINK, val);
3170 if (ret)
3171 goto err;
3173 ret = vsc8584_cmd(phydev,
3174 PROC_CMD_MCB_ACCESS_MAC_CONF |
3175 PROC_CMD_RST_CONF_PORT |
3176 PROC_CMD_READ_MOD_WRITE_PORT | PROC_CMD_QSGMII_MAC);
3177 if (ret)
3178 goto err;
3180 /* 6g mcb */
3181 phy_update_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0);
3182 /* lcpll mcb */
3183 phy_update_mcb_s6g(phydev, PHY_S6G_LCPLL_CFG, 0);
3184 /* pll5gcfg0 */
3185 ret = vsc85xx_csr_ctrl_phy_write(phydev, PHY_MCB_TARGET,
3186 PHY_S6G_PLL5G_CFG0, 0x7036f145);
3187 if (ret)
3188 goto err;
3190 phy_commit_mcb_s6g(phydev, PHY_S6G_LCPLL_CFG, 0);
3191 /* pllcfg */
3192 ret = vsc85xx_csr_ctrl_phy_write(phydev, PHY_MCB_TARGET,
3193 PHY_S6G_PLL_CFG,
3194 (3 << PHY_S6G_PLL_ENA_OFFS_POS) |
3195 (120 << PHY_S6G_PLL_FSM_CTRL_DATA_POS)
3196 | (0 << PHY_S6G_PLL_FSM_ENA_POS));
3197 if (ret)
3198 goto err;
3200 /* commoncfg */
3201 ret = vsc85xx_csr_ctrl_phy_write(phydev, PHY_MCB_TARGET,
3202 PHY_S6G_COMMON_CFG,
3203 (0 << PHY_S6G_SYS_RST_POS) |
3204 (0 << PHY_S6G_ENA_LANE_POS) |
3205 (0 << PHY_S6G_ENA_LOOP_POS) |
3206 (0 << PHY_S6G_QRATE_POS) |
3207 (3 << PHY_S6G_IF_MODE_POS));
3208 if (ret)
3209 goto err;
3211 /* misccfg */
3212 ret = vsc85xx_csr_ctrl_phy_write(phydev, PHY_MCB_TARGET,
3213 PHY_S6G_MISC_CFG, 1);
3214 if (ret)
3215 goto err;
3217 /* gpcfg */
3218 ret = vsc85xx_csr_ctrl_phy_write(phydev, PHY_MCB_TARGET,
3219 PHY_S6G_GPC_CFG, 768);
3220 if (ret)
3221 goto err;
3223 phy_commit_mcb_s6g(phydev, PHY_S6G_DFT_CFG2, 0);
3225 deadline = jiffies + msecs_to_jiffies(PROC_CMD_NCOMPLETED_TIMEOUT_MS);
3226 do {
3227 usleep_range(500, 1000);
3228 phy_update_mcb_s6g(phydev, PHY_MCB_S6G_CFG,
3229 0); /* read 6G MCB into CSRs */
3230 reg = vsc85xx_csr_ctrl_phy_read(phydev, PHY_MCB_TARGET,
3231 PHY_S6G_PLL_STATUS);
3232 if (reg == 0xffffffff) {
3233 mutex_unlock(&phydev->mdio.bus->mdio_lock);
3234 return -EIO;
3237 } while (time_before(jiffies, deadline) && (reg & BIT(12)));
3239 if (reg & BIT(12)) {
3240 mutex_unlock(&phydev->mdio.bus->mdio_lock);
3241 return -ETIMEDOUT;
3244 /* misccfg */
3245 ret = vsc85xx_csr_ctrl_phy_write(phydev, PHY_MCB_TARGET,
3246 PHY_S6G_MISC_CFG, 0);
3247 if (ret)
3248 goto err;
3250 phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0);
3252 deadline = jiffies + msecs_to_jiffies(PROC_CMD_NCOMPLETED_TIMEOUT_MS);
3253 do {
3254 usleep_range(500, 1000);
3255 phy_update_mcb_s6g(phydev, PHY_MCB_S6G_CFG,
3256 0); /* read 6G MCB into CSRs */
3257 reg = vsc85xx_csr_ctrl_phy_read(phydev, PHY_MCB_TARGET,
3258 PHY_S6G_IB_STATUS0);
3259 if (reg == 0xffffffff) {
3260 mutex_unlock(&phydev->mdio.bus->mdio_lock);
3261 return -EIO;
3264 } while (time_before(jiffies, deadline) && !(reg & BIT(8)));
3266 if (!(reg & BIT(8))) {
3267 mutex_unlock(&phydev->mdio.bus->mdio_lock);
3268 return -ETIMEDOUT;
3271 mutex_unlock(&phydev->mdio.bus->mdio_lock);
3273 ret = phy_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
3275 if (ret)
3276 return ret;
3278 ret = phy_modify(phydev, MSCC_PHY_EXT_PHY_CNTL_1, MEDIA_OP_MODE_MASK,
3279 MEDIA_OP_MODE_COPPER);
3281 if (ret)
3282 return ret;
3284 ret = genphy_soft_reset(phydev);
3286 if (ret)
3287 return ret;
3289 for (i = 0; i < vsc8531->nleds; i++) {
3290 ret = vsc85xx_led_cntl_set(phydev, i, vsc8531->leds_mode[i]);
3291 if (ret)
3292 return ret;
3295 return ret;
3297 err:
3298 mutex_unlock(&phydev->mdio.bus->mdio_lock);
3299 return ret;
3302 static int vsc85xx_ack_interrupt(struct phy_device *phydev)
3304 int rc = 0;
3306 if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
3307 rc = phy_read(phydev, MII_VSC85XX_INT_STATUS);
3309 return (rc < 0) ? rc : 0;
3312 static int vsc85xx_config_intr(struct phy_device *phydev)
3314 int rc;
3316 if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
3317 #if IS_ENABLED(CONFIG_MACSEC)
3318 phy_write(phydev, MSCC_EXT_PAGE_ACCESS,
3319 MSCC_PHY_PAGE_EXTENDED_2);
3320 phy_write(phydev, MSCC_PHY_EXTENDED_INT,
3321 MSCC_PHY_EXTENDED_INT_MS_EGR);
3322 phy_write(phydev, MSCC_EXT_PAGE_ACCESS,
3323 MSCC_PHY_PAGE_STANDARD);
3325 vsc8584_macsec_phy_write(phydev, MACSEC_EGR,
3326 MSCC_MS_AIC_CTRL, 0xf);
3327 vsc8584_macsec_phy_write(phydev, MACSEC_EGR,
3328 MSCC_MS_INTR_CTRL_STATUS,
3329 MSCC_MS_INTR_CTRL_STATUS_INTR_ENABLE(MACSEC_INTR_CTRL_STATUS_ROLLOVER));
3330 #endif
3331 rc = phy_write(phydev, MII_VSC85XX_INT_MASK,
3332 MII_VSC85XX_INT_MASK_MASK);
3333 } else {
3334 rc = phy_write(phydev, MII_VSC85XX_INT_MASK, 0);
3335 if (rc < 0)
3336 return rc;
3337 rc = phy_read(phydev, MII_VSC85XX_INT_STATUS);
3340 return rc;
3343 static int vsc85xx_config_aneg(struct phy_device *phydev)
3345 int rc;
3347 rc = vsc85xx_mdix_set(phydev, phydev->mdix_ctrl);
3348 if (rc < 0)
3349 return rc;
3351 return genphy_config_aneg(phydev);
3354 static int vsc85xx_read_status(struct phy_device *phydev)
3356 int rc;
3358 rc = vsc85xx_mdix_get(phydev, &phydev->mdix);
3359 if (rc < 0)
3360 return rc;
3362 return genphy_read_status(phydev);
3365 static int vsc8514_probe(struct phy_device *phydev)
3367 struct vsc8531_private *vsc8531;
3368 u32 default_mode[4] = {VSC8531_LINK_1000_ACTIVITY,
3369 VSC8531_LINK_100_ACTIVITY, VSC8531_LINK_ACTIVITY,
3370 VSC8531_DUPLEX_COLLISION};
3372 vsc8531 = devm_kzalloc(&phydev->mdio.dev, sizeof(*vsc8531), GFP_KERNEL);
3373 if (!vsc8531)
3374 return -ENOMEM;
3376 phydev->priv = vsc8531;
3378 vsc8531->nleds = 4;
3379 vsc8531->supp_led_modes = VSC85XX_SUPP_LED_MODES;
3380 vsc8531->hw_stats = vsc85xx_hw_stats;
3381 vsc8531->nstats = ARRAY_SIZE(vsc85xx_hw_stats);
3382 vsc8531->stats = devm_kcalloc(&phydev->mdio.dev, vsc8531->nstats,
3383 sizeof(u64), GFP_KERNEL);
3384 if (!vsc8531->stats)
3385 return -ENOMEM;
3387 return vsc85xx_dt_led_modes_get(phydev, default_mode);
3390 static int vsc8574_probe(struct phy_device *phydev)
3392 struct vsc8531_private *vsc8531;
3393 u32 default_mode[4] = {VSC8531_LINK_1000_ACTIVITY,
3394 VSC8531_LINK_100_ACTIVITY, VSC8531_LINK_ACTIVITY,
3395 VSC8531_DUPLEX_COLLISION};
3397 vsc8531 = devm_kzalloc(&phydev->mdio.dev, sizeof(*vsc8531), GFP_KERNEL);
3398 if (!vsc8531)
3399 return -ENOMEM;
3401 phydev->priv = vsc8531;
3403 vsc8531->nleds = 4;
3404 vsc8531->supp_led_modes = VSC8584_SUPP_LED_MODES;
3405 vsc8531->hw_stats = vsc8584_hw_stats;
3406 vsc8531->nstats = ARRAY_SIZE(vsc8584_hw_stats);
3407 vsc8531->stats = devm_kcalloc(&phydev->mdio.dev, vsc8531->nstats,
3408 sizeof(u64), GFP_KERNEL);
3409 if (!vsc8531->stats)
3410 return -ENOMEM;
3412 return vsc85xx_dt_led_modes_get(phydev, default_mode);
3415 static int vsc8584_probe(struct phy_device *phydev)
3417 struct vsc8531_private *vsc8531;
3418 u32 default_mode[4] = {VSC8531_LINK_1000_ACTIVITY,
3419 VSC8531_LINK_100_ACTIVITY, VSC8531_LINK_ACTIVITY,
3420 VSC8531_DUPLEX_COLLISION};
3422 if ((phydev->phy_id & MSCC_DEV_REV_MASK) != VSC8584_REVB) {
3423 dev_err(&phydev->mdio.dev, "Only VSC8584 revB is supported.\n");
3424 return -ENOTSUPP;
3427 vsc8531 = devm_kzalloc(&phydev->mdio.dev, sizeof(*vsc8531), GFP_KERNEL);
3428 if (!vsc8531)
3429 return -ENOMEM;
3431 phydev->priv = vsc8531;
3433 vsc8531->nleds = 4;
3434 vsc8531->supp_led_modes = VSC8584_SUPP_LED_MODES;
3435 vsc8531->hw_stats = vsc8584_hw_stats;
3436 vsc8531->nstats = ARRAY_SIZE(vsc8584_hw_stats);
3437 vsc8531->stats = devm_kcalloc(&phydev->mdio.dev, vsc8531->nstats,
3438 sizeof(u64), GFP_KERNEL);
3439 if (!vsc8531->stats)
3440 return -ENOMEM;
3442 return vsc85xx_dt_led_modes_get(phydev, default_mode);
3445 static int vsc85xx_probe(struct phy_device *phydev)
3447 struct vsc8531_private *vsc8531;
3448 int rate_magic;
3449 u32 default_mode[2] = {VSC8531_LINK_1000_ACTIVITY,
3450 VSC8531_LINK_100_ACTIVITY};
3452 rate_magic = vsc85xx_edge_rate_magic_get(phydev);
3453 if (rate_magic < 0)
3454 return rate_magic;
3456 vsc8531 = devm_kzalloc(&phydev->mdio.dev, sizeof(*vsc8531), GFP_KERNEL);
3457 if (!vsc8531)
3458 return -ENOMEM;
3460 phydev->priv = vsc8531;
3462 vsc8531->rate_magic = rate_magic;
3463 vsc8531->nleds = 2;
3464 vsc8531->supp_led_modes = VSC85XX_SUPP_LED_MODES;
3465 vsc8531->hw_stats = vsc85xx_hw_stats;
3466 vsc8531->nstats = ARRAY_SIZE(vsc85xx_hw_stats);
3467 vsc8531->stats = devm_kcalloc(&phydev->mdio.dev, vsc8531->nstats,
3468 sizeof(u64), GFP_KERNEL);
3469 if (!vsc8531->stats)
3470 return -ENOMEM;
3472 return vsc85xx_dt_led_modes_get(phydev, default_mode);
3475 /* Microsemi VSC85xx PHYs */
3476 static struct phy_driver vsc85xx_driver[] = {
3478 .phy_id = PHY_ID_VSC8504,
3479 .name = "Microsemi GE VSC8504 SyncE",
3480 .phy_id_mask = 0xfffffff0,
3481 /* PHY_GBIT_FEATURES */
3482 .soft_reset = &genphy_soft_reset,
3483 .config_init = &vsc8584_config_init,
3484 .config_aneg = &vsc85xx_config_aneg,
3485 .aneg_done = &genphy_aneg_done,
3486 .read_status = &vsc85xx_read_status,
3487 .ack_interrupt = &vsc85xx_ack_interrupt,
3488 .config_intr = &vsc85xx_config_intr,
3489 .did_interrupt = &vsc8584_did_interrupt,
3490 .suspend = &genphy_suspend,
3491 .resume = &genphy_resume,
3492 .probe = &vsc8574_probe,
3493 .set_wol = &vsc85xx_wol_set,
3494 .get_wol = &vsc85xx_wol_get,
3495 .get_tunable = &vsc85xx_get_tunable,
3496 .set_tunable = &vsc85xx_set_tunable,
3497 .read_page = &vsc85xx_phy_read_page,
3498 .write_page = &vsc85xx_phy_write_page,
3499 .get_sset_count = &vsc85xx_get_sset_count,
3500 .get_strings = &vsc85xx_get_strings,
3501 .get_stats = &vsc85xx_get_stats,
3504 .phy_id = PHY_ID_VSC8514,
3505 .name = "Microsemi GE VSC8514 SyncE",
3506 .phy_id_mask = 0xfffffff0,
3507 .soft_reset = &genphy_soft_reset,
3508 .config_init = &vsc8514_config_init,
3509 .config_aneg = &vsc85xx_config_aneg,
3510 .read_status = &vsc85xx_read_status,
3511 .ack_interrupt = &vsc85xx_ack_interrupt,
3512 .config_intr = &vsc85xx_config_intr,
3513 .suspend = &genphy_suspend,
3514 .resume = &genphy_resume,
3515 .probe = &vsc8514_probe,
3516 .set_wol = &vsc85xx_wol_set,
3517 .get_wol = &vsc85xx_wol_get,
3518 .get_tunable = &vsc85xx_get_tunable,
3519 .set_tunable = &vsc85xx_set_tunable,
3520 .read_page = &vsc85xx_phy_read_page,
3521 .write_page = &vsc85xx_phy_write_page,
3522 .get_sset_count = &vsc85xx_get_sset_count,
3523 .get_strings = &vsc85xx_get_strings,
3524 .get_stats = &vsc85xx_get_stats,
3527 .phy_id = PHY_ID_VSC8530,
3528 .name = "Microsemi FE VSC8530",
3529 .phy_id_mask = 0xfffffff0,
3530 /* PHY_BASIC_FEATURES */
3531 .soft_reset = &genphy_soft_reset,
3532 .config_init = &vsc85xx_config_init,
3533 .config_aneg = &vsc85xx_config_aneg,
3534 .read_status = &vsc85xx_read_status,
3535 .ack_interrupt = &vsc85xx_ack_interrupt,
3536 .config_intr = &vsc85xx_config_intr,
3537 .suspend = &genphy_suspend,
3538 .resume = &genphy_resume,
3539 .probe = &vsc85xx_probe,
3540 .set_wol = &vsc85xx_wol_set,
3541 .get_wol = &vsc85xx_wol_get,
3542 .get_tunable = &vsc85xx_get_tunable,
3543 .set_tunable = &vsc85xx_set_tunable,
3544 .read_page = &vsc85xx_phy_read_page,
3545 .write_page = &vsc85xx_phy_write_page,
3546 .get_sset_count = &vsc85xx_get_sset_count,
3547 .get_strings = &vsc85xx_get_strings,
3548 .get_stats = &vsc85xx_get_stats,
3551 .phy_id = PHY_ID_VSC8531,
3552 .name = "Microsemi VSC8531",
3553 .phy_id_mask = 0xfffffff0,
3554 /* PHY_GBIT_FEATURES */
3555 .soft_reset = &genphy_soft_reset,
3556 .config_init = &vsc85xx_config_init,
3557 .config_aneg = &vsc85xx_config_aneg,
3558 .read_status = &vsc85xx_read_status,
3559 .ack_interrupt = &vsc85xx_ack_interrupt,
3560 .config_intr = &vsc85xx_config_intr,
3561 .suspend = &genphy_suspend,
3562 .resume = &genphy_resume,
3563 .probe = &vsc85xx_probe,
3564 .set_wol = &vsc85xx_wol_set,
3565 .get_wol = &vsc85xx_wol_get,
3566 .get_tunable = &vsc85xx_get_tunable,
3567 .set_tunable = &vsc85xx_set_tunable,
3568 .read_page = &vsc85xx_phy_read_page,
3569 .write_page = &vsc85xx_phy_write_page,
3570 .get_sset_count = &vsc85xx_get_sset_count,
3571 .get_strings = &vsc85xx_get_strings,
3572 .get_stats = &vsc85xx_get_stats,
3575 .phy_id = PHY_ID_VSC8540,
3576 .name = "Microsemi FE VSC8540 SyncE",
3577 .phy_id_mask = 0xfffffff0,
3578 /* PHY_BASIC_FEATURES */
3579 .soft_reset = &genphy_soft_reset,
3580 .config_init = &vsc85xx_config_init,
3581 .config_aneg = &vsc85xx_config_aneg,
3582 .read_status = &vsc85xx_read_status,
3583 .ack_interrupt = &vsc85xx_ack_interrupt,
3584 .config_intr = &vsc85xx_config_intr,
3585 .suspend = &genphy_suspend,
3586 .resume = &genphy_resume,
3587 .probe = &vsc85xx_probe,
3588 .set_wol = &vsc85xx_wol_set,
3589 .get_wol = &vsc85xx_wol_get,
3590 .get_tunable = &vsc85xx_get_tunable,
3591 .set_tunable = &vsc85xx_set_tunable,
3592 .read_page = &vsc85xx_phy_read_page,
3593 .write_page = &vsc85xx_phy_write_page,
3594 .get_sset_count = &vsc85xx_get_sset_count,
3595 .get_strings = &vsc85xx_get_strings,
3596 .get_stats = &vsc85xx_get_stats,
3599 .phy_id = PHY_ID_VSC8541,
3600 .name = "Microsemi VSC8541 SyncE",
3601 .phy_id_mask = 0xfffffff0,
3602 /* PHY_GBIT_FEATURES */
3603 .soft_reset = &genphy_soft_reset,
3604 .config_init = &vsc85xx_config_init,
3605 .config_aneg = &vsc85xx_config_aneg,
3606 .read_status = &vsc85xx_read_status,
3607 .ack_interrupt = &vsc85xx_ack_interrupt,
3608 .config_intr = &vsc85xx_config_intr,
3609 .suspend = &genphy_suspend,
3610 .resume = &genphy_resume,
3611 .probe = &vsc85xx_probe,
3612 .set_wol = &vsc85xx_wol_set,
3613 .get_wol = &vsc85xx_wol_get,
3614 .get_tunable = &vsc85xx_get_tunable,
3615 .set_tunable = &vsc85xx_set_tunable,
3616 .read_page = &vsc85xx_phy_read_page,
3617 .write_page = &vsc85xx_phy_write_page,
3618 .get_sset_count = &vsc85xx_get_sset_count,
3619 .get_strings = &vsc85xx_get_strings,
3620 .get_stats = &vsc85xx_get_stats,
3623 .phy_id = PHY_ID_VSC8552,
3624 .name = "Microsemi GE VSC8552 SyncE",
3625 .phy_id_mask = 0xfffffff0,
3626 /* PHY_GBIT_FEATURES */
3627 .soft_reset = &genphy_soft_reset,
3628 .config_init = &vsc8584_config_init,
3629 .config_aneg = &vsc85xx_config_aneg,
3630 .read_status = &vsc85xx_read_status,
3631 .ack_interrupt = &vsc85xx_ack_interrupt,
3632 .config_intr = &vsc85xx_config_intr,
3633 .did_interrupt = &vsc8584_did_interrupt,
3634 .suspend = &genphy_suspend,
3635 .resume = &genphy_resume,
3636 .probe = &vsc8574_probe,
3637 .set_wol = &vsc85xx_wol_set,
3638 .get_wol = &vsc85xx_wol_get,
3639 .get_tunable = &vsc85xx_get_tunable,
3640 .set_tunable = &vsc85xx_set_tunable,
3641 .read_page = &vsc85xx_phy_read_page,
3642 .write_page = &vsc85xx_phy_write_page,
3643 .get_sset_count = &vsc85xx_get_sset_count,
3644 .get_strings = &vsc85xx_get_strings,
3645 .get_stats = &vsc85xx_get_stats,
3648 .phy_id = PHY_ID_VSC856X,
3649 .name = "Microsemi GE VSC856X SyncE",
3650 .phy_id_mask = 0xfffffff0,
3651 /* PHY_GBIT_FEATURES */
3652 .soft_reset = &genphy_soft_reset,
3653 .config_init = &vsc8584_config_init,
3654 .config_aneg = &vsc85xx_config_aneg,
3655 .read_status = &vsc85xx_read_status,
3656 .ack_interrupt = &vsc85xx_ack_interrupt,
3657 .config_intr = &vsc85xx_config_intr,
3658 .did_interrupt = &vsc8584_did_interrupt,
3659 .suspend = &genphy_suspend,
3660 .resume = &genphy_resume,
3661 .probe = &vsc8584_probe,
3662 .get_tunable = &vsc85xx_get_tunable,
3663 .set_tunable = &vsc85xx_set_tunable,
3664 .read_page = &vsc85xx_phy_read_page,
3665 .write_page = &vsc85xx_phy_write_page,
3666 .get_sset_count = &vsc85xx_get_sset_count,
3667 .get_strings = &vsc85xx_get_strings,
3668 .get_stats = &vsc85xx_get_stats,
3671 .phy_id = PHY_ID_VSC8572,
3672 .name = "Microsemi GE VSC8572 SyncE",
3673 .phy_id_mask = 0xfffffff0,
3674 /* PHY_GBIT_FEATURES */
3675 .soft_reset = &genphy_soft_reset,
3676 .config_init = &vsc8584_config_init,
3677 .config_aneg = &vsc85xx_config_aneg,
3678 .aneg_done = &genphy_aneg_done,
3679 .read_status = &vsc85xx_read_status,
3680 .handle_interrupt = &vsc8584_handle_interrupt,
3681 .ack_interrupt = &vsc85xx_ack_interrupt,
3682 .config_intr = &vsc85xx_config_intr,
3683 .did_interrupt = &vsc8584_did_interrupt,
3684 .suspend = &genphy_suspend,
3685 .resume = &genphy_resume,
3686 .probe = &vsc8574_probe,
3687 .set_wol = &vsc85xx_wol_set,
3688 .get_wol = &vsc85xx_wol_get,
3689 .get_tunable = &vsc85xx_get_tunable,
3690 .set_tunable = &vsc85xx_set_tunable,
3691 .read_page = &vsc85xx_phy_read_page,
3692 .write_page = &vsc85xx_phy_write_page,
3693 .get_sset_count = &vsc85xx_get_sset_count,
3694 .get_strings = &vsc85xx_get_strings,
3695 .get_stats = &vsc85xx_get_stats,
3698 .phy_id = PHY_ID_VSC8574,
3699 .name = "Microsemi GE VSC8574 SyncE",
3700 .phy_id_mask = 0xfffffff0,
3701 /* PHY_GBIT_FEATURES */
3702 .soft_reset = &genphy_soft_reset,
3703 .config_init = &vsc8584_config_init,
3704 .config_aneg = &vsc85xx_config_aneg,
3705 .aneg_done = &genphy_aneg_done,
3706 .read_status = &vsc85xx_read_status,
3707 .ack_interrupt = &vsc85xx_ack_interrupt,
3708 .config_intr = &vsc85xx_config_intr,
3709 .did_interrupt = &vsc8584_did_interrupt,
3710 .suspend = &genphy_suspend,
3711 .resume = &genphy_resume,
3712 .probe = &vsc8574_probe,
3713 .set_wol = &vsc85xx_wol_set,
3714 .get_wol = &vsc85xx_wol_get,
3715 .get_tunable = &vsc85xx_get_tunable,
3716 .set_tunable = &vsc85xx_set_tunable,
3717 .read_page = &vsc85xx_phy_read_page,
3718 .write_page = &vsc85xx_phy_write_page,
3719 .get_sset_count = &vsc85xx_get_sset_count,
3720 .get_strings = &vsc85xx_get_strings,
3721 .get_stats = &vsc85xx_get_stats,
3724 .phy_id = PHY_ID_VSC8575,
3725 .name = "Microsemi GE VSC8575 SyncE",
3726 .phy_id_mask = 0xfffffff0,
3727 /* PHY_GBIT_FEATURES */
3728 .soft_reset = &genphy_soft_reset,
3729 .config_init = &vsc8584_config_init,
3730 .config_aneg = &vsc85xx_config_aneg,
3731 .aneg_done = &genphy_aneg_done,
3732 .read_status = &vsc85xx_read_status,
3733 .handle_interrupt = &vsc8584_handle_interrupt,
3734 .ack_interrupt = &vsc85xx_ack_interrupt,
3735 .config_intr = &vsc85xx_config_intr,
3736 .did_interrupt = &vsc8584_did_interrupt,
3737 .suspend = &genphy_suspend,
3738 .resume = &genphy_resume,
3739 .probe = &vsc8584_probe,
3740 .get_tunable = &vsc85xx_get_tunable,
3741 .set_tunable = &vsc85xx_set_tunable,
3742 .read_page = &vsc85xx_phy_read_page,
3743 .write_page = &vsc85xx_phy_write_page,
3744 .get_sset_count = &vsc85xx_get_sset_count,
3745 .get_strings = &vsc85xx_get_strings,
3746 .get_stats = &vsc85xx_get_stats,
3749 .phy_id = PHY_ID_VSC8582,
3750 .name = "Microsemi GE VSC8582 SyncE",
3751 .phy_id_mask = 0xfffffff0,
3752 /* PHY_GBIT_FEATURES */
3753 .soft_reset = &genphy_soft_reset,
3754 .config_init = &vsc8584_config_init,
3755 .config_aneg = &vsc85xx_config_aneg,
3756 .aneg_done = &genphy_aneg_done,
3757 .read_status = &vsc85xx_read_status,
3758 .handle_interrupt = &vsc8584_handle_interrupt,
3759 .ack_interrupt = &vsc85xx_ack_interrupt,
3760 .config_intr = &vsc85xx_config_intr,
3761 .did_interrupt = &vsc8584_did_interrupt,
3762 .suspend = &genphy_suspend,
3763 .resume = &genphy_resume,
3764 .probe = &vsc8584_probe,
3765 .get_tunable = &vsc85xx_get_tunable,
3766 .set_tunable = &vsc85xx_set_tunable,
3767 .read_page = &vsc85xx_phy_read_page,
3768 .write_page = &vsc85xx_phy_write_page,
3769 .get_sset_count = &vsc85xx_get_sset_count,
3770 .get_strings = &vsc85xx_get_strings,
3771 .get_stats = &vsc85xx_get_stats,
3774 .phy_id = PHY_ID_VSC8584,
3775 .name = "Microsemi GE VSC8584 SyncE",
3776 .phy_id_mask = 0xfffffff0,
3777 /* PHY_GBIT_FEATURES */
3778 .soft_reset = &genphy_soft_reset,
3779 .config_init = &vsc8584_config_init,
3780 .config_aneg = &vsc85xx_config_aneg,
3781 .aneg_done = &genphy_aneg_done,
3782 .read_status = &vsc85xx_read_status,
3783 .handle_interrupt = &vsc8584_handle_interrupt,
3784 .ack_interrupt = &vsc85xx_ack_interrupt,
3785 .config_intr = &vsc85xx_config_intr,
3786 .did_interrupt = &vsc8584_did_interrupt,
3787 .suspend = &genphy_suspend,
3788 .resume = &genphy_resume,
3789 .probe = &vsc8584_probe,
3790 .get_tunable = &vsc85xx_get_tunable,
3791 .set_tunable = &vsc85xx_set_tunable,
3792 .read_page = &vsc85xx_phy_read_page,
3793 .write_page = &vsc85xx_phy_write_page,
3794 .get_sset_count = &vsc85xx_get_sset_count,
3795 .get_strings = &vsc85xx_get_strings,
3796 .get_stats = &vsc85xx_get_stats,
3801 module_phy_driver(vsc85xx_driver);
3803 static struct mdio_device_id __maybe_unused vsc85xx_tbl[] = {
3804 { PHY_ID_VSC8504, 0xfffffff0, },
3805 { PHY_ID_VSC8514, 0xfffffff0, },
3806 { PHY_ID_VSC8530, 0xfffffff0, },
3807 { PHY_ID_VSC8531, 0xfffffff0, },
3808 { PHY_ID_VSC8540, 0xfffffff0, },
3809 { PHY_ID_VSC8541, 0xfffffff0, },
3810 { PHY_ID_VSC8552, 0xfffffff0, },
3811 { PHY_ID_VSC856X, 0xfffffff0, },
3812 { PHY_ID_VSC8572, 0xfffffff0, },
3813 { PHY_ID_VSC8574, 0xfffffff0, },
3814 { PHY_ID_VSC8575, 0xfffffff0, },
3815 { PHY_ID_VSC8582, 0xfffffff0, },
3816 { PHY_ID_VSC8584, 0xfffffff0, },
3820 MODULE_DEVICE_TABLE(mdio, vsc85xx_tbl);
3822 MODULE_DESCRIPTION("Microsemi VSC85xx PHY driver");
3823 MODULE_AUTHOR("Nagaraju Lakkaraju");
3824 MODULE_LICENSE("Dual MIT/GPL");