1 // SPDX-License-Identifier: (GPL-2.0 OR MIT)
3 * Driver for Microsemi VSC85xx PHYs
5 * Author: Nagaraju Lakkaraju
6 * License: Dual MIT/GPL
7 * Copyright (c) 2016 Microsemi Corporation
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>
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>
28 #include "mscc_macsec.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_MDINT BIT(15)
84 #define MII_VSC85XX_INT_MASK_LINK_CHG BIT(13)
85 #define MII_VSC85XX_INT_MASK_WOL BIT(6)
86 #define MII_VSC85XX_INT_MASK_EXT BIT(5)
87 #define MII_VSC85XX_INT_STATUS 26
89 #define MII_VSC85XX_INT_MASK_MASK (MII_VSC85XX_INT_MASK_MDINT | \
90 MII_VSC85XX_INT_MASK_LINK_CHG | \
91 MII_VSC85XX_INT_MASK_EXT)
93 #define MSCC_PHY_WOL_MAC_CONTROL 27
94 #define EDGE_RATE_CNTL_POS 5
95 #define EDGE_RATE_CNTL_MASK 0x00E0
97 #define MSCC_PHY_DEV_AUX_CNTL 28
98 #define HP_AUTO_MDIX_X_OVER_IND_MASK 0x2000
100 #define MSCC_PHY_LED_MODE_SEL 29
101 #define LED_MODE_SEL_POS(x) ((x) * 4)
102 #define LED_MODE_SEL_MASK(x) (GENMASK(3, 0) << LED_MODE_SEL_POS(x))
103 #define LED_MODE_SEL(x, mode) (((mode) << LED_MODE_SEL_POS(x)) & LED_MODE_SEL_MASK(x))
105 #define MSCC_EXT_PAGE_CSR_CNTL_17 17
106 #define MSCC_EXT_PAGE_CSR_CNTL_18 18
108 #define MSCC_EXT_PAGE_CSR_CNTL_19 19
109 #define MSCC_PHY_CSR_CNTL_19_REG_ADDR(x) (x)
110 #define MSCC_PHY_CSR_CNTL_19_TARGET(x) ((x) << 12)
111 #define MSCC_PHY_CSR_CNTL_19_READ BIT(14)
112 #define MSCC_PHY_CSR_CNTL_19_CMD BIT(15)
114 #define MSCC_EXT_PAGE_CSR_CNTL_20 20
115 #define MSCC_PHY_CSR_CNTL_20_TARGET(x) (x)
117 #define PHY_MCB_TARGET 0x07
118 #define PHY_MCB_S6G_WRITE BIT(31)
119 #define PHY_MCB_S6G_READ BIT(30)
121 #define PHY_S6G_PLL5G_CFG0 0x06
122 #define PHY_S6G_LCPLL_CFG 0x11
123 #define PHY_S6G_PLL_CFG 0x2b
124 #define PHY_S6G_COMMON_CFG 0x2c
125 #define PHY_S6G_GPC_CFG 0x2e
126 #define PHY_S6G_MISC_CFG 0x3b
127 #define PHY_MCB_S6G_CFG 0x3f
128 #define PHY_S6G_DFT_CFG2 0x3e
129 #define PHY_S6G_PLL_STATUS 0x31
130 #define PHY_S6G_IB_STATUS0 0x2f
132 #define PHY_S6G_SYS_RST_POS 31
133 #define PHY_S6G_ENA_LANE_POS 18
134 #define PHY_S6G_ENA_LOOP_POS 8
135 #define PHY_S6G_QRATE_POS 6
136 #define PHY_S6G_IF_MODE_POS 4
137 #define PHY_S6G_PLL_ENA_OFFS_POS 21
138 #define PHY_S6G_PLL_FSM_CTRL_DATA_POS 8
139 #define PHY_S6G_PLL_FSM_ENA_POS 7
141 #define MSCC_EXT_PAGE_MACSEC_17 17
142 #define MSCC_EXT_PAGE_MACSEC_18 18
144 #define MSCC_EXT_PAGE_MACSEC_19 19
145 #define MSCC_PHY_MACSEC_19_REG_ADDR(x) (x)
146 #define MSCC_PHY_MACSEC_19_TARGET(x) ((x) << 12)
147 #define MSCC_PHY_MACSEC_19_READ BIT(14)
148 #define MSCC_PHY_MACSEC_19_CMD BIT(15)
150 #define MSCC_EXT_PAGE_MACSEC_20 20
151 #define MSCC_PHY_MACSEC_20_TARGET(x) (x)
161 #define MSCC_EXT_PAGE_ACCESS 31
162 #define MSCC_PHY_PAGE_STANDARD 0x0000 /* Standard registers */
163 #define MSCC_PHY_PAGE_EXTENDED 0x0001 /* Extended registers */
164 #define MSCC_PHY_PAGE_EXTENDED_2 0x0002 /* Extended reg - page 2 */
165 #define MSCC_PHY_PAGE_EXTENDED_3 0x0003 /* Extended reg - page 3 */
166 #define MSCC_PHY_PAGE_EXTENDED_4 0x0004 /* Extended reg - page 4 */
167 #define MSCC_PHY_PAGE_CSR_CNTL MSCC_PHY_PAGE_EXTENDED_4
168 #define MSCC_PHY_PAGE_MACSEC MSCC_PHY_PAGE_EXTENDED_4
169 /* Extended reg - GPIO; this is a bank of registers that are shared for all PHYs
170 * in the same package.
172 #define MSCC_PHY_PAGE_EXTENDED_GPIO 0x0010 /* Extended reg - GPIO */
173 #define MSCC_PHY_PAGE_TEST 0x2a30 /* Test reg */
174 #define MSCC_PHY_PAGE_TR 0x52b5 /* Token ring registers */
176 /* Extended Page 1 Registers */
177 #define MSCC_PHY_CU_MEDIA_CRC_VALID_CNT 18
178 #define VALID_CRC_CNT_CRC_MASK GENMASK(13, 0)
180 #define MSCC_PHY_EXT_MODE_CNTL 19
181 #define FORCE_MDI_CROSSOVER_MASK 0x000C
182 #define FORCE_MDI_CROSSOVER_MDIX 0x000C
183 #define FORCE_MDI_CROSSOVER_MDI 0x0008
185 #define MSCC_PHY_ACTIPHY_CNTL 20
186 #define PHY_ADDR_REVERSED 0x0200
187 #define DOWNSHIFT_CNTL_MASK 0x001C
188 #define DOWNSHIFT_EN 0x0010
189 #define DOWNSHIFT_CNTL_POS 2
191 #define MSCC_PHY_EXT_PHY_CNTL_4 23
192 #define PHY_CNTL_4_ADDR_POS 11
194 #define MSCC_PHY_VERIPHY_CNTL_2 25
196 #define MSCC_PHY_VERIPHY_CNTL_3 26
198 /* Extended Page 2 Registers */
199 #define MSCC_PHY_CU_PMD_TX_CNTL 16
201 #define MSCC_PHY_RGMII_CNTL 20
202 #define RGMII_RX_CLK_DELAY_MASK 0x0070
203 #define RGMII_RX_CLK_DELAY_POS 4
205 #define MSCC_PHY_WOL_LOWER_MAC_ADDR 21
206 #define MSCC_PHY_WOL_MID_MAC_ADDR 22
207 #define MSCC_PHY_WOL_UPPER_MAC_ADDR 23
208 #define MSCC_PHY_WOL_LOWER_PASSWD 24
209 #define MSCC_PHY_WOL_MID_PASSWD 25
210 #define MSCC_PHY_WOL_UPPER_PASSWD 26
212 #define MSCC_PHY_WOL_MAC_CONTROL 27
213 #define SECURE_ON_ENABLE 0x8000
214 #define SECURE_ON_PASSWD_LEN_4 0x4000
216 #define MSCC_PHY_EXTENDED_INT 28
217 #define MSCC_PHY_EXTENDED_INT_MS_EGR BIT(9)
219 /* Extended Page 3 Registers */
220 #define MSCC_PHY_SERDES_TX_VALID_CNT 21
221 #define MSCC_PHY_SERDES_TX_CRC_ERR_CNT 22
222 #define MSCC_PHY_SERDES_RX_VALID_CNT 28
223 #define MSCC_PHY_SERDES_RX_CRC_ERR_CNT 29
225 /* Extended page GPIO Registers */
226 #define MSCC_DW8051_CNTL_STATUS 0
227 #define MICRO_NSOFT_RESET 0x8000
228 #define RUN_FROM_INT_ROM 0x4000
229 #define AUTOINC_ADDR 0x2000
230 #define PATCH_RAM_CLK 0x1000
231 #define MICRO_PATCH_EN 0x0080
232 #define DW8051_CLK_EN 0x0010
233 #define MICRO_CLK_EN 0x0008
234 #define MICRO_CLK_DIVIDE(x) ((x) >> 1)
235 #define MSCC_DW8051_VLD_MASK 0xf1ff
237 /* x Address in range 1-4 */
238 #define MSCC_TRAP_ROM_ADDR(x) ((x) * 2 + 1)
239 #define MSCC_PATCH_RAM_ADDR(x) (((x) + 1) * 2)
240 #define MSCC_INT_MEM_ADDR 11
242 #define MSCC_INT_MEM_CNTL 12
243 #define READ_SFR 0x6000
244 #define READ_PRAM 0x4000
245 #define READ_ROM 0x2000
246 #define READ_RAM 0x0000
247 #define INT_MEM_WRITE_EN 0x1000
248 #define EN_PATCH_RAM_TRAP_ADDR(x) (0x0100 << ((x) - 1))
249 #define INT_MEM_DATA_M 0x00ff
250 #define INT_MEM_DATA(x) (INT_MEM_DATA_M & (x))
252 #define MSCC_PHY_PROC_CMD 18
253 #define PROC_CMD_NCOMPLETED 0x8000
254 #define PROC_CMD_FAILED 0x4000
255 #define PROC_CMD_SGMII_PORT(x) ((x) << 8)
256 #define PROC_CMD_FIBER_PORT(x) (0x0100 << (x) % 4)
257 #define PROC_CMD_QSGMII_PORT 0x0c00
258 #define PROC_CMD_RST_CONF_PORT 0x0080
259 #define PROC_CMD_RECONF_PORT 0x0000
260 #define PROC_CMD_READ_MOD_WRITE_PORT 0x0040
261 #define PROC_CMD_WRITE 0x0040
262 #define PROC_CMD_READ 0x0000
263 #define PROC_CMD_FIBER_DISABLE 0x0020
264 #define PROC_CMD_FIBER_100BASE_FX 0x0010
265 #define PROC_CMD_FIBER_1000BASE_X 0x0000
266 #define PROC_CMD_SGMII_MAC 0x0030
267 #define PROC_CMD_QSGMII_MAC 0x0020
268 #define PROC_CMD_NO_MAC_CONF 0x0000
269 #define PROC_CMD_1588_DEFAULT_INIT 0x0010
270 #define PROC_CMD_NOP 0x000f
271 #define PROC_CMD_PHY_INIT 0x000a
272 #define PROC_CMD_CRC16 0x0008
273 #define PROC_CMD_FIBER_MEDIA_CONF 0x0001
274 #define PROC_CMD_MCB_ACCESS_MAC_CONF 0x0000
275 #define PROC_CMD_NCOMPLETED_TIMEOUT_MS 500
277 #define MSCC_PHY_MAC_CFG_FASTLINK 19
278 #define MAC_CFG_MASK 0xc000
279 #define MAC_CFG_SGMII 0x0000
280 #define MAC_CFG_QSGMII 0x4000
282 /* Test page Registers */
283 #define MSCC_PHY_TEST_PAGE_5 5
284 #define MSCC_PHY_TEST_PAGE_8 8
285 #define MSCC_PHY_TEST_PAGE_9 9
286 #define MSCC_PHY_TEST_PAGE_20 20
287 #define MSCC_PHY_TEST_PAGE_24 24
289 /* Token ring page Registers */
290 #define MSCC_PHY_TR_CNTL 16
291 #define TR_WRITE 0x8000
292 #define TR_ADDR(x) (0x7fff & (x))
293 #define MSCC_PHY_TR_LSB 17
294 #define MSCC_PHY_TR_MSB 18
296 /* Microsemi PHY ID's
297 * Code assumes lowest nibble is 0
299 #define PHY_ID_VSC8504 0x000704c0
300 #define PHY_ID_VSC8514 0x00070670
301 #define PHY_ID_VSC8530 0x00070560
302 #define PHY_ID_VSC8531 0x00070570
303 #define PHY_ID_VSC8540 0x00070760
304 #define PHY_ID_VSC8541 0x00070770
305 #define PHY_ID_VSC8552 0x000704e0
306 #define PHY_ID_VSC856X 0x000707e0
307 #define PHY_ID_VSC8572 0x000704d0
308 #define PHY_ID_VSC8574 0x000704a0
309 #define PHY_ID_VSC8575 0x000707d0
310 #define PHY_ID_VSC8582 0x000707b0
311 #define PHY_ID_VSC8584 0x000707c0
313 #define MSCC_VDDMAC_1500 1500
314 #define MSCC_VDDMAC_1800 1800
315 #define MSCC_VDDMAC_2500 2500
316 #define MSCC_VDDMAC_3300 3300
318 #define DOWNSHIFT_COUNT_MAX 5
322 #define VSC8584_SUPP_LED_MODES (BIT(VSC8531_LINK_ACTIVITY) | \
323 BIT(VSC8531_LINK_1000_ACTIVITY) | \
324 BIT(VSC8531_LINK_100_ACTIVITY) | \
325 BIT(VSC8531_LINK_10_ACTIVITY) | \
326 BIT(VSC8531_LINK_100_1000_ACTIVITY) | \
327 BIT(VSC8531_LINK_10_1000_ACTIVITY) | \
328 BIT(VSC8531_LINK_10_100_ACTIVITY) | \
329 BIT(VSC8584_LINK_100FX_1000X_ACTIVITY) | \
330 BIT(VSC8531_DUPLEX_COLLISION) | \
331 BIT(VSC8531_COLLISION) | \
332 BIT(VSC8531_ACTIVITY) | \
333 BIT(VSC8584_100FX_1000X_ACTIVITY) | \
334 BIT(VSC8531_AUTONEG_FAULT) | \
335 BIT(VSC8531_SERIAL_MODE) | \
336 BIT(VSC8531_FORCE_LED_OFF) | \
337 BIT(VSC8531_FORCE_LED_ON))
339 #define VSC85XX_SUPP_LED_MODES (BIT(VSC8531_LINK_ACTIVITY) | \
340 BIT(VSC8531_LINK_1000_ACTIVITY) | \
341 BIT(VSC8531_LINK_100_ACTIVITY) | \
342 BIT(VSC8531_LINK_10_ACTIVITY) | \
343 BIT(VSC8531_LINK_100_1000_ACTIVITY) | \
344 BIT(VSC8531_LINK_10_1000_ACTIVITY) | \
345 BIT(VSC8531_LINK_10_100_ACTIVITY) | \
346 BIT(VSC8531_DUPLEX_COLLISION) | \
347 BIT(VSC8531_COLLISION) | \
348 BIT(VSC8531_ACTIVITY) | \
349 BIT(VSC8531_AUTONEG_FAULT) | \
350 BIT(VSC8531_SERIAL_MODE) | \
351 BIT(VSC8531_FORCE_LED_OFF) | \
352 BIT(VSC8531_FORCE_LED_ON))
354 #define MSCC_VSC8584_REVB_INT8051_FW "microchip/mscc_vsc8584_revb_int8051_fb48.bin"
355 #define MSCC_VSC8584_REVB_INT8051_FW_START_ADDR 0xe800
356 #define MSCC_VSC8584_REVB_INT8051_FW_CRC 0xfb48
358 #define MSCC_VSC8574_REVB_INT8051_FW "microchip/mscc_vsc8574_revb_int8051_29e8.bin"
359 #define MSCC_VSC8574_REVB_INT8051_FW_START_ADDR 0x4000
360 #define MSCC_VSC8574_REVB_INT8051_FW_CRC 0x29e8
362 #define VSC8584_REVB 0x0001
363 #define MSCC_DEV_REV_MASK GENMASK(3, 0)
370 struct vsc85xx_hw_stat {
377 static const struct vsc85xx_hw_stat vsc85xx_hw_stats[] = {
379 .string = "phy_receive_errors",
380 .reg = MSCC_PHY_ERR_RX_CNT,
381 .page = MSCC_PHY_PAGE_STANDARD,
382 .mask = ERR_CNT_MASK,
384 .string = "phy_false_carrier",
385 .reg = MSCC_PHY_ERR_FALSE_CARRIER_CNT,
386 .page = MSCC_PHY_PAGE_STANDARD,
387 .mask = ERR_CNT_MASK,
389 .string = "phy_cu_media_link_disconnect",
390 .reg = MSCC_PHY_ERR_LINK_DISCONNECT_CNT,
391 .page = MSCC_PHY_PAGE_STANDARD,
392 .mask = ERR_CNT_MASK,
394 .string = "phy_cu_media_crc_good_count",
395 .reg = MSCC_PHY_CU_MEDIA_CRC_VALID_CNT,
396 .page = MSCC_PHY_PAGE_EXTENDED,
397 .mask = VALID_CRC_CNT_CRC_MASK,
399 .string = "phy_cu_media_crc_error_count",
400 .reg = MSCC_PHY_EXT_PHY_CNTL_4,
401 .page = MSCC_PHY_PAGE_EXTENDED,
402 .mask = ERR_CNT_MASK,
406 static const struct vsc85xx_hw_stat vsc8584_hw_stats[] = {
408 .string = "phy_receive_errors",
409 .reg = MSCC_PHY_ERR_RX_CNT,
410 .page = MSCC_PHY_PAGE_STANDARD,
411 .mask = ERR_CNT_MASK,
413 .string = "phy_false_carrier",
414 .reg = MSCC_PHY_ERR_FALSE_CARRIER_CNT,
415 .page = MSCC_PHY_PAGE_STANDARD,
416 .mask = ERR_CNT_MASK,
418 .string = "phy_cu_media_link_disconnect",
419 .reg = MSCC_PHY_ERR_LINK_DISCONNECT_CNT,
420 .page = MSCC_PHY_PAGE_STANDARD,
421 .mask = ERR_CNT_MASK,
423 .string = "phy_cu_media_crc_good_count",
424 .reg = MSCC_PHY_CU_MEDIA_CRC_VALID_CNT,
425 .page = MSCC_PHY_PAGE_EXTENDED,
426 .mask = VALID_CRC_CNT_CRC_MASK,
428 .string = "phy_cu_media_crc_error_count",
429 .reg = MSCC_PHY_EXT_PHY_CNTL_4,
430 .page = MSCC_PHY_PAGE_EXTENDED,
431 .mask = ERR_CNT_MASK,
433 .string = "phy_serdes_tx_good_pkt_count",
434 .reg = MSCC_PHY_SERDES_TX_VALID_CNT,
435 .page = MSCC_PHY_PAGE_EXTENDED_3,
436 .mask = VALID_CRC_CNT_CRC_MASK,
438 .string = "phy_serdes_tx_bad_crc_count",
439 .reg = MSCC_PHY_SERDES_TX_CRC_ERR_CNT,
440 .page = MSCC_PHY_PAGE_EXTENDED_3,
441 .mask = ERR_CNT_MASK,
443 .string = "phy_serdes_rx_good_pkt_count",
444 .reg = MSCC_PHY_SERDES_RX_VALID_CNT,
445 .page = MSCC_PHY_PAGE_EXTENDED_3,
446 .mask = VALID_CRC_CNT_CRC_MASK,
448 .string = "phy_serdes_rx_bad_crc_count",
449 .reg = MSCC_PHY_SERDES_RX_CRC_ERR_CNT,
450 .page = MSCC_PHY_PAGE_EXTENDED_3,
451 .mask = ERR_CNT_MASK,
455 #if IS_ENABLED(CONFIG_MACSEC)
457 struct list_head list;
458 enum mscc_macsec_destination_ports port;
459 enum macsec_bank bank;
462 bool has_transformation;
464 /* Highest takes precedence [0..15] */
467 u8 key[MACSEC_KEYID_LEN];
470 struct macsec_rx_sa *rx_sa;
471 struct macsec_tx_sa *tx_sa;
493 struct vsc8531_private {
496 u32 leds_mode[MAX_LEDS];
498 const struct vsc85xx_hw_stat *hw_stats;
502 /* For multiple port PHYs; the MDIO address of the base PHY in the
505 unsigned int base_addr;
507 #if IS_ENABLED(CONFIG_MACSEC)
509 * - One SecY per device (enforced at the s/w implementation level)
510 * - macsec_flows: list of h/w flows
511 * - ingr_flows: bitmap of ingress flows
512 * - egr_flows: bitmap of egress flows
514 struct macsec_secy *secy;
515 struct list_head macsec_flows;
516 unsigned long ingr_flows;
517 unsigned long egr_flows;
521 #ifdef CONFIG_OF_MDIO
522 struct vsc8531_edge_rate_table {
527 static const struct vsc8531_edge_rate_table edge_table[] = {
528 {MSCC_VDDMAC_3300, { 0, 2, 4, 7, 10, 17, 29, 53} },
529 {MSCC_VDDMAC_2500, { 0, 3, 6, 10, 14, 23, 37, 63} },
530 {MSCC_VDDMAC_1800, { 0, 5, 9, 16, 23, 35, 52, 76} },
531 {MSCC_VDDMAC_1500, { 0, 6, 14, 21, 29, 42, 58, 77} },
533 #endif /* CONFIG_OF_MDIO */
535 static int vsc85xx_phy_read_page(struct phy_device *phydev)
537 return __phy_read(phydev, MSCC_EXT_PAGE_ACCESS);
540 static int vsc85xx_phy_write_page(struct phy_device *phydev, int page)
542 return __phy_write(phydev, MSCC_EXT_PAGE_ACCESS, page);
545 static int vsc85xx_get_sset_count(struct phy_device *phydev)
547 struct vsc8531_private *priv = phydev->priv;
555 static void vsc85xx_get_strings(struct phy_device *phydev, u8 *data)
557 struct vsc8531_private *priv = phydev->priv;
563 for (i = 0; i < priv->nstats; i++)
564 strlcpy(data + i * ETH_GSTRING_LEN, priv->hw_stats[i].string,
568 static u64 vsc85xx_get_stat(struct phy_device *phydev, int i)
570 struct vsc8531_private *priv = phydev->priv;
573 val = phy_read_paged(phydev, priv->hw_stats[i].page,
574 priv->hw_stats[i].reg);
578 val = val & priv->hw_stats[i].mask;
579 priv->stats[i] += val;
581 return priv->stats[i];
584 static void vsc85xx_get_stats(struct phy_device *phydev,
585 struct ethtool_stats *stats, u64 *data)
587 struct vsc8531_private *priv = phydev->priv;
593 for (i = 0; i < priv->nstats; i++)
594 data[i] = vsc85xx_get_stat(phydev, i);
597 static int vsc85xx_led_cntl_set(struct phy_device *phydev,
604 mutex_lock(&phydev->lock);
605 reg_val = phy_read(phydev, MSCC_PHY_LED_MODE_SEL);
606 reg_val &= ~LED_MODE_SEL_MASK(led_num);
607 reg_val |= LED_MODE_SEL(led_num, (u16)mode);
608 rc = phy_write(phydev, MSCC_PHY_LED_MODE_SEL, reg_val);
609 mutex_unlock(&phydev->lock);
614 static int vsc85xx_mdix_get(struct phy_device *phydev, u8 *mdix)
618 reg_val = phy_read(phydev, MSCC_PHY_DEV_AUX_CNTL);
619 if (reg_val & HP_AUTO_MDIX_X_OVER_IND_MASK)
620 *mdix = ETH_TP_MDI_X;
627 static int vsc85xx_mdix_set(struct phy_device *phydev, u8 mdix)
632 reg_val = phy_read(phydev, MSCC_PHY_BYPASS_CONTROL);
633 if (mdix == ETH_TP_MDI || mdix == ETH_TP_MDI_X) {
634 reg_val |= (DISABLE_PAIR_SWAP_CORR_MASK |
635 DISABLE_POLARITY_CORR_MASK |
636 DISABLE_HP_AUTO_MDIX_MASK);
638 reg_val &= ~(DISABLE_PAIR_SWAP_CORR_MASK |
639 DISABLE_POLARITY_CORR_MASK |
640 DISABLE_HP_AUTO_MDIX_MASK);
642 rc = phy_write(phydev, MSCC_PHY_BYPASS_CONTROL, reg_val);
648 if (mdix == ETH_TP_MDI)
649 reg_val = FORCE_MDI_CROSSOVER_MDI;
650 else if (mdix == ETH_TP_MDI_X)
651 reg_val = FORCE_MDI_CROSSOVER_MDIX;
653 rc = phy_modify_paged(phydev, MSCC_PHY_PAGE_EXTENDED,
654 MSCC_PHY_EXT_MODE_CNTL, FORCE_MDI_CROSSOVER_MASK,
659 return genphy_restart_aneg(phydev);
662 static int vsc85xx_downshift_get(struct phy_device *phydev, u8 *count)
666 reg_val = phy_read_paged(phydev, MSCC_PHY_PAGE_EXTENDED,
667 MSCC_PHY_ACTIPHY_CNTL);
671 reg_val &= DOWNSHIFT_CNTL_MASK;
672 if (!(reg_val & DOWNSHIFT_EN))
673 *count = DOWNSHIFT_DEV_DISABLE;
675 *count = ((reg_val & ~DOWNSHIFT_EN) >> DOWNSHIFT_CNTL_POS) + 2;
680 static int vsc85xx_downshift_set(struct phy_device *phydev, u8 count)
682 if (count == DOWNSHIFT_DEV_DEFAULT_COUNT) {
683 /* Default downshift count 3 (i.e. Bit3:2 = 0b01) */
684 count = ((1 << DOWNSHIFT_CNTL_POS) | DOWNSHIFT_EN);
685 } else if (count > DOWNSHIFT_COUNT_MAX || count == 1) {
686 phydev_err(phydev, "Downshift count should be 2,3,4 or 5\n");
689 /* Downshift count is either 2,3,4 or 5 */
690 count = (((count - 2) << DOWNSHIFT_CNTL_POS) | DOWNSHIFT_EN);
693 return phy_modify_paged(phydev, MSCC_PHY_PAGE_EXTENDED,
694 MSCC_PHY_ACTIPHY_CNTL, DOWNSHIFT_CNTL_MASK,
698 static int vsc85xx_wol_set(struct phy_device *phydev,
699 struct ethtool_wolinfo *wol)
704 u16 pwd[3] = {0, 0, 0};
705 struct ethtool_wolinfo *wol_conf = wol;
706 u8 *mac_addr = phydev->attached_dev->dev_addr;
708 mutex_lock(&phydev->lock);
709 rc = phy_select_page(phydev, MSCC_PHY_PAGE_EXTENDED_2);
711 rc = phy_restore_page(phydev, rc, rc);
715 if (wol->wolopts & WAKE_MAGIC) {
716 /* Store the device address for the magic packet */
717 for (i = 0; i < ARRAY_SIZE(pwd); i++)
718 pwd[i] = mac_addr[5 - (i * 2 + 1)] << 8 |
720 __phy_write(phydev, MSCC_PHY_WOL_LOWER_MAC_ADDR, pwd[0]);
721 __phy_write(phydev, MSCC_PHY_WOL_MID_MAC_ADDR, pwd[1]);
722 __phy_write(phydev, MSCC_PHY_WOL_UPPER_MAC_ADDR, pwd[2]);
724 __phy_write(phydev, MSCC_PHY_WOL_LOWER_MAC_ADDR, 0);
725 __phy_write(phydev, MSCC_PHY_WOL_MID_MAC_ADDR, 0);
726 __phy_write(phydev, MSCC_PHY_WOL_UPPER_MAC_ADDR, 0);
729 if (wol_conf->wolopts & WAKE_MAGICSECURE) {
730 for (i = 0; i < ARRAY_SIZE(pwd); i++)
731 pwd[i] = wol_conf->sopass[5 - (i * 2 + 1)] << 8 |
732 wol_conf->sopass[5 - i * 2];
733 __phy_write(phydev, MSCC_PHY_WOL_LOWER_PASSWD, pwd[0]);
734 __phy_write(phydev, MSCC_PHY_WOL_MID_PASSWD, pwd[1]);
735 __phy_write(phydev, MSCC_PHY_WOL_UPPER_PASSWD, pwd[2]);
737 __phy_write(phydev, MSCC_PHY_WOL_LOWER_PASSWD, 0);
738 __phy_write(phydev, MSCC_PHY_WOL_MID_PASSWD, 0);
739 __phy_write(phydev, MSCC_PHY_WOL_UPPER_PASSWD, 0);
742 reg_val = __phy_read(phydev, MSCC_PHY_WOL_MAC_CONTROL);
743 if (wol_conf->wolopts & WAKE_MAGICSECURE)
744 reg_val |= SECURE_ON_ENABLE;
746 reg_val &= ~SECURE_ON_ENABLE;
747 __phy_write(phydev, MSCC_PHY_WOL_MAC_CONTROL, reg_val);
749 rc = phy_restore_page(phydev, rc, rc > 0 ? 0 : rc);
753 if (wol->wolopts & WAKE_MAGIC) {
754 /* Enable the WOL interrupt */
755 reg_val = phy_read(phydev, MII_VSC85XX_INT_MASK);
756 reg_val |= MII_VSC85XX_INT_MASK_WOL;
757 rc = phy_write(phydev, MII_VSC85XX_INT_MASK, reg_val);
761 /* Disable the WOL interrupt */
762 reg_val = phy_read(phydev, MII_VSC85XX_INT_MASK);
763 reg_val &= (~MII_VSC85XX_INT_MASK_WOL);
764 rc = phy_write(phydev, MII_VSC85XX_INT_MASK, reg_val);
768 /* Clear WOL iterrupt status */
769 reg_val = phy_read(phydev, MII_VSC85XX_INT_STATUS);
772 mutex_unlock(&phydev->lock);
777 static void vsc85xx_wol_get(struct phy_device *phydev,
778 struct ethtool_wolinfo *wol)
783 u16 pwd[3] = {0, 0, 0};
784 struct ethtool_wolinfo *wol_conf = wol;
786 mutex_lock(&phydev->lock);
787 rc = phy_select_page(phydev, MSCC_PHY_PAGE_EXTENDED_2);
791 reg_val = __phy_read(phydev, MSCC_PHY_WOL_MAC_CONTROL);
792 if (reg_val & SECURE_ON_ENABLE)
793 wol_conf->wolopts |= WAKE_MAGICSECURE;
794 if (wol_conf->wolopts & WAKE_MAGICSECURE) {
795 pwd[0] = __phy_read(phydev, MSCC_PHY_WOL_LOWER_PASSWD);
796 pwd[1] = __phy_read(phydev, MSCC_PHY_WOL_MID_PASSWD);
797 pwd[2] = __phy_read(phydev, MSCC_PHY_WOL_UPPER_PASSWD);
798 for (i = 0; i < ARRAY_SIZE(pwd); i++) {
799 wol_conf->sopass[5 - i * 2] = pwd[i] & 0x00ff;
800 wol_conf->sopass[5 - (i * 2 + 1)] = (pwd[i] & 0xff00)
806 phy_restore_page(phydev, rc, rc > 0 ? 0 : rc);
807 mutex_unlock(&phydev->lock);
810 #ifdef CONFIG_OF_MDIO
811 static int vsc85xx_edge_rate_magic_get(struct phy_device *phydev)
815 struct device *dev = &phydev->mdio.dev;
816 struct device_node *of_node = dev->of_node;
817 u8 sd_array_size = ARRAY_SIZE(edge_table[0].slowdown);
822 if (of_property_read_u32(of_node, "vsc8531,vddmac", &vdd))
823 vdd = MSCC_VDDMAC_3300;
825 if (of_property_read_u32(of_node, "vsc8531,edge-slowdown", &sd))
828 for (i = 0; i < ARRAY_SIZE(edge_table); i++)
829 if (edge_table[i].vddmac == vdd)
830 for (j = 0; j < sd_array_size; j++)
831 if (edge_table[i].slowdown[j] == sd)
832 return (sd_array_size - j - 1);
837 static int vsc85xx_dt_led_mode_get(struct phy_device *phydev,
841 struct vsc8531_private *priv = phydev->priv;
842 struct device *dev = &phydev->mdio.dev;
843 struct device_node *of_node = dev->of_node;
850 led_mode = default_mode;
851 err = of_property_read_u32(of_node, led, &led_mode);
852 if (!err && !(BIT(led_mode) & priv->supp_led_modes)) {
853 phydev_err(phydev, "DT %s invalid\n", led);
861 static int vsc85xx_edge_rate_magic_get(struct phy_device *phydev)
866 static int vsc85xx_dt_led_mode_get(struct phy_device *phydev,
872 #endif /* CONFIG_OF_MDIO */
874 static int vsc85xx_dt_led_modes_get(struct phy_device *phydev,
877 struct vsc8531_private *priv = phydev->priv;
878 char led_dt_prop[28];
881 for (i = 0; i < priv->nleds; i++) {
882 ret = sprintf(led_dt_prop, "vsc8531,led-%d-mode", i);
886 ret = vsc85xx_dt_led_mode_get(phydev, led_dt_prop,
890 priv->leds_mode[i] = ret;
896 static int vsc85xx_edge_rate_cntl_set(struct phy_device *phydev, u8 edge_rate)
900 mutex_lock(&phydev->lock);
901 rc = phy_modify_paged(phydev, MSCC_PHY_PAGE_EXTENDED_2,
902 MSCC_PHY_WOL_MAC_CONTROL, EDGE_RATE_CNTL_MASK,
903 edge_rate << EDGE_RATE_CNTL_POS);
904 mutex_unlock(&phydev->lock);
909 static int vsc85xx_mac_if_set(struct phy_device *phydev,
910 phy_interface_t interface)
915 mutex_lock(&phydev->lock);
916 reg_val = phy_read(phydev, MSCC_PHY_EXT_PHY_CNTL_1);
917 reg_val &= ~(MAC_IF_SELECTION_MASK);
919 case PHY_INTERFACE_MODE_RGMII:
920 reg_val |= (MAC_IF_SELECTION_RGMII << MAC_IF_SELECTION_POS);
922 case PHY_INTERFACE_MODE_RMII:
923 reg_val |= (MAC_IF_SELECTION_RMII << MAC_IF_SELECTION_POS);
925 case PHY_INTERFACE_MODE_MII:
926 case PHY_INTERFACE_MODE_GMII:
927 reg_val |= (MAC_IF_SELECTION_GMII << MAC_IF_SELECTION_POS);
933 rc = phy_write(phydev, MSCC_PHY_EXT_PHY_CNTL_1, reg_val);
937 rc = genphy_soft_reset(phydev);
940 mutex_unlock(&phydev->lock);
945 static int vsc85xx_default_config(struct phy_device *phydev)
950 phydev->mdix_ctrl = ETH_TP_MDI_AUTO;
951 mutex_lock(&phydev->lock);
953 reg_val = RGMII_RX_CLK_DELAY_1_1_NS << RGMII_RX_CLK_DELAY_POS;
955 rc = phy_modify_paged(phydev, MSCC_PHY_PAGE_EXTENDED_2,
956 MSCC_PHY_RGMII_CNTL, RGMII_RX_CLK_DELAY_MASK,
959 mutex_unlock(&phydev->lock);
964 static int vsc85xx_get_tunable(struct phy_device *phydev,
965 struct ethtool_tunable *tuna, void *data)
968 case ETHTOOL_PHY_DOWNSHIFT:
969 return vsc85xx_downshift_get(phydev, (u8 *)data);
975 static int vsc85xx_set_tunable(struct phy_device *phydev,
976 struct ethtool_tunable *tuna,
980 case ETHTOOL_PHY_DOWNSHIFT:
981 return vsc85xx_downshift_set(phydev, *(u8 *)data);
987 /* mdiobus lock should be locked when using this function */
988 static void vsc85xx_tr_write(struct phy_device *phydev, u16 addr, u32 val)
990 __phy_write(phydev, MSCC_PHY_TR_MSB, val >> 16);
991 __phy_write(phydev, MSCC_PHY_TR_LSB, val & GENMASK(15, 0));
992 __phy_write(phydev, MSCC_PHY_TR_CNTL, TR_WRITE | TR_ADDR(addr));
995 static int vsc8531_pre_init_seq_set(struct phy_device *phydev)
998 static const struct reg_val init_seq[] = {
999 {0x0f90, 0x00688980},
1000 {0x0696, 0x00000003},
1001 {0x07fa, 0x0050100f},
1002 {0x1686, 0x00000004},
1007 rc = phy_modify_paged(phydev, MSCC_PHY_PAGE_STANDARD,
1008 MSCC_PHY_EXT_CNTL_STATUS, SMI_BROADCAST_WR_EN,
1009 SMI_BROADCAST_WR_EN);
1012 rc = phy_modify_paged(phydev, MSCC_PHY_PAGE_TEST,
1013 MSCC_PHY_TEST_PAGE_24, 0, 0x0400);
1016 rc = phy_modify_paged(phydev, MSCC_PHY_PAGE_TEST,
1017 MSCC_PHY_TEST_PAGE_5, 0x0a00, 0x0e00);
1020 rc = phy_modify_paged(phydev, MSCC_PHY_PAGE_TEST,
1021 MSCC_PHY_TEST_PAGE_8, 0x8000, 0x8000);
1025 mutex_lock(&phydev->lock);
1026 oldpage = phy_select_page(phydev, MSCC_PHY_PAGE_TR);
1030 for (i = 0; i < ARRAY_SIZE(init_seq); i++)
1031 vsc85xx_tr_write(phydev, init_seq[i].reg, init_seq[i].val);
1034 oldpage = phy_restore_page(phydev, oldpage, oldpage);
1035 mutex_unlock(&phydev->lock);
1040 static int vsc85xx_eee_init_seq_set(struct phy_device *phydev)
1042 static const struct reg_val init_eee[] = {
1043 {0x0f82, 0x0012b00a},
1044 {0x1686, 0x00000004},
1045 {0x168c, 0x00d2c46f},
1046 {0x17a2, 0x00000620},
1047 {0x16a0, 0x00eeffdd},
1048 {0x16a6, 0x00071448},
1049 {0x16a4, 0x0013132f},
1050 {0x16a8, 0x00000000},
1051 {0x0ffc, 0x00c0a028},
1052 {0x0fe8, 0x0091b06c},
1053 {0x0fea, 0x00041600},
1054 {0x0f80, 0x00000af4},
1055 {0x0fec, 0x00901809},
1056 {0x0fee, 0x0000a6a1},
1057 {0x0ffe, 0x00b01007},
1058 {0x16b0, 0x00eeff00},
1059 {0x16b2, 0x00007000},
1060 {0x16b4, 0x00000814},
1065 mutex_lock(&phydev->lock);
1066 oldpage = phy_select_page(phydev, MSCC_PHY_PAGE_TR);
1070 for (i = 0; i < ARRAY_SIZE(init_eee); i++)
1071 vsc85xx_tr_write(phydev, init_eee[i].reg, init_eee[i].val);
1074 oldpage = phy_restore_page(phydev, oldpage, oldpage);
1075 mutex_unlock(&phydev->lock);
1080 /* phydev->bus->mdio_lock should be locked when using this function */
1081 static int phy_base_write(struct phy_device *phydev, u32 regnum, u16 val)
1083 struct vsc8531_private *priv = phydev->priv;
1085 if (unlikely(!mutex_is_locked(&phydev->mdio.bus->mdio_lock))) {
1086 dev_err(&phydev->mdio.dev, "MDIO bus lock not held!\n");
1090 return __mdiobus_write(phydev->mdio.bus, priv->base_addr, regnum, val);
1093 /* phydev->bus->mdio_lock should be locked when using this function */
1094 static int phy_base_read(struct phy_device *phydev, u32 regnum)
1096 struct vsc8531_private *priv = phydev->priv;
1098 if (unlikely(!mutex_is_locked(&phydev->mdio.bus->mdio_lock))) {
1099 dev_err(&phydev->mdio.dev, "MDIO bus lock not held!\n");
1103 return __mdiobus_read(phydev->mdio.bus, priv->base_addr, regnum);
1106 /* bus->mdio_lock should be locked when using this function */
1107 static void vsc8584_csr_write(struct phy_device *phydev, u16 addr, u32 val)
1109 phy_base_write(phydev, MSCC_PHY_TR_MSB, val >> 16);
1110 phy_base_write(phydev, MSCC_PHY_TR_LSB, val & GENMASK(15, 0));
1111 phy_base_write(phydev, MSCC_PHY_TR_CNTL, TR_WRITE | TR_ADDR(addr));
1114 /* bus->mdio_lock should be locked when using this function */
1115 static int vsc8584_cmd(struct phy_device *phydev, u16 val)
1117 unsigned long deadline;
1120 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS,
1121 MSCC_PHY_PAGE_EXTENDED_GPIO);
1123 phy_base_write(phydev, MSCC_PHY_PROC_CMD, PROC_CMD_NCOMPLETED | val);
1125 deadline = jiffies + msecs_to_jiffies(PROC_CMD_NCOMPLETED_TIMEOUT_MS);
1127 reg_val = phy_base_read(phydev, MSCC_PHY_PROC_CMD);
1128 } while (time_before(jiffies, deadline) &&
1129 (reg_val & PROC_CMD_NCOMPLETED) &&
1130 !(reg_val & PROC_CMD_FAILED));
1132 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
1134 if (reg_val & PROC_CMD_FAILED)
1137 if (reg_val & PROC_CMD_NCOMPLETED)
1143 /* bus->mdio_lock should be locked when using this function */
1144 static int vsc8584_micro_deassert_reset(struct phy_device *phydev,
1147 u32 enable, release;
1149 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS,
1150 MSCC_PHY_PAGE_EXTENDED_GPIO);
1152 enable = RUN_FROM_INT_ROM | MICRO_CLK_EN | DW8051_CLK_EN;
1153 release = MICRO_NSOFT_RESET | RUN_FROM_INT_ROM | DW8051_CLK_EN |
1157 enable |= MICRO_PATCH_EN;
1158 release |= MICRO_PATCH_EN;
1160 /* Clear all patches */
1161 phy_base_write(phydev, MSCC_INT_MEM_CNTL, READ_RAM);
1164 /* Enable 8051 Micro clock; CLEAR/SET patch present; disable PRAM clock
1165 * override and addr. auto-incr; operate at 125 MHz
1167 phy_base_write(phydev, MSCC_DW8051_CNTL_STATUS, enable);
1168 /* Release 8051 Micro SW reset */
1169 phy_base_write(phydev, MSCC_DW8051_CNTL_STATUS, release);
1171 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
1176 /* bus->mdio_lock should be locked when using this function */
1177 static int vsc8584_micro_assert_reset(struct phy_device *phydev)
1182 ret = vsc8584_cmd(phydev, PROC_CMD_NOP);
1186 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS,
1187 MSCC_PHY_PAGE_EXTENDED_GPIO);
1189 reg = phy_base_read(phydev, MSCC_INT_MEM_CNTL);
1190 reg &= ~EN_PATCH_RAM_TRAP_ADDR(4);
1191 phy_base_write(phydev, MSCC_INT_MEM_CNTL, reg);
1193 phy_base_write(phydev, MSCC_TRAP_ROM_ADDR(4), 0x005b);
1194 phy_base_write(phydev, MSCC_PATCH_RAM_ADDR(4), 0x005b);
1196 reg = phy_base_read(phydev, MSCC_INT_MEM_CNTL);
1197 reg |= EN_PATCH_RAM_TRAP_ADDR(4);
1198 phy_base_write(phydev, MSCC_INT_MEM_CNTL, reg);
1200 phy_base_write(phydev, MSCC_PHY_PROC_CMD, PROC_CMD_NOP);
1202 reg = phy_base_read(phydev, MSCC_DW8051_CNTL_STATUS);
1203 reg &= ~MICRO_NSOFT_RESET;
1204 phy_base_write(phydev, MSCC_DW8051_CNTL_STATUS, reg);
1206 phy_base_write(phydev, MSCC_PHY_PROC_CMD, PROC_CMD_MCB_ACCESS_MAC_CONF |
1207 PROC_CMD_SGMII_PORT(0) | PROC_CMD_NO_MAC_CONF |
1210 reg = phy_base_read(phydev, MSCC_INT_MEM_CNTL);
1211 reg &= ~EN_PATCH_RAM_TRAP_ADDR(4);
1212 phy_base_write(phydev, MSCC_INT_MEM_CNTL, reg);
1214 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
1219 /* bus->mdio_lock should be locked when using this function */
1220 static int vsc8584_get_fw_crc(struct phy_device *phydev, u16 start, u16 size,
1225 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_EXTENDED);
1227 phy_base_write(phydev, MSCC_PHY_VERIPHY_CNTL_2, start);
1228 phy_base_write(phydev, MSCC_PHY_VERIPHY_CNTL_3, size);
1230 /* Start Micro command */
1231 ret = vsc8584_cmd(phydev, PROC_CMD_CRC16);
1235 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_EXTENDED);
1237 *crc = phy_base_read(phydev, MSCC_PHY_VERIPHY_CNTL_2);
1240 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
1245 /* bus->mdio_lock should be locked when using this function */
1246 static int vsc8584_patch_fw(struct phy_device *phydev,
1247 const struct firmware *fw)
1251 ret = vsc8584_micro_assert_reset(phydev);
1253 dev_err(&phydev->mdio.dev,
1254 "%s: failed to assert reset of micro\n", __func__);
1258 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS,
1259 MSCC_PHY_PAGE_EXTENDED_GPIO);
1261 /* Hold 8051 Micro in SW Reset, Enable auto incr address and patch clock
1262 * Disable the 8051 Micro clock
1264 phy_base_write(phydev, MSCC_DW8051_CNTL_STATUS, RUN_FROM_INT_ROM |
1265 AUTOINC_ADDR | PATCH_RAM_CLK | MICRO_CLK_EN |
1266 MICRO_CLK_DIVIDE(2));
1267 phy_base_write(phydev, MSCC_INT_MEM_CNTL, READ_PRAM | INT_MEM_WRITE_EN |
1269 phy_base_write(phydev, MSCC_INT_MEM_ADDR, 0x0000);
1271 for (i = 0; i < fw->size; i++)
1272 phy_base_write(phydev, MSCC_INT_MEM_CNTL, READ_PRAM |
1273 INT_MEM_WRITE_EN | fw->data[i]);
1275 /* Clear internal memory access */
1276 phy_base_write(phydev, MSCC_INT_MEM_CNTL, READ_RAM);
1278 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
1283 /* bus->mdio_lock should be locked when using this function */
1284 static bool vsc8574_is_serdes_init(struct phy_device *phydev)
1289 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS,
1290 MSCC_PHY_PAGE_EXTENDED_GPIO);
1292 reg = phy_base_read(phydev, MSCC_TRAP_ROM_ADDR(1));
1293 if (reg != 0x3eb7) {
1298 reg = phy_base_read(phydev, MSCC_PATCH_RAM_ADDR(1));
1299 if (reg != 0x4012) {
1304 reg = phy_base_read(phydev, MSCC_INT_MEM_CNTL);
1305 if (reg != EN_PATCH_RAM_TRAP_ADDR(1)) {
1310 reg = phy_base_read(phydev, MSCC_DW8051_CNTL_STATUS);
1311 if ((MICRO_NSOFT_RESET | RUN_FROM_INT_ROM | DW8051_CLK_EN |
1312 MICRO_CLK_EN) != (reg & MSCC_DW8051_VLD_MASK)) {
1319 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
1324 /* bus->mdio_lock should be locked when using this function */
1325 static int vsc8574_config_pre_init(struct phy_device *phydev)
1327 static const struct reg_val pre_init1[] = {
1328 {0x0fae, 0x000401bd},
1329 {0x0fac, 0x000f000f},
1330 {0x17a0, 0x00a0f147},
1331 {0x0fe4, 0x00052f54},
1332 {0x1792, 0x0027303d},
1333 {0x07fe, 0x00000704},
1334 {0x0fe0, 0x00060150},
1335 {0x0f82, 0x0012b00a},
1336 {0x0f80, 0x00000d74},
1337 {0x02e0, 0x00000012},
1338 {0x03a2, 0x00050208},
1339 {0x03b2, 0x00009186},
1340 {0x0fb0, 0x000e3700},
1341 {0x1688, 0x00049f81},
1342 {0x0fd2, 0x0000ffff},
1343 {0x168a, 0x00039fa2},
1344 {0x1690, 0x0020640b},
1345 {0x0258, 0x00002220},
1346 {0x025a, 0x00002a20},
1347 {0x025c, 0x00003060},
1348 {0x025e, 0x00003fa0},
1349 {0x03a6, 0x0000e0f0},
1350 {0x0f92, 0x00001489},
1351 {0x16a2, 0x00007000},
1352 {0x16a6, 0x00071448},
1353 {0x16a0, 0x00eeffdd},
1354 {0x0fe8, 0x0091b06c},
1355 {0x0fea, 0x00041600},
1356 {0x16b0, 0x00eeff00},
1357 {0x16b2, 0x00007000},
1358 {0x16b4, 0x00000814},
1359 {0x0f90, 0x00688980},
1360 {0x03a4, 0x0000d8f0},
1361 {0x0fc0, 0x00000400},
1362 {0x07fa, 0x0050100f},
1363 {0x0796, 0x00000003},
1364 {0x07f8, 0x00c3ff98},
1365 {0x0fa4, 0x0018292a},
1366 {0x168c, 0x00d2c46f},
1367 {0x17a2, 0x00000620},
1368 {0x16a4, 0x0013132f},
1369 {0x16a8, 0x00000000},
1370 {0x0ffc, 0x00c0a028},
1371 {0x0fec, 0x00901c09},
1372 {0x0fee, 0x0004a6a1},
1373 {0x0ffe, 0x00b01807},
1375 static const struct reg_val pre_init2[] = {
1376 {0x0486, 0x0008a518},
1377 {0x0488, 0x006dc696},
1378 {0x048a, 0x00000912},
1379 {0x048e, 0x00000db6},
1380 {0x049c, 0x00596596},
1381 {0x049e, 0x00000514},
1382 {0x04a2, 0x00410280},
1383 {0x04a4, 0x00000000},
1384 {0x04a6, 0x00000000},
1385 {0x04a8, 0x00000000},
1386 {0x04aa, 0x00000000},
1387 {0x04ae, 0x007df7dd},
1388 {0x04b0, 0x006d95d4},
1389 {0x04b2, 0x00492410},
1391 struct device *dev = &phydev->mdio.dev;
1392 const struct firmware *fw;
1398 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
1400 /* all writes below are broadcasted to all PHYs in the same package */
1401 reg = phy_base_read(phydev, MSCC_PHY_EXT_CNTL_STATUS);
1402 reg |= SMI_BROADCAST_WR_EN;
1403 phy_base_write(phydev, MSCC_PHY_EXT_CNTL_STATUS, reg);
1405 phy_base_write(phydev, MII_VSC85XX_INT_MASK, 0);
1407 /* The below register writes are tweaking analog and electrical
1408 * configuration that were determined through characterization by PHY
1409 * engineers. These don't mean anything more than "these are the best
1412 phy_base_write(phydev, MSCC_PHY_EXT_PHY_CNTL_2, 0x0040);
1414 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_TEST);
1416 phy_base_write(phydev, MSCC_PHY_TEST_PAGE_20, 0x4320);
1417 phy_base_write(phydev, MSCC_PHY_TEST_PAGE_24, 0x0c00);
1418 phy_base_write(phydev, MSCC_PHY_TEST_PAGE_9, 0x18ca);
1419 phy_base_write(phydev, MSCC_PHY_TEST_PAGE_5, 0x1b20);
1421 reg = phy_base_read(phydev, MSCC_PHY_TEST_PAGE_8);
1423 phy_base_write(phydev, MSCC_PHY_TEST_PAGE_8, reg);
1425 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_TR);
1427 for (i = 0; i < ARRAY_SIZE(pre_init1); i++)
1428 vsc8584_csr_write(phydev, pre_init1[i].reg, pre_init1[i].val);
1430 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_EXTENDED_2);
1432 phy_base_write(phydev, MSCC_PHY_CU_PMD_TX_CNTL, 0x028e);
1434 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_TR);
1436 for (i = 0; i < ARRAY_SIZE(pre_init2); i++)
1437 vsc8584_csr_write(phydev, pre_init2[i].reg, pre_init2[i].val);
1439 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_TEST);
1441 reg = phy_base_read(phydev, MSCC_PHY_TEST_PAGE_8);
1443 phy_base_write(phydev, MSCC_PHY_TEST_PAGE_8, reg);
1445 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
1447 /* end of write broadcasting */
1448 reg = phy_base_read(phydev, MSCC_PHY_EXT_CNTL_STATUS);
1449 reg &= ~SMI_BROADCAST_WR_EN;
1450 phy_base_write(phydev, MSCC_PHY_EXT_CNTL_STATUS, reg);
1452 ret = request_firmware(&fw, MSCC_VSC8574_REVB_INT8051_FW, dev);
1454 dev_err(dev, "failed to load firmware %s, ret: %d\n",
1455 MSCC_VSC8574_REVB_INT8051_FW, ret);
1459 /* Add one byte to size for the one added by the patch_fw function */
1460 ret = vsc8584_get_fw_crc(phydev,
1461 MSCC_VSC8574_REVB_INT8051_FW_START_ADDR,
1462 fw->size + 1, &crc);
1466 if (crc == MSCC_VSC8574_REVB_INT8051_FW_CRC) {
1467 serdes_init = vsc8574_is_serdes_init(phydev);
1470 ret = vsc8584_micro_assert_reset(phydev);
1473 "%s: failed to assert reset of micro\n",
1479 dev_dbg(dev, "FW CRC is not the expected one, patching FW\n");
1481 serdes_init = false;
1483 if (vsc8584_patch_fw(phydev, fw))
1485 "failed to patch FW, expect non-optimal device\n");
1489 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS,
1490 MSCC_PHY_PAGE_EXTENDED_GPIO);
1492 phy_base_write(phydev, MSCC_TRAP_ROM_ADDR(1), 0x3eb7);
1493 phy_base_write(phydev, MSCC_PATCH_RAM_ADDR(1), 0x4012);
1494 phy_base_write(phydev, MSCC_INT_MEM_CNTL,
1495 EN_PATCH_RAM_TRAP_ADDR(1));
1497 vsc8584_micro_deassert_reset(phydev, false);
1499 /* Add one byte to size for the one added by the patch_fw
1502 ret = vsc8584_get_fw_crc(phydev,
1503 MSCC_VSC8574_REVB_INT8051_FW_START_ADDR,
1504 fw->size + 1, &crc);
1508 if (crc != MSCC_VSC8574_REVB_INT8051_FW_CRC)
1510 "FW CRC after patching is not the expected one, expect non-optimal device\n");
1513 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS,
1514 MSCC_PHY_PAGE_EXTENDED_GPIO);
1516 ret = vsc8584_cmd(phydev, PROC_CMD_1588_DEFAULT_INIT |
1520 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
1522 release_firmware(fw);
1527 /* bus->mdio_lock should be locked when using this function */
1528 static int vsc8584_config_pre_init(struct phy_device *phydev)
1530 static const struct reg_val pre_init1[] = {
1531 {0x07fa, 0x0050100f},
1532 {0x1688, 0x00049f81},
1533 {0x0f90, 0x00688980},
1534 {0x03a4, 0x0000d8f0},
1535 {0x0fc0, 0x00000400},
1536 {0x0f82, 0x0012b002},
1537 {0x1686, 0x00000004},
1538 {0x168c, 0x00d2c46f},
1539 {0x17a2, 0x00000620},
1540 {0x16a0, 0x00eeffdd},
1541 {0x16a6, 0x00071448},
1542 {0x16a4, 0x0013132f},
1543 {0x16a8, 0x00000000},
1544 {0x0ffc, 0x00c0a028},
1545 {0x0fe8, 0x0091b06c},
1546 {0x0fea, 0x00041600},
1547 {0x0f80, 0x00fffaff},
1548 {0x0fec, 0x00901809},
1549 {0x0ffe, 0x00b01007},
1550 {0x16b0, 0x00eeff00},
1551 {0x16b2, 0x00007000},
1552 {0x16b4, 0x00000814},
1554 static const struct reg_val pre_init2[] = {
1555 {0x0486, 0x0008a518},
1556 {0x0488, 0x006dc696},
1557 {0x048a, 0x00000912},
1559 const struct firmware *fw;
1560 struct device *dev = &phydev->mdio.dev;
1565 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
1567 /* all writes below are broadcasted to all PHYs in the same package */
1568 reg = phy_base_read(phydev, MSCC_PHY_EXT_CNTL_STATUS);
1569 reg |= SMI_BROADCAST_WR_EN;
1570 phy_base_write(phydev, MSCC_PHY_EXT_CNTL_STATUS, reg);
1572 phy_base_write(phydev, MII_VSC85XX_INT_MASK, 0);
1574 reg = phy_base_read(phydev, MSCC_PHY_BYPASS_CONTROL);
1575 reg |= PARALLEL_DET_IGNORE_ADVERTISED;
1576 phy_base_write(phydev, MSCC_PHY_BYPASS_CONTROL, reg);
1578 /* The below register writes are tweaking analog and electrical
1579 * configuration that were determined through characterization by PHY
1580 * engineers. These don't mean anything more than "these are the best
1583 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_EXTENDED_3);
1585 phy_base_write(phydev, MSCC_PHY_SERDES_TX_CRC_ERR_CNT, 0x2000);
1587 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_TEST);
1589 phy_base_write(phydev, MSCC_PHY_TEST_PAGE_5, 0x1f20);
1591 reg = phy_base_read(phydev, MSCC_PHY_TEST_PAGE_8);
1593 phy_base_write(phydev, MSCC_PHY_TEST_PAGE_8, reg);
1595 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_TR);
1597 phy_base_write(phydev, MSCC_PHY_TR_CNTL, TR_WRITE | TR_ADDR(0x2fa4));
1599 reg = phy_base_read(phydev, MSCC_PHY_TR_MSB);
1602 phy_base_write(phydev, MSCC_PHY_TR_MSB, reg);
1604 phy_base_write(phydev, MSCC_PHY_TR_CNTL, TR_WRITE | TR_ADDR(0x0fa4));
1606 for (i = 0; i < ARRAY_SIZE(pre_init1); i++)
1607 vsc8584_csr_write(phydev, pre_init1[i].reg, pre_init1[i].val);
1609 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_EXTENDED_2);
1611 phy_base_write(phydev, MSCC_PHY_CU_PMD_TX_CNTL, 0x028e);
1613 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_TR);
1615 for (i = 0; i < ARRAY_SIZE(pre_init2); i++)
1616 vsc8584_csr_write(phydev, pre_init2[i].reg, pre_init2[i].val);
1618 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_TEST);
1620 reg = phy_base_read(phydev, MSCC_PHY_TEST_PAGE_8);
1622 phy_base_write(phydev, MSCC_PHY_TEST_PAGE_8, reg);
1624 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
1626 /* end of write broadcasting */
1627 reg = phy_base_read(phydev, MSCC_PHY_EXT_CNTL_STATUS);
1628 reg &= ~SMI_BROADCAST_WR_EN;
1629 phy_base_write(phydev, MSCC_PHY_EXT_CNTL_STATUS, reg);
1631 ret = request_firmware(&fw, MSCC_VSC8584_REVB_INT8051_FW, dev);
1633 dev_err(dev, "failed to load firmware %s, ret: %d\n",
1634 MSCC_VSC8584_REVB_INT8051_FW, ret);
1638 /* Add one byte to size for the one added by the patch_fw function */
1639 ret = vsc8584_get_fw_crc(phydev,
1640 MSCC_VSC8584_REVB_INT8051_FW_START_ADDR,
1641 fw->size + 1, &crc);
1645 if (crc != MSCC_VSC8584_REVB_INT8051_FW_CRC) {
1646 dev_dbg(dev, "FW CRC is not the expected one, patching FW\n");
1647 if (vsc8584_patch_fw(phydev, fw))
1649 "failed to patch FW, expect non-optimal device\n");
1652 vsc8584_micro_deassert_reset(phydev, false);
1654 /* Add one byte to size for the one added by the patch_fw function */
1655 ret = vsc8584_get_fw_crc(phydev,
1656 MSCC_VSC8584_REVB_INT8051_FW_START_ADDR,
1657 fw->size + 1, &crc);
1661 if (crc != MSCC_VSC8584_REVB_INT8051_FW_CRC)
1663 "FW CRC after patching is not the expected one, expect non-optimal device\n");
1665 ret = vsc8584_micro_assert_reset(phydev);
1669 vsc8584_micro_deassert_reset(phydev, true);
1672 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
1674 release_firmware(fw);
1679 #if IS_ENABLED(CONFIG_MACSEC)
1680 static u32 vsc8584_macsec_phy_read(struct phy_device *phydev,
1681 enum macsec_bank bank, u32 reg)
1683 u32 val, val_l = 0, val_h = 0;
1684 unsigned long deadline;
1687 rc = phy_select_page(phydev, MSCC_PHY_PAGE_MACSEC);
1691 __phy_write(phydev, MSCC_EXT_PAGE_MACSEC_20,
1692 MSCC_PHY_MACSEC_20_TARGET(bank >> 2));
1694 if (bank >> 2 == 0x1)
1695 /* non-MACsec access */
1700 __phy_write(phydev, MSCC_EXT_PAGE_MACSEC_19,
1701 MSCC_PHY_MACSEC_19_CMD | MSCC_PHY_MACSEC_19_READ |
1702 MSCC_PHY_MACSEC_19_REG_ADDR(reg) |
1703 MSCC_PHY_MACSEC_19_TARGET(bank));
1705 deadline = jiffies + msecs_to_jiffies(PROC_CMD_NCOMPLETED_TIMEOUT_MS);
1707 val = __phy_read(phydev, MSCC_EXT_PAGE_MACSEC_19);
1708 } while (time_before(jiffies, deadline) && !(val & MSCC_PHY_MACSEC_19_CMD));
1710 val_l = __phy_read(phydev, MSCC_EXT_PAGE_MACSEC_17);
1711 val_h = __phy_read(phydev, MSCC_EXT_PAGE_MACSEC_18);
1714 phy_restore_page(phydev, rc, rc);
1716 return (val_h << 16) | val_l;
1719 static void vsc8584_macsec_phy_write(struct phy_device *phydev,
1720 enum macsec_bank bank, u32 reg, u32 val)
1722 unsigned long deadline;
1725 rc = phy_select_page(phydev, MSCC_PHY_PAGE_MACSEC);
1729 __phy_write(phydev, MSCC_EXT_PAGE_MACSEC_20,
1730 MSCC_PHY_MACSEC_20_TARGET(bank >> 2));
1732 if ((bank >> 2 == 0x1) || (bank >> 2 == 0x3))
1738 __phy_write(phydev, MSCC_EXT_PAGE_MACSEC_17, (u16)val);
1739 __phy_write(phydev, MSCC_EXT_PAGE_MACSEC_18, (u16)(val >> 16));
1741 __phy_write(phydev, MSCC_EXT_PAGE_MACSEC_19,
1742 MSCC_PHY_MACSEC_19_CMD | MSCC_PHY_MACSEC_19_REG_ADDR(reg) |
1743 MSCC_PHY_MACSEC_19_TARGET(bank));
1745 deadline = jiffies + msecs_to_jiffies(PROC_CMD_NCOMPLETED_TIMEOUT_MS);
1747 val = __phy_read(phydev, MSCC_EXT_PAGE_MACSEC_19);
1748 } while (time_before(jiffies, deadline) && !(val & MSCC_PHY_MACSEC_19_CMD));
1751 phy_restore_page(phydev, rc, rc);
1754 static void vsc8584_macsec_classification(struct phy_device *phydev,
1755 enum macsec_bank bank)
1757 /* enable VLAN tag parsing */
1758 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_CP_TAG,
1759 MSCC_MS_SAM_CP_TAG_PARSE_STAG |
1760 MSCC_MS_SAM_CP_TAG_PARSE_QTAG |
1761 MSCC_MS_SAM_CP_TAG_PARSE_QINQ);
1764 static void vsc8584_macsec_flow_default_action(struct phy_device *phydev,
1765 enum macsec_bank bank,
1768 u32 port = (bank == MACSEC_INGR) ?
1769 MSCC_MS_PORT_UNCONTROLLED : MSCC_MS_PORT_COMMON;
1770 u32 action = MSCC_MS_FLOW_BYPASS;
1773 action = MSCC_MS_FLOW_DROP;
1775 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_NM_FLOW_NCP,
1776 /* MACsec untagged */
1777 MSCC_MS_SAM_NM_FLOW_NCP_UNTAGGED_FLOW_TYPE(action) |
1778 MSCC_MS_SAM_NM_FLOW_NCP_UNTAGGED_DROP_ACTION(MSCC_MS_ACTION_DROP) |
1779 MSCC_MS_SAM_NM_FLOW_NCP_UNTAGGED_DEST_PORT(port) |
1781 MSCC_MS_SAM_NM_FLOW_NCP_TAGGED_FLOW_TYPE(action) |
1782 MSCC_MS_SAM_NM_FLOW_NCP_TAGGED_DROP_ACTION(MSCC_MS_ACTION_DROP) |
1783 MSCC_MS_SAM_NM_FLOW_NCP_TAGGED_DEST_PORT(port) |
1785 MSCC_MS_SAM_NM_FLOW_NCP_BADTAG_FLOW_TYPE(action) |
1786 MSCC_MS_SAM_NM_FLOW_NCP_BADTAG_DROP_ACTION(MSCC_MS_ACTION_DROP) |
1787 MSCC_MS_SAM_NM_FLOW_NCP_BADTAG_DEST_PORT(port) |
1789 MSCC_MS_SAM_NM_FLOW_NCP_KAY_FLOW_TYPE(action) |
1790 MSCC_MS_SAM_NM_FLOW_NCP_KAY_DROP_ACTION(MSCC_MS_ACTION_DROP) |
1791 MSCC_MS_SAM_NM_FLOW_NCP_KAY_DEST_PORT(port));
1792 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_NM_FLOW_CP,
1793 /* MACsec untagged */
1794 MSCC_MS_SAM_NM_FLOW_NCP_UNTAGGED_FLOW_TYPE(action) |
1795 MSCC_MS_SAM_NM_FLOW_CP_UNTAGGED_DROP_ACTION(MSCC_MS_ACTION_DROP) |
1796 MSCC_MS_SAM_NM_FLOW_CP_UNTAGGED_DEST_PORT(port) |
1798 MSCC_MS_SAM_NM_FLOW_NCP_TAGGED_FLOW_TYPE(action) |
1799 MSCC_MS_SAM_NM_FLOW_CP_TAGGED_DROP_ACTION(MSCC_MS_ACTION_DROP) |
1800 MSCC_MS_SAM_NM_FLOW_CP_TAGGED_DEST_PORT(port) |
1802 MSCC_MS_SAM_NM_FLOW_NCP_BADTAG_FLOW_TYPE(action) |
1803 MSCC_MS_SAM_NM_FLOW_CP_BADTAG_DROP_ACTION(MSCC_MS_ACTION_DROP) |
1804 MSCC_MS_SAM_NM_FLOW_CP_BADTAG_DEST_PORT(port) |
1806 MSCC_MS_SAM_NM_FLOW_NCP_KAY_FLOW_TYPE(action) |
1807 MSCC_MS_SAM_NM_FLOW_CP_KAY_DROP_ACTION(MSCC_MS_ACTION_DROP) |
1808 MSCC_MS_SAM_NM_FLOW_CP_KAY_DEST_PORT(port));
1811 static void vsc8584_macsec_integrity_checks(struct phy_device *phydev,
1812 enum macsec_bank bank)
1816 if (bank != MACSEC_INGR)
1819 /* Set default rules to pass unmatched frames */
1820 val = vsc8584_macsec_phy_read(phydev, bank,
1821 MSCC_MS_PARAMS2_IG_CC_CONTROL);
1822 val |= MSCC_MS_PARAMS2_IG_CC_CONTROL_NON_MATCH_CTRL_ACT |
1823 MSCC_MS_PARAMS2_IG_CC_CONTROL_NON_MATCH_ACT;
1824 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_PARAMS2_IG_CC_CONTROL,
1827 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_PARAMS2_IG_CP_TAG,
1828 MSCC_MS_PARAMS2_IG_CP_TAG_PARSE_STAG |
1829 MSCC_MS_PARAMS2_IG_CP_TAG_PARSE_QTAG |
1830 MSCC_MS_PARAMS2_IG_CP_TAG_PARSE_QINQ);
1833 static void vsc8584_macsec_block_init(struct phy_device *phydev,
1834 enum macsec_bank bank)
1839 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_ENA_CFG,
1840 MSCC_MS_ENA_CFG_SW_RST |
1841 MSCC_MS_ENA_CFG_MACSEC_BYPASS_ENA);
1843 /* Set the MACsec block out of s/w reset and enable clocks */
1844 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_ENA_CFG,
1845 MSCC_MS_ENA_CFG_CLK_ENA);
1847 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_STATUS_CONTEXT_CTRL,
1848 bank == MACSEC_INGR ? 0xe5880214 : 0xe5880218);
1849 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_MISC_CONTROL,
1850 MSCC_MS_MISC_CONTROL_MC_LATENCY_FIX(bank == MACSEC_INGR ? 57 : 40) |
1851 MSCC_MS_MISC_CONTROL_XFORM_REC_SIZE(bank == MACSEC_INGR ? 1 : 2));
1853 /* Clear the counters */
1854 val = vsc8584_macsec_phy_read(phydev, bank, MSCC_MS_COUNT_CONTROL);
1855 val |= MSCC_MS_COUNT_CONTROL_AUTO_CNTR_RESET;
1856 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_COUNT_CONTROL, val);
1858 /* Enable octet increment mode */
1859 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_PP_CTRL,
1860 MSCC_MS_PP_CTRL_MACSEC_OCTET_INCR_MODE);
1862 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_BLOCK_CTX_UPDATE, 0x3);
1864 val = vsc8584_macsec_phy_read(phydev, bank, MSCC_MS_COUNT_CONTROL);
1865 val |= MSCC_MS_COUNT_CONTROL_RESET_ALL;
1866 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_COUNT_CONTROL, val);
1869 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_NON_VLAN_MTU_CHECK,
1870 MSCC_MS_NON_VLAN_MTU_CHECK_NV_MTU_COMPARE(32761) |
1871 MSCC_MS_NON_VLAN_MTU_CHECK_NV_MTU_COMP_DROP);
1873 for (i = 0; i < 8; i++)
1874 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_VLAN_MTU_CHECK(i),
1875 MSCC_MS_VLAN_MTU_CHECK_MTU_COMPARE(32761) |
1876 MSCC_MS_VLAN_MTU_CHECK_MTU_COMP_DROP);
1878 if (bank == MACSEC_EGR) {
1879 val = vsc8584_macsec_phy_read(phydev, bank, MSCC_MS_INTR_CTRL_STATUS);
1880 val &= ~MSCC_MS_INTR_CTRL_STATUS_INTR_ENABLE_M;
1881 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_INTR_CTRL_STATUS, val);
1883 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_FC_CFG,
1884 MSCC_MS_FC_CFG_FCBUF_ENA |
1885 MSCC_MS_FC_CFG_LOW_THRESH(0x1) |
1886 MSCC_MS_FC_CFG_HIGH_THRESH(0x4) |
1887 MSCC_MS_FC_CFG_LOW_BYTES_VAL(0x4) |
1888 MSCC_MS_FC_CFG_HIGH_BYTES_VAL(0x6));
1891 vsc8584_macsec_classification(phydev, bank);
1892 vsc8584_macsec_flow_default_action(phydev, bank, false);
1893 vsc8584_macsec_integrity_checks(phydev, bank);
1895 /* Enable the MACsec block */
1896 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_ENA_CFG,
1897 MSCC_MS_ENA_CFG_CLK_ENA |
1898 MSCC_MS_ENA_CFG_MACSEC_ENA |
1899 MSCC_MS_ENA_CFG_MACSEC_SPEED_MODE(0x5));
1902 static void vsc8584_macsec_mac_init(struct phy_device *phydev,
1903 enum macsec_bank bank)
1908 /* Clear host & line stats */
1909 for (i = 0; i < 36; i++)
1910 vsc8584_macsec_phy_write(phydev, bank, 0x1c + i, 0);
1912 val = vsc8584_macsec_phy_read(phydev, bank,
1913 MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL);
1914 val &= ~MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL_PAUSE_MODE_M;
1915 val |= MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL_PAUSE_MODE(2) |
1916 MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL_PAUSE_VALUE(0xffff);
1917 vsc8584_macsec_phy_write(phydev, bank,
1918 MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL, val);
1920 val = vsc8584_macsec_phy_read(phydev, bank,
1921 MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL_2);
1923 vsc8584_macsec_phy_write(phydev, bank,
1924 MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL_2, val);
1926 val = vsc8584_macsec_phy_read(phydev, bank,
1927 MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL);
1928 if (bank == HOST_MAC)
1929 val |= MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL_PAUSE_TIMER_ENA |
1930 MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL_PAUSE_FRAME_DROP_ENA;
1932 val |= MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL_PAUSE_REACT_ENA |
1933 MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL_PAUSE_FRAME_DROP_ENA |
1934 MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL_PAUSE_MODE |
1935 MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL_EARLY_PAUSE_DETECT_ENA;
1936 vsc8584_macsec_phy_write(phydev, bank,
1937 MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL, val);
1939 vsc8584_macsec_phy_write(phydev, bank, MSCC_MAC_CFG_PKTINF_CFG,
1940 MSCC_MAC_CFG_PKTINF_CFG_STRIP_FCS_ENA |
1941 MSCC_MAC_CFG_PKTINF_CFG_INSERT_FCS_ENA |
1942 MSCC_MAC_CFG_PKTINF_CFG_LPI_RELAY_ENA |
1943 MSCC_MAC_CFG_PKTINF_CFG_STRIP_PREAMBLE_ENA |
1944 MSCC_MAC_CFG_PKTINF_CFG_INSERT_PREAMBLE_ENA |
1946 MSCC_MAC_CFG_PKTINF_CFG_ENABLE_TX_PADDING : 0));
1948 val = vsc8584_macsec_phy_read(phydev, bank, MSCC_MAC_CFG_MODE_CFG);
1949 val &= ~MSCC_MAC_CFG_MODE_CFG_DISABLE_DIC;
1950 vsc8584_macsec_phy_write(phydev, bank, MSCC_MAC_CFG_MODE_CFG, val);
1952 val = vsc8584_macsec_phy_read(phydev, bank, MSCC_MAC_CFG_MAXLEN_CFG);
1953 val &= ~MSCC_MAC_CFG_MAXLEN_CFG_MAX_LEN_M;
1954 val |= MSCC_MAC_CFG_MAXLEN_CFG_MAX_LEN(10240);
1955 vsc8584_macsec_phy_write(phydev, bank, MSCC_MAC_CFG_MAXLEN_CFG, val);
1957 vsc8584_macsec_phy_write(phydev, bank, MSCC_MAC_CFG_ADV_CHK_CFG,
1958 MSCC_MAC_CFG_ADV_CHK_CFG_SFD_CHK_ENA |
1959 MSCC_MAC_CFG_ADV_CHK_CFG_PRM_CHK_ENA |
1960 MSCC_MAC_CFG_ADV_CHK_CFG_OOR_ERR_ENA |
1961 MSCC_MAC_CFG_ADV_CHK_CFG_INR_ERR_ENA);
1963 val = vsc8584_macsec_phy_read(phydev, bank, MSCC_MAC_CFG_LFS_CFG);
1964 val &= ~MSCC_MAC_CFG_LFS_CFG_LFS_MODE_ENA;
1965 vsc8584_macsec_phy_write(phydev, bank, MSCC_MAC_CFG_LFS_CFG, val);
1967 vsc8584_macsec_phy_write(phydev, bank, MSCC_MAC_CFG_ENA_CFG,
1968 MSCC_MAC_CFG_ENA_CFG_RX_CLK_ENA |
1969 MSCC_MAC_CFG_ENA_CFG_TX_CLK_ENA |
1970 MSCC_MAC_CFG_ENA_CFG_RX_ENA |
1971 MSCC_MAC_CFG_ENA_CFG_TX_ENA);
1974 /* Must be called with mdio_lock taken */
1975 static int vsc8584_macsec_init(struct phy_device *phydev)
1979 vsc8584_macsec_block_init(phydev, MACSEC_INGR);
1980 vsc8584_macsec_block_init(phydev, MACSEC_EGR);
1981 vsc8584_macsec_mac_init(phydev, HOST_MAC);
1982 vsc8584_macsec_mac_init(phydev, LINE_MAC);
1984 vsc8584_macsec_phy_write(phydev, FC_BUFFER,
1985 MSCC_FCBUF_FC_READ_THRESH_CFG,
1986 MSCC_FCBUF_FC_READ_THRESH_CFG_TX_THRESH(4) |
1987 MSCC_FCBUF_FC_READ_THRESH_CFG_RX_THRESH(5));
1989 val = vsc8584_macsec_phy_read(phydev, FC_BUFFER, MSCC_FCBUF_MODE_CFG);
1990 val |= MSCC_FCBUF_MODE_CFG_PAUSE_GEN_ENA |
1991 MSCC_FCBUF_MODE_CFG_RX_PPM_RATE_ADAPT_ENA |
1992 MSCC_FCBUF_MODE_CFG_TX_PPM_RATE_ADAPT_ENA;
1993 vsc8584_macsec_phy_write(phydev, FC_BUFFER, MSCC_FCBUF_MODE_CFG, val);
1995 vsc8584_macsec_phy_write(phydev, FC_BUFFER, MSCC_FCBUF_PPM_RATE_ADAPT_THRESH_CFG,
1996 MSCC_FCBUF_PPM_RATE_ADAPT_THRESH_CFG_TX_THRESH(8) |
1997 MSCC_FCBUF_PPM_RATE_ADAPT_THRESH_CFG_TX_OFFSET(9));
1999 val = vsc8584_macsec_phy_read(phydev, FC_BUFFER,
2000 MSCC_FCBUF_TX_DATA_QUEUE_CFG);
2001 val &= ~(MSCC_FCBUF_TX_DATA_QUEUE_CFG_START_M |
2002 MSCC_FCBUF_TX_DATA_QUEUE_CFG_END_M);
2003 val |= MSCC_FCBUF_TX_DATA_QUEUE_CFG_START(0) |
2004 MSCC_FCBUF_TX_DATA_QUEUE_CFG_END(5119);
2005 vsc8584_macsec_phy_write(phydev, FC_BUFFER,
2006 MSCC_FCBUF_TX_DATA_QUEUE_CFG, val);
2008 val = vsc8584_macsec_phy_read(phydev, FC_BUFFER, MSCC_FCBUF_ENA_CFG);
2009 val |= MSCC_FCBUF_ENA_CFG_TX_ENA | MSCC_FCBUF_ENA_CFG_RX_ENA;
2010 vsc8584_macsec_phy_write(phydev, FC_BUFFER, MSCC_FCBUF_ENA_CFG, val);
2012 val = vsc8584_macsec_phy_read(phydev, IP_1588,
2013 MSCC_PROC_0_IP_1588_TOP_CFG_STAT_MODE_CTL);
2014 val &= ~MSCC_PROC_0_IP_1588_TOP_CFG_STAT_MODE_CTL_PROTOCOL_MODE_M;
2015 val |= MSCC_PROC_0_IP_1588_TOP_CFG_STAT_MODE_CTL_PROTOCOL_MODE(4);
2016 vsc8584_macsec_phy_write(phydev, IP_1588,
2017 MSCC_PROC_0_IP_1588_TOP_CFG_STAT_MODE_CTL, val);
2022 static void vsc8584_macsec_flow(struct phy_device *phydev,
2023 struct macsec_flow *flow)
2025 struct vsc8531_private *priv = phydev->priv;
2026 enum macsec_bank bank = flow->bank;
2027 u32 val, match = 0, mask = 0, action = 0, idx = flow->index;
2029 if (flow->match.tagged)
2030 match |= MSCC_MS_SAM_MISC_MATCH_TAGGED;
2031 if (flow->match.untagged)
2032 match |= MSCC_MS_SAM_MISC_MATCH_UNTAGGED;
2034 if (bank == MACSEC_INGR && flow->assoc_num >= 0) {
2035 match |= MSCC_MS_SAM_MISC_MATCH_AN(flow->assoc_num);
2036 mask |= MSCC_MS_SAM_MASK_AN_MASK(0x3);
2039 if (bank == MACSEC_INGR && flow->match.sci && flow->rx_sa->sc->sci) {
2040 match |= MSCC_MS_SAM_MISC_MATCH_TCI(BIT(3));
2041 mask |= MSCC_MS_SAM_MASK_TCI_MASK(BIT(3)) |
2042 MSCC_MS_SAM_MASK_SCI_MASK;
2044 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_MATCH_SCI_LO(idx),
2045 lower_32_bits(flow->rx_sa->sc->sci));
2046 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_MATCH_SCI_HI(idx),
2047 upper_32_bits(flow->rx_sa->sc->sci));
2050 if (flow->match.etype) {
2051 mask |= MSCC_MS_SAM_MASK_MAC_ETYPE_MASK;
2053 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_MAC_SA_MATCH_HI(idx),
2054 MSCC_MS_SAM_MAC_SA_MATCH_HI_ETYPE(htons(flow->etype)));
2057 match |= MSCC_MS_SAM_MISC_MATCH_PRIORITY(flow->priority);
2059 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_MISC_MATCH(idx), match);
2060 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_MASK(idx), mask);
2062 /* Action for matching packets */
2063 if (flow->action.drop)
2064 action = MSCC_MS_FLOW_DROP;
2065 else if (flow->action.bypass || flow->port == MSCC_MS_PORT_UNCONTROLLED)
2066 action = MSCC_MS_FLOW_BYPASS;
2068 action = (bank == MACSEC_INGR) ?
2069 MSCC_MS_FLOW_INGRESS : MSCC_MS_FLOW_EGRESS;
2071 val = MSCC_MS_SAM_FLOW_CTRL_FLOW_TYPE(action) |
2072 MSCC_MS_SAM_FLOW_CTRL_DROP_ACTION(MSCC_MS_ACTION_DROP) |
2073 MSCC_MS_SAM_FLOW_CTRL_DEST_PORT(flow->port);
2075 if (action == MSCC_MS_FLOW_BYPASS)
2078 if (bank == MACSEC_INGR) {
2079 if (priv->secy->replay_protect)
2080 val |= MSCC_MS_SAM_FLOW_CTRL_REPLAY_PROTECT;
2081 if (priv->secy->validate_frames == MACSEC_VALIDATE_STRICT)
2082 val |= MSCC_MS_SAM_FLOW_CTRL_VALIDATE_FRAMES(MSCC_MS_VALIDATE_STRICT);
2083 else if (priv->secy->validate_frames == MACSEC_VALIDATE_CHECK)
2084 val |= MSCC_MS_SAM_FLOW_CTRL_VALIDATE_FRAMES(MSCC_MS_VALIDATE_CHECK);
2085 } else if (bank == MACSEC_EGR) {
2086 if (priv->secy->protect_frames)
2087 val |= MSCC_MS_SAM_FLOW_CTRL_PROTECT_FRAME;
2088 if (priv->secy->tx_sc.encrypt)
2089 val |= MSCC_MS_SAM_FLOW_CTRL_CONF_PROTECT;
2090 if (priv->secy->tx_sc.send_sci)
2091 val |= MSCC_MS_SAM_FLOW_CTRL_INCLUDE_SCI;
2095 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_FLOW_CTRL(idx), val);
2098 static struct macsec_flow *vsc8584_macsec_find_flow(struct macsec_context *ctx,
2099 enum macsec_bank bank)
2101 struct vsc8531_private *priv = ctx->phydev->priv;
2102 struct macsec_flow *pos, *tmp;
2104 list_for_each_entry_safe(pos, tmp, &priv->macsec_flows, list)
2105 if (pos->assoc_num == ctx->sa.assoc_num && pos->bank == bank)
2108 return ERR_PTR(-ENOENT);
2111 static void vsc8584_macsec_flow_enable(struct phy_device *phydev,
2112 struct macsec_flow *flow)
2114 enum macsec_bank bank = flow->bank;
2115 u32 val, idx = flow->index;
2117 if ((flow->bank == MACSEC_INGR && flow->rx_sa && !flow->rx_sa->active) ||
2118 (flow->bank == MACSEC_EGR && flow->tx_sa && !flow->tx_sa->active))
2122 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_ENTRY_SET1, BIT(idx));
2125 val = vsc8584_macsec_phy_read(phydev, bank, MSCC_MS_SAM_FLOW_CTRL(idx));
2126 val |= MSCC_MS_SAM_FLOW_CTRL_SA_IN_USE;
2127 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_FLOW_CTRL(idx), val);
2130 static void vsc8584_macsec_flow_disable(struct phy_device *phydev,
2131 struct macsec_flow *flow)
2133 enum macsec_bank bank = flow->bank;
2134 u32 val, idx = flow->index;
2137 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_ENTRY_CLEAR1, BIT(idx));
2140 val = vsc8584_macsec_phy_read(phydev, bank, MSCC_MS_SAM_FLOW_CTRL(idx));
2141 val &= ~MSCC_MS_SAM_FLOW_CTRL_SA_IN_USE;
2142 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_FLOW_CTRL(idx), val);
2145 static u32 vsc8584_macsec_flow_context_id(struct macsec_flow *flow)
2147 if (flow->bank == MACSEC_INGR)
2148 return flow->index + MSCC_MS_MAX_FLOWS;
2153 /* Derive the AES key to get a key for the hash autentication */
2154 static int vsc8584_macsec_derive_key(const u8 key[MACSEC_KEYID_LEN],
2155 u16 key_len, u8 hkey[16])
2157 struct crypto_skcipher *tfm = crypto_alloc_skcipher("ecb(aes)", 0, 0);
2158 struct skcipher_request *req = NULL;
2159 struct scatterlist src, dst;
2160 DECLARE_CRYPTO_WAIT(wait);
2165 return PTR_ERR(tfm);
2167 req = skcipher_request_alloc(tfm, GFP_KERNEL);
2173 skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
2174 CRYPTO_TFM_REQ_MAY_SLEEP, crypto_req_done,
2176 ret = crypto_skcipher_setkey(tfm, key, key_len);
2180 sg_init_one(&src, input, 16);
2181 sg_init_one(&dst, hkey, 16);
2182 skcipher_request_set_crypt(req, &src, &dst, 16, NULL);
2184 ret = crypto_wait_req(crypto_skcipher_encrypt(req), &wait);
2187 skcipher_request_free(req);
2188 crypto_free_skcipher(tfm);
2192 static int vsc8584_macsec_transformation(struct phy_device *phydev,
2193 struct macsec_flow *flow)
2195 struct vsc8531_private *priv = phydev->priv;
2196 enum macsec_bank bank = flow->bank;
2197 int i, ret, index = flow->index;
2198 u32 rec = 0, control = 0;
2202 ret = vsc8584_macsec_derive_key(flow->key, priv->secy->key_len, hkey);
2206 switch (priv->secy->key_len) {
2208 control |= CONTROL_CRYPTO_ALG(CTRYPTO_ALG_AES_CTR_128);
2211 control |= CONTROL_CRYPTO_ALG(CTRYPTO_ALG_AES_CTR_256);
2217 control |= (bank == MACSEC_EGR) ?
2218 (CONTROL_TYPE_EGRESS | CONTROL_AN(priv->secy->tx_sc.encoding_sa)) :
2219 (CONTROL_TYPE_INGRESS | CONTROL_SEQ_MASK);
2221 control |= CONTROL_UPDATE_SEQ | CONTROL_ENCRYPT_AUTH | CONTROL_KEY_IN_CTX |
2222 CONTROL_IV0 | CONTROL_IV1 | CONTROL_IV_IN_SEQ |
2223 CONTROL_DIGEST_TYPE(0x2) | CONTROL_SEQ_TYPE(0x1) |
2224 CONTROL_AUTH_ALG(AUTH_ALG_AES_GHAS) | CONTROL_CONTEXT_ID;
2226 /* Set the control word */
2227 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_XFORM_REC(index, rec++),
2230 /* Set the context ID. Must be unique. */
2231 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_XFORM_REC(index, rec++),
2232 vsc8584_macsec_flow_context_id(flow));
2234 /* Set the encryption/decryption key */
2235 for (i = 0; i < priv->secy->key_len / sizeof(u32); i++)
2236 vsc8584_macsec_phy_write(phydev, bank,
2237 MSCC_MS_XFORM_REC(index, rec++),
2238 ((u32 *)flow->key)[i]);
2240 /* Set the authentication key */
2241 for (i = 0; i < 4; i++)
2242 vsc8584_macsec_phy_write(phydev, bank,
2243 MSCC_MS_XFORM_REC(index, rec++),
2246 /* Initial sequence number */
2247 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_XFORM_REC(index, rec++),
2248 bank == MACSEC_INGR ?
2249 flow->rx_sa->next_pn : flow->tx_sa->next_pn);
2251 if (bank == MACSEC_INGR)
2252 /* Set the mask (replay window size) */
2253 vsc8584_macsec_phy_write(phydev, bank,
2254 MSCC_MS_XFORM_REC(index, rec++),
2255 priv->secy->replay_window);
2257 /* Set the input vectors */
2258 sci = bank == MACSEC_INGR ? flow->rx_sa->sc->sci : priv->secy->sci;
2259 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_XFORM_REC(index, rec++),
2260 lower_32_bits(sci));
2261 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_XFORM_REC(index, rec++),
2262 upper_32_bits(sci));
2265 vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_XFORM_REC(index, rec++),
2268 flow->has_transformation = true;
2272 static struct macsec_flow *vsc8584_macsec_alloc_flow(struct vsc8531_private *priv,
2273 enum macsec_bank bank)
2275 unsigned long *bitmap = bank == MACSEC_INGR ?
2276 &priv->ingr_flows : &priv->egr_flows;
2277 struct macsec_flow *flow;
2280 index = find_first_zero_bit(bitmap, MSCC_MS_MAX_FLOWS);
2282 if (index == MSCC_MS_MAX_FLOWS)
2283 return ERR_PTR(-ENOMEM);
2285 flow = kzalloc(sizeof(*flow), GFP_KERNEL);
2287 return ERR_PTR(-ENOMEM);
2289 set_bit(index, bitmap);
2290 flow->index = index;
2293 flow->assoc_num = -1;
2295 list_add_tail(&flow->list, &priv->macsec_flows);
2299 static void vsc8584_macsec_free_flow(struct vsc8531_private *priv,
2300 struct macsec_flow *flow)
2302 unsigned long *bitmap = flow->bank == MACSEC_INGR ?
2303 &priv->ingr_flows : &priv->egr_flows;
2305 list_del(&flow->list);
2306 clear_bit(flow->index, bitmap);
2310 static int vsc8584_macsec_add_flow(struct phy_device *phydev,
2311 struct macsec_flow *flow, bool update)
2315 flow->port = MSCC_MS_PORT_CONTROLLED;
2316 vsc8584_macsec_flow(phydev, flow);
2321 ret = vsc8584_macsec_transformation(phydev, flow);
2323 vsc8584_macsec_free_flow(phydev->priv, flow);
2330 static int vsc8584_macsec_default_flows(struct phy_device *phydev)
2332 struct macsec_flow *flow;
2334 /* Add a rule to let the MKA traffic go through, ingress */
2335 flow = vsc8584_macsec_alloc_flow(phydev->priv, MACSEC_INGR);
2337 return PTR_ERR(flow);
2339 flow->priority = 15;
2340 flow->port = MSCC_MS_PORT_UNCONTROLLED;
2341 flow->match.tagged = 1;
2342 flow->match.untagged = 1;
2343 flow->match.etype = 1;
2344 flow->etype = ETH_P_PAE;
2345 flow->action.bypass = 1;
2347 vsc8584_macsec_flow(phydev, flow);
2348 vsc8584_macsec_flow_enable(phydev, flow);
2350 /* Add a rule to let the MKA traffic go through, egress */
2351 flow = vsc8584_macsec_alloc_flow(phydev->priv, MACSEC_EGR);
2353 return PTR_ERR(flow);
2355 flow->priority = 15;
2356 flow->port = MSCC_MS_PORT_COMMON;
2357 flow->match.untagged = 1;
2358 flow->match.etype = 1;
2359 flow->etype = ETH_P_PAE;
2360 flow->action.bypass = 1;
2362 vsc8584_macsec_flow(phydev, flow);
2363 vsc8584_macsec_flow_enable(phydev, flow);
2368 static void vsc8584_macsec_del_flow(struct phy_device *phydev,
2369 struct macsec_flow *flow)
2371 vsc8584_macsec_flow_disable(phydev, flow);
2372 vsc8584_macsec_free_flow(phydev->priv, flow);
2375 static int __vsc8584_macsec_add_rxsa(struct macsec_context *ctx,
2376 struct macsec_flow *flow, bool update)
2378 struct phy_device *phydev = ctx->phydev;
2379 struct vsc8531_private *priv = phydev->priv;
2382 flow = vsc8584_macsec_alloc_flow(priv, MACSEC_INGR);
2384 return PTR_ERR(flow);
2386 memcpy(flow->key, ctx->sa.key, priv->secy->key_len);
2389 flow->assoc_num = ctx->sa.assoc_num;
2390 flow->rx_sa = ctx->sa.rx_sa;
2392 /* Always match tagged packets on ingress */
2393 flow->match.tagged = 1;
2394 flow->match.sci = 1;
2396 if (priv->secy->validate_frames != MACSEC_VALIDATE_DISABLED)
2397 flow->match.untagged = 1;
2399 return vsc8584_macsec_add_flow(phydev, flow, update);
2402 static int __vsc8584_macsec_add_txsa(struct macsec_context *ctx,
2403 struct macsec_flow *flow, bool update)
2405 struct phy_device *phydev = ctx->phydev;
2406 struct vsc8531_private *priv = phydev->priv;
2409 flow = vsc8584_macsec_alloc_flow(priv, MACSEC_EGR);
2411 return PTR_ERR(flow);
2413 memcpy(flow->key, ctx->sa.key, priv->secy->key_len);
2416 flow->assoc_num = ctx->sa.assoc_num;
2417 flow->tx_sa = ctx->sa.tx_sa;
2419 /* Always match untagged packets on egress */
2420 flow->match.untagged = 1;
2422 return vsc8584_macsec_add_flow(phydev, flow, update);
2425 static int vsc8584_macsec_dev_open(struct macsec_context *ctx)
2427 struct vsc8531_private *priv = ctx->phydev->priv;
2428 struct macsec_flow *flow, *tmp;
2430 /* No operation to perform before the commit step */
2434 list_for_each_entry_safe(flow, tmp, &priv->macsec_flows, list)
2435 vsc8584_macsec_flow_enable(ctx->phydev, flow);
2440 static int vsc8584_macsec_dev_stop(struct macsec_context *ctx)
2442 struct vsc8531_private *priv = ctx->phydev->priv;
2443 struct macsec_flow *flow, *tmp;
2445 /* No operation to perform before the commit step */
2449 list_for_each_entry_safe(flow, tmp, &priv->macsec_flows, list)
2450 vsc8584_macsec_flow_disable(ctx->phydev, flow);
2455 static int vsc8584_macsec_add_secy(struct macsec_context *ctx)
2457 struct vsc8531_private *priv = ctx->phydev->priv;
2458 struct macsec_secy *secy = ctx->secy;
2469 vsc8584_macsec_flow_default_action(ctx->phydev, MACSEC_EGR,
2470 secy->validate_frames != MACSEC_VALIDATE_DISABLED);
2471 vsc8584_macsec_flow_default_action(ctx->phydev, MACSEC_INGR,
2472 secy->validate_frames != MACSEC_VALIDATE_DISABLED);
2474 return vsc8584_macsec_default_flows(ctx->phydev);
2477 static int vsc8584_macsec_del_secy(struct macsec_context *ctx)
2479 struct vsc8531_private *priv = ctx->phydev->priv;
2480 struct macsec_flow *flow, *tmp;
2482 /* No operation to perform before the commit step */
2486 list_for_each_entry_safe(flow, tmp, &priv->macsec_flows, list)
2487 vsc8584_macsec_del_flow(ctx->phydev, flow);
2489 vsc8584_macsec_flow_default_action(ctx->phydev, MACSEC_EGR, false);
2490 vsc8584_macsec_flow_default_action(ctx->phydev, MACSEC_INGR, false);
2496 static int vsc8584_macsec_upd_secy(struct macsec_context *ctx)
2498 /* No operation to perform before the commit step */
2502 vsc8584_macsec_del_secy(ctx);
2503 return vsc8584_macsec_add_secy(ctx);
2506 static int vsc8584_macsec_add_rxsc(struct macsec_context *ctx)
2512 static int vsc8584_macsec_upd_rxsc(struct macsec_context *ctx)
2517 static int vsc8584_macsec_del_rxsc(struct macsec_context *ctx)
2519 struct vsc8531_private *priv = ctx->phydev->priv;
2520 struct macsec_flow *flow, *tmp;
2522 /* No operation to perform before the commit step */
2526 list_for_each_entry_safe(flow, tmp, &priv->macsec_flows, list) {
2527 if (flow->bank == MACSEC_INGR && flow->rx_sa &&
2528 flow->rx_sa->sc->sci == ctx->rx_sc->sci)
2529 vsc8584_macsec_del_flow(ctx->phydev, flow);
2535 static int vsc8584_macsec_add_rxsa(struct macsec_context *ctx)
2537 struct macsec_flow *flow = NULL;
2540 return __vsc8584_macsec_add_rxsa(ctx, flow, false);
2542 flow = vsc8584_macsec_find_flow(ctx, MACSEC_INGR);
2544 return PTR_ERR(flow);
2546 vsc8584_macsec_flow_enable(ctx->phydev, flow);
2550 static int vsc8584_macsec_upd_rxsa(struct macsec_context *ctx)
2552 struct macsec_flow *flow;
2554 flow = vsc8584_macsec_find_flow(ctx, MACSEC_INGR);
2556 return PTR_ERR(flow);
2559 /* Make sure the flow is disabled before updating it */
2560 vsc8584_macsec_flow_disable(ctx->phydev, flow);
2562 return __vsc8584_macsec_add_rxsa(ctx, flow, true);
2565 vsc8584_macsec_flow_enable(ctx->phydev, flow);
2569 static int vsc8584_macsec_del_rxsa(struct macsec_context *ctx)
2571 struct macsec_flow *flow;
2573 flow = vsc8584_macsec_find_flow(ctx, MACSEC_INGR);
2576 return PTR_ERR(flow);
2580 vsc8584_macsec_del_flow(ctx->phydev, flow);
2584 static int vsc8584_macsec_add_txsa(struct macsec_context *ctx)
2586 struct macsec_flow *flow = NULL;
2589 return __vsc8584_macsec_add_txsa(ctx, flow, false);
2591 flow = vsc8584_macsec_find_flow(ctx, MACSEC_EGR);
2593 return PTR_ERR(flow);
2595 vsc8584_macsec_flow_enable(ctx->phydev, flow);
2599 static int vsc8584_macsec_upd_txsa(struct macsec_context *ctx)
2601 struct macsec_flow *flow;
2603 flow = vsc8584_macsec_find_flow(ctx, MACSEC_EGR);
2605 return PTR_ERR(flow);
2608 /* Make sure the flow is disabled before updating it */
2609 vsc8584_macsec_flow_disable(ctx->phydev, flow);
2611 return __vsc8584_macsec_add_txsa(ctx, flow, true);
2614 vsc8584_macsec_flow_enable(ctx->phydev, flow);
2618 static int vsc8584_macsec_del_txsa(struct macsec_context *ctx)
2620 struct macsec_flow *flow;
2622 flow = vsc8584_macsec_find_flow(ctx, MACSEC_EGR);
2625 return PTR_ERR(flow);
2629 vsc8584_macsec_del_flow(ctx->phydev, flow);
2633 static struct macsec_ops vsc8584_macsec_ops = {
2634 .mdo_dev_open = vsc8584_macsec_dev_open,
2635 .mdo_dev_stop = vsc8584_macsec_dev_stop,
2636 .mdo_add_secy = vsc8584_macsec_add_secy,
2637 .mdo_upd_secy = vsc8584_macsec_upd_secy,
2638 .mdo_del_secy = vsc8584_macsec_del_secy,
2639 .mdo_add_rxsc = vsc8584_macsec_add_rxsc,
2640 .mdo_upd_rxsc = vsc8584_macsec_upd_rxsc,
2641 .mdo_del_rxsc = vsc8584_macsec_del_rxsc,
2642 .mdo_add_rxsa = vsc8584_macsec_add_rxsa,
2643 .mdo_upd_rxsa = vsc8584_macsec_upd_rxsa,
2644 .mdo_del_rxsa = vsc8584_macsec_del_rxsa,
2645 .mdo_add_txsa = vsc8584_macsec_add_txsa,
2646 .mdo_upd_txsa = vsc8584_macsec_upd_txsa,
2647 .mdo_del_txsa = vsc8584_macsec_del_txsa,
2649 #endif /* CONFIG_MACSEC */
2651 /* Check if one PHY has already done the init of the parts common to all PHYs
2652 * in the Quad PHY package.
2654 static bool vsc8584_is_pkg_init(struct phy_device *phydev, bool reversed)
2656 struct mdio_device **map = phydev->mdio.bus->mdio_map;
2657 struct vsc8531_private *vsc8531;
2658 struct phy_device *phy;
2661 /* VSC8584 is a Quad PHY */
2662 for (i = 0; i < 4; i++) {
2663 vsc8531 = phydev->priv;
2666 addr = vsc8531->base_addr - i;
2668 addr = vsc8531->base_addr + i;
2673 phy = container_of(map[addr], struct phy_device, mdio);
2675 if ((phy->phy_id & phydev->drv->phy_id_mask) !=
2676 (phydev->drv->phy_id & phydev->drv->phy_id_mask))
2679 vsc8531 = phy->priv;
2681 if (vsc8531 && vsc8531->pkg_init)
2688 static int vsc8584_config_init(struct phy_device *phydev)
2690 struct vsc8531_private *vsc8531 = phydev->priv;
2694 phydev->mdix_ctrl = ETH_TP_MDI_AUTO;
2696 mutex_lock(&phydev->mdio.bus->mdio_lock);
2698 __mdiobus_write(phydev->mdio.bus, phydev->mdio.addr,
2699 MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_EXTENDED);
2700 addr = __mdiobus_read(phydev->mdio.bus, phydev->mdio.addr,
2701 MSCC_PHY_EXT_PHY_CNTL_4);
2702 addr >>= PHY_CNTL_4_ADDR_POS;
2704 val = __mdiobus_read(phydev->mdio.bus, phydev->mdio.addr,
2705 MSCC_PHY_ACTIPHY_CNTL);
2706 if (val & PHY_ADDR_REVERSED)
2707 vsc8531->base_addr = phydev->mdio.addr + addr;
2709 vsc8531->base_addr = phydev->mdio.addr - addr;
2711 /* Some parts of the init sequence are identical for every PHY in the
2712 * package. Some parts are modifying the GPIO register bank which is a
2713 * set of registers that are affecting all PHYs, a few resetting the
2714 * microprocessor common to all PHYs. The CRC check responsible of the
2715 * checking the firmware within the 8051 microprocessor can only be
2716 * accessed via the PHY whose internal address in the package is 0.
2717 * All PHYs' interrupts mask register has to be zeroed before enabling
2718 * any PHY's interrupt in this register.
2719 * For all these reasons, we need to do the init sequence once and only
2720 * once whatever is the first PHY in the package that is initialized and
2721 * do the correct init sequence for all PHYs that are package-critical
2722 * in this pre-init function.
2724 if (!vsc8584_is_pkg_init(phydev, val & PHY_ADDR_REVERSED ? 1 : 0)) {
2725 /* The following switch statement assumes that the lowest
2726 * nibble of the phy_id_mask is always 0. This works because
2727 * the lowest nibble of the PHY_ID's below are also 0.
2729 WARN_ON(phydev->drv->phy_id_mask & 0xf);
2731 switch (phydev->phy_id & phydev->drv->phy_id_mask) {
2732 case PHY_ID_VSC8504:
2733 case PHY_ID_VSC8552:
2734 case PHY_ID_VSC8572:
2735 case PHY_ID_VSC8574:
2736 ret = vsc8574_config_pre_init(phydev);
2738 case PHY_ID_VSC856X:
2739 case PHY_ID_VSC8575:
2740 case PHY_ID_VSC8582:
2741 case PHY_ID_VSC8584:
2742 ret = vsc8584_config_pre_init(phydev);
2753 vsc8531->pkg_init = true;
2755 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS,
2756 MSCC_PHY_PAGE_EXTENDED_GPIO);
2758 val = phy_base_read(phydev, MSCC_PHY_MAC_CFG_FASTLINK);
2759 val &= ~MAC_CFG_MASK;
2760 if (phydev->interface == PHY_INTERFACE_MODE_QSGMII)
2761 val |= MAC_CFG_QSGMII;
2763 val |= MAC_CFG_SGMII;
2765 ret = phy_base_write(phydev, MSCC_PHY_MAC_CFG_FASTLINK, val);
2769 val = PROC_CMD_MCB_ACCESS_MAC_CONF | PROC_CMD_RST_CONF_PORT |
2770 PROC_CMD_READ_MOD_WRITE_PORT;
2771 if (phydev->interface == PHY_INTERFACE_MODE_QSGMII)
2772 val |= PROC_CMD_QSGMII_MAC;
2774 val |= PROC_CMD_SGMII_MAC;
2776 ret = vsc8584_cmd(phydev, val);
2780 usleep_range(10000, 20000);
2782 /* Disable SerDes for 100Base-FX */
2783 ret = vsc8584_cmd(phydev, PROC_CMD_FIBER_MEDIA_CONF |
2784 PROC_CMD_FIBER_PORT(addr) | PROC_CMD_FIBER_DISABLE |
2785 PROC_CMD_READ_MOD_WRITE_PORT |
2786 PROC_CMD_RST_CONF_PORT | PROC_CMD_FIBER_100BASE_FX);
2790 /* Disable SerDes for 1000Base-X */
2791 ret = vsc8584_cmd(phydev, PROC_CMD_FIBER_MEDIA_CONF |
2792 PROC_CMD_FIBER_PORT(addr) | PROC_CMD_FIBER_DISABLE |
2793 PROC_CMD_READ_MOD_WRITE_PORT |
2794 PROC_CMD_RST_CONF_PORT | PROC_CMD_FIBER_1000BASE_X);
2798 mutex_unlock(&phydev->mdio.bus->mdio_lock);
2800 #if IS_ENABLED(CONFIG_MACSEC)
2802 switch (phydev->phy_id & phydev->drv->phy_id_mask) {
2803 case PHY_ID_VSC856X:
2804 case PHY_ID_VSC8575:
2805 case PHY_ID_VSC8582:
2806 case PHY_ID_VSC8584:
2807 INIT_LIST_HEAD(&vsc8531->macsec_flows);
2808 vsc8531->secy = NULL;
2810 phydev->macsec_ops = &vsc8584_macsec_ops;
2812 ret = vsc8584_macsec_init(phydev);
2818 phy_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
2820 val = phy_read(phydev, MSCC_PHY_EXT_PHY_CNTL_1);
2821 val &= ~(MEDIA_OP_MODE_MASK | VSC8584_MAC_IF_SELECTION_MASK);
2822 val |= (MEDIA_OP_MODE_COPPER << MEDIA_OP_MODE_POS) |
2823 (VSC8584_MAC_IF_SELECTION_SGMII << VSC8584_MAC_IF_SELECTION_POS);
2824 ret = phy_write(phydev, MSCC_PHY_EXT_PHY_CNTL_1, val);
2826 ret = genphy_soft_reset(phydev);
2830 for (i = 0; i < vsc8531->nleds; i++) {
2831 ret = vsc85xx_led_cntl_set(phydev, i, vsc8531->leds_mode[i]);
2839 mutex_unlock(&phydev->mdio.bus->mdio_lock);
2843 static int vsc8584_handle_interrupt(struct phy_device *phydev)
2845 #if IS_ENABLED(CONFIG_MACSEC)
2846 struct vsc8531_private *priv = phydev->priv;
2847 struct macsec_flow *flow, *tmp;
2850 /* Check MACsec PN rollover */
2851 cause = vsc8584_macsec_phy_read(phydev, MACSEC_EGR,
2852 MSCC_MS_INTR_CTRL_STATUS);
2853 cause &= MSCC_MS_INTR_CTRL_STATUS_INTR_CLR_STATUS_M;
2854 if (!(cause & MACSEC_INTR_CTRL_STATUS_ROLLOVER))
2857 rec = 6 + priv->secy->key_len / sizeof(u32);
2858 list_for_each_entry_safe(flow, tmp, &priv->macsec_flows, list) {
2861 if (flow->bank != MACSEC_EGR || !flow->has_transformation)
2864 val = vsc8584_macsec_phy_read(phydev, MACSEC_EGR,
2865 MSCC_MS_XFORM_REC(flow->index, rec));
2866 if (val == 0xffffffff) {
2867 vsc8584_macsec_flow_disable(phydev, flow);
2868 macsec_pn_wrapped(priv->secy, flow->tx_sa);
2876 phy_mac_interrupt(phydev);
2880 static int vsc85xx_config_init(struct phy_device *phydev)
2883 struct vsc8531_private *vsc8531 = phydev->priv;
2885 rc = vsc85xx_default_config(phydev);
2889 rc = vsc85xx_mac_if_set(phydev, phydev->interface);
2893 rc = vsc85xx_edge_rate_cntl_set(phydev, vsc8531->rate_magic);
2897 phy_id = phydev->drv->phy_id & phydev->drv->phy_id_mask;
2898 if (PHY_ID_VSC8531 == phy_id || PHY_ID_VSC8541 == phy_id ||
2899 PHY_ID_VSC8530 == phy_id || PHY_ID_VSC8540 == phy_id) {
2900 rc = vsc8531_pre_init_seq_set(phydev);
2905 rc = vsc85xx_eee_init_seq_set(phydev);
2909 for (i = 0; i < vsc8531->nleds; i++) {
2910 rc = vsc85xx_led_cntl_set(phydev, i, vsc8531->leds_mode[i]);
2918 static int vsc8584_did_interrupt(struct phy_device *phydev)
2922 if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
2923 rc = phy_read(phydev, MII_VSC85XX_INT_STATUS);
2925 return (rc < 0) ? 0 : rc & MII_VSC85XX_INT_MASK_MASK;
2928 static int vsc8514_config_pre_init(struct phy_device *phydev)
2930 /* These are the settings to override the silicon default
2931 * values to handle hardware performance of PHY. They
2932 * are set at Power-On state and remain until PHY Reset.
2934 static const struct reg_val pre_init1[] = {
2935 {0x0f90, 0x00688980},
2936 {0x0786, 0x00000003},
2937 {0x07fa, 0x0050100f},
2938 {0x0f82, 0x0012b002},
2939 {0x1686, 0x00000004},
2940 {0x168c, 0x00d2c46f},
2941 {0x17a2, 0x00000620},
2942 {0x16a0, 0x00eeffdd},
2943 {0x16a6, 0x00071448},
2944 {0x16a4, 0x0013132f},
2945 {0x16a8, 0x00000000},
2946 {0x0ffc, 0x00c0a028},
2947 {0x0fe8, 0x0091b06c},
2948 {0x0fea, 0x00041600},
2949 {0x0f80, 0x00fffaff},
2950 {0x0fec, 0x00901809},
2951 {0x0ffe, 0x00b01007},
2952 {0x16b0, 0x00eeff00},
2953 {0x16b2, 0x00007000},
2954 {0x16b4, 0x00000814},
2959 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
2961 /* all writes below are broadcasted to all PHYs in the same package */
2962 reg = phy_base_read(phydev, MSCC_PHY_EXT_CNTL_STATUS);
2963 reg |= SMI_BROADCAST_WR_EN;
2964 phy_base_write(phydev, MSCC_PHY_EXT_CNTL_STATUS, reg);
2966 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_TEST);
2968 reg = phy_base_read(phydev, MSCC_PHY_TEST_PAGE_8);
2970 phy_base_write(phydev, MSCC_PHY_TEST_PAGE_8, reg);
2972 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_TR);
2974 for (i = 0; i < ARRAY_SIZE(pre_init1); i++)
2975 vsc8584_csr_write(phydev, pre_init1[i].reg, pre_init1[i].val);
2977 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_TEST);
2979 reg = phy_base_read(phydev, MSCC_PHY_TEST_PAGE_8);
2981 phy_base_write(phydev, MSCC_PHY_TEST_PAGE_8, reg);
2983 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
2985 reg = phy_base_read(phydev, MSCC_PHY_EXT_CNTL_STATUS);
2986 reg &= ~SMI_BROADCAST_WR_EN;
2987 phy_base_write(phydev, MSCC_PHY_EXT_CNTL_STATUS, reg);
2992 static u32 vsc85xx_csr_ctrl_phy_read(struct phy_device *phydev,
2993 u32 target, u32 reg)
2995 unsigned long deadline;
2996 u32 val, val_l, val_h;
2998 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_CSR_CNTL);
3000 /* CSR registers are grouped under different Target IDs.
3001 * 6-bit Target_ID is split between MSCC_EXT_PAGE_CSR_CNTL_20 and
3002 * MSCC_EXT_PAGE_CSR_CNTL_19 registers.
3003 * Target_ID[5:2] maps to bits[3:0] of MSCC_EXT_PAGE_CSR_CNTL_20
3004 * and Target_ID[1:0] maps to bits[13:12] of MSCC_EXT_PAGE_CSR_CNTL_19.
3007 /* Setup the Target ID */
3008 phy_base_write(phydev, MSCC_EXT_PAGE_CSR_CNTL_20,
3009 MSCC_PHY_CSR_CNTL_20_TARGET(target >> 2));
3011 /* Trigger CSR Action - Read into the CSR's */
3012 phy_base_write(phydev, MSCC_EXT_PAGE_CSR_CNTL_19,
3013 MSCC_PHY_CSR_CNTL_19_CMD | MSCC_PHY_CSR_CNTL_19_READ |
3014 MSCC_PHY_CSR_CNTL_19_REG_ADDR(reg) |
3015 MSCC_PHY_CSR_CNTL_19_TARGET(target & 0x3));
3017 /* Wait for register access*/
3018 deadline = jiffies + msecs_to_jiffies(PROC_CMD_NCOMPLETED_TIMEOUT_MS);
3020 usleep_range(500, 1000);
3021 val = phy_base_read(phydev, MSCC_EXT_PAGE_CSR_CNTL_19);
3022 } while (time_before(jiffies, deadline) &&
3023 !(val & MSCC_PHY_CSR_CNTL_19_CMD));
3025 if (!(val & MSCC_PHY_CSR_CNTL_19_CMD))
3028 /* Read the Least Significant Word (LSW) (17) */
3029 val_l = phy_base_read(phydev, MSCC_EXT_PAGE_CSR_CNTL_17);
3031 /* Read the Most Significant Word (MSW) (18) */
3032 val_h = phy_base_read(phydev, MSCC_EXT_PAGE_CSR_CNTL_18);
3034 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS,
3035 MSCC_PHY_PAGE_STANDARD);
3037 return (val_h << 16) | val_l;
3040 static int vsc85xx_csr_ctrl_phy_write(struct phy_device *phydev,
3041 u32 target, u32 reg, u32 val)
3043 unsigned long deadline;
3045 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_CSR_CNTL);
3047 /* CSR registers are grouped under different Target IDs.
3048 * 6-bit Target_ID is split between MSCC_EXT_PAGE_CSR_CNTL_20 and
3049 * MSCC_EXT_PAGE_CSR_CNTL_19 registers.
3050 * Target_ID[5:2] maps to bits[3:0] of MSCC_EXT_PAGE_CSR_CNTL_20
3051 * and Target_ID[1:0] maps to bits[13:12] of MSCC_EXT_PAGE_CSR_CNTL_19.
3054 /* Setup the Target ID */
3055 phy_base_write(phydev, MSCC_EXT_PAGE_CSR_CNTL_20,
3056 MSCC_PHY_CSR_CNTL_20_TARGET(target >> 2));
3058 /* Write the Least Significant Word (LSW) (17) */
3059 phy_base_write(phydev, MSCC_EXT_PAGE_CSR_CNTL_17, (u16)val);
3061 /* Write the Most Significant Word (MSW) (18) */
3062 phy_base_write(phydev, MSCC_EXT_PAGE_CSR_CNTL_18, (u16)(val >> 16));
3064 /* Trigger CSR Action - Write into the CSR's */
3065 phy_base_write(phydev, MSCC_EXT_PAGE_CSR_CNTL_19,
3066 MSCC_PHY_CSR_CNTL_19_CMD |
3067 MSCC_PHY_CSR_CNTL_19_REG_ADDR(reg) |
3068 MSCC_PHY_CSR_CNTL_19_TARGET(target & 0x3));
3070 /* Wait for register access */
3071 deadline = jiffies + msecs_to_jiffies(PROC_CMD_NCOMPLETED_TIMEOUT_MS);
3073 usleep_range(500, 1000);
3074 val = phy_base_read(phydev, MSCC_EXT_PAGE_CSR_CNTL_19);
3075 } while (time_before(jiffies, deadline) &&
3076 !(val & MSCC_PHY_CSR_CNTL_19_CMD));
3078 if (!(val & MSCC_PHY_CSR_CNTL_19_CMD))
3081 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS,
3082 MSCC_PHY_PAGE_STANDARD);
3087 static int __phy_write_mcb_s6g(struct phy_device *phydev, u32 reg, u8 mcb,
3090 unsigned long deadline;
3094 ret = vsc85xx_csr_ctrl_phy_write(phydev, PHY_MCB_TARGET, reg,
3099 deadline = jiffies + msecs_to_jiffies(PROC_CMD_NCOMPLETED_TIMEOUT_MS);
3101 usleep_range(500, 1000);
3102 val = vsc85xx_csr_ctrl_phy_read(phydev, PHY_MCB_TARGET, reg);
3104 if (val == 0xffffffff)
3107 } while (time_before(jiffies, deadline) && (val & op));
3115 /* Trigger a read to the spcified MCB */
3116 static int phy_update_mcb_s6g(struct phy_device *phydev, u32 reg, u8 mcb)
3118 return __phy_write_mcb_s6g(phydev, reg, mcb, PHY_MCB_S6G_READ);
3121 /* Trigger a write to the spcified MCB */
3122 static int phy_commit_mcb_s6g(struct phy_device *phydev, u32 reg, u8 mcb)
3124 return __phy_write_mcb_s6g(phydev, reg, mcb, PHY_MCB_S6G_WRITE);
3127 static int vsc8514_config_init(struct phy_device *phydev)
3129 struct vsc8531_private *vsc8531 = phydev->priv;
3130 unsigned long deadline;
3135 phydev->mdix_ctrl = ETH_TP_MDI_AUTO;
3137 mutex_lock(&phydev->mdio.bus->mdio_lock);
3139 __phy_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_EXTENDED);
3141 addr = __phy_read(phydev, MSCC_PHY_EXT_PHY_CNTL_4);
3142 addr >>= PHY_CNTL_4_ADDR_POS;
3144 val = __phy_read(phydev, MSCC_PHY_ACTIPHY_CNTL);
3146 if (val & PHY_ADDR_REVERSED)
3147 vsc8531->base_addr = phydev->mdio.addr + addr;
3149 vsc8531->base_addr = phydev->mdio.addr - addr;
3151 /* Some parts of the init sequence are identical for every PHY in the
3152 * package. Some parts are modifying the GPIO register bank which is a
3153 * set of registers that are affecting all PHYs, a few resetting the
3154 * microprocessor common to all PHYs.
3155 * All PHYs' interrupts mask register has to be zeroed before enabling
3156 * any PHY's interrupt in this register.
3157 * For all these reasons, we need to do the init sequence once and only
3158 * once whatever is the first PHY in the package that is initialized and
3159 * do the correct init sequence for all PHYs that are package-critical
3160 * in this pre-init function.
3162 if (!vsc8584_is_pkg_init(phydev, val & PHY_ADDR_REVERSED ? 1 : 0))
3163 vsc8514_config_pre_init(phydev);
3165 vsc8531->pkg_init = true;
3167 phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS,
3168 MSCC_PHY_PAGE_EXTENDED_GPIO);
3170 val = phy_base_read(phydev, MSCC_PHY_MAC_CFG_FASTLINK);
3172 val &= ~MAC_CFG_MASK;
3173 val |= MAC_CFG_QSGMII;
3174 ret = phy_base_write(phydev, MSCC_PHY_MAC_CFG_FASTLINK, val);
3179 ret = vsc8584_cmd(phydev,
3180 PROC_CMD_MCB_ACCESS_MAC_CONF |
3181 PROC_CMD_RST_CONF_PORT |
3182 PROC_CMD_READ_MOD_WRITE_PORT | PROC_CMD_QSGMII_MAC);
3187 phy_update_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0);
3189 phy_update_mcb_s6g(phydev, PHY_S6G_LCPLL_CFG, 0);
3191 ret = vsc85xx_csr_ctrl_phy_write(phydev, PHY_MCB_TARGET,
3192 PHY_S6G_PLL5G_CFG0, 0x7036f145);
3196 phy_commit_mcb_s6g(phydev, PHY_S6G_LCPLL_CFG, 0);
3198 ret = vsc85xx_csr_ctrl_phy_write(phydev, PHY_MCB_TARGET,
3200 (3 << PHY_S6G_PLL_ENA_OFFS_POS) |
3201 (120 << PHY_S6G_PLL_FSM_CTRL_DATA_POS)
3202 | (0 << PHY_S6G_PLL_FSM_ENA_POS));
3207 ret = vsc85xx_csr_ctrl_phy_write(phydev, PHY_MCB_TARGET,
3209 (0 << PHY_S6G_SYS_RST_POS) |
3210 (0 << PHY_S6G_ENA_LANE_POS) |
3211 (0 << PHY_S6G_ENA_LOOP_POS) |
3212 (0 << PHY_S6G_QRATE_POS) |
3213 (3 << PHY_S6G_IF_MODE_POS));
3218 ret = vsc85xx_csr_ctrl_phy_write(phydev, PHY_MCB_TARGET,
3219 PHY_S6G_MISC_CFG, 1);
3224 ret = vsc85xx_csr_ctrl_phy_write(phydev, PHY_MCB_TARGET,
3225 PHY_S6G_GPC_CFG, 768);
3229 phy_commit_mcb_s6g(phydev, PHY_S6G_DFT_CFG2, 0);
3231 deadline = jiffies + msecs_to_jiffies(PROC_CMD_NCOMPLETED_TIMEOUT_MS);
3233 usleep_range(500, 1000);
3234 phy_update_mcb_s6g(phydev, PHY_MCB_S6G_CFG,
3235 0); /* read 6G MCB into CSRs */
3236 reg = vsc85xx_csr_ctrl_phy_read(phydev, PHY_MCB_TARGET,
3237 PHY_S6G_PLL_STATUS);
3238 if (reg == 0xffffffff) {
3239 mutex_unlock(&phydev->mdio.bus->mdio_lock);
3243 } while (time_before(jiffies, deadline) && (reg & BIT(12)));
3245 if (reg & BIT(12)) {
3246 mutex_unlock(&phydev->mdio.bus->mdio_lock);
3251 ret = vsc85xx_csr_ctrl_phy_write(phydev, PHY_MCB_TARGET,
3252 PHY_S6G_MISC_CFG, 0);
3256 phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0);
3258 deadline = jiffies + msecs_to_jiffies(PROC_CMD_NCOMPLETED_TIMEOUT_MS);
3260 usleep_range(500, 1000);
3261 phy_update_mcb_s6g(phydev, PHY_MCB_S6G_CFG,
3262 0); /* read 6G MCB into CSRs */
3263 reg = vsc85xx_csr_ctrl_phy_read(phydev, PHY_MCB_TARGET,
3264 PHY_S6G_IB_STATUS0);
3265 if (reg == 0xffffffff) {
3266 mutex_unlock(&phydev->mdio.bus->mdio_lock);
3270 } while (time_before(jiffies, deadline) && !(reg & BIT(8)));
3272 if (!(reg & BIT(8))) {
3273 mutex_unlock(&phydev->mdio.bus->mdio_lock);
3277 mutex_unlock(&phydev->mdio.bus->mdio_lock);
3279 ret = phy_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
3284 ret = phy_modify(phydev, MSCC_PHY_EXT_PHY_CNTL_1, MEDIA_OP_MODE_MASK,
3285 MEDIA_OP_MODE_COPPER << MEDIA_OP_MODE_POS);
3290 ret = genphy_soft_reset(phydev);
3295 for (i = 0; i < vsc8531->nleds; i++) {
3296 ret = vsc85xx_led_cntl_set(phydev, i, vsc8531->leds_mode[i]);
3304 mutex_unlock(&phydev->mdio.bus->mdio_lock);
3308 static int vsc85xx_ack_interrupt(struct phy_device *phydev)
3312 if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
3313 rc = phy_read(phydev, MII_VSC85XX_INT_STATUS);
3315 return (rc < 0) ? rc : 0;
3318 static int vsc85xx_config_intr(struct phy_device *phydev)
3322 if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
3323 #if IS_ENABLED(CONFIG_MACSEC)
3324 phy_write(phydev, MSCC_EXT_PAGE_ACCESS,
3325 MSCC_PHY_PAGE_EXTENDED_2);
3326 phy_write(phydev, MSCC_PHY_EXTENDED_INT,
3327 MSCC_PHY_EXTENDED_INT_MS_EGR);
3328 phy_write(phydev, MSCC_EXT_PAGE_ACCESS,
3329 MSCC_PHY_PAGE_STANDARD);
3331 vsc8584_macsec_phy_write(phydev, MACSEC_EGR,
3332 MSCC_MS_AIC_CTRL, 0xf);
3333 vsc8584_macsec_phy_write(phydev, MACSEC_EGR,
3334 MSCC_MS_INTR_CTRL_STATUS,
3335 MSCC_MS_INTR_CTRL_STATUS_INTR_ENABLE(MACSEC_INTR_CTRL_STATUS_ROLLOVER));
3337 rc = phy_write(phydev, MII_VSC85XX_INT_MASK,
3338 MII_VSC85XX_INT_MASK_MASK);
3340 rc = phy_write(phydev, MII_VSC85XX_INT_MASK, 0);
3343 rc = phy_read(phydev, MII_VSC85XX_INT_STATUS);
3349 static int vsc85xx_config_aneg(struct phy_device *phydev)
3353 rc = vsc85xx_mdix_set(phydev, phydev->mdix_ctrl);
3357 return genphy_config_aneg(phydev);
3360 static int vsc85xx_read_status(struct phy_device *phydev)
3364 rc = vsc85xx_mdix_get(phydev, &phydev->mdix);
3368 return genphy_read_status(phydev);
3371 static int vsc8514_probe(struct phy_device *phydev)
3373 struct vsc8531_private *vsc8531;
3374 u32 default_mode[4] = {VSC8531_LINK_1000_ACTIVITY,
3375 VSC8531_LINK_100_ACTIVITY, VSC8531_LINK_ACTIVITY,
3376 VSC8531_DUPLEX_COLLISION};
3378 vsc8531 = devm_kzalloc(&phydev->mdio.dev, sizeof(*vsc8531), GFP_KERNEL);
3382 phydev->priv = vsc8531;
3385 vsc8531->supp_led_modes = VSC85XX_SUPP_LED_MODES;
3386 vsc8531->hw_stats = vsc85xx_hw_stats;
3387 vsc8531->nstats = ARRAY_SIZE(vsc85xx_hw_stats);
3388 vsc8531->stats = devm_kcalloc(&phydev->mdio.dev, vsc8531->nstats,
3389 sizeof(u64), GFP_KERNEL);
3390 if (!vsc8531->stats)
3393 return vsc85xx_dt_led_modes_get(phydev, default_mode);
3396 static int vsc8574_probe(struct phy_device *phydev)
3398 struct vsc8531_private *vsc8531;
3399 u32 default_mode[4] = {VSC8531_LINK_1000_ACTIVITY,
3400 VSC8531_LINK_100_ACTIVITY, VSC8531_LINK_ACTIVITY,
3401 VSC8531_DUPLEX_COLLISION};
3403 vsc8531 = devm_kzalloc(&phydev->mdio.dev, sizeof(*vsc8531), GFP_KERNEL);
3407 phydev->priv = vsc8531;
3410 vsc8531->supp_led_modes = VSC8584_SUPP_LED_MODES;
3411 vsc8531->hw_stats = vsc8584_hw_stats;
3412 vsc8531->nstats = ARRAY_SIZE(vsc8584_hw_stats);
3413 vsc8531->stats = devm_kcalloc(&phydev->mdio.dev, vsc8531->nstats,
3414 sizeof(u64), GFP_KERNEL);
3415 if (!vsc8531->stats)
3418 return vsc85xx_dt_led_modes_get(phydev, default_mode);
3421 static int vsc8584_probe(struct phy_device *phydev)
3423 struct vsc8531_private *vsc8531;
3424 u32 default_mode[4] = {VSC8531_LINK_1000_ACTIVITY,
3425 VSC8531_LINK_100_ACTIVITY, VSC8531_LINK_ACTIVITY,
3426 VSC8531_DUPLEX_COLLISION};
3428 if ((phydev->phy_id & MSCC_DEV_REV_MASK) != VSC8584_REVB) {
3429 dev_err(&phydev->mdio.dev, "Only VSC8584 revB is supported.\n");
3433 vsc8531 = devm_kzalloc(&phydev->mdio.dev, sizeof(*vsc8531), GFP_KERNEL);
3437 phydev->priv = vsc8531;
3440 vsc8531->supp_led_modes = VSC8584_SUPP_LED_MODES;
3441 vsc8531->hw_stats = vsc8584_hw_stats;
3442 vsc8531->nstats = ARRAY_SIZE(vsc8584_hw_stats);
3443 vsc8531->stats = devm_kcalloc(&phydev->mdio.dev, vsc8531->nstats,
3444 sizeof(u64), GFP_KERNEL);
3445 if (!vsc8531->stats)
3448 return vsc85xx_dt_led_modes_get(phydev, default_mode);
3451 static int vsc85xx_probe(struct phy_device *phydev)
3453 struct vsc8531_private *vsc8531;
3455 u32 default_mode[2] = {VSC8531_LINK_1000_ACTIVITY,
3456 VSC8531_LINK_100_ACTIVITY};
3458 rate_magic = vsc85xx_edge_rate_magic_get(phydev);
3462 vsc8531 = devm_kzalloc(&phydev->mdio.dev, sizeof(*vsc8531), GFP_KERNEL);
3466 phydev->priv = vsc8531;
3468 vsc8531->rate_magic = rate_magic;
3470 vsc8531->supp_led_modes = VSC85XX_SUPP_LED_MODES;
3471 vsc8531->hw_stats = vsc85xx_hw_stats;
3472 vsc8531->nstats = ARRAY_SIZE(vsc85xx_hw_stats);
3473 vsc8531->stats = devm_kcalloc(&phydev->mdio.dev, vsc8531->nstats,
3474 sizeof(u64), GFP_KERNEL);
3475 if (!vsc8531->stats)
3478 return vsc85xx_dt_led_modes_get(phydev, default_mode);
3481 /* Microsemi VSC85xx PHYs */
3482 static struct phy_driver vsc85xx_driver[] = {
3484 .phy_id = PHY_ID_VSC8504,
3485 .name = "Microsemi GE VSC8504 SyncE",
3486 .phy_id_mask = 0xfffffff0,
3487 /* PHY_GBIT_FEATURES */
3488 .soft_reset = &genphy_soft_reset,
3489 .config_init = &vsc8584_config_init,
3490 .config_aneg = &vsc85xx_config_aneg,
3491 .aneg_done = &genphy_aneg_done,
3492 .read_status = &vsc85xx_read_status,
3493 .ack_interrupt = &vsc85xx_ack_interrupt,
3494 .config_intr = &vsc85xx_config_intr,
3495 .did_interrupt = &vsc8584_did_interrupt,
3496 .suspend = &genphy_suspend,
3497 .resume = &genphy_resume,
3498 .probe = &vsc8574_probe,
3499 .set_wol = &vsc85xx_wol_set,
3500 .get_wol = &vsc85xx_wol_get,
3501 .get_tunable = &vsc85xx_get_tunable,
3502 .set_tunable = &vsc85xx_set_tunable,
3503 .read_page = &vsc85xx_phy_read_page,
3504 .write_page = &vsc85xx_phy_write_page,
3505 .get_sset_count = &vsc85xx_get_sset_count,
3506 .get_strings = &vsc85xx_get_strings,
3507 .get_stats = &vsc85xx_get_stats,
3510 .phy_id = PHY_ID_VSC8514,
3511 .name = "Microsemi GE VSC8514 SyncE",
3512 .phy_id_mask = 0xfffffff0,
3513 .soft_reset = &genphy_soft_reset,
3514 .config_init = &vsc8514_config_init,
3515 .config_aneg = &vsc85xx_config_aneg,
3516 .read_status = &vsc85xx_read_status,
3517 .ack_interrupt = &vsc85xx_ack_interrupt,
3518 .config_intr = &vsc85xx_config_intr,
3519 .suspend = &genphy_suspend,
3520 .resume = &genphy_resume,
3521 .probe = &vsc8514_probe,
3522 .set_wol = &vsc85xx_wol_set,
3523 .get_wol = &vsc85xx_wol_get,
3524 .get_tunable = &vsc85xx_get_tunable,
3525 .set_tunable = &vsc85xx_set_tunable,
3526 .read_page = &vsc85xx_phy_read_page,
3527 .write_page = &vsc85xx_phy_write_page,
3528 .get_sset_count = &vsc85xx_get_sset_count,
3529 .get_strings = &vsc85xx_get_strings,
3530 .get_stats = &vsc85xx_get_stats,
3533 .phy_id = PHY_ID_VSC8530,
3534 .name = "Microsemi FE VSC8530",
3535 .phy_id_mask = 0xfffffff0,
3536 /* PHY_BASIC_FEATURES */
3537 .soft_reset = &genphy_soft_reset,
3538 .config_init = &vsc85xx_config_init,
3539 .config_aneg = &vsc85xx_config_aneg,
3540 .read_status = &vsc85xx_read_status,
3541 .ack_interrupt = &vsc85xx_ack_interrupt,
3542 .config_intr = &vsc85xx_config_intr,
3543 .suspend = &genphy_suspend,
3544 .resume = &genphy_resume,
3545 .probe = &vsc85xx_probe,
3546 .set_wol = &vsc85xx_wol_set,
3547 .get_wol = &vsc85xx_wol_get,
3548 .get_tunable = &vsc85xx_get_tunable,
3549 .set_tunable = &vsc85xx_set_tunable,
3550 .read_page = &vsc85xx_phy_read_page,
3551 .write_page = &vsc85xx_phy_write_page,
3552 .get_sset_count = &vsc85xx_get_sset_count,
3553 .get_strings = &vsc85xx_get_strings,
3554 .get_stats = &vsc85xx_get_stats,
3557 .phy_id = PHY_ID_VSC8531,
3558 .name = "Microsemi VSC8531",
3559 .phy_id_mask = 0xfffffff0,
3560 /* PHY_GBIT_FEATURES */
3561 .soft_reset = &genphy_soft_reset,
3562 .config_init = &vsc85xx_config_init,
3563 .config_aneg = &vsc85xx_config_aneg,
3564 .read_status = &vsc85xx_read_status,
3565 .ack_interrupt = &vsc85xx_ack_interrupt,
3566 .config_intr = &vsc85xx_config_intr,
3567 .suspend = &genphy_suspend,
3568 .resume = &genphy_resume,
3569 .probe = &vsc85xx_probe,
3570 .set_wol = &vsc85xx_wol_set,
3571 .get_wol = &vsc85xx_wol_get,
3572 .get_tunable = &vsc85xx_get_tunable,
3573 .set_tunable = &vsc85xx_set_tunable,
3574 .read_page = &vsc85xx_phy_read_page,
3575 .write_page = &vsc85xx_phy_write_page,
3576 .get_sset_count = &vsc85xx_get_sset_count,
3577 .get_strings = &vsc85xx_get_strings,
3578 .get_stats = &vsc85xx_get_stats,
3581 .phy_id = PHY_ID_VSC8540,
3582 .name = "Microsemi FE VSC8540 SyncE",
3583 .phy_id_mask = 0xfffffff0,
3584 /* PHY_BASIC_FEATURES */
3585 .soft_reset = &genphy_soft_reset,
3586 .config_init = &vsc85xx_config_init,
3587 .config_aneg = &vsc85xx_config_aneg,
3588 .read_status = &vsc85xx_read_status,
3589 .ack_interrupt = &vsc85xx_ack_interrupt,
3590 .config_intr = &vsc85xx_config_intr,
3591 .suspend = &genphy_suspend,
3592 .resume = &genphy_resume,
3593 .probe = &vsc85xx_probe,
3594 .set_wol = &vsc85xx_wol_set,
3595 .get_wol = &vsc85xx_wol_get,
3596 .get_tunable = &vsc85xx_get_tunable,
3597 .set_tunable = &vsc85xx_set_tunable,
3598 .read_page = &vsc85xx_phy_read_page,
3599 .write_page = &vsc85xx_phy_write_page,
3600 .get_sset_count = &vsc85xx_get_sset_count,
3601 .get_strings = &vsc85xx_get_strings,
3602 .get_stats = &vsc85xx_get_stats,
3605 .phy_id = PHY_ID_VSC8541,
3606 .name = "Microsemi VSC8541 SyncE",
3607 .phy_id_mask = 0xfffffff0,
3608 /* PHY_GBIT_FEATURES */
3609 .soft_reset = &genphy_soft_reset,
3610 .config_init = &vsc85xx_config_init,
3611 .config_aneg = &vsc85xx_config_aneg,
3612 .read_status = &vsc85xx_read_status,
3613 .ack_interrupt = &vsc85xx_ack_interrupt,
3614 .config_intr = &vsc85xx_config_intr,
3615 .suspend = &genphy_suspend,
3616 .resume = &genphy_resume,
3617 .probe = &vsc85xx_probe,
3618 .set_wol = &vsc85xx_wol_set,
3619 .get_wol = &vsc85xx_wol_get,
3620 .get_tunable = &vsc85xx_get_tunable,
3621 .set_tunable = &vsc85xx_set_tunable,
3622 .read_page = &vsc85xx_phy_read_page,
3623 .write_page = &vsc85xx_phy_write_page,
3624 .get_sset_count = &vsc85xx_get_sset_count,
3625 .get_strings = &vsc85xx_get_strings,
3626 .get_stats = &vsc85xx_get_stats,
3629 .phy_id = PHY_ID_VSC8552,
3630 .name = "Microsemi GE VSC8552 SyncE",
3631 .phy_id_mask = 0xfffffff0,
3632 /* PHY_GBIT_FEATURES */
3633 .soft_reset = &genphy_soft_reset,
3634 .config_init = &vsc8584_config_init,
3635 .config_aneg = &vsc85xx_config_aneg,
3636 .read_status = &vsc85xx_read_status,
3637 .ack_interrupt = &vsc85xx_ack_interrupt,
3638 .config_intr = &vsc85xx_config_intr,
3639 .did_interrupt = &vsc8584_did_interrupt,
3640 .suspend = &genphy_suspend,
3641 .resume = &genphy_resume,
3642 .probe = &vsc8574_probe,
3643 .set_wol = &vsc85xx_wol_set,
3644 .get_wol = &vsc85xx_wol_get,
3645 .get_tunable = &vsc85xx_get_tunable,
3646 .set_tunable = &vsc85xx_set_tunable,
3647 .read_page = &vsc85xx_phy_read_page,
3648 .write_page = &vsc85xx_phy_write_page,
3649 .get_sset_count = &vsc85xx_get_sset_count,
3650 .get_strings = &vsc85xx_get_strings,
3651 .get_stats = &vsc85xx_get_stats,
3654 .phy_id = PHY_ID_VSC856X,
3655 .name = "Microsemi GE VSC856X SyncE",
3656 .phy_id_mask = 0xfffffff0,
3657 /* PHY_GBIT_FEATURES */
3658 .soft_reset = &genphy_soft_reset,
3659 .config_init = &vsc8584_config_init,
3660 .config_aneg = &vsc85xx_config_aneg,
3661 .read_status = &vsc85xx_read_status,
3662 .ack_interrupt = &vsc85xx_ack_interrupt,
3663 .config_intr = &vsc85xx_config_intr,
3664 .did_interrupt = &vsc8584_did_interrupt,
3665 .suspend = &genphy_suspend,
3666 .resume = &genphy_resume,
3667 .probe = &vsc8584_probe,
3668 .get_tunable = &vsc85xx_get_tunable,
3669 .set_tunable = &vsc85xx_set_tunable,
3670 .read_page = &vsc85xx_phy_read_page,
3671 .write_page = &vsc85xx_phy_write_page,
3672 .get_sset_count = &vsc85xx_get_sset_count,
3673 .get_strings = &vsc85xx_get_strings,
3674 .get_stats = &vsc85xx_get_stats,
3677 .phy_id = PHY_ID_VSC8572,
3678 .name = "Microsemi GE VSC8572 SyncE",
3679 .phy_id_mask = 0xfffffff0,
3680 /* PHY_GBIT_FEATURES */
3681 .soft_reset = &genphy_soft_reset,
3682 .config_init = &vsc8584_config_init,
3683 .config_aneg = &vsc85xx_config_aneg,
3684 .aneg_done = &genphy_aneg_done,
3685 .read_status = &vsc85xx_read_status,
3686 .handle_interrupt = &vsc8584_handle_interrupt,
3687 .ack_interrupt = &vsc85xx_ack_interrupt,
3688 .config_intr = &vsc85xx_config_intr,
3689 .did_interrupt = &vsc8584_did_interrupt,
3690 .suspend = &genphy_suspend,
3691 .resume = &genphy_resume,
3692 .probe = &vsc8574_probe,
3693 .set_wol = &vsc85xx_wol_set,
3694 .get_wol = &vsc85xx_wol_get,
3695 .get_tunable = &vsc85xx_get_tunable,
3696 .set_tunable = &vsc85xx_set_tunable,
3697 .read_page = &vsc85xx_phy_read_page,
3698 .write_page = &vsc85xx_phy_write_page,
3699 .get_sset_count = &vsc85xx_get_sset_count,
3700 .get_strings = &vsc85xx_get_strings,
3701 .get_stats = &vsc85xx_get_stats,
3704 .phy_id = PHY_ID_VSC8574,
3705 .name = "Microsemi GE VSC8574 SyncE",
3706 .phy_id_mask = 0xfffffff0,
3707 /* PHY_GBIT_FEATURES */
3708 .soft_reset = &genphy_soft_reset,
3709 .config_init = &vsc8584_config_init,
3710 .config_aneg = &vsc85xx_config_aneg,
3711 .aneg_done = &genphy_aneg_done,
3712 .read_status = &vsc85xx_read_status,
3713 .ack_interrupt = &vsc85xx_ack_interrupt,
3714 .config_intr = &vsc85xx_config_intr,
3715 .did_interrupt = &vsc8584_did_interrupt,
3716 .suspend = &genphy_suspend,
3717 .resume = &genphy_resume,
3718 .probe = &vsc8574_probe,
3719 .set_wol = &vsc85xx_wol_set,
3720 .get_wol = &vsc85xx_wol_get,
3721 .get_tunable = &vsc85xx_get_tunable,
3722 .set_tunable = &vsc85xx_set_tunable,
3723 .read_page = &vsc85xx_phy_read_page,
3724 .write_page = &vsc85xx_phy_write_page,
3725 .get_sset_count = &vsc85xx_get_sset_count,
3726 .get_strings = &vsc85xx_get_strings,
3727 .get_stats = &vsc85xx_get_stats,
3730 .phy_id = PHY_ID_VSC8575,
3731 .name = "Microsemi GE VSC8575 SyncE",
3732 .phy_id_mask = 0xfffffff0,
3733 /* PHY_GBIT_FEATURES */
3734 .soft_reset = &genphy_soft_reset,
3735 .config_init = &vsc8584_config_init,
3736 .config_aneg = &vsc85xx_config_aneg,
3737 .aneg_done = &genphy_aneg_done,
3738 .read_status = &vsc85xx_read_status,
3739 .handle_interrupt = &vsc8584_handle_interrupt,
3740 .ack_interrupt = &vsc85xx_ack_interrupt,
3741 .config_intr = &vsc85xx_config_intr,
3742 .did_interrupt = &vsc8584_did_interrupt,
3743 .suspend = &genphy_suspend,
3744 .resume = &genphy_resume,
3745 .probe = &vsc8584_probe,
3746 .get_tunable = &vsc85xx_get_tunable,
3747 .set_tunable = &vsc85xx_set_tunable,
3748 .read_page = &vsc85xx_phy_read_page,
3749 .write_page = &vsc85xx_phy_write_page,
3750 .get_sset_count = &vsc85xx_get_sset_count,
3751 .get_strings = &vsc85xx_get_strings,
3752 .get_stats = &vsc85xx_get_stats,
3755 .phy_id = PHY_ID_VSC8582,
3756 .name = "Microsemi GE VSC8582 SyncE",
3757 .phy_id_mask = 0xfffffff0,
3758 /* PHY_GBIT_FEATURES */
3759 .soft_reset = &genphy_soft_reset,
3760 .config_init = &vsc8584_config_init,
3761 .config_aneg = &vsc85xx_config_aneg,
3762 .aneg_done = &genphy_aneg_done,
3763 .read_status = &vsc85xx_read_status,
3764 .handle_interrupt = &vsc8584_handle_interrupt,
3765 .ack_interrupt = &vsc85xx_ack_interrupt,
3766 .config_intr = &vsc85xx_config_intr,
3767 .did_interrupt = &vsc8584_did_interrupt,
3768 .suspend = &genphy_suspend,
3769 .resume = &genphy_resume,
3770 .probe = &vsc8584_probe,
3771 .get_tunable = &vsc85xx_get_tunable,
3772 .set_tunable = &vsc85xx_set_tunable,
3773 .read_page = &vsc85xx_phy_read_page,
3774 .write_page = &vsc85xx_phy_write_page,
3775 .get_sset_count = &vsc85xx_get_sset_count,
3776 .get_strings = &vsc85xx_get_strings,
3777 .get_stats = &vsc85xx_get_stats,
3780 .phy_id = PHY_ID_VSC8584,
3781 .name = "Microsemi GE VSC8584 SyncE",
3782 .phy_id_mask = 0xfffffff0,
3783 /* PHY_GBIT_FEATURES */
3784 .soft_reset = &genphy_soft_reset,
3785 .config_init = &vsc8584_config_init,
3786 .config_aneg = &vsc85xx_config_aneg,
3787 .aneg_done = &genphy_aneg_done,
3788 .read_status = &vsc85xx_read_status,
3789 .handle_interrupt = &vsc8584_handle_interrupt,
3790 .ack_interrupt = &vsc85xx_ack_interrupt,
3791 .config_intr = &vsc85xx_config_intr,
3792 .did_interrupt = &vsc8584_did_interrupt,
3793 .suspend = &genphy_suspend,
3794 .resume = &genphy_resume,
3795 .probe = &vsc8584_probe,
3796 .get_tunable = &vsc85xx_get_tunable,
3797 .set_tunable = &vsc85xx_set_tunable,
3798 .read_page = &vsc85xx_phy_read_page,
3799 .write_page = &vsc85xx_phy_write_page,
3800 .get_sset_count = &vsc85xx_get_sset_count,
3801 .get_strings = &vsc85xx_get_strings,
3802 .get_stats = &vsc85xx_get_stats,
3807 module_phy_driver(vsc85xx_driver);
3809 static struct mdio_device_id __maybe_unused vsc85xx_tbl[] = {
3810 { PHY_ID_VSC8504, 0xfffffff0, },
3811 { PHY_ID_VSC8514, 0xfffffff0, },
3812 { PHY_ID_VSC8530, 0xfffffff0, },
3813 { PHY_ID_VSC8531, 0xfffffff0, },
3814 { PHY_ID_VSC8540, 0xfffffff0, },
3815 { PHY_ID_VSC8541, 0xfffffff0, },
3816 { PHY_ID_VSC8552, 0xfffffff0, },
3817 { PHY_ID_VSC856X, 0xfffffff0, },
3818 { PHY_ID_VSC8572, 0xfffffff0, },
3819 { PHY_ID_VSC8574, 0xfffffff0, },
3820 { PHY_ID_VSC8575, 0xfffffff0, },
3821 { PHY_ID_VSC8582, 0xfffffff0, },
3822 { PHY_ID_VSC8584, 0xfffffff0, },
3826 MODULE_DEVICE_TABLE(mdio, vsc85xx_tbl);
3828 MODULE_DESCRIPTION("Microsemi VSC85xx PHY driver");
3829 MODULE_AUTHOR("Nagaraju Lakkaraju");
3830 MODULE_LICENSE("Dual MIT/GPL");