xref: /openbmc/linux/drivers/net/phy/mscc/mscc_macsec.c (revision e0a8c918)
1fa164e40SAntoine Tenart // SPDX-License-Identifier: (GPL-2.0 OR MIT)
2fa164e40SAntoine Tenart /*
3c7cd2a6aSAntoine Tenart  * Driver for Microsemi VSC85xx PHYs - MACsec support
4fa164e40SAntoine Tenart  *
5c7cd2a6aSAntoine Tenart  * Author: Antoine Tenart
6fa164e40SAntoine Tenart  * License: Dual MIT/GPL
7c7cd2a6aSAntoine Tenart  * Copyright (c) 2020 Microsemi Corporation
8fa164e40SAntoine Tenart  */
9fa164e40SAntoine Tenart 
10fa164e40SAntoine Tenart #include <linux/phy.h>
11fa164e40SAntoine Tenart #include <dt-bindings/net/mscc-phy-vsc8531.h>
12fa164e40SAntoine Tenart 
135a3235e5SArd Biesheuvel #include <crypto/aes.h>
14fa164e40SAntoine Tenart 
15fa164e40SAntoine Tenart #include <net/macsec.h>
16fa164e40SAntoine Tenart 
17fa164e40SAntoine Tenart #include "mscc.h"
18fa164e40SAntoine Tenart #include "mscc_mac.h"
19fa164e40SAntoine Tenart #include "mscc_macsec.h"
20fa164e40SAntoine Tenart #include "mscc_fc_buffer.h"
21fa164e40SAntoine Tenart 
vsc8584_macsec_phy_read(struct phy_device * phydev,enum macsec_bank bank,u32 reg)22fa164e40SAntoine Tenart static u32 vsc8584_macsec_phy_read(struct phy_device *phydev,
23fa164e40SAntoine Tenart 				   enum macsec_bank bank, u32 reg)
24fa164e40SAntoine Tenart {
25fa164e40SAntoine Tenart 	u32 val, val_l = 0, val_h = 0;
26fa164e40SAntoine Tenart 	unsigned long deadline;
27fa164e40SAntoine Tenart 	int rc;
28fa164e40SAntoine Tenart 
29fa164e40SAntoine Tenart 	rc = phy_select_page(phydev, MSCC_PHY_PAGE_MACSEC);
30fa164e40SAntoine Tenart 	if (rc < 0)
31fa164e40SAntoine Tenart 		goto failed;
32fa164e40SAntoine Tenart 
33fa164e40SAntoine Tenart 	__phy_write(phydev, MSCC_EXT_PAGE_MACSEC_20,
34fa164e40SAntoine Tenart 		    MSCC_PHY_MACSEC_20_TARGET(bank >> 2));
35fa164e40SAntoine Tenart 
36fa164e40SAntoine Tenart 	if (bank >> 2 == 0x1)
37fa164e40SAntoine Tenart 		/* non-MACsec access */
38fa164e40SAntoine Tenart 		bank &= 0x3;
39fa164e40SAntoine Tenart 	else
40fa164e40SAntoine Tenart 		bank = 0;
41fa164e40SAntoine Tenart 
42fa164e40SAntoine Tenart 	__phy_write(phydev, MSCC_EXT_PAGE_MACSEC_19,
43fa164e40SAntoine Tenart 		    MSCC_PHY_MACSEC_19_CMD | MSCC_PHY_MACSEC_19_READ |
44fa164e40SAntoine Tenart 		    MSCC_PHY_MACSEC_19_REG_ADDR(reg) |
45fa164e40SAntoine Tenart 		    MSCC_PHY_MACSEC_19_TARGET(bank));
46fa164e40SAntoine Tenart 
47fa164e40SAntoine Tenart 	deadline = jiffies + msecs_to_jiffies(PROC_CMD_NCOMPLETED_TIMEOUT_MS);
48fa164e40SAntoine Tenart 	do {
49fa164e40SAntoine Tenart 		val = __phy_read(phydev, MSCC_EXT_PAGE_MACSEC_19);
50fa164e40SAntoine Tenart 	} while (time_before(jiffies, deadline) && !(val & MSCC_PHY_MACSEC_19_CMD));
51fa164e40SAntoine Tenart 
52fa164e40SAntoine Tenart 	val_l = __phy_read(phydev, MSCC_EXT_PAGE_MACSEC_17);
53fa164e40SAntoine Tenart 	val_h = __phy_read(phydev, MSCC_EXT_PAGE_MACSEC_18);
54fa164e40SAntoine Tenart 
55fa164e40SAntoine Tenart failed:
56fa164e40SAntoine Tenart 	phy_restore_page(phydev, rc, rc);
57fa164e40SAntoine Tenart 
58fa164e40SAntoine Tenart 	return (val_h << 16) | val_l;
59fa164e40SAntoine Tenart }
60fa164e40SAntoine Tenart 
vsc8584_macsec_phy_write(struct phy_device * phydev,enum macsec_bank bank,u32 reg,u32 val)61fa164e40SAntoine Tenart static void vsc8584_macsec_phy_write(struct phy_device *phydev,
62fa164e40SAntoine Tenart 				     enum macsec_bank bank, u32 reg, u32 val)
63fa164e40SAntoine Tenart {
64fa164e40SAntoine Tenart 	unsigned long deadline;
65fa164e40SAntoine Tenart 	int rc;
66fa164e40SAntoine Tenart 
67fa164e40SAntoine Tenart 	rc = phy_select_page(phydev, MSCC_PHY_PAGE_MACSEC);
68fa164e40SAntoine Tenart 	if (rc < 0)
69fa164e40SAntoine Tenart 		goto failed;
70fa164e40SAntoine Tenart 
71fa164e40SAntoine Tenart 	__phy_write(phydev, MSCC_EXT_PAGE_MACSEC_20,
72fa164e40SAntoine Tenart 		    MSCC_PHY_MACSEC_20_TARGET(bank >> 2));
73fa164e40SAntoine Tenart 
74fa164e40SAntoine Tenart 	if ((bank >> 2 == 0x1) || (bank >> 2 == 0x3))
75fa164e40SAntoine Tenart 		bank &= 0x3;
76fa164e40SAntoine Tenart 	else
77fa164e40SAntoine Tenart 		/* MACsec access */
78fa164e40SAntoine Tenart 		bank = 0;
79fa164e40SAntoine Tenart 
80fa164e40SAntoine Tenart 	__phy_write(phydev, MSCC_EXT_PAGE_MACSEC_17, (u16)val);
81fa164e40SAntoine Tenart 	__phy_write(phydev, MSCC_EXT_PAGE_MACSEC_18, (u16)(val >> 16));
82fa164e40SAntoine Tenart 
83fa164e40SAntoine Tenart 	__phy_write(phydev, MSCC_EXT_PAGE_MACSEC_19,
84fa164e40SAntoine Tenart 		    MSCC_PHY_MACSEC_19_CMD | MSCC_PHY_MACSEC_19_REG_ADDR(reg) |
85fa164e40SAntoine Tenart 		    MSCC_PHY_MACSEC_19_TARGET(bank));
86fa164e40SAntoine Tenart 
87fa164e40SAntoine Tenart 	deadline = jiffies + msecs_to_jiffies(PROC_CMD_NCOMPLETED_TIMEOUT_MS);
88fa164e40SAntoine Tenart 	do {
89fa164e40SAntoine Tenart 		val = __phy_read(phydev, MSCC_EXT_PAGE_MACSEC_19);
90fa164e40SAntoine Tenart 	} while (time_before(jiffies, deadline) && !(val & MSCC_PHY_MACSEC_19_CMD));
91fa164e40SAntoine Tenart 
92fa164e40SAntoine Tenart failed:
93fa164e40SAntoine Tenart 	phy_restore_page(phydev, rc, rc);
94fa164e40SAntoine Tenart }
95fa164e40SAntoine Tenart 
vsc8584_macsec_classification(struct phy_device * phydev,enum macsec_bank bank)96fa164e40SAntoine Tenart static void vsc8584_macsec_classification(struct phy_device *phydev,
97fa164e40SAntoine Tenart 					  enum macsec_bank bank)
98fa164e40SAntoine Tenart {
99fa164e40SAntoine Tenart 	/* enable VLAN tag parsing */
100fa164e40SAntoine Tenart 	vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_CP_TAG,
101fa164e40SAntoine Tenart 				 MSCC_MS_SAM_CP_TAG_PARSE_STAG |
102fa164e40SAntoine Tenart 				 MSCC_MS_SAM_CP_TAG_PARSE_QTAG |
103fa164e40SAntoine Tenart 				 MSCC_MS_SAM_CP_TAG_PARSE_QINQ);
104fa164e40SAntoine Tenart }
105fa164e40SAntoine Tenart 
vsc8584_macsec_flow_default_action(struct phy_device * phydev,enum macsec_bank bank,bool block)106fa164e40SAntoine Tenart static void vsc8584_macsec_flow_default_action(struct phy_device *phydev,
107fa164e40SAntoine Tenart 					       enum macsec_bank bank,
108fa164e40SAntoine Tenart 					       bool block)
109fa164e40SAntoine Tenart {
110fa164e40SAntoine Tenart 	u32 port = (bank == MACSEC_INGR) ?
111fa164e40SAntoine Tenart 		    MSCC_MS_PORT_UNCONTROLLED : MSCC_MS_PORT_COMMON;
112fa164e40SAntoine Tenart 	u32 action = MSCC_MS_FLOW_BYPASS;
113fa164e40SAntoine Tenart 
114fa164e40SAntoine Tenart 	if (block)
115fa164e40SAntoine Tenart 		action = MSCC_MS_FLOW_DROP;
116fa164e40SAntoine Tenart 
117fa164e40SAntoine Tenart 	vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_NM_FLOW_NCP,
118fa164e40SAntoine Tenart 				 /* MACsec untagged */
119fa164e40SAntoine Tenart 				 MSCC_MS_SAM_NM_FLOW_NCP_UNTAGGED_FLOW_TYPE(action) |
120fa164e40SAntoine Tenart 				 MSCC_MS_SAM_NM_FLOW_NCP_UNTAGGED_DROP_ACTION(MSCC_MS_ACTION_DROP) |
121fa164e40SAntoine Tenart 				 MSCC_MS_SAM_NM_FLOW_NCP_UNTAGGED_DEST_PORT(port) |
122fa164e40SAntoine Tenart 				 /* MACsec tagged */
123fa164e40SAntoine Tenart 				 MSCC_MS_SAM_NM_FLOW_NCP_TAGGED_FLOW_TYPE(action) |
124fa164e40SAntoine Tenart 				 MSCC_MS_SAM_NM_FLOW_NCP_TAGGED_DROP_ACTION(MSCC_MS_ACTION_DROP) |
125fa164e40SAntoine Tenart 				 MSCC_MS_SAM_NM_FLOW_NCP_TAGGED_DEST_PORT(port) |
126fa164e40SAntoine Tenart 				 /* Bad tag */
127fa164e40SAntoine Tenart 				 MSCC_MS_SAM_NM_FLOW_NCP_BADTAG_FLOW_TYPE(action) |
128fa164e40SAntoine Tenart 				 MSCC_MS_SAM_NM_FLOW_NCP_BADTAG_DROP_ACTION(MSCC_MS_ACTION_DROP) |
129fa164e40SAntoine Tenart 				 MSCC_MS_SAM_NM_FLOW_NCP_BADTAG_DEST_PORT(port) |
130fa164e40SAntoine Tenart 				 /* Kay tag */
131fa164e40SAntoine Tenart 				 MSCC_MS_SAM_NM_FLOW_NCP_KAY_FLOW_TYPE(action) |
132fa164e40SAntoine Tenart 				 MSCC_MS_SAM_NM_FLOW_NCP_KAY_DROP_ACTION(MSCC_MS_ACTION_DROP) |
133fa164e40SAntoine Tenart 				 MSCC_MS_SAM_NM_FLOW_NCP_KAY_DEST_PORT(port));
134fa164e40SAntoine Tenart 	vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_NM_FLOW_CP,
135fa164e40SAntoine Tenart 				 /* MACsec untagged */
136fa164e40SAntoine Tenart 				 MSCC_MS_SAM_NM_FLOW_NCP_UNTAGGED_FLOW_TYPE(action) |
137fa164e40SAntoine Tenart 				 MSCC_MS_SAM_NM_FLOW_CP_UNTAGGED_DROP_ACTION(MSCC_MS_ACTION_DROP) |
138fa164e40SAntoine Tenart 				 MSCC_MS_SAM_NM_FLOW_CP_UNTAGGED_DEST_PORT(port) |
139fa164e40SAntoine Tenart 				 /* MACsec tagged */
140fa164e40SAntoine Tenart 				 MSCC_MS_SAM_NM_FLOW_NCP_TAGGED_FLOW_TYPE(action) |
141fa164e40SAntoine Tenart 				 MSCC_MS_SAM_NM_FLOW_CP_TAGGED_DROP_ACTION(MSCC_MS_ACTION_DROP) |
142fa164e40SAntoine Tenart 				 MSCC_MS_SAM_NM_FLOW_CP_TAGGED_DEST_PORT(port) |
143fa164e40SAntoine Tenart 				 /* Bad tag */
144fa164e40SAntoine Tenart 				 MSCC_MS_SAM_NM_FLOW_NCP_BADTAG_FLOW_TYPE(action) |
145fa164e40SAntoine Tenart 				 MSCC_MS_SAM_NM_FLOW_CP_BADTAG_DROP_ACTION(MSCC_MS_ACTION_DROP) |
146fa164e40SAntoine Tenart 				 MSCC_MS_SAM_NM_FLOW_CP_BADTAG_DEST_PORT(port) |
147fa164e40SAntoine Tenart 				 /* Kay tag */
148fa164e40SAntoine Tenart 				 MSCC_MS_SAM_NM_FLOW_NCP_KAY_FLOW_TYPE(action) |
149fa164e40SAntoine Tenart 				 MSCC_MS_SAM_NM_FLOW_CP_KAY_DROP_ACTION(MSCC_MS_ACTION_DROP) |
150fa164e40SAntoine Tenart 				 MSCC_MS_SAM_NM_FLOW_CP_KAY_DEST_PORT(port));
151fa164e40SAntoine Tenart }
152fa164e40SAntoine Tenart 
vsc8584_macsec_integrity_checks(struct phy_device * phydev,enum macsec_bank bank)153fa164e40SAntoine Tenart static void vsc8584_macsec_integrity_checks(struct phy_device *phydev,
154fa164e40SAntoine Tenart 					    enum macsec_bank bank)
155fa164e40SAntoine Tenart {
156fa164e40SAntoine Tenart 	u32 val;
157fa164e40SAntoine Tenart 
158fa164e40SAntoine Tenart 	if (bank != MACSEC_INGR)
159fa164e40SAntoine Tenart 		return;
160fa164e40SAntoine Tenart 
161fa164e40SAntoine Tenart 	/* Set default rules to pass unmatched frames */
162fa164e40SAntoine Tenart 	val = vsc8584_macsec_phy_read(phydev, bank,
163fa164e40SAntoine Tenart 				      MSCC_MS_PARAMS2_IG_CC_CONTROL);
164fa164e40SAntoine Tenart 	val |= MSCC_MS_PARAMS2_IG_CC_CONTROL_NON_MATCH_CTRL_ACT |
165fa164e40SAntoine Tenart 	       MSCC_MS_PARAMS2_IG_CC_CONTROL_NON_MATCH_ACT;
166fa164e40SAntoine Tenart 	vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_PARAMS2_IG_CC_CONTROL,
167fa164e40SAntoine Tenart 				 val);
168fa164e40SAntoine Tenart 
169fa164e40SAntoine Tenart 	vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_PARAMS2_IG_CP_TAG,
170fa164e40SAntoine Tenart 				 MSCC_MS_PARAMS2_IG_CP_TAG_PARSE_STAG |
171fa164e40SAntoine Tenart 				 MSCC_MS_PARAMS2_IG_CP_TAG_PARSE_QTAG |
172fa164e40SAntoine Tenart 				 MSCC_MS_PARAMS2_IG_CP_TAG_PARSE_QINQ);
173fa164e40SAntoine Tenart }
174fa164e40SAntoine Tenart 
vsc8584_macsec_block_init(struct phy_device * phydev,enum macsec_bank bank)175fa164e40SAntoine Tenart static void vsc8584_macsec_block_init(struct phy_device *phydev,
176fa164e40SAntoine Tenart 				      enum macsec_bank bank)
177fa164e40SAntoine Tenart {
178fa164e40SAntoine Tenart 	u32 val;
179fa164e40SAntoine Tenart 	int i;
180fa164e40SAntoine Tenart 
181fa164e40SAntoine Tenart 	vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_ENA_CFG,
182fa164e40SAntoine Tenart 				 MSCC_MS_ENA_CFG_SW_RST |
183fa164e40SAntoine Tenart 				 MSCC_MS_ENA_CFG_MACSEC_BYPASS_ENA);
184fa164e40SAntoine Tenart 
185fa164e40SAntoine Tenart 	/* Set the MACsec block out of s/w reset and enable clocks */
186fa164e40SAntoine Tenart 	vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_ENA_CFG,
187fa164e40SAntoine Tenart 				 MSCC_MS_ENA_CFG_CLK_ENA);
188fa164e40SAntoine Tenart 
189fa164e40SAntoine Tenart 	vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_STATUS_CONTEXT_CTRL,
190fa164e40SAntoine Tenart 				 bank == MACSEC_INGR ? 0xe5880214 : 0xe5880218);
191fa164e40SAntoine Tenart 	vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_MISC_CONTROL,
192fa164e40SAntoine Tenart 				 MSCC_MS_MISC_CONTROL_MC_LATENCY_FIX(bank == MACSEC_INGR ? 57 : 40) |
193fa164e40SAntoine Tenart 				 MSCC_MS_MISC_CONTROL_XFORM_REC_SIZE(bank == MACSEC_INGR ? 1 : 2));
194fa164e40SAntoine Tenart 
195fa164e40SAntoine Tenart 	/* Clear the counters */
196fa164e40SAntoine Tenart 	val = vsc8584_macsec_phy_read(phydev, bank, MSCC_MS_COUNT_CONTROL);
197fa164e40SAntoine Tenart 	val |= MSCC_MS_COUNT_CONTROL_AUTO_CNTR_RESET;
198fa164e40SAntoine Tenart 	vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_COUNT_CONTROL, val);
199fa164e40SAntoine Tenart 
200fa164e40SAntoine Tenart 	/* Enable octet increment mode */
201fa164e40SAntoine Tenart 	vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_PP_CTRL,
202fa164e40SAntoine Tenart 				 MSCC_MS_PP_CTRL_MACSEC_OCTET_INCR_MODE);
203fa164e40SAntoine Tenart 
204fa164e40SAntoine Tenart 	vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_BLOCK_CTX_UPDATE, 0x3);
205fa164e40SAntoine Tenart 
206fa164e40SAntoine Tenart 	val = vsc8584_macsec_phy_read(phydev, bank, MSCC_MS_COUNT_CONTROL);
207fa164e40SAntoine Tenart 	val |= MSCC_MS_COUNT_CONTROL_RESET_ALL;
208fa164e40SAntoine Tenart 	vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_COUNT_CONTROL, val);
209fa164e40SAntoine Tenart 
210fa164e40SAntoine Tenart 	/* Set the MTU */
211fa164e40SAntoine Tenart 	vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_NON_VLAN_MTU_CHECK,
212fa164e40SAntoine Tenart 				 MSCC_MS_NON_VLAN_MTU_CHECK_NV_MTU_COMPARE(32761) |
213fa164e40SAntoine Tenart 				 MSCC_MS_NON_VLAN_MTU_CHECK_NV_MTU_COMP_DROP);
214fa164e40SAntoine Tenart 
215fa164e40SAntoine Tenart 	for (i = 0; i < 8; i++)
216fa164e40SAntoine Tenart 		vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_VLAN_MTU_CHECK(i),
217fa164e40SAntoine Tenart 					 MSCC_MS_VLAN_MTU_CHECK_MTU_COMPARE(32761) |
218fa164e40SAntoine Tenart 					 MSCC_MS_VLAN_MTU_CHECK_MTU_COMP_DROP);
219fa164e40SAntoine Tenart 
220fa164e40SAntoine Tenart 	if (bank == MACSEC_EGR) {
221fa164e40SAntoine Tenart 		val = vsc8584_macsec_phy_read(phydev, bank, MSCC_MS_INTR_CTRL_STATUS);
222fa164e40SAntoine Tenart 		val &= ~MSCC_MS_INTR_CTRL_STATUS_INTR_ENABLE_M;
223fa164e40SAntoine Tenart 		vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_INTR_CTRL_STATUS, val);
224fa164e40SAntoine Tenart 
225fa164e40SAntoine Tenart 		vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_FC_CFG,
226fa164e40SAntoine Tenart 					 MSCC_MS_FC_CFG_FCBUF_ENA |
227fa164e40SAntoine Tenart 					 MSCC_MS_FC_CFG_LOW_THRESH(0x1) |
228fa164e40SAntoine Tenart 					 MSCC_MS_FC_CFG_HIGH_THRESH(0x4) |
229fa164e40SAntoine Tenart 					 MSCC_MS_FC_CFG_LOW_BYTES_VAL(0x4) |
230fa164e40SAntoine Tenart 					 MSCC_MS_FC_CFG_HIGH_BYTES_VAL(0x6));
231fa164e40SAntoine Tenart 	}
232fa164e40SAntoine Tenart 
233fa164e40SAntoine Tenart 	vsc8584_macsec_classification(phydev, bank);
234fa164e40SAntoine Tenart 	vsc8584_macsec_flow_default_action(phydev, bank, false);
235fa164e40SAntoine Tenart 	vsc8584_macsec_integrity_checks(phydev, bank);
236fa164e40SAntoine Tenart 
237fa164e40SAntoine Tenart 	/* Enable the MACsec block */
238fa164e40SAntoine Tenart 	vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_ENA_CFG,
239fa164e40SAntoine Tenart 				 MSCC_MS_ENA_CFG_CLK_ENA |
240fa164e40SAntoine Tenart 				 MSCC_MS_ENA_CFG_MACSEC_ENA |
241fa164e40SAntoine Tenart 				 MSCC_MS_ENA_CFG_MACSEC_SPEED_MODE(0x5));
242fa164e40SAntoine Tenart }
243fa164e40SAntoine Tenart 
vsc8584_macsec_mac_init(struct phy_device * phydev,enum macsec_bank bank)244fa164e40SAntoine Tenart static void vsc8584_macsec_mac_init(struct phy_device *phydev,
245fa164e40SAntoine Tenart 				    enum macsec_bank bank)
246fa164e40SAntoine Tenart {
247fa164e40SAntoine Tenart 	u32 val;
248fa164e40SAntoine Tenart 	int i;
249fa164e40SAntoine Tenart 
250fa164e40SAntoine Tenart 	/* Clear host & line stats */
251fa164e40SAntoine Tenart 	for (i = 0; i < 36; i++)
252fa164e40SAntoine Tenart 		vsc8584_macsec_phy_write(phydev, bank, 0x1c + i, 0);
253fa164e40SAntoine Tenart 
254fa164e40SAntoine Tenart 	val = vsc8584_macsec_phy_read(phydev, bank,
255fa164e40SAntoine Tenart 				      MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL);
256fa164e40SAntoine Tenart 	val &= ~MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL_PAUSE_MODE_M;
257fa164e40SAntoine Tenart 	val |= MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL_PAUSE_MODE(2) |
258fa164e40SAntoine Tenart 	       MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL_PAUSE_VALUE(0xffff);
259fa164e40SAntoine Tenart 	vsc8584_macsec_phy_write(phydev, bank,
260fa164e40SAntoine Tenart 				 MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL, val);
261fa164e40SAntoine Tenart 
262fa164e40SAntoine Tenart 	val = vsc8584_macsec_phy_read(phydev, bank,
263fa164e40SAntoine Tenart 				      MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL_2);
264fa164e40SAntoine Tenart 	val |= 0xffff;
265fa164e40SAntoine Tenart 	vsc8584_macsec_phy_write(phydev, bank,
266fa164e40SAntoine Tenart 				 MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL_2, val);
267fa164e40SAntoine Tenart 
268fa164e40SAntoine Tenart 	val = vsc8584_macsec_phy_read(phydev, bank,
269fa164e40SAntoine Tenart 				      MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL);
270fa164e40SAntoine Tenart 	if (bank == HOST_MAC)
271fa164e40SAntoine Tenart 		val |= MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL_PAUSE_TIMER_ENA |
272fa164e40SAntoine Tenart 		       MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL_PAUSE_FRAME_DROP_ENA;
273fa164e40SAntoine Tenart 	else
274fa164e40SAntoine Tenart 		val |= MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL_PAUSE_REACT_ENA |
275fa164e40SAntoine Tenart 		       MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL_PAUSE_FRAME_DROP_ENA |
276fa164e40SAntoine Tenart 		       MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL_PAUSE_MODE |
277fa164e40SAntoine Tenart 		       MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL_EARLY_PAUSE_DETECT_ENA;
278fa164e40SAntoine Tenart 	vsc8584_macsec_phy_write(phydev, bank,
279fa164e40SAntoine Tenart 				 MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL, val);
280fa164e40SAntoine Tenart 
281fa164e40SAntoine Tenart 	vsc8584_macsec_phy_write(phydev, bank, MSCC_MAC_CFG_PKTINF_CFG,
282fa164e40SAntoine Tenart 				 MSCC_MAC_CFG_PKTINF_CFG_STRIP_FCS_ENA |
283fa164e40SAntoine Tenart 				 MSCC_MAC_CFG_PKTINF_CFG_INSERT_FCS_ENA |
284fa164e40SAntoine Tenart 				 MSCC_MAC_CFG_PKTINF_CFG_LPI_RELAY_ENA |
285fa164e40SAntoine Tenart 				 MSCC_MAC_CFG_PKTINF_CFG_STRIP_PREAMBLE_ENA |
286fa164e40SAntoine Tenart 				 MSCC_MAC_CFG_PKTINF_CFG_INSERT_PREAMBLE_ENA |
287fa164e40SAntoine Tenart 				 (bank == HOST_MAC ?
2884c8c5dc5SAntoine Tenart 				  MSCC_MAC_CFG_PKTINF_CFG_ENABLE_TX_PADDING : 0) |
2894c8c5dc5SAntoine Tenart 				 (IS_ENABLED(CONFIG_NETWORK_PHY_TIMESTAMPING) ?
2904c8c5dc5SAntoine Tenart 				  MSCC_MAC_CFG_PKTINF_CFG_MACSEC_BYPASS_NUM_PTP_STALL_CLKS(0x8) : 0));
291fa164e40SAntoine Tenart 
292fa164e40SAntoine Tenart 	val = vsc8584_macsec_phy_read(phydev, bank, MSCC_MAC_CFG_MODE_CFG);
293fa164e40SAntoine Tenart 	val &= ~MSCC_MAC_CFG_MODE_CFG_DISABLE_DIC;
294fa164e40SAntoine Tenart 	vsc8584_macsec_phy_write(phydev, bank, MSCC_MAC_CFG_MODE_CFG, val);
295fa164e40SAntoine Tenart 
296fa164e40SAntoine Tenart 	val = vsc8584_macsec_phy_read(phydev, bank, MSCC_MAC_CFG_MAXLEN_CFG);
297fa164e40SAntoine Tenart 	val &= ~MSCC_MAC_CFG_MAXLEN_CFG_MAX_LEN_M;
298fa164e40SAntoine Tenart 	val |= MSCC_MAC_CFG_MAXLEN_CFG_MAX_LEN(10240);
299fa164e40SAntoine Tenart 	vsc8584_macsec_phy_write(phydev, bank, MSCC_MAC_CFG_MAXLEN_CFG, val);
300fa164e40SAntoine Tenart 
301fa164e40SAntoine Tenart 	vsc8584_macsec_phy_write(phydev, bank, MSCC_MAC_CFG_ADV_CHK_CFG,
302fa164e40SAntoine Tenart 				 MSCC_MAC_CFG_ADV_CHK_CFG_SFD_CHK_ENA |
303fa164e40SAntoine Tenart 				 MSCC_MAC_CFG_ADV_CHK_CFG_PRM_CHK_ENA |
304fa164e40SAntoine Tenart 				 MSCC_MAC_CFG_ADV_CHK_CFG_OOR_ERR_ENA |
305fa164e40SAntoine Tenart 				 MSCC_MAC_CFG_ADV_CHK_CFG_INR_ERR_ENA);
306fa164e40SAntoine Tenart 
307fa164e40SAntoine Tenart 	val = vsc8584_macsec_phy_read(phydev, bank, MSCC_MAC_CFG_LFS_CFG);
308fa164e40SAntoine Tenart 	val &= ~MSCC_MAC_CFG_LFS_CFG_LFS_MODE_ENA;
309fa164e40SAntoine Tenart 	vsc8584_macsec_phy_write(phydev, bank, MSCC_MAC_CFG_LFS_CFG, val);
310fa164e40SAntoine Tenart 
311fa164e40SAntoine Tenart 	vsc8584_macsec_phy_write(phydev, bank, MSCC_MAC_CFG_ENA_CFG,
312fa164e40SAntoine Tenart 				 MSCC_MAC_CFG_ENA_CFG_RX_CLK_ENA |
313fa164e40SAntoine Tenart 				 MSCC_MAC_CFG_ENA_CFG_TX_CLK_ENA |
314fa164e40SAntoine Tenart 				 MSCC_MAC_CFG_ENA_CFG_RX_ENA |
315fa164e40SAntoine Tenart 				 MSCC_MAC_CFG_ENA_CFG_TX_ENA);
316fa164e40SAntoine Tenart }
317fa164e40SAntoine Tenart 
318fa164e40SAntoine Tenart /* Must be called with mdio_lock taken */
__vsc8584_macsec_init(struct phy_device * phydev)319fa164e40SAntoine Tenart static int __vsc8584_macsec_init(struct phy_device *phydev)
320fa164e40SAntoine Tenart {
3210ddfee1fSAntoine Tenart 	struct vsc8531_private *priv = phydev->priv;
3220ddfee1fSAntoine Tenart 	enum macsec_bank proc_bank;
323fa164e40SAntoine Tenart 	u32 val;
324fa164e40SAntoine Tenart 
325fa164e40SAntoine Tenart 	vsc8584_macsec_block_init(phydev, MACSEC_INGR);
326fa164e40SAntoine Tenart 	vsc8584_macsec_block_init(phydev, MACSEC_EGR);
327fa164e40SAntoine Tenart 	vsc8584_macsec_mac_init(phydev, HOST_MAC);
328fa164e40SAntoine Tenart 	vsc8584_macsec_mac_init(phydev, LINE_MAC);
329fa164e40SAntoine Tenart 
330fa164e40SAntoine Tenart 	vsc8584_macsec_phy_write(phydev, FC_BUFFER,
331fa164e40SAntoine Tenart 				 MSCC_FCBUF_FC_READ_THRESH_CFG,
332fa164e40SAntoine Tenart 				 MSCC_FCBUF_FC_READ_THRESH_CFG_TX_THRESH(4) |
333fa164e40SAntoine Tenart 				 MSCC_FCBUF_FC_READ_THRESH_CFG_RX_THRESH(5));
334fa164e40SAntoine Tenart 
335fa164e40SAntoine Tenart 	val = vsc8584_macsec_phy_read(phydev, FC_BUFFER, MSCC_FCBUF_MODE_CFG);
336fa164e40SAntoine Tenart 	val |= MSCC_FCBUF_MODE_CFG_PAUSE_GEN_ENA |
337fa164e40SAntoine Tenart 	       MSCC_FCBUF_MODE_CFG_RX_PPM_RATE_ADAPT_ENA |
338fa164e40SAntoine Tenart 	       MSCC_FCBUF_MODE_CFG_TX_PPM_RATE_ADAPT_ENA;
339fa164e40SAntoine Tenart 	vsc8584_macsec_phy_write(phydev, FC_BUFFER, MSCC_FCBUF_MODE_CFG, val);
340fa164e40SAntoine Tenart 
341fa164e40SAntoine Tenart 	vsc8584_macsec_phy_write(phydev, FC_BUFFER, MSCC_FCBUF_PPM_RATE_ADAPT_THRESH_CFG,
342fa164e40SAntoine Tenart 				 MSCC_FCBUF_PPM_RATE_ADAPT_THRESH_CFG_TX_THRESH(8) |
343fa164e40SAntoine Tenart 				 MSCC_FCBUF_PPM_RATE_ADAPT_THRESH_CFG_TX_OFFSET(9));
344fa164e40SAntoine Tenart 
345fa164e40SAntoine Tenart 	val = vsc8584_macsec_phy_read(phydev, FC_BUFFER,
346fa164e40SAntoine Tenart 				      MSCC_FCBUF_TX_DATA_QUEUE_CFG);
347fa164e40SAntoine Tenart 	val &= ~(MSCC_FCBUF_TX_DATA_QUEUE_CFG_START_M |
348fa164e40SAntoine Tenart 		 MSCC_FCBUF_TX_DATA_QUEUE_CFG_END_M);
349fa164e40SAntoine Tenart 	val |= MSCC_FCBUF_TX_DATA_QUEUE_CFG_START(0) |
350fa164e40SAntoine Tenart 		MSCC_FCBUF_TX_DATA_QUEUE_CFG_END(5119);
351fa164e40SAntoine Tenart 	vsc8584_macsec_phy_write(phydev, FC_BUFFER,
352fa164e40SAntoine Tenart 				 MSCC_FCBUF_TX_DATA_QUEUE_CFG, val);
353fa164e40SAntoine Tenart 
354fa164e40SAntoine Tenart 	val = vsc8584_macsec_phy_read(phydev, FC_BUFFER, MSCC_FCBUF_ENA_CFG);
355fa164e40SAntoine Tenart 	val |= MSCC_FCBUF_ENA_CFG_TX_ENA | MSCC_FCBUF_ENA_CFG_RX_ENA;
356fa164e40SAntoine Tenart 	vsc8584_macsec_phy_write(phydev, FC_BUFFER, MSCC_FCBUF_ENA_CFG, val);
357fa164e40SAntoine Tenart 
3580ddfee1fSAntoine Tenart 	proc_bank = (priv->addr < 2) ? PROC_0 : PROC_2;
3590ddfee1fSAntoine Tenart 
3600ddfee1fSAntoine Tenart 	val = vsc8584_macsec_phy_read(phydev, proc_bank,
3610ddfee1fSAntoine Tenart 				      MSCC_PROC_IP_1588_TOP_CFG_STAT_MODE_CTL);
3620ddfee1fSAntoine Tenart 	val &= ~MSCC_PROC_IP_1588_TOP_CFG_STAT_MODE_CTL_PROTOCOL_MODE_M;
3630ddfee1fSAntoine Tenart 	val |= MSCC_PROC_IP_1588_TOP_CFG_STAT_MODE_CTL_PROTOCOL_MODE(4);
3640ddfee1fSAntoine Tenart 	vsc8584_macsec_phy_write(phydev, proc_bank,
3650ddfee1fSAntoine Tenart 				 MSCC_PROC_IP_1588_TOP_CFG_STAT_MODE_CTL, val);
366fa164e40SAntoine Tenart 
367fa164e40SAntoine Tenart 	return 0;
368fa164e40SAntoine Tenart }
369fa164e40SAntoine Tenart 
vsc8584_macsec_flow(struct phy_device * phydev,struct macsec_flow * flow)370fa164e40SAntoine Tenart static void vsc8584_macsec_flow(struct phy_device *phydev,
371fa164e40SAntoine Tenart 				struct macsec_flow *flow)
372fa164e40SAntoine Tenart {
373fa164e40SAntoine Tenart 	struct vsc8531_private *priv = phydev->priv;
374fa164e40SAntoine Tenart 	enum macsec_bank bank = flow->bank;
375fa164e40SAntoine Tenart 	u32 val, match = 0, mask = 0, action = 0, idx = flow->index;
376fa164e40SAntoine Tenart 
377fa164e40SAntoine Tenart 	if (flow->match.tagged)
378fa164e40SAntoine Tenart 		match |= MSCC_MS_SAM_MISC_MATCH_TAGGED;
379fa164e40SAntoine Tenart 	if (flow->match.untagged)
380fa164e40SAntoine Tenart 		match |= MSCC_MS_SAM_MISC_MATCH_UNTAGGED;
381fa164e40SAntoine Tenart 
382fa164e40SAntoine Tenart 	if (bank == MACSEC_INGR && flow->assoc_num >= 0) {
383fa164e40SAntoine Tenart 		match |= MSCC_MS_SAM_MISC_MATCH_AN(flow->assoc_num);
384fa164e40SAntoine Tenart 		mask |= MSCC_MS_SAM_MASK_AN_MASK(0x3);
385fa164e40SAntoine Tenart 	}
386fa164e40SAntoine Tenart 
387fa164e40SAntoine Tenart 	if (bank == MACSEC_INGR && flow->match.sci && flow->rx_sa->sc->sci) {
388853bede8SAntoine Tenart 		u64 sci = (__force u64)flow->rx_sa->sc->sci;
389853bede8SAntoine Tenart 
390fa164e40SAntoine Tenart 		match |= MSCC_MS_SAM_MISC_MATCH_TCI(BIT(3));
391fa164e40SAntoine Tenart 		mask |= MSCC_MS_SAM_MASK_TCI_MASK(BIT(3)) |
392fa164e40SAntoine Tenart 			MSCC_MS_SAM_MASK_SCI_MASK;
393fa164e40SAntoine Tenart 
394fa164e40SAntoine Tenart 		vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_MATCH_SCI_LO(idx),
395853bede8SAntoine Tenart 					 lower_32_bits(sci));
396fa164e40SAntoine Tenart 		vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_MATCH_SCI_HI(idx),
397853bede8SAntoine Tenart 					 upper_32_bits(sci));
398fa164e40SAntoine Tenart 	}
399fa164e40SAntoine Tenart 
400fa164e40SAntoine Tenart 	if (flow->match.etype) {
401fa164e40SAntoine Tenart 		mask |= MSCC_MS_SAM_MASK_MAC_ETYPE_MASK;
402fa164e40SAntoine Tenart 
403fa164e40SAntoine Tenart 		vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_MAC_SA_MATCH_HI(idx),
404853bede8SAntoine Tenart 					 MSCC_MS_SAM_MAC_SA_MATCH_HI_ETYPE((__force u32)htons(flow->etype)));
405fa164e40SAntoine Tenart 	}
406fa164e40SAntoine Tenart 
407fa164e40SAntoine Tenart 	match |= MSCC_MS_SAM_MISC_MATCH_PRIORITY(flow->priority);
408fa164e40SAntoine Tenart 
409fa164e40SAntoine Tenart 	vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_MISC_MATCH(idx), match);
410fa164e40SAntoine Tenart 	vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_MASK(idx), mask);
411fa164e40SAntoine Tenart 
412fa164e40SAntoine Tenart 	/* Action for matching packets */
413fa164e40SAntoine Tenart 	if (flow->action.drop)
414fa164e40SAntoine Tenart 		action = MSCC_MS_FLOW_DROP;
415fa164e40SAntoine Tenart 	else if (flow->action.bypass || flow->port == MSCC_MS_PORT_UNCONTROLLED)
416fa164e40SAntoine Tenart 		action = MSCC_MS_FLOW_BYPASS;
417fa164e40SAntoine Tenart 	else
418fa164e40SAntoine Tenart 		action = (bank == MACSEC_INGR) ?
419fa164e40SAntoine Tenart 			 MSCC_MS_FLOW_INGRESS : MSCC_MS_FLOW_EGRESS;
420fa164e40SAntoine Tenart 
421fa164e40SAntoine Tenart 	val = MSCC_MS_SAM_FLOW_CTRL_FLOW_TYPE(action) |
422fa164e40SAntoine Tenart 	      MSCC_MS_SAM_FLOW_CTRL_DROP_ACTION(MSCC_MS_ACTION_DROP) |
423fa164e40SAntoine Tenart 	      MSCC_MS_SAM_FLOW_CTRL_DEST_PORT(flow->port);
424fa164e40SAntoine Tenart 
425fa164e40SAntoine Tenart 	if (action == MSCC_MS_FLOW_BYPASS)
426fa164e40SAntoine Tenart 		goto write_ctrl;
427fa164e40SAntoine Tenart 
428fa164e40SAntoine Tenart 	if (bank == MACSEC_INGR) {
429fa164e40SAntoine Tenart 		if (priv->secy->replay_protect)
430fa164e40SAntoine Tenart 			val |= MSCC_MS_SAM_FLOW_CTRL_REPLAY_PROTECT;
431fa164e40SAntoine Tenart 		if (priv->secy->validate_frames == MACSEC_VALIDATE_STRICT)
432fa164e40SAntoine Tenart 			val |= MSCC_MS_SAM_FLOW_CTRL_VALIDATE_FRAMES(MSCC_MS_VALIDATE_STRICT);
433fa164e40SAntoine Tenart 		else if (priv->secy->validate_frames == MACSEC_VALIDATE_CHECK)
434fa164e40SAntoine Tenart 			val |= MSCC_MS_SAM_FLOW_CTRL_VALIDATE_FRAMES(MSCC_MS_VALIDATE_CHECK);
435fa164e40SAntoine Tenart 	} else if (bank == MACSEC_EGR) {
436fa164e40SAntoine Tenart 		if (priv->secy->protect_frames)
437fa164e40SAntoine Tenart 			val |= MSCC_MS_SAM_FLOW_CTRL_PROTECT_FRAME;
438fa164e40SAntoine Tenart 		if (priv->secy->tx_sc.encrypt)
439fa164e40SAntoine Tenart 			val |= MSCC_MS_SAM_FLOW_CTRL_CONF_PROTECT;
440fa164e40SAntoine Tenart 		if (priv->secy->tx_sc.send_sci)
441fa164e40SAntoine Tenart 			val |= MSCC_MS_SAM_FLOW_CTRL_INCLUDE_SCI;
442fa164e40SAntoine Tenart 	}
443fa164e40SAntoine Tenart 
444fa164e40SAntoine Tenart write_ctrl:
445fa164e40SAntoine Tenart 	vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_FLOW_CTRL(idx), val);
446fa164e40SAntoine Tenart }
447fa164e40SAntoine Tenart 
vsc8584_macsec_find_flow(struct macsec_context * ctx,enum macsec_bank bank)448fa164e40SAntoine Tenart static struct macsec_flow *vsc8584_macsec_find_flow(struct macsec_context *ctx,
449fa164e40SAntoine Tenart 						    enum macsec_bank bank)
450fa164e40SAntoine Tenart {
451fa164e40SAntoine Tenart 	struct vsc8531_private *priv = ctx->phydev->priv;
452fa164e40SAntoine Tenart 	struct macsec_flow *pos, *tmp;
453fa164e40SAntoine Tenart 
454fa164e40SAntoine Tenart 	list_for_each_entry_safe(pos, tmp, &priv->macsec_flows, list)
455fa164e40SAntoine Tenart 		if (pos->assoc_num == ctx->sa.assoc_num && pos->bank == bank)
456fa164e40SAntoine Tenart 			return pos;
457fa164e40SAntoine Tenart 
458fa164e40SAntoine Tenart 	return ERR_PTR(-ENOENT);
459fa164e40SAntoine Tenart }
460fa164e40SAntoine Tenart 
vsc8584_macsec_flow_enable(struct phy_device * phydev,struct macsec_flow * flow)461fa164e40SAntoine Tenart static void vsc8584_macsec_flow_enable(struct phy_device *phydev,
462fa164e40SAntoine Tenart 				       struct macsec_flow *flow)
463fa164e40SAntoine Tenart {
464fa164e40SAntoine Tenart 	enum macsec_bank bank = flow->bank;
465fa164e40SAntoine Tenart 	u32 val, idx = flow->index;
466fa164e40SAntoine Tenart 
467fa164e40SAntoine Tenart 	if ((flow->bank == MACSEC_INGR && flow->rx_sa && !flow->rx_sa->active) ||
468fa164e40SAntoine Tenart 	    (flow->bank == MACSEC_EGR && flow->tx_sa && !flow->tx_sa->active))
469fa164e40SAntoine Tenart 		return;
470fa164e40SAntoine Tenart 
471fa164e40SAntoine Tenart 	/* Enable */
472fa164e40SAntoine Tenart 	vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_ENTRY_SET1, BIT(idx));
473fa164e40SAntoine Tenart 
474fa164e40SAntoine Tenart 	/* Set in-use */
475fa164e40SAntoine Tenart 	val = vsc8584_macsec_phy_read(phydev, bank, MSCC_MS_SAM_FLOW_CTRL(idx));
476fa164e40SAntoine Tenart 	val |= MSCC_MS_SAM_FLOW_CTRL_SA_IN_USE;
477fa164e40SAntoine Tenart 	vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_FLOW_CTRL(idx), val);
478fa164e40SAntoine Tenart }
479fa164e40SAntoine Tenart 
vsc8584_macsec_flow_disable(struct phy_device * phydev,struct macsec_flow * flow)480fa164e40SAntoine Tenart static void vsc8584_macsec_flow_disable(struct phy_device *phydev,
481fa164e40SAntoine Tenart 					struct macsec_flow *flow)
482fa164e40SAntoine Tenart {
483fa164e40SAntoine Tenart 	enum macsec_bank bank = flow->bank;
484fa164e40SAntoine Tenart 	u32 val, idx = flow->index;
485fa164e40SAntoine Tenart 
486fa164e40SAntoine Tenart 	/* Disable */
487fa164e40SAntoine Tenart 	vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_ENTRY_CLEAR1, BIT(idx));
488fa164e40SAntoine Tenart 
489fa164e40SAntoine Tenart 	/* Clear in-use */
490fa164e40SAntoine Tenart 	val = vsc8584_macsec_phy_read(phydev, bank, MSCC_MS_SAM_FLOW_CTRL(idx));
491fa164e40SAntoine Tenart 	val &= ~MSCC_MS_SAM_FLOW_CTRL_SA_IN_USE;
492fa164e40SAntoine Tenart 	vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_FLOW_CTRL(idx), val);
493fa164e40SAntoine Tenart }
494fa164e40SAntoine Tenart 
vsc8584_macsec_flow_context_id(struct macsec_flow * flow)495fa164e40SAntoine Tenart static u32 vsc8584_macsec_flow_context_id(struct macsec_flow *flow)
496fa164e40SAntoine Tenart {
497fa164e40SAntoine Tenart 	if (flow->bank == MACSEC_INGR)
498fa164e40SAntoine Tenart 		return flow->index + MSCC_MS_MAX_FLOWS;
499fa164e40SAntoine Tenart 
500fa164e40SAntoine Tenart 	return flow->index;
501fa164e40SAntoine Tenart }
502fa164e40SAntoine Tenart 
503fa164e40SAntoine Tenart /* Derive the AES key to get a key for the hash autentication */
vsc8584_macsec_derive_key(const u8 * key,u16 key_len,u8 hkey[16])5040dc33c65SAntoine Tenart static int vsc8584_macsec_derive_key(const u8 *key, u16 key_len, u8 hkey[16])
505fa164e40SAntoine Tenart {
5065a3235e5SArd Biesheuvel 	const u8 input[AES_BLOCK_SIZE] = {0};
5075a3235e5SArd Biesheuvel 	struct crypto_aes_ctx ctx;
508fa164e40SAntoine Tenart 	int ret;
509fa164e40SAntoine Tenart 
5105a3235e5SArd Biesheuvel 	ret = aes_expandkey(&ctx, key, key_len);
5115a3235e5SArd Biesheuvel 	if (ret)
512fa164e40SAntoine Tenart 		return ret;
5135a3235e5SArd Biesheuvel 
5145a3235e5SArd Biesheuvel 	aes_encrypt(&ctx, hkey, input);
5155a3235e5SArd Biesheuvel 	memzero_explicit(&ctx, sizeof(ctx));
5165a3235e5SArd Biesheuvel 	return 0;
517fa164e40SAntoine Tenart }
518fa164e40SAntoine Tenart 
vsc8584_macsec_transformation(struct phy_device * phydev,struct macsec_flow * flow,const u8 * key)519fa164e40SAntoine Tenart static int vsc8584_macsec_transformation(struct phy_device *phydev,
5200dc33c65SAntoine Tenart 					 struct macsec_flow *flow,
5210dc33c65SAntoine Tenart 					 const u8 *key)
522fa164e40SAntoine Tenart {
523fa164e40SAntoine Tenart 	struct vsc8531_private *priv = phydev->priv;
524fa164e40SAntoine Tenart 	enum macsec_bank bank = flow->bank;
525fa164e40SAntoine Tenart 	int i, ret, index = flow->index;
526fa164e40SAntoine Tenart 	u32 rec = 0, control = 0;
527fa164e40SAntoine Tenart 	u8 hkey[16];
528853bede8SAntoine Tenart 	u64 sci;
529fa164e40SAntoine Tenart 
5300dc33c65SAntoine Tenart 	ret = vsc8584_macsec_derive_key(key, priv->secy->key_len, hkey);
531fa164e40SAntoine Tenart 	if (ret)
532fa164e40SAntoine Tenart 		return ret;
533fa164e40SAntoine Tenart 
534fa164e40SAntoine Tenart 	switch (priv->secy->key_len) {
535fa164e40SAntoine Tenart 	case 16:
536fa164e40SAntoine Tenart 		control |= CONTROL_CRYPTO_ALG(CTRYPTO_ALG_AES_CTR_128);
537fa164e40SAntoine Tenart 		break;
538fa164e40SAntoine Tenart 	case 32:
539fa164e40SAntoine Tenart 		control |= CONTROL_CRYPTO_ALG(CTRYPTO_ALG_AES_CTR_256);
540fa164e40SAntoine Tenart 		break;
541fa164e40SAntoine Tenart 	default:
542fa164e40SAntoine Tenart 		return -EINVAL;
543fa164e40SAntoine Tenart 	}
544fa164e40SAntoine Tenart 
545fa164e40SAntoine Tenart 	control |= (bank == MACSEC_EGR) ?
546fa164e40SAntoine Tenart 		   (CONTROL_TYPE_EGRESS | CONTROL_AN(priv->secy->tx_sc.encoding_sa)) :
547fa164e40SAntoine Tenart 		   (CONTROL_TYPE_INGRESS | CONTROL_SEQ_MASK);
548fa164e40SAntoine Tenart 
549fa164e40SAntoine Tenart 	control |= CONTROL_UPDATE_SEQ | CONTROL_ENCRYPT_AUTH | CONTROL_KEY_IN_CTX |
550fa164e40SAntoine Tenart 		   CONTROL_IV0 | CONTROL_IV1 | CONTROL_IV_IN_SEQ |
551fa164e40SAntoine Tenart 		   CONTROL_DIGEST_TYPE(0x2) | CONTROL_SEQ_TYPE(0x1) |
552fa164e40SAntoine Tenart 		   CONTROL_AUTH_ALG(AUTH_ALG_AES_GHAS) | CONTROL_CONTEXT_ID;
553fa164e40SAntoine Tenart 
554fa164e40SAntoine Tenart 	/* Set the control word */
555fa164e40SAntoine Tenart 	vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_XFORM_REC(index, rec++),
556fa164e40SAntoine Tenart 				 control);
557fa164e40SAntoine Tenart 
558fa164e40SAntoine Tenart 	/* Set the context ID. Must be unique. */
559fa164e40SAntoine Tenart 	vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_XFORM_REC(index, rec++),
560fa164e40SAntoine Tenart 				 vsc8584_macsec_flow_context_id(flow));
561fa164e40SAntoine Tenart 
562fa164e40SAntoine Tenart 	/* Set the encryption/decryption key */
563fa164e40SAntoine Tenart 	for (i = 0; i < priv->secy->key_len / sizeof(u32); i++)
564fa164e40SAntoine Tenart 		vsc8584_macsec_phy_write(phydev, bank,
565fa164e40SAntoine Tenart 					 MSCC_MS_XFORM_REC(index, rec++),
5660dc33c65SAntoine Tenart 					 ((u32 *)key)[i]);
567fa164e40SAntoine Tenart 
568fa164e40SAntoine Tenart 	/* Set the authentication key */
569fa164e40SAntoine Tenart 	for (i = 0; i < 4; i++)
570fa164e40SAntoine Tenart 		vsc8584_macsec_phy_write(phydev, bank,
571fa164e40SAntoine Tenart 					 MSCC_MS_XFORM_REC(index, rec++),
572fa164e40SAntoine Tenart 					 ((u32 *)hkey)[i]);
573fa164e40SAntoine Tenart 
574fa164e40SAntoine Tenart 	/* Initial sequence number */
575fa164e40SAntoine Tenart 	vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_XFORM_REC(index, rec++),
576fa164e40SAntoine Tenart 				 bank == MACSEC_INGR ?
577fa164e40SAntoine Tenart 				 flow->rx_sa->next_pn : flow->tx_sa->next_pn);
578fa164e40SAntoine Tenart 
579fa164e40SAntoine Tenart 	if (bank == MACSEC_INGR)
580fa164e40SAntoine Tenart 		/* Set the mask (replay window size) */
581fa164e40SAntoine Tenart 		vsc8584_macsec_phy_write(phydev, bank,
582fa164e40SAntoine Tenart 					 MSCC_MS_XFORM_REC(index, rec++),
583fa164e40SAntoine Tenart 					 priv->secy->replay_window);
584fa164e40SAntoine Tenart 
585fa164e40SAntoine Tenart 	/* Set the input vectors */
586853bede8SAntoine Tenart 	sci = (__force u64)(bank == MACSEC_INGR ? flow->rx_sa->sc->sci : priv->secy->sci);
587fa164e40SAntoine Tenart 	vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_XFORM_REC(index, rec++),
588fa164e40SAntoine Tenart 				 lower_32_bits(sci));
589fa164e40SAntoine Tenart 	vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_XFORM_REC(index, rec++),
590fa164e40SAntoine Tenart 				 upper_32_bits(sci));
591fa164e40SAntoine Tenart 
592fa164e40SAntoine Tenart 	while (rec < 20)
593fa164e40SAntoine Tenart 		vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_XFORM_REC(index, rec++),
594fa164e40SAntoine Tenart 					 0);
595fa164e40SAntoine Tenart 
596fa164e40SAntoine Tenart 	flow->has_transformation = true;
597fa164e40SAntoine Tenart 	return 0;
598fa164e40SAntoine Tenart }
599fa164e40SAntoine Tenart 
vsc8584_macsec_alloc_flow(struct vsc8531_private * priv,enum macsec_bank bank)600fa164e40SAntoine Tenart static struct macsec_flow *vsc8584_macsec_alloc_flow(struct vsc8531_private *priv,
601fa164e40SAntoine Tenart 						     enum macsec_bank bank)
602fa164e40SAntoine Tenart {
603fa164e40SAntoine Tenart 	unsigned long *bitmap = bank == MACSEC_INGR ?
604fa164e40SAntoine Tenart 				&priv->ingr_flows : &priv->egr_flows;
605fa164e40SAntoine Tenart 	struct macsec_flow *flow;
606fa164e40SAntoine Tenart 	int index;
607fa164e40SAntoine Tenart 
608fa164e40SAntoine Tenart 	index = find_first_zero_bit(bitmap, MSCC_MS_MAX_FLOWS);
609fa164e40SAntoine Tenart 
610fa164e40SAntoine Tenart 	if (index == MSCC_MS_MAX_FLOWS)
611fa164e40SAntoine Tenart 		return ERR_PTR(-ENOMEM);
612fa164e40SAntoine Tenart 
613fa164e40SAntoine Tenart 	flow = kzalloc(sizeof(*flow), GFP_KERNEL);
614fa164e40SAntoine Tenart 	if (!flow)
615fa164e40SAntoine Tenart 		return ERR_PTR(-ENOMEM);
616fa164e40SAntoine Tenart 
617fa164e40SAntoine Tenart 	set_bit(index, bitmap);
618fa164e40SAntoine Tenart 	flow->index = index;
619fa164e40SAntoine Tenart 	flow->bank = bank;
620fa164e40SAntoine Tenart 	flow->priority = 8;
621fa164e40SAntoine Tenart 	flow->assoc_num = -1;
622fa164e40SAntoine Tenart 
623fa164e40SAntoine Tenart 	list_add_tail(&flow->list, &priv->macsec_flows);
624fa164e40SAntoine Tenart 	return flow;
625fa164e40SAntoine Tenart }
626fa164e40SAntoine Tenart 
vsc8584_macsec_free_flow(struct vsc8531_private * priv,struct macsec_flow * flow)627fa164e40SAntoine Tenart static void vsc8584_macsec_free_flow(struct vsc8531_private *priv,
628fa164e40SAntoine Tenart 				     struct macsec_flow *flow)
629fa164e40SAntoine Tenart {
630fa164e40SAntoine Tenart 	unsigned long *bitmap = flow->bank == MACSEC_INGR ?
631fa164e40SAntoine Tenart 				&priv->ingr_flows : &priv->egr_flows;
632fa164e40SAntoine Tenart 
633fa164e40SAntoine Tenart 	list_del(&flow->list);
634fa164e40SAntoine Tenart 	clear_bit(flow->index, bitmap);
635fa164e40SAntoine Tenart 	kfree(flow);
636fa164e40SAntoine Tenart }
637fa164e40SAntoine Tenart 
vsc8584_macsec_add_flow(struct phy_device * phydev,struct macsec_flow * flow)6380dc33c65SAntoine Tenart static void vsc8584_macsec_add_flow(struct phy_device *phydev,
6390dc33c65SAntoine Tenart 				    struct macsec_flow *flow)
640fa164e40SAntoine Tenart {
641fa164e40SAntoine Tenart 	flow->port = MSCC_MS_PORT_CONTROLLED;
642fa164e40SAntoine Tenart 	vsc8584_macsec_flow(phydev, flow);
643fa164e40SAntoine Tenart }
644fa164e40SAntoine Tenart 
vsc8584_macsec_default_flows(struct phy_device * phydev)645fa164e40SAntoine Tenart static int vsc8584_macsec_default_flows(struct phy_device *phydev)
646fa164e40SAntoine Tenart {
647fa164e40SAntoine Tenart 	struct macsec_flow *flow;
648fa164e40SAntoine Tenart 
649fa164e40SAntoine Tenart 	/* Add a rule to let the MKA traffic go through, ingress */
650fa164e40SAntoine Tenart 	flow = vsc8584_macsec_alloc_flow(phydev->priv, MACSEC_INGR);
651fa164e40SAntoine Tenart 	if (IS_ERR(flow))
652fa164e40SAntoine Tenart 		return PTR_ERR(flow);
653fa164e40SAntoine Tenart 
654fa164e40SAntoine Tenart 	flow->priority = 15;
655fa164e40SAntoine Tenart 	flow->port = MSCC_MS_PORT_UNCONTROLLED;
656fa164e40SAntoine Tenart 	flow->match.tagged = 1;
657fa164e40SAntoine Tenart 	flow->match.untagged = 1;
658fa164e40SAntoine Tenart 	flow->match.etype = 1;
659fa164e40SAntoine Tenart 	flow->etype = ETH_P_PAE;
660fa164e40SAntoine Tenart 	flow->action.bypass = 1;
661fa164e40SAntoine Tenart 
662fa164e40SAntoine Tenart 	vsc8584_macsec_flow(phydev, flow);
663fa164e40SAntoine Tenart 	vsc8584_macsec_flow_enable(phydev, flow);
664fa164e40SAntoine Tenart 
665fa164e40SAntoine Tenart 	/* Add a rule to let the MKA traffic go through, egress */
666fa164e40SAntoine Tenart 	flow = vsc8584_macsec_alloc_flow(phydev->priv, MACSEC_EGR);
667fa164e40SAntoine Tenart 	if (IS_ERR(flow))
668fa164e40SAntoine Tenart 		return PTR_ERR(flow);
669fa164e40SAntoine Tenart 
670fa164e40SAntoine Tenart 	flow->priority = 15;
671fa164e40SAntoine Tenart 	flow->port = MSCC_MS_PORT_COMMON;
672fa164e40SAntoine Tenart 	flow->match.untagged = 1;
673fa164e40SAntoine Tenart 	flow->match.etype = 1;
674fa164e40SAntoine Tenart 	flow->etype = ETH_P_PAE;
675fa164e40SAntoine Tenart 	flow->action.bypass = 1;
676fa164e40SAntoine Tenart 
677fa164e40SAntoine Tenart 	vsc8584_macsec_flow(phydev, flow);
678fa164e40SAntoine Tenart 	vsc8584_macsec_flow_enable(phydev, flow);
679fa164e40SAntoine Tenart 
680fa164e40SAntoine Tenart 	return 0;
681fa164e40SAntoine Tenart }
682fa164e40SAntoine Tenart 
vsc8584_macsec_del_flow(struct phy_device * phydev,struct macsec_flow * flow)683fa164e40SAntoine Tenart static void vsc8584_macsec_del_flow(struct phy_device *phydev,
684fa164e40SAntoine Tenart 				    struct macsec_flow *flow)
685fa164e40SAntoine Tenart {
686fa164e40SAntoine Tenart 	vsc8584_macsec_flow_disable(phydev, flow);
687fa164e40SAntoine Tenart 	vsc8584_macsec_free_flow(phydev->priv, flow);
688fa164e40SAntoine Tenart }
689fa164e40SAntoine Tenart 
__vsc8584_macsec_add_rxsa(struct macsec_context * ctx,struct macsec_flow * flow,bool update)690fa164e40SAntoine Tenart static int __vsc8584_macsec_add_rxsa(struct macsec_context *ctx,
691fa164e40SAntoine Tenart 				     struct macsec_flow *flow, bool update)
692fa164e40SAntoine Tenart {
693fa164e40SAntoine Tenart 	struct phy_device *phydev = ctx->phydev;
694fa164e40SAntoine Tenart 	struct vsc8531_private *priv = phydev->priv;
6950dc33c65SAntoine Tenart 	int ret;
696fa164e40SAntoine Tenart 
697fa164e40SAntoine Tenart 	flow->assoc_num = ctx->sa.assoc_num;
698fa164e40SAntoine Tenart 	flow->rx_sa = ctx->sa.rx_sa;
699fa164e40SAntoine Tenart 
700fa164e40SAntoine Tenart 	/* Always match tagged packets on ingress */
701fa164e40SAntoine Tenart 	flow->match.tagged = 1;
702fa164e40SAntoine Tenart 	flow->match.sci = 1;
703fa164e40SAntoine Tenart 
704fa164e40SAntoine Tenart 	if (priv->secy->validate_frames != MACSEC_VALIDATE_DISABLED)
705fa164e40SAntoine Tenart 		flow->match.untagged = 1;
706fa164e40SAntoine Tenart 
7070dc33c65SAntoine Tenart 	vsc8584_macsec_add_flow(phydev, flow);
7080dc33c65SAntoine Tenart 
7090dc33c65SAntoine Tenart 	if (update)
7100dc33c65SAntoine Tenart 		return 0;
7110dc33c65SAntoine Tenart 
7120dc33c65SAntoine Tenart 	ret = vsc8584_macsec_transformation(phydev, flow, ctx->sa.key);
7130dc33c65SAntoine Tenart 	if (ret)
7140dc33c65SAntoine Tenart 		vsc8584_macsec_free_flow(phydev->priv, flow);
7150dc33c65SAntoine Tenart 
7160dc33c65SAntoine Tenart 	return ret;
717fa164e40SAntoine Tenart }
718fa164e40SAntoine Tenart 
__vsc8584_macsec_add_txsa(struct macsec_context * ctx,struct macsec_flow * flow,bool update)719fa164e40SAntoine Tenart static int __vsc8584_macsec_add_txsa(struct macsec_context *ctx,
720fa164e40SAntoine Tenart 				     struct macsec_flow *flow, bool update)
721fa164e40SAntoine Tenart {
7220dc33c65SAntoine Tenart 	int ret;
7230dc33c65SAntoine Tenart 
724fa164e40SAntoine Tenart 	flow->assoc_num = ctx->sa.assoc_num;
725fa164e40SAntoine Tenart 	flow->tx_sa = ctx->sa.tx_sa;
726fa164e40SAntoine Tenart 
727fa164e40SAntoine Tenart 	/* Always match untagged packets on egress */
728fa164e40SAntoine Tenart 	flow->match.untagged = 1;
729fa164e40SAntoine Tenart 
7300dc33c65SAntoine Tenart 	vsc8584_macsec_add_flow(ctx->phydev, flow);
7310dc33c65SAntoine Tenart 
7320dc33c65SAntoine Tenart 	if (update)
7330dc33c65SAntoine Tenart 		return 0;
7340dc33c65SAntoine Tenart 
7350dc33c65SAntoine Tenart 	ret = vsc8584_macsec_transformation(ctx->phydev, flow, ctx->sa.key);
7360dc33c65SAntoine Tenart 	if (ret)
7370dc33c65SAntoine Tenart 		vsc8584_macsec_free_flow(ctx->phydev->priv, flow);
7380dc33c65SAntoine Tenart 
7390dc33c65SAntoine Tenart 	return ret;
740fa164e40SAntoine Tenart }
741fa164e40SAntoine Tenart 
vsc8584_macsec_dev_open(struct macsec_context * ctx)742fa164e40SAntoine Tenart static int vsc8584_macsec_dev_open(struct macsec_context *ctx)
743fa164e40SAntoine Tenart {
744fa164e40SAntoine Tenart 	struct vsc8531_private *priv = ctx->phydev->priv;
745fa164e40SAntoine Tenart 	struct macsec_flow *flow, *tmp;
746fa164e40SAntoine Tenart 
747fa164e40SAntoine Tenart 	list_for_each_entry_safe(flow, tmp, &priv->macsec_flows, list)
748fa164e40SAntoine Tenart 		vsc8584_macsec_flow_enable(ctx->phydev, flow);
749fa164e40SAntoine Tenart 
750fa164e40SAntoine Tenart 	return 0;
751fa164e40SAntoine Tenart }
752fa164e40SAntoine Tenart 
vsc8584_macsec_dev_stop(struct macsec_context * ctx)753fa164e40SAntoine Tenart static int vsc8584_macsec_dev_stop(struct macsec_context *ctx)
754fa164e40SAntoine Tenart {
755fa164e40SAntoine Tenart 	struct vsc8531_private *priv = ctx->phydev->priv;
756fa164e40SAntoine Tenart 	struct macsec_flow *flow, *tmp;
757fa164e40SAntoine Tenart 
758fa164e40SAntoine Tenart 	list_for_each_entry_safe(flow, tmp, &priv->macsec_flows, list)
759fa164e40SAntoine Tenart 		vsc8584_macsec_flow_disable(ctx->phydev, flow);
760fa164e40SAntoine Tenart 
761fa164e40SAntoine Tenart 	return 0;
762fa164e40SAntoine Tenart }
763fa164e40SAntoine Tenart 
vsc8584_macsec_add_secy(struct macsec_context * ctx)764fa164e40SAntoine Tenart static int vsc8584_macsec_add_secy(struct macsec_context *ctx)
765fa164e40SAntoine Tenart {
766fa164e40SAntoine Tenart 	struct vsc8531_private *priv = ctx->phydev->priv;
767fa164e40SAntoine Tenart 	struct macsec_secy *secy = ctx->secy;
768fa164e40SAntoine Tenart 
769fa164e40SAntoine Tenart 	if (priv->secy)
770fa164e40SAntoine Tenart 		return -EEXIST;
771fa164e40SAntoine Tenart 
772fa164e40SAntoine Tenart 	priv->secy = secy;
773fa164e40SAntoine Tenart 
774fa164e40SAntoine Tenart 	vsc8584_macsec_flow_default_action(ctx->phydev, MACSEC_EGR,
775fa164e40SAntoine Tenart 					   secy->validate_frames != MACSEC_VALIDATE_DISABLED);
776fa164e40SAntoine Tenart 	vsc8584_macsec_flow_default_action(ctx->phydev, MACSEC_INGR,
777fa164e40SAntoine Tenart 					   secy->validate_frames != MACSEC_VALIDATE_DISABLED);
778fa164e40SAntoine Tenart 
779fa164e40SAntoine Tenart 	return vsc8584_macsec_default_flows(ctx->phydev);
780fa164e40SAntoine Tenart }
781fa164e40SAntoine Tenart 
vsc8584_macsec_del_secy(struct macsec_context * ctx)782fa164e40SAntoine Tenart static int vsc8584_macsec_del_secy(struct macsec_context *ctx)
783fa164e40SAntoine Tenart {
784fa164e40SAntoine Tenart 	struct vsc8531_private *priv = ctx->phydev->priv;
785fa164e40SAntoine Tenart 	struct macsec_flow *flow, *tmp;
786fa164e40SAntoine Tenart 
787fa164e40SAntoine Tenart 	list_for_each_entry_safe(flow, tmp, &priv->macsec_flows, list)
788fa164e40SAntoine Tenart 		vsc8584_macsec_del_flow(ctx->phydev, flow);
789fa164e40SAntoine Tenart 
790fa164e40SAntoine Tenart 	vsc8584_macsec_flow_default_action(ctx->phydev, MACSEC_EGR, false);
791fa164e40SAntoine Tenart 	vsc8584_macsec_flow_default_action(ctx->phydev, MACSEC_INGR, false);
792fa164e40SAntoine Tenart 
793fa164e40SAntoine Tenart 	priv->secy = NULL;
794fa164e40SAntoine Tenart 	return 0;
795fa164e40SAntoine Tenart }
796fa164e40SAntoine Tenart 
vsc8584_macsec_upd_secy(struct macsec_context * ctx)797fa164e40SAntoine Tenart static int vsc8584_macsec_upd_secy(struct macsec_context *ctx)
798fa164e40SAntoine Tenart {
799fa164e40SAntoine Tenart 	vsc8584_macsec_del_secy(ctx);
800fa164e40SAntoine Tenart 	return vsc8584_macsec_add_secy(ctx);
801fa164e40SAntoine Tenart }
802fa164e40SAntoine Tenart 
vsc8584_macsec_add_rxsc(struct macsec_context * ctx)803fa164e40SAntoine Tenart static int vsc8584_macsec_add_rxsc(struct macsec_context *ctx)
804fa164e40SAntoine Tenart {
805fa164e40SAntoine Tenart 	/* Nothing to do */
806fa164e40SAntoine Tenart 	return 0;
807fa164e40SAntoine Tenart }
808fa164e40SAntoine Tenart 
vsc8584_macsec_upd_rxsc(struct macsec_context * ctx)809fa164e40SAntoine Tenart static int vsc8584_macsec_upd_rxsc(struct macsec_context *ctx)
810fa164e40SAntoine Tenart {
811fa164e40SAntoine Tenart 	return -EOPNOTSUPP;
812fa164e40SAntoine Tenart }
813fa164e40SAntoine Tenart 
vsc8584_macsec_del_rxsc(struct macsec_context * ctx)814fa164e40SAntoine Tenart static int vsc8584_macsec_del_rxsc(struct macsec_context *ctx)
815fa164e40SAntoine Tenart {
816fa164e40SAntoine Tenart 	struct vsc8531_private *priv = ctx->phydev->priv;
817fa164e40SAntoine Tenart 	struct macsec_flow *flow, *tmp;
818fa164e40SAntoine Tenart 
819fa164e40SAntoine Tenart 	list_for_each_entry_safe(flow, tmp, &priv->macsec_flows, list) {
820fa164e40SAntoine Tenart 		if (flow->bank == MACSEC_INGR && flow->rx_sa &&
821fa164e40SAntoine Tenart 		    flow->rx_sa->sc->sci == ctx->rx_sc->sci)
822fa164e40SAntoine Tenart 			vsc8584_macsec_del_flow(ctx->phydev, flow);
823fa164e40SAntoine Tenart 	}
824fa164e40SAntoine Tenart 
825fa164e40SAntoine Tenart 	return 0;
826fa164e40SAntoine Tenart }
827fa164e40SAntoine Tenart 
vsc8584_macsec_add_rxsa(struct macsec_context * ctx)828fa164e40SAntoine Tenart static int vsc8584_macsec_add_rxsa(struct macsec_context *ctx)
829fa164e40SAntoine Tenart {
830920d998eSAntoine Tenart 	struct phy_device *phydev = ctx->phydev;
831920d998eSAntoine Tenart 	struct vsc8531_private *priv = phydev->priv;
832920d998eSAntoine Tenart 	struct macsec_flow *flow;
833920d998eSAntoine Tenart 	int ret;
834fa164e40SAntoine Tenart 
835920d998eSAntoine Tenart 	flow = vsc8584_macsec_alloc_flow(priv, MACSEC_INGR);
836fa164e40SAntoine Tenart 	if (IS_ERR(flow))
837fa164e40SAntoine Tenart 		return PTR_ERR(flow);
838fa164e40SAntoine Tenart 
839920d998eSAntoine Tenart 	ret = __vsc8584_macsec_add_rxsa(ctx, flow, false);
840920d998eSAntoine Tenart 	if (ret)
841920d998eSAntoine Tenart 		return ret;
842920d998eSAntoine Tenart 
843920d998eSAntoine Tenart 	vsc8584_macsec_flow_enable(phydev, flow);
844fa164e40SAntoine Tenart 	return 0;
845fa164e40SAntoine Tenart }
846fa164e40SAntoine Tenart 
vsc8584_macsec_upd_rxsa(struct macsec_context * ctx)847fa164e40SAntoine Tenart static int vsc8584_macsec_upd_rxsa(struct macsec_context *ctx)
848fa164e40SAntoine Tenart {
849fa164e40SAntoine Tenart 	struct macsec_flow *flow;
850920d998eSAntoine Tenart 	int ret;
851920d998eSAntoine Tenart 
852*e0a8c918SRadu Pirea (NXP OSS) 	if (ctx->sa.update_pn)
853*e0a8c918SRadu Pirea (NXP OSS) 		return -EINVAL;
854*e0a8c918SRadu Pirea (NXP OSS) 
855fa164e40SAntoine Tenart 	flow = vsc8584_macsec_find_flow(ctx, MACSEC_INGR);
856fa164e40SAntoine Tenart 	if (IS_ERR(flow))
857fa164e40SAntoine Tenart 		return PTR_ERR(flow);
858fa164e40SAntoine Tenart 
859fa164e40SAntoine Tenart 	/* Make sure the flow is disabled before updating it */
860fa164e40SAntoine Tenart 	vsc8584_macsec_flow_disable(ctx->phydev, flow);
861fa164e40SAntoine Tenart 
862920d998eSAntoine Tenart 	ret = __vsc8584_macsec_add_rxsa(ctx, flow, true);
863920d998eSAntoine Tenart 	if (ret)
864920d998eSAntoine Tenart 		return ret;
865fa164e40SAntoine Tenart 
866fa164e40SAntoine Tenart 	vsc8584_macsec_flow_enable(ctx->phydev, flow);
867fa164e40SAntoine Tenart 	return 0;
868fa164e40SAntoine Tenart }
869fa164e40SAntoine Tenart 
vsc8584_macsec_del_rxsa(struct macsec_context * ctx)870fa164e40SAntoine Tenart static int vsc8584_macsec_del_rxsa(struct macsec_context *ctx)
871fa164e40SAntoine Tenart {
872fa164e40SAntoine Tenart 	struct macsec_flow *flow;
873fa164e40SAntoine Tenart 
874920d998eSAntoine Tenart 	flow = vsc8584_macsec_find_flow(ctx, MACSEC_INGR);
875920d998eSAntoine Tenart 	if (IS_ERR(flow))
876920d998eSAntoine Tenart 		return PTR_ERR(flow);
877920d998eSAntoine Tenart 
878fa164e40SAntoine Tenart 	vsc8584_macsec_del_flow(ctx->phydev, flow);
879fa164e40SAntoine Tenart 	return 0;
880fa164e40SAntoine Tenart }
881fa164e40SAntoine Tenart 
vsc8584_macsec_add_txsa(struct macsec_context * ctx)882fa164e40SAntoine Tenart static int vsc8584_macsec_add_txsa(struct macsec_context *ctx)
883fa164e40SAntoine Tenart {
884920d998eSAntoine Tenart 	struct phy_device *phydev = ctx->phydev;
885920d998eSAntoine Tenart 	struct vsc8531_private *priv = phydev->priv;
886920d998eSAntoine Tenart 	struct macsec_flow *flow;
887920d998eSAntoine Tenart 	int ret;
888fa164e40SAntoine Tenart 
889920d998eSAntoine Tenart 	flow = vsc8584_macsec_alloc_flow(priv, MACSEC_EGR);
890fa164e40SAntoine Tenart 	if (IS_ERR(flow))
891fa164e40SAntoine Tenart 		return PTR_ERR(flow);
892fa164e40SAntoine Tenart 
893920d998eSAntoine Tenart 	ret = __vsc8584_macsec_add_txsa(ctx, flow, false);
894920d998eSAntoine Tenart 	if (ret)
895920d998eSAntoine Tenart 		return ret;
896920d998eSAntoine Tenart 
897920d998eSAntoine Tenart 	vsc8584_macsec_flow_enable(phydev, flow);
898fa164e40SAntoine Tenart 	return 0;
899fa164e40SAntoine Tenart }
900fa164e40SAntoine Tenart 
vsc8584_macsec_upd_txsa(struct macsec_context * ctx)901fa164e40SAntoine Tenart static int vsc8584_macsec_upd_txsa(struct macsec_context *ctx)
902fa164e40SAntoine Tenart {
903fa164e40SAntoine Tenart 	struct macsec_flow *flow;
904920d998eSAntoine Tenart 	int ret;
905920d998eSAntoine Tenart 
906*e0a8c918SRadu Pirea (NXP OSS) 	if (ctx->sa.update_pn)
907*e0a8c918SRadu Pirea (NXP OSS) 		return -EINVAL;
908*e0a8c918SRadu Pirea (NXP OSS) 
909fa164e40SAntoine Tenart 	flow = vsc8584_macsec_find_flow(ctx, MACSEC_EGR);
910fa164e40SAntoine Tenart 	if (IS_ERR(flow))
911fa164e40SAntoine Tenart 		return PTR_ERR(flow);
912fa164e40SAntoine Tenart 
913fa164e40SAntoine Tenart 	/* Make sure the flow is disabled before updating it */
914fa164e40SAntoine Tenart 	vsc8584_macsec_flow_disable(ctx->phydev, flow);
915fa164e40SAntoine Tenart 
916920d998eSAntoine Tenart 	ret = __vsc8584_macsec_add_txsa(ctx, flow, true);
917920d998eSAntoine Tenart 	if (ret)
918920d998eSAntoine Tenart 		return ret;
919fa164e40SAntoine Tenart 
920fa164e40SAntoine Tenart 	vsc8584_macsec_flow_enable(ctx->phydev, flow);
921fa164e40SAntoine Tenart 	return 0;
922fa164e40SAntoine Tenart }
923fa164e40SAntoine Tenart 
vsc8584_macsec_del_txsa(struct macsec_context * ctx)924fa164e40SAntoine Tenart static int vsc8584_macsec_del_txsa(struct macsec_context *ctx)
925fa164e40SAntoine Tenart {
926fa164e40SAntoine Tenart 	struct macsec_flow *flow;
927fa164e40SAntoine Tenart 
928920d998eSAntoine Tenart 	flow = vsc8584_macsec_find_flow(ctx, MACSEC_EGR);
929920d998eSAntoine Tenart 	if (IS_ERR(flow))
930920d998eSAntoine Tenart 		return PTR_ERR(flow);
931920d998eSAntoine Tenart 
932fa164e40SAntoine Tenart 	vsc8584_macsec_del_flow(ctx->phydev, flow);
933fa164e40SAntoine Tenart 	return 0;
934fa164e40SAntoine Tenart }
935fa164e40SAntoine Tenart 
93673a9df4cSRikard Falkeborn static const struct macsec_ops vsc8584_macsec_ops = {
937fa164e40SAntoine Tenart 	.mdo_dev_open = vsc8584_macsec_dev_open,
938fa164e40SAntoine Tenart 	.mdo_dev_stop = vsc8584_macsec_dev_stop,
939fa164e40SAntoine Tenart 	.mdo_add_secy = vsc8584_macsec_add_secy,
940fa164e40SAntoine Tenart 	.mdo_upd_secy = vsc8584_macsec_upd_secy,
941fa164e40SAntoine Tenart 	.mdo_del_secy = vsc8584_macsec_del_secy,
942fa164e40SAntoine Tenart 	.mdo_add_rxsc = vsc8584_macsec_add_rxsc,
943fa164e40SAntoine Tenart 	.mdo_upd_rxsc = vsc8584_macsec_upd_rxsc,
944fa164e40SAntoine Tenart 	.mdo_del_rxsc = vsc8584_macsec_del_rxsc,
945fa164e40SAntoine Tenart 	.mdo_add_rxsa = vsc8584_macsec_add_rxsa,
946fa164e40SAntoine Tenart 	.mdo_upd_rxsa = vsc8584_macsec_upd_rxsa,
947fa164e40SAntoine Tenart 	.mdo_del_rxsa = vsc8584_macsec_del_rxsa,
948fa164e40SAntoine Tenart 	.mdo_add_txsa = vsc8584_macsec_add_txsa,
949fa164e40SAntoine Tenart 	.mdo_upd_txsa = vsc8584_macsec_upd_txsa,
950fa164e40SAntoine Tenart 	.mdo_del_txsa = vsc8584_macsec_del_txsa,
951fa164e40SAntoine Tenart };
952fa164e40SAntoine Tenart 
vsc8584_macsec_init(struct phy_device * phydev)953fa164e40SAntoine Tenart int vsc8584_macsec_init(struct phy_device *phydev)
954fa164e40SAntoine Tenart {
955fa164e40SAntoine Tenart 	struct vsc8531_private *vsc8531 = phydev->priv;
956fa164e40SAntoine Tenart 
957fa164e40SAntoine Tenart 	switch (phydev->phy_id & phydev->drv->phy_id_mask) {
958fa164e40SAntoine Tenart 	case PHY_ID_VSC856X:
959fa164e40SAntoine Tenart 	case PHY_ID_VSC8582:
960fa164e40SAntoine Tenart 	case PHY_ID_VSC8584:
961fa164e40SAntoine Tenart 		INIT_LIST_HEAD(&vsc8531->macsec_flows);
962fa164e40SAntoine Tenart 		vsc8531->secy = NULL;
963fa164e40SAntoine Tenart 
964fa164e40SAntoine Tenart 		phydev->macsec_ops = &vsc8584_macsec_ops;
965fa164e40SAntoine Tenart 
966fa164e40SAntoine Tenart 		return __vsc8584_macsec_init(phydev);
967fa164e40SAntoine Tenart 	}
968fa164e40SAntoine Tenart 
969fa164e40SAntoine Tenart 	return 0;
970fa164e40SAntoine Tenart }
971fa164e40SAntoine Tenart 
vsc8584_handle_macsec_interrupt(struct phy_device * phydev)972fa164e40SAntoine Tenart void vsc8584_handle_macsec_interrupt(struct phy_device *phydev)
973fa164e40SAntoine Tenart {
974fa164e40SAntoine Tenart 	struct vsc8531_private *priv = phydev->priv;
975fa164e40SAntoine Tenart 	struct macsec_flow *flow, *tmp;
976fa164e40SAntoine Tenart 	u32 cause, rec;
977fa164e40SAntoine Tenart 
978fa164e40SAntoine Tenart 	/* Check MACsec PN rollover */
979fa164e40SAntoine Tenart 	cause = vsc8584_macsec_phy_read(phydev, MACSEC_EGR,
980fa164e40SAntoine Tenart 					MSCC_MS_INTR_CTRL_STATUS);
981fa164e40SAntoine Tenart 	cause &= MSCC_MS_INTR_CTRL_STATUS_INTR_CLR_STATUS_M;
982fa164e40SAntoine Tenart 	if (!(cause & MACSEC_INTR_CTRL_STATUS_ROLLOVER))
983fa164e40SAntoine Tenart 		return;
984fa164e40SAntoine Tenart 
985fa164e40SAntoine Tenart 	rec = 6 + priv->secy->key_len / sizeof(u32);
986fa164e40SAntoine Tenart 	list_for_each_entry_safe(flow, tmp, &priv->macsec_flows, list) {
987fa164e40SAntoine Tenart 		u32 val;
988fa164e40SAntoine Tenart 
989fa164e40SAntoine Tenart 		if (flow->bank != MACSEC_EGR || !flow->has_transformation)
990fa164e40SAntoine Tenart 			continue;
991fa164e40SAntoine Tenart 
992fa164e40SAntoine Tenart 		val = vsc8584_macsec_phy_read(phydev, MACSEC_EGR,
993fa164e40SAntoine Tenart 					      MSCC_MS_XFORM_REC(flow->index, rec));
994fa164e40SAntoine Tenart 		if (val == 0xffffffff) {
995fa164e40SAntoine Tenart 			vsc8584_macsec_flow_disable(phydev, flow);
996fa164e40SAntoine Tenart 			macsec_pn_wrapped(priv->secy, flow->tx_sa);
997fa164e40SAntoine Tenart 			return;
998fa164e40SAntoine Tenart 		}
999fa164e40SAntoine Tenart 	}
1000fa164e40SAntoine Tenart }
1001fa164e40SAntoine Tenart 
vsc8584_config_macsec_intr(struct phy_device * phydev)1002fa164e40SAntoine Tenart void vsc8584_config_macsec_intr(struct phy_device *phydev)
1003fa164e40SAntoine Tenart {
1004fa164e40SAntoine Tenart 	phy_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_EXTENDED_2);
1005fa164e40SAntoine Tenart 	phy_write(phydev, MSCC_PHY_EXTENDED_INT, MSCC_PHY_EXTENDED_INT_MS_EGR);
1006fa164e40SAntoine Tenart 	phy_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
1007fa164e40SAntoine Tenart 
1008fa164e40SAntoine Tenart 	vsc8584_macsec_phy_write(phydev, MACSEC_EGR, MSCC_MS_AIC_CTRL, 0xf);
1009fa164e40SAntoine Tenart 	vsc8584_macsec_phy_write(phydev, MACSEC_EGR, MSCC_MS_INTR_CTRL_STATUS,
1010fa164e40SAntoine Tenart 				 MSCC_MS_INTR_CTRL_STATUS_INTR_ENABLE(MACSEC_INTR_CTRL_STATUS_ROLLOVER));
1011fa164e40SAntoine Tenart }
1012