xref: /openbmc/linux/drivers/net/ethernet/marvell/octeontx2/af/mcs_cnf10kb.c (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
1ca7f49ffSGeetha sowjanya // SPDX-License-Identifier: GPL-2.0
2ca7f49ffSGeetha sowjanya /* Marvell MCS driver
3ca7f49ffSGeetha sowjanya  *
4ca7f49ffSGeetha sowjanya  * Copyright (C) 2022 Marvell.
5ca7f49ffSGeetha sowjanya  */
6ca7f49ffSGeetha sowjanya 
7ca7f49ffSGeetha sowjanya #include "mcs.h"
8ca7f49ffSGeetha sowjanya #include "mcs_reg.h"
9ca7f49ffSGeetha sowjanya 
10ca7f49ffSGeetha sowjanya static struct mcs_ops cnf10kb_mcs_ops   = {
11ca7f49ffSGeetha sowjanya 	.mcs_set_hw_capabilities	= cnf10kb_mcs_set_hw_capabilities,
12ca7f49ffSGeetha sowjanya 	.mcs_parser_cfg			= cnf10kb_mcs_parser_cfg,
13cfc14181SGeetha sowjanya 	.mcs_tx_sa_mem_map_write	= cnf10kb_mcs_tx_sa_mem_map_write,
14cfc14181SGeetha sowjanya 	.mcs_rx_sa_mem_map_write	= cnf10kb_mcs_rx_sa_mem_map_write,
15cfc14181SGeetha sowjanya 	.mcs_flowid_secy_map		= cnf10kb_mcs_flowid_secy_map,
16*b8aebeaaSGeetha sowjanya 	.mcs_bbe_intr_handler		= cnf10kb_mcs_bbe_intr_handler,
17*b8aebeaaSGeetha sowjanya 	.mcs_pab_intr_handler		= cnf10kb_mcs_pab_intr_handler,
18ca7f49ffSGeetha sowjanya };
19ca7f49ffSGeetha sowjanya 
cnf10kb_get_mac_ops(void)20ca7f49ffSGeetha sowjanya struct mcs_ops *cnf10kb_get_mac_ops(void)
21ca7f49ffSGeetha sowjanya {
22ca7f49ffSGeetha sowjanya 	return &cnf10kb_mcs_ops;
23ca7f49ffSGeetha sowjanya }
24ca7f49ffSGeetha sowjanya 
cnf10kb_mcs_set_hw_capabilities(struct mcs * mcs)25ca7f49ffSGeetha sowjanya void cnf10kb_mcs_set_hw_capabilities(struct mcs *mcs)
26ca7f49ffSGeetha sowjanya {
27ca7f49ffSGeetha sowjanya 	struct hwinfo *hw = mcs->hw;
28ca7f49ffSGeetha sowjanya 
29ca7f49ffSGeetha sowjanya 	hw->tcam_entries = 64;		/* TCAM entries */
30ca7f49ffSGeetha sowjanya 	hw->secy_entries  = 64;		/* SecY entries */
31ca7f49ffSGeetha sowjanya 	hw->sc_entries = 64;		/* SC CAM entries */
32ca7f49ffSGeetha sowjanya 	hw->sa_entries = 128;		/* SA entries */
33ca7f49ffSGeetha sowjanya 	hw->lmac_cnt = 4;		/* lmacs/ports per mcs block */
34ca7f49ffSGeetha sowjanya 	hw->mcs_x2p_intf = 1;		/* x2p clabration intf */
35ca7f49ffSGeetha sowjanya 	hw->mcs_blks = 7;		/* MCS blocks */
36*b8aebeaaSGeetha sowjanya 	hw->ip_vec = MCS_CNF10KB_INT_VEC_IP; /* IP vector */
37ca7f49ffSGeetha sowjanya }
38ca7f49ffSGeetha sowjanya 
cnf10kb_mcs_parser_cfg(struct mcs * mcs)39ca7f49ffSGeetha sowjanya void cnf10kb_mcs_parser_cfg(struct mcs *mcs)
40ca7f49ffSGeetha sowjanya {
41ca7f49ffSGeetha sowjanya 	u64 reg, val;
42ca7f49ffSGeetha sowjanya 
43ca7f49ffSGeetha sowjanya 	/* VLAN Ctag */
44ca7f49ffSGeetha sowjanya 	val = (0x8100ull & 0xFFFF) | BIT_ULL(20) | BIT_ULL(22);
45ca7f49ffSGeetha sowjanya 
46ca7f49ffSGeetha sowjanya 	reg = MCSX_PEX_RX_SLAVE_CUSTOM_TAGX(0);
47ca7f49ffSGeetha sowjanya 	mcs_reg_write(mcs, reg, val);
48ca7f49ffSGeetha sowjanya 
49ca7f49ffSGeetha sowjanya 	reg = MCSX_PEX_TX_SLAVE_CUSTOM_TAGX(0);
50ca7f49ffSGeetha sowjanya 	mcs_reg_write(mcs, reg, val);
51ca7f49ffSGeetha sowjanya 
52ca7f49ffSGeetha sowjanya 	/* VLAN STag */
53ca7f49ffSGeetha sowjanya 	val = (0x88a8ull & 0xFFFF) | BIT_ULL(20) | BIT_ULL(23);
54ca7f49ffSGeetha sowjanya 
55ca7f49ffSGeetha sowjanya 	/* RX */
56ca7f49ffSGeetha sowjanya 	reg = MCSX_PEX_RX_SLAVE_CUSTOM_TAGX(1);
57ca7f49ffSGeetha sowjanya 	mcs_reg_write(mcs, reg, val);
58ca7f49ffSGeetha sowjanya 
59ca7f49ffSGeetha sowjanya 	/* TX */
60ca7f49ffSGeetha sowjanya 	reg = MCSX_PEX_TX_SLAVE_CUSTOM_TAGX(1);
61ca7f49ffSGeetha sowjanya 	mcs_reg_write(mcs, reg, val);
62ca7f49ffSGeetha sowjanya 
63ca7f49ffSGeetha sowjanya 	/* Enable custom tage 0 and 1 and sectag */
64ca7f49ffSGeetha sowjanya 	val = BIT_ULL(0) | BIT_ULL(1) | BIT_ULL(12);
65ca7f49ffSGeetha sowjanya 
66ca7f49ffSGeetha sowjanya 	reg = MCSX_PEX_RX_SLAVE_ETYPE_ENABLE;
67ca7f49ffSGeetha sowjanya 	mcs_reg_write(mcs, reg, val);
68ca7f49ffSGeetha sowjanya 
69ca7f49ffSGeetha sowjanya 	reg = MCSX_PEX_TX_SLAVE_ETYPE_ENABLE;
70ca7f49ffSGeetha sowjanya 	mcs_reg_write(mcs, reg, val);
71ca7f49ffSGeetha sowjanya }
72cfc14181SGeetha sowjanya 
cnf10kb_mcs_flowid_secy_map(struct mcs * mcs,struct secy_mem_map * map,int dir)73cfc14181SGeetha sowjanya void cnf10kb_mcs_flowid_secy_map(struct mcs *mcs, struct secy_mem_map *map, int dir)
74cfc14181SGeetha sowjanya {
75cfc14181SGeetha sowjanya 	u64 reg, val;
76cfc14181SGeetha sowjanya 
77cfc14181SGeetha sowjanya 	val = (map->secy & 0x3F) | (map->ctrl_pkt & 0x1) << 6;
78cfc14181SGeetha sowjanya 	if (dir == MCS_RX) {
79cfc14181SGeetha sowjanya 		reg = MCSX_CPM_RX_SLAVE_SECY_MAP_MEMX(map->flow_id);
80cfc14181SGeetha sowjanya 	} else {
81cfc14181SGeetha sowjanya 		reg = MCSX_CPM_TX_SLAVE_SECY_MAP_MEM_0X(map->flow_id);
82cfc14181SGeetha sowjanya 		mcs_reg_write(mcs, reg, map->sci);
83cfc14181SGeetha sowjanya 		val |= (map->sc & 0x3F) << 7;
84cfc14181SGeetha sowjanya 		reg = MCSX_CPM_TX_SLAVE_SECY_MAP_MEM_1X(map->flow_id);
85cfc14181SGeetha sowjanya 	}
86cfc14181SGeetha sowjanya 
87cfc14181SGeetha sowjanya 	mcs_reg_write(mcs, reg, val);
88cfc14181SGeetha sowjanya }
89cfc14181SGeetha sowjanya 
cnf10kb_mcs_tx_sa_mem_map_write(struct mcs * mcs,struct mcs_tx_sc_sa_map * map)90cfc14181SGeetha sowjanya void cnf10kb_mcs_tx_sa_mem_map_write(struct mcs *mcs, struct mcs_tx_sc_sa_map *map)
91cfc14181SGeetha sowjanya {
92cfc14181SGeetha sowjanya 	u64 reg, val;
93cfc14181SGeetha sowjanya 
94cfc14181SGeetha sowjanya 	val = (map->sa_index0 & 0x7F) | (map->sa_index1 & 0x7F) << 7;
95cfc14181SGeetha sowjanya 
96cfc14181SGeetha sowjanya 	reg = MCSX_CPM_TX_SLAVE_SA_MAP_MEM_0X(map->sc_id);
97cfc14181SGeetha sowjanya 	mcs_reg_write(mcs, reg, val);
98cfc14181SGeetha sowjanya 
99cfc14181SGeetha sowjanya 	reg = MCSX_CPM_TX_SLAVE_AUTO_REKEY_ENABLE_0;
100cfc14181SGeetha sowjanya 	val = mcs_reg_read(mcs, reg);
1016c635f78SGeetha sowjanya 
1026c635f78SGeetha sowjanya 	if (map->rekey_ena)
103cfc14181SGeetha sowjanya 		val |= BIT_ULL(map->sc_id);
1046c635f78SGeetha sowjanya 	else
1056c635f78SGeetha sowjanya 		val &= ~BIT_ULL(map->sc_id);
1066c635f78SGeetha sowjanya 
107cfc14181SGeetha sowjanya 	mcs_reg_write(mcs, reg, val);
108cfc14181SGeetha sowjanya 
1096c635f78SGeetha sowjanya 	mcs_reg_write(mcs, MCSX_CPM_TX_SLAVE_SA_INDEX0_VLDX(map->sc_id), map->sa_index0_vld);
1106c635f78SGeetha sowjanya 	mcs_reg_write(mcs, MCSX_CPM_TX_SLAVE_SA_INDEX1_VLDX(map->sc_id), map->sa_index1_vld);
111cfc14181SGeetha sowjanya 
112cfc14181SGeetha sowjanya 	mcs_reg_write(mcs, MCSX_CPM_TX_SLAVE_TX_SA_ACTIVEX(map->sc_id), map->tx_sa_active);
113cfc14181SGeetha sowjanya }
114cfc14181SGeetha sowjanya 
cnf10kb_mcs_rx_sa_mem_map_write(struct mcs * mcs,struct mcs_rx_sc_sa_map * map)115cfc14181SGeetha sowjanya void cnf10kb_mcs_rx_sa_mem_map_write(struct mcs *mcs, struct mcs_rx_sc_sa_map *map)
116cfc14181SGeetha sowjanya {
117cfc14181SGeetha sowjanya 	u64 val, reg;
118cfc14181SGeetha sowjanya 
119cfc14181SGeetha sowjanya 	val = (map->sa_index & 0x7F) | (map->sa_in_use << 7);
120cfc14181SGeetha sowjanya 
121cfc14181SGeetha sowjanya 	reg = MCSX_CPM_RX_SLAVE_SA_MAP_MEMX((4 * map->sc_id) + map->an);
122cfc14181SGeetha sowjanya 	mcs_reg_write(mcs, reg, val);
123cfc14181SGeetha sowjanya }
1249312150aSGeetha sowjanya 
mcs_set_force_clk_en(struct mcs * mcs,bool set)1259312150aSGeetha sowjanya int mcs_set_force_clk_en(struct mcs *mcs, bool set)
1269312150aSGeetha sowjanya {
1279312150aSGeetha sowjanya 	unsigned long timeout = jiffies + usecs_to_jiffies(2000);
1289312150aSGeetha sowjanya 	u64 val;
1299312150aSGeetha sowjanya 
1309312150aSGeetha sowjanya 	val = mcs_reg_read(mcs, MCSX_MIL_GLOBAL);
1319312150aSGeetha sowjanya 
1329312150aSGeetha sowjanya 	if (set) {
1339312150aSGeetha sowjanya 		val |= BIT_ULL(4);
1349312150aSGeetha sowjanya 		mcs_reg_write(mcs, MCSX_MIL_GLOBAL, val);
1359312150aSGeetha sowjanya 
1369312150aSGeetha sowjanya 		/* Poll till mcsx_mil_ip_gbl_status.mcs_ip_stats_ready value is 1 */
1379312150aSGeetha sowjanya 		while (!(mcs_reg_read(mcs, MCSX_MIL_IP_GBL_STATUS) & BIT_ULL(0))) {
1389312150aSGeetha sowjanya 			if (time_after(jiffies, timeout)) {
1399312150aSGeetha sowjanya 				dev_err(mcs->dev, "MCS set force clk enable failed\n");
1409312150aSGeetha sowjanya 				break;
1419312150aSGeetha sowjanya 			}
1429312150aSGeetha sowjanya 		}
1439312150aSGeetha sowjanya 	} else {
1449312150aSGeetha sowjanya 		val &= ~BIT_ULL(4);
1459312150aSGeetha sowjanya 		mcs_reg_write(mcs, MCSX_MIL_GLOBAL, val);
1469312150aSGeetha sowjanya 	}
1479312150aSGeetha sowjanya 
1489312150aSGeetha sowjanya 	return 0;
1499312150aSGeetha sowjanya }
1506c635f78SGeetha sowjanya 
1516c635f78SGeetha sowjanya /* TX SA interrupt is raised only if autorekey is enabled.
1526c635f78SGeetha sowjanya  * MCS_CPM_TX_SLAVE_SA_MAP_MEM_0X[sc].tx_sa_active bit gets toggled if
1536c635f78SGeetha sowjanya  * one of two SAs mapped to SC gets expired. If tx_sa_active=0 implies
1546c635f78SGeetha sowjanya  * SA in SA_index1 got expired else SA in SA_index0 got expired.
1556c635f78SGeetha sowjanya  */
cnf10kb_mcs_tx_pn_thresh_reached_handler(struct mcs * mcs)1566c635f78SGeetha sowjanya void cnf10kb_mcs_tx_pn_thresh_reached_handler(struct mcs *mcs)
1576c635f78SGeetha sowjanya {
1586c635f78SGeetha sowjanya 	struct mcs_intr_event event;
1596c635f78SGeetha sowjanya 	struct rsrc_bmap *sc_bmap;
1606c635f78SGeetha sowjanya 	unsigned long rekey_ena;
1616c635f78SGeetha sowjanya 	u64 val, sa_status;
1626c635f78SGeetha sowjanya 	int sc;
1636c635f78SGeetha sowjanya 
1646c635f78SGeetha sowjanya 	sc_bmap = &mcs->tx.sc;
1656c635f78SGeetha sowjanya 
1666c635f78SGeetha sowjanya 	event.mcs_id = mcs->mcs_id;
1676c635f78SGeetha sowjanya 	event.intr_mask = MCS_CPM_TX_PN_THRESH_REACHED_INT;
1686c635f78SGeetha sowjanya 
1696c635f78SGeetha sowjanya 	rekey_ena = mcs_reg_read(mcs, MCSX_CPM_TX_SLAVE_AUTO_REKEY_ENABLE_0);
1706c635f78SGeetha sowjanya 
1716c635f78SGeetha sowjanya 	for_each_set_bit(sc, sc_bmap->bmap, mcs->hw->sc_entries) {
1726c635f78SGeetha sowjanya 		/* Auto rekey is enable */
1736c635f78SGeetha sowjanya 		if (!test_bit(sc, &rekey_ena))
1746c635f78SGeetha sowjanya 			continue;
1756c635f78SGeetha sowjanya 		sa_status = mcs_reg_read(mcs, MCSX_CPM_TX_SLAVE_TX_SA_ACTIVEX(sc));
1766c635f78SGeetha sowjanya 		/* Check if tx_sa_active status had changed */
1776c635f78SGeetha sowjanya 		if (sa_status == mcs->tx_sa_active[sc])
1786c635f78SGeetha sowjanya 			continue;
1796c635f78SGeetha sowjanya 
1806c635f78SGeetha sowjanya 		/* SA_index0 is expired */
1816c635f78SGeetha sowjanya 		val = mcs_reg_read(mcs, MCSX_CPM_TX_SLAVE_SA_MAP_MEM_0X(sc));
1826c635f78SGeetha sowjanya 		if (sa_status)
1836c635f78SGeetha sowjanya 			event.sa_id = val & 0x7F;
1846c635f78SGeetha sowjanya 		else
1856c635f78SGeetha sowjanya 			event.sa_id = (val >> 7) & 0x7F;
1866c635f78SGeetha sowjanya 
1876c635f78SGeetha sowjanya 		event.pcifunc = mcs->tx.sa2pf_map[event.sa_id];
1886c635f78SGeetha sowjanya 		mcs_add_intr_wq_entry(mcs, &event);
1896c635f78SGeetha sowjanya 	}
1906c635f78SGeetha sowjanya }
1916c635f78SGeetha sowjanya 
cnf10kb_mcs_tx_pn_wrapped_handler(struct mcs * mcs)1926c635f78SGeetha sowjanya void cnf10kb_mcs_tx_pn_wrapped_handler(struct mcs *mcs)
1936c635f78SGeetha sowjanya {
1946c635f78SGeetha sowjanya 	struct mcs_intr_event event = { 0 };
1956c635f78SGeetha sowjanya 	struct rsrc_bmap *sc_bmap;
1966c635f78SGeetha sowjanya 	u64 val;
1976c635f78SGeetha sowjanya 	int sc;
1986c635f78SGeetha sowjanya 
1996c635f78SGeetha sowjanya 	sc_bmap = &mcs->tx.sc;
2006c635f78SGeetha sowjanya 
2016c635f78SGeetha sowjanya 	event.mcs_id = mcs->mcs_id;
2026c635f78SGeetha sowjanya 	event.intr_mask = MCS_CPM_TX_PACKET_XPN_EQ0_INT;
2036c635f78SGeetha sowjanya 
2046c635f78SGeetha sowjanya 	for_each_set_bit(sc, sc_bmap->bmap, mcs->hw->sc_entries) {
2056c635f78SGeetha sowjanya 		val = mcs_reg_read(mcs, MCSX_CPM_TX_SLAVE_SA_MAP_MEM_0X(sc));
2066c635f78SGeetha sowjanya 
2076c635f78SGeetha sowjanya 		if (mcs->tx_sa_active[sc])
2086c635f78SGeetha sowjanya 			/* SA_index1 was used and got expired */
2096c635f78SGeetha sowjanya 			event.sa_id = (val >> 7) & 0x7F;
2106c635f78SGeetha sowjanya 		else
2116c635f78SGeetha sowjanya 			/* SA_index0 was used and got expired */
2126c635f78SGeetha sowjanya 			event.sa_id = val & 0x7F;
2136c635f78SGeetha sowjanya 
2146c635f78SGeetha sowjanya 		event.pcifunc = mcs->tx.sa2pf_map[event.sa_id];
2156c635f78SGeetha sowjanya 		mcs_add_intr_wq_entry(mcs, &event);
2166c635f78SGeetha sowjanya 	}
2176c635f78SGeetha sowjanya }
218*b8aebeaaSGeetha sowjanya 
cnf10kb_mcs_bbe_intr_handler(struct mcs * mcs,u64 intr,enum mcs_direction dir)219*b8aebeaaSGeetha sowjanya void cnf10kb_mcs_bbe_intr_handler(struct mcs *mcs, u64 intr,
220*b8aebeaaSGeetha sowjanya 				  enum mcs_direction dir)
221*b8aebeaaSGeetha sowjanya {
222*b8aebeaaSGeetha sowjanya 	struct mcs_intr_event event = { 0 };
223*b8aebeaaSGeetha sowjanya 	int i;
224*b8aebeaaSGeetha sowjanya 
225*b8aebeaaSGeetha sowjanya 	if (!(intr & MCS_BBE_INT_MASK))
226*b8aebeaaSGeetha sowjanya 		return;
227*b8aebeaaSGeetha sowjanya 
228*b8aebeaaSGeetha sowjanya 	event.mcs_id = mcs->mcs_id;
229*b8aebeaaSGeetha sowjanya 	event.pcifunc = mcs->pf_map[0];
230*b8aebeaaSGeetha sowjanya 
231*b8aebeaaSGeetha sowjanya 	for (i = 0; i < MCS_MAX_BBE_INT; i++) {
232*b8aebeaaSGeetha sowjanya 		if (!(intr & BIT_ULL(i)))
233*b8aebeaaSGeetha sowjanya 			continue;
234*b8aebeaaSGeetha sowjanya 
235*b8aebeaaSGeetha sowjanya 		/* Lower nibble denotes data fifo overflow interrupts and
236*b8aebeaaSGeetha sowjanya 		 * upper nibble indicates policy fifo overflow interrupts.
237*b8aebeaaSGeetha sowjanya 		 */
238*b8aebeaaSGeetha sowjanya 		if (intr & 0xFULL)
239*b8aebeaaSGeetha sowjanya 			event.intr_mask = (dir == MCS_RX) ?
240*b8aebeaaSGeetha sowjanya 					  MCS_BBE_RX_DFIFO_OVERFLOW_INT :
241*b8aebeaaSGeetha sowjanya 					  MCS_BBE_TX_DFIFO_OVERFLOW_INT;
242*b8aebeaaSGeetha sowjanya 		else
243*b8aebeaaSGeetha sowjanya 			event.intr_mask = (dir == MCS_RX) ?
244*b8aebeaaSGeetha sowjanya 					  MCS_BBE_RX_PLFIFO_OVERFLOW_INT :
245*b8aebeaaSGeetha sowjanya 					  MCS_BBE_TX_PLFIFO_OVERFLOW_INT;
246*b8aebeaaSGeetha sowjanya 
247*b8aebeaaSGeetha sowjanya 		/* Notify the lmac_id info which ran into BBE fatal error */
248*b8aebeaaSGeetha sowjanya 		event.lmac_id = i & 0x3ULL;
249*b8aebeaaSGeetha sowjanya 		mcs_add_intr_wq_entry(mcs, &event);
250*b8aebeaaSGeetha sowjanya 	}
251*b8aebeaaSGeetha sowjanya }
252*b8aebeaaSGeetha sowjanya 
cnf10kb_mcs_pab_intr_handler(struct mcs * mcs,u64 intr,enum mcs_direction dir)253*b8aebeaaSGeetha sowjanya void cnf10kb_mcs_pab_intr_handler(struct mcs *mcs, u64 intr,
254*b8aebeaaSGeetha sowjanya 				  enum mcs_direction dir)
255*b8aebeaaSGeetha sowjanya {
256*b8aebeaaSGeetha sowjanya 	struct mcs_intr_event event = { 0 };
257*b8aebeaaSGeetha sowjanya 	int i;
258*b8aebeaaSGeetha sowjanya 
259*b8aebeaaSGeetha sowjanya 	if (!(intr & MCS_PAB_INT_MASK))
260*b8aebeaaSGeetha sowjanya 		return;
261*b8aebeaaSGeetha sowjanya 
262*b8aebeaaSGeetha sowjanya 	event.mcs_id = mcs->mcs_id;
263*b8aebeaaSGeetha sowjanya 	event.pcifunc = mcs->pf_map[0];
264*b8aebeaaSGeetha sowjanya 
265*b8aebeaaSGeetha sowjanya 	for (i = 0; i < MCS_MAX_PAB_INT; i++) {
266*b8aebeaaSGeetha sowjanya 		if (!(intr & BIT_ULL(i)))
267*b8aebeaaSGeetha sowjanya 			continue;
268*b8aebeaaSGeetha sowjanya 
269*b8aebeaaSGeetha sowjanya 		event.intr_mask = (dir == MCS_RX) ?
270*b8aebeaaSGeetha sowjanya 				  MCS_PAB_RX_CHAN_OVERFLOW_INT :
271*b8aebeaaSGeetha sowjanya 				  MCS_PAB_TX_CHAN_OVERFLOW_INT;
272*b8aebeaaSGeetha sowjanya 
273*b8aebeaaSGeetha sowjanya 		/* Notify the lmac_id info which ran into PAB fatal error */
274*b8aebeaaSGeetha sowjanya 		event.lmac_id = i;
275*b8aebeaaSGeetha sowjanya 		mcs_add_intr_wq_entry(mcs, &event);
276*b8aebeaaSGeetha sowjanya 	}
277*b8aebeaaSGeetha sowjanya }
278