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