xref: /linux/drivers/net/ethernet/marvell/octeontx2/af/mcs_cnf10kb.c (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Marvell MCS driver
3  *
4  * Copyright (C) 2022 Marvell.
5  */
6 
7 #include "mcs.h"
8 #include "mcs_reg.h"
9 
10 static struct mcs_ops cnf10kb_mcs_ops   = {
11 	.mcs_set_hw_capabilities	= cnf10kb_mcs_set_hw_capabilities,
12 	.mcs_parser_cfg			= cnf10kb_mcs_parser_cfg,
13 	.mcs_tx_sa_mem_map_write	= cnf10kb_mcs_tx_sa_mem_map_write,
14 	.mcs_rx_sa_mem_map_write	= cnf10kb_mcs_rx_sa_mem_map_write,
15 	.mcs_flowid_secy_map		= cnf10kb_mcs_flowid_secy_map,
16 	.mcs_bbe_intr_handler		= cnf10kb_mcs_bbe_intr_handler,
17 	.mcs_pab_intr_handler		= cnf10kb_mcs_pab_intr_handler,
18 };
19 
cnf10kb_get_mac_ops(void)20 struct mcs_ops *cnf10kb_get_mac_ops(void)
21 {
22 	return &cnf10kb_mcs_ops;
23 }
24 
cnf10kb_mcs_set_hw_capabilities(struct mcs * mcs)25 void cnf10kb_mcs_set_hw_capabilities(struct mcs *mcs)
26 {
27 	struct hwinfo *hw = mcs->hw;
28 
29 	hw->tcam_entries = 64;		/* TCAM entries */
30 	hw->secy_entries  = 64;		/* SecY entries */
31 	hw->sc_entries = 64;		/* SC CAM entries */
32 	hw->sa_entries = 128;		/* SA entries */
33 	hw->lmac_cnt = 4;		/* lmacs/ports per mcs block */
34 	hw->mcs_x2p_intf = 1;		/* x2p clabration intf */
35 	hw->mcs_blks = 7;		/* MCS blocks */
36 	hw->ip_vec = MCS_CNF10KB_INT_VEC_IP; /* IP vector */
37 }
38 
cnf10kb_mcs_parser_cfg(struct mcs * mcs)39 void cnf10kb_mcs_parser_cfg(struct mcs *mcs)
40 {
41 	u64 reg, val;
42 
43 	/* VLAN Ctag */
44 	val = (0x8100ull & 0xFFFF) | BIT_ULL(20) | BIT_ULL(22);
45 
46 	reg = MCSX_PEX_RX_SLAVE_CUSTOM_TAGX(0);
47 	mcs_reg_write(mcs, reg, val);
48 
49 	reg = MCSX_PEX_TX_SLAVE_CUSTOM_TAGX(0);
50 	mcs_reg_write(mcs, reg, val);
51 
52 	/* VLAN STag */
53 	val = (0x88a8ull & 0xFFFF) | BIT_ULL(20) | BIT_ULL(23);
54 
55 	/* RX */
56 	reg = MCSX_PEX_RX_SLAVE_CUSTOM_TAGX(1);
57 	mcs_reg_write(mcs, reg, val);
58 
59 	/* TX */
60 	reg = MCSX_PEX_TX_SLAVE_CUSTOM_TAGX(1);
61 	mcs_reg_write(mcs, reg, val);
62 
63 	/* Enable custom tage 0 and 1 and sectag */
64 	val = BIT_ULL(0) | BIT_ULL(1) | BIT_ULL(12);
65 
66 	reg = MCSX_PEX_RX_SLAVE_ETYPE_ENABLE;
67 	mcs_reg_write(mcs, reg, val);
68 
69 	reg = MCSX_PEX_TX_SLAVE_ETYPE_ENABLE;
70 	mcs_reg_write(mcs, reg, val);
71 }
72 
cnf10kb_mcs_flowid_secy_map(struct mcs * mcs,struct secy_mem_map * map,int dir)73 void cnf10kb_mcs_flowid_secy_map(struct mcs *mcs, struct secy_mem_map *map, int dir)
74 {
75 	u64 reg, val;
76 
77 	val = (map->secy & 0x3F) | (map->ctrl_pkt & 0x1) << 6;
78 	if (dir == MCS_RX) {
79 		reg = MCSX_CPM_RX_SLAVE_SECY_MAP_MEMX(map->flow_id);
80 	} else {
81 		reg = MCSX_CPM_TX_SLAVE_SECY_MAP_MEM_0X(map->flow_id);
82 		mcs_reg_write(mcs, reg, map->sci);
83 		val |= (map->sc & 0x3F) << 7;
84 		reg = MCSX_CPM_TX_SLAVE_SECY_MAP_MEM_1X(map->flow_id);
85 	}
86 
87 	mcs_reg_write(mcs, reg, val);
88 }
89 
cnf10kb_mcs_tx_sa_mem_map_write(struct mcs * mcs,struct mcs_tx_sc_sa_map * map)90 void cnf10kb_mcs_tx_sa_mem_map_write(struct mcs *mcs, struct mcs_tx_sc_sa_map *map)
91 {
92 	u64 reg, val;
93 
94 	val = (map->sa_index0 & 0x7F) | (map->sa_index1 & 0x7F) << 7;
95 
96 	reg = MCSX_CPM_TX_SLAVE_SA_MAP_MEM_0X(map->sc_id);
97 	mcs_reg_write(mcs, reg, val);
98 
99 	reg = MCSX_CPM_TX_SLAVE_AUTO_REKEY_ENABLE_0;
100 	val = mcs_reg_read(mcs, reg);
101 
102 	if (map->rekey_ena)
103 		val |= BIT_ULL(map->sc_id);
104 	else
105 		val &= ~BIT_ULL(map->sc_id);
106 
107 	mcs_reg_write(mcs, reg, val);
108 
109 	mcs_reg_write(mcs, MCSX_CPM_TX_SLAVE_SA_INDEX0_VLDX(map->sc_id), map->sa_index0_vld);
110 	mcs_reg_write(mcs, MCSX_CPM_TX_SLAVE_SA_INDEX1_VLDX(map->sc_id), map->sa_index1_vld);
111 
112 	mcs_reg_write(mcs, MCSX_CPM_TX_SLAVE_TX_SA_ACTIVEX(map->sc_id), map->tx_sa_active);
113 }
114 
cnf10kb_mcs_rx_sa_mem_map_write(struct mcs * mcs,struct mcs_rx_sc_sa_map * map)115 void cnf10kb_mcs_rx_sa_mem_map_write(struct mcs *mcs, struct mcs_rx_sc_sa_map *map)
116 {
117 	u64 val, reg;
118 
119 	val = (map->sa_index & 0x7F) | (map->sa_in_use << 7);
120 
121 	reg = MCSX_CPM_RX_SLAVE_SA_MAP_MEMX((4 * map->sc_id) + map->an);
122 	mcs_reg_write(mcs, reg, val);
123 }
124 
mcs_set_force_clk_en(struct mcs * mcs,bool set)125 int mcs_set_force_clk_en(struct mcs *mcs, bool set)
126 {
127 	unsigned long timeout = jiffies + usecs_to_jiffies(2000);
128 	u64 val;
129 
130 	val = mcs_reg_read(mcs, MCSX_MIL_GLOBAL);
131 
132 	if (set) {
133 		val |= BIT_ULL(4);
134 		mcs_reg_write(mcs, MCSX_MIL_GLOBAL, val);
135 
136 		/* Poll till mcsx_mil_ip_gbl_status.mcs_ip_stats_ready value is 1 */
137 		while (!(mcs_reg_read(mcs, MCSX_MIL_IP_GBL_STATUS) & BIT_ULL(0))) {
138 			if (time_after(jiffies, timeout)) {
139 				dev_err(mcs->dev, "MCS set force clk enable failed\n");
140 				break;
141 			}
142 		}
143 	} else {
144 		val &= ~BIT_ULL(4);
145 		mcs_reg_write(mcs, MCSX_MIL_GLOBAL, val);
146 	}
147 
148 	return 0;
149 }
150 
151 /* TX SA interrupt is raised only if autorekey is enabled.
152  * MCS_CPM_TX_SLAVE_SA_MAP_MEM_0X[sc].tx_sa_active bit gets toggled if
153  * one of two SAs mapped to SC gets expired. If tx_sa_active=0 implies
154  * SA in SA_index1 got expired else SA in SA_index0 got expired.
155  */
cnf10kb_mcs_tx_pn_thresh_reached_handler(struct mcs * mcs)156 void cnf10kb_mcs_tx_pn_thresh_reached_handler(struct mcs *mcs)
157 {
158 	struct mcs_intr_event event;
159 	struct rsrc_bmap *sc_bmap;
160 	unsigned long rekey_ena;
161 	u64 val, sa_status;
162 	int sc;
163 
164 	sc_bmap = &mcs->tx.sc;
165 
166 	event.mcs_id = mcs->mcs_id;
167 	event.intr_mask = MCS_CPM_TX_PN_THRESH_REACHED_INT;
168 
169 	rekey_ena = mcs_reg_read(mcs, MCSX_CPM_TX_SLAVE_AUTO_REKEY_ENABLE_0);
170 
171 	for_each_set_bit(sc, sc_bmap->bmap, mcs->hw->sc_entries) {
172 		/* Auto rekey is enable */
173 		if (!test_bit(sc, &rekey_ena))
174 			continue;
175 		sa_status = mcs_reg_read(mcs, MCSX_CPM_TX_SLAVE_TX_SA_ACTIVEX(sc));
176 		/* Check if tx_sa_active status had changed */
177 		if (sa_status == mcs->tx_sa_active[sc])
178 			continue;
179 
180 		/* SA_index0 is expired */
181 		val = mcs_reg_read(mcs, MCSX_CPM_TX_SLAVE_SA_MAP_MEM_0X(sc));
182 		if (sa_status)
183 			event.sa_id = val & 0x7F;
184 		else
185 			event.sa_id = (val >> 7) & 0x7F;
186 
187 		event.pcifunc = mcs->tx.sa2pf_map[event.sa_id];
188 		mcs_add_intr_wq_entry(mcs, &event);
189 	}
190 }
191 
cnf10kb_mcs_tx_pn_wrapped_handler(struct mcs * mcs)192 void cnf10kb_mcs_tx_pn_wrapped_handler(struct mcs *mcs)
193 {
194 	struct mcs_intr_event event = { 0 };
195 	struct rsrc_bmap *sc_bmap;
196 	u64 val;
197 	int sc;
198 
199 	sc_bmap = &mcs->tx.sc;
200 
201 	event.mcs_id = mcs->mcs_id;
202 	event.intr_mask = MCS_CPM_TX_PACKET_XPN_EQ0_INT;
203 
204 	for_each_set_bit(sc, sc_bmap->bmap, mcs->hw->sc_entries) {
205 		val = mcs_reg_read(mcs, MCSX_CPM_TX_SLAVE_SA_MAP_MEM_0X(sc));
206 
207 		if (mcs->tx_sa_active[sc])
208 			/* SA_index1 was used and got expired */
209 			event.sa_id = (val >> 7) & 0x7F;
210 		else
211 			/* SA_index0 was used and got expired */
212 			event.sa_id = val & 0x7F;
213 
214 		event.pcifunc = mcs->tx.sa2pf_map[event.sa_id];
215 		mcs_add_intr_wq_entry(mcs, &event);
216 	}
217 }
218 
cnf10kb_mcs_bbe_intr_handler(struct mcs * mcs,u64 intr,enum mcs_direction dir)219 void cnf10kb_mcs_bbe_intr_handler(struct mcs *mcs, u64 intr,
220 				  enum mcs_direction dir)
221 {
222 	struct mcs_intr_event event = { 0 };
223 	int i;
224 
225 	if (!(intr & MCS_BBE_INT_MASK))
226 		return;
227 
228 	event.mcs_id = mcs->mcs_id;
229 	event.pcifunc = mcs->pf_map[0];
230 
231 	for (i = 0; i < MCS_MAX_BBE_INT; i++) {
232 		if (!(intr & BIT_ULL(i)))
233 			continue;
234 
235 		/* Lower nibble denotes data fifo overflow interrupts and
236 		 * upper nibble indicates policy fifo overflow interrupts.
237 		 */
238 		if (intr & 0xFULL)
239 			event.intr_mask = (dir == MCS_RX) ?
240 					  MCS_BBE_RX_DFIFO_OVERFLOW_INT :
241 					  MCS_BBE_TX_DFIFO_OVERFLOW_INT;
242 		else
243 			event.intr_mask = (dir == MCS_RX) ?
244 					  MCS_BBE_RX_PLFIFO_OVERFLOW_INT :
245 					  MCS_BBE_TX_PLFIFO_OVERFLOW_INT;
246 
247 		/* Notify the lmac_id info which ran into BBE fatal error */
248 		event.lmac_id = i & 0x3ULL;
249 		mcs_add_intr_wq_entry(mcs, &event);
250 	}
251 }
252 
cnf10kb_mcs_pab_intr_handler(struct mcs * mcs,u64 intr,enum mcs_direction dir)253 void cnf10kb_mcs_pab_intr_handler(struct mcs *mcs, u64 intr,
254 				  enum mcs_direction dir)
255 {
256 	struct mcs_intr_event event = { 0 };
257 	int i;
258 
259 	if (!(intr & MCS_PAB_INT_MASK))
260 		return;
261 
262 	event.mcs_id = mcs->mcs_id;
263 	event.pcifunc = mcs->pf_map[0];
264 
265 	for (i = 0; i < MCS_MAX_PAB_INT; i++) {
266 		if (!(intr & BIT_ULL(i)))
267 			continue;
268 
269 		event.intr_mask = (dir == MCS_RX) ?
270 				  MCS_PAB_RX_CHAN_OVERFLOW_INT :
271 				  MCS_PAB_TX_CHAN_OVERFLOW_INT;
272 
273 		/* Notify the lmac_id info which ran into PAB fatal error */
274 		event.lmac_id = i;
275 		mcs_add_intr_wq_entry(mcs, &event);
276 	}
277 }
278