Skip to content

Commit e9b4ece

Browse files
danish-tidavem330
authored andcommitted
net: ti: icssg-prueth: Add Firmware config and classification APIs.
Add icssg_config.h / .c and icssg_classifier.c files. These are firmware configuration and classification related files. These will be used by ICSSG ethernet driver. Reviewed-by: Andrew Lunn <[email protected]> Signed-off-by: MD Danish Anwar <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent b6ba775 commit e9b4ece

File tree

4 files changed

+1032
-0
lines changed

4 files changed

+1032
-0
lines changed
Lines changed: 367 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,367 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/* Texas Instruments ICSSG Ethernet Driver
3+
*
4+
* Copyright (C) 2018-2022 Texas Instruments Incorporated - https://www.ti.com/
5+
*
6+
*/
7+
8+
#include <linux/etherdevice.h>
9+
#include <linux/types.h>
10+
#include <linux/regmap.h>
11+
12+
#include "icssg_prueth.h"
13+
14+
#define ICSSG_NUM_CLASSIFIERS 16
15+
#define ICSSG_NUM_FT1_SLOTS 8
16+
#define ICSSG_NUM_FT3_SLOTS 16
17+
18+
#define ICSSG_NUM_CLASSIFIERS_IN_USE 5
19+
20+
/* Filter 1 - FT1 */
21+
#define FT1_NUM_SLOTS 8
22+
#define FT1_SLOT_SIZE 0x10 /* bytes */
23+
24+
/* offsets from FT1 slot base i.e. slot 1 start */
25+
#define FT1_DA0 0x0
26+
#define FT1_DA1 0x4
27+
#define FT1_DA0_MASK 0x8
28+
#define FT1_DA1_MASK 0xc
29+
30+
#define FT1_N_REG(slize, n, reg) \
31+
(offs[slice].ft1_slot_base + FT1_SLOT_SIZE * (n) + (reg))
32+
33+
#define FT1_LEN_MASK GENMASK(19, 16)
34+
#define FT1_LEN_SHIFT 16
35+
#define FT1_LEN(len) (((len) << FT1_LEN_SHIFT) & FT1_LEN_MASK)
36+
#define FT1_START_MASK GENMASK(14, 0)
37+
#define FT1_START(start) ((start) & FT1_START_MASK)
38+
#define FT1_MATCH_SLOT(n) (GENMASK(23, 16) & (BIT(n) << 16))
39+
40+
/* FT1 config type */
41+
enum ft1_cfg_type {
42+
FT1_CFG_TYPE_DISABLED = 0,
43+
FT1_CFG_TYPE_EQ,
44+
FT1_CFG_TYPE_GT,
45+
FT1_CFG_TYPE_LT,
46+
};
47+
48+
#define FT1_CFG_SHIFT(n) (2 * (n))
49+
#define FT1_CFG_MASK(n) (0x3 << FT1_CFG_SHIFT((n)))
50+
51+
/* Filter 3 - FT3 */
52+
#define FT3_NUM_SLOTS 16
53+
#define FT3_SLOT_SIZE 0x20 /* bytes */
54+
55+
/* offsets from FT3 slot n's base */
56+
#define FT3_START 0
57+
#define FT3_START_AUTO 0x4
58+
#define FT3_START_OFFSET 0x8
59+
#define FT3_JUMP_OFFSET 0xc
60+
#define FT3_LEN 0x10
61+
#define FT3_CFG 0x14
62+
#define FT3_T 0x18
63+
#define FT3_T_MASK 0x1c
64+
65+
#define FT3_N_REG(slize, n, reg) \
66+
(offs[slice].ft3_slot_base + FT3_SLOT_SIZE * (n) + (reg))
67+
68+
/* offsets from rx_class n's base */
69+
#define RX_CLASS_AND_EN 0
70+
#define RX_CLASS_OR_EN 0x4
71+
#define RX_CLASS_NUM_SLOTS 16
72+
#define RX_CLASS_EN_SIZE 0x8 /* bytes */
73+
74+
#define RX_CLASS_N_REG(slice, n, reg) \
75+
(offs[slice].rx_class_base + RX_CLASS_EN_SIZE * (n) + (reg))
76+
77+
/* RX Class Gates */
78+
#define RX_CLASS_GATES_SIZE 0x4 /* bytes */
79+
80+
#define RX_CLASS_GATES_N_REG(slice, n) \
81+
(offs[slice].rx_class_gates_base + RX_CLASS_GATES_SIZE * (n))
82+
83+
#define RX_CLASS_GATES_ALLOW_MASK BIT(6)
84+
#define RX_CLASS_GATES_RAW_MASK BIT(5)
85+
#define RX_CLASS_GATES_PHASE_MASK BIT(4)
86+
87+
/* RX Class traffic data matching bits */
88+
#define RX_CLASS_FT_UC BIT(31)
89+
#define RX_CLASS_FT_MC BIT(30)
90+
#define RX_CLASS_FT_BC BIT(29)
91+
#define RX_CLASS_FT_FW BIT(28)
92+
#define RX_CLASS_FT_RCV BIT(27)
93+
#define RX_CLASS_FT_VLAN BIT(26)
94+
#define RX_CLASS_FT_DA_P BIT(25)
95+
#define RX_CLASS_FT_DA_I BIT(24)
96+
#define RX_CLASS_FT_FT1_MATCH_MASK GENMASK(23, 16)
97+
#define RX_CLASS_FT_FT1_MATCH_SHIFT 16
98+
#define RX_CLASS_FT_FT3_MATCH_MASK GENMASK(15, 0)
99+
#define RX_CLASS_FT_FT3_MATCH_SHIFT 0
100+
101+
#define RX_CLASS_FT_FT1_MATCH(slot) \
102+
((BIT(slot) << RX_CLASS_FT_FT1_MATCH_SHIFT) & \
103+
RX_CLASS_FT_FT1_MATCH_MASK)
104+
105+
/* RX class type */
106+
enum rx_class_sel_type {
107+
RX_CLASS_SEL_TYPE_OR = 0,
108+
RX_CLASS_SEL_TYPE_AND = 1,
109+
RX_CLASS_SEL_TYPE_OR_AND_AND = 2,
110+
RX_CLASS_SEL_TYPE_OR_OR_AND = 3,
111+
};
112+
113+
#define FT1_CFG_SHIFT(n) (2 * (n))
114+
#define FT1_CFG_MASK(n) (0x3 << FT1_CFG_SHIFT((n)))
115+
116+
#define RX_CLASS_SEL_SHIFT(n) (2 * (n))
117+
#define RX_CLASS_SEL_MASK(n) (0x3 << RX_CLASS_SEL_SHIFT((n)))
118+
119+
#define ICSSG_CFG_OFFSET 0
120+
#define MAC_INTERFACE_0 0x18
121+
#define MAC_INTERFACE_1 0x1c
122+
123+
#define ICSSG_CFG_RX_L2_G_EN BIT(2)
124+
125+
/* These are register offsets per PRU */
126+
struct miig_rt_offsets {
127+
u32 mac0;
128+
u32 mac1;
129+
u32 ft1_start_len;
130+
u32 ft1_cfg;
131+
u32 ft1_slot_base;
132+
u32 ft3_slot_base;
133+
u32 ft3_p_base;
134+
u32 ft_rx_ptr;
135+
u32 rx_class_base;
136+
u32 rx_class_cfg1;
137+
u32 rx_class_cfg2;
138+
u32 rx_class_gates_base;
139+
u32 rx_green;
140+
u32 rx_rate_cfg_base;
141+
u32 rx_rate_src_sel0;
142+
u32 rx_rate_src_sel1;
143+
u32 tx_rate_cfg_base;
144+
u32 stat_base;
145+
u32 tx_hsr_tag;
146+
u32 tx_hsr_seq;
147+
u32 tx_vlan_type;
148+
u32 tx_vlan_ins;
149+
};
150+
151+
/* These are the offset values for miig_rt_offsets registers */
152+
static const struct miig_rt_offsets offs[] = {
153+
/* PRU0 */
154+
{
155+
0x8,
156+
0xc,
157+
0x80,
158+
0x84,
159+
0x88,
160+
0x108,
161+
0x308,
162+
0x408,
163+
0x40c,
164+
0x48c,
165+
0x490,
166+
0x494,
167+
0x4d4,
168+
0x4e4,
169+
0x504,
170+
0x508,
171+
0x50c,
172+
0x54c,
173+
0x63c,
174+
0x640,
175+
0x644,
176+
0x648,
177+
},
178+
/* PRU1 */
179+
{
180+
0x10,
181+
0x14,
182+
0x64c,
183+
0x650,
184+
0x654,
185+
0x6d4,
186+
0x8d4,
187+
0x9d4,
188+
0x9d8,
189+
0xa58,
190+
0xa5c,
191+
0xa60,
192+
0xaa0,
193+
0xab0,
194+
0xad0,
195+
0xad4,
196+
0xad8,
197+
0xb18,
198+
0xc08,
199+
0xc0c,
200+
0xc10,
201+
0xc14,
202+
},
203+
};
204+
205+
static void rx_class_ft1_set_start_len(struct regmap *miig_rt, int slice,
206+
u16 start, u8 len)
207+
{
208+
u32 offset, val;
209+
210+
offset = offs[slice].ft1_start_len;
211+
val = FT1_LEN(len) | FT1_START(start);
212+
regmap_write(miig_rt, offset, val);
213+
}
214+
215+
static void rx_class_ft1_set_da(struct regmap *miig_rt, int slice,
216+
int n, const u8 *addr)
217+
{
218+
u32 offset;
219+
220+
offset = FT1_N_REG(slice, n, FT1_DA0);
221+
regmap_write(miig_rt, offset, (u32)(addr[0] | addr[1] << 8 |
222+
addr[2] << 16 | addr[3] << 24));
223+
offset = FT1_N_REG(slice, n, FT1_DA1);
224+
regmap_write(miig_rt, offset, (u32)(addr[4] | addr[5] << 8));
225+
}
226+
227+
static void rx_class_ft1_set_da_mask(struct regmap *miig_rt, int slice,
228+
int n, const u8 *addr)
229+
{
230+
u32 offset;
231+
232+
offset = FT1_N_REG(slice, n, FT1_DA0_MASK);
233+
regmap_write(miig_rt, offset, (u32)(addr[0] | addr[1] << 8 |
234+
addr[2] << 16 | addr[3] << 24));
235+
offset = FT1_N_REG(slice, n, FT1_DA1_MASK);
236+
regmap_write(miig_rt, offset, (u32)(addr[4] | addr[5] << 8));
237+
}
238+
239+
static void rx_class_ft1_cfg_set_type(struct regmap *miig_rt, int slice, int n,
240+
enum ft1_cfg_type type)
241+
{
242+
u32 offset;
243+
244+
offset = offs[slice].ft1_cfg;
245+
regmap_update_bits(miig_rt, offset, FT1_CFG_MASK(n),
246+
type << FT1_CFG_SHIFT(n));
247+
}
248+
249+
static void rx_class_sel_set_type(struct regmap *miig_rt, int slice, int n,
250+
enum rx_class_sel_type type)
251+
{
252+
u32 offset;
253+
254+
offset = offs[slice].rx_class_cfg1;
255+
regmap_update_bits(miig_rt, offset, RX_CLASS_SEL_MASK(n),
256+
type << RX_CLASS_SEL_SHIFT(n));
257+
}
258+
259+
static void rx_class_set_and(struct regmap *miig_rt, int slice, int n,
260+
u32 data)
261+
{
262+
u32 offset;
263+
264+
offset = RX_CLASS_N_REG(slice, n, RX_CLASS_AND_EN);
265+
regmap_write(miig_rt, offset, data);
266+
}
267+
268+
static void rx_class_set_or(struct regmap *miig_rt, int slice, int n,
269+
u32 data)
270+
{
271+
u32 offset;
272+
273+
offset = RX_CLASS_N_REG(slice, n, RX_CLASS_OR_EN);
274+
regmap_write(miig_rt, offset, data);
275+
}
276+
277+
void icssg_class_set_host_mac_addr(struct regmap *miig_rt, const u8 *mac)
278+
{
279+
regmap_write(miig_rt, MAC_INTERFACE_0, (u32)(mac[0] | mac[1] << 8 |
280+
mac[2] << 16 | mac[3] << 24));
281+
regmap_write(miig_rt, MAC_INTERFACE_1, (u32)(mac[4] | mac[5] << 8));
282+
}
283+
284+
void icssg_class_set_mac_addr(struct regmap *miig_rt, int slice, u8 *mac)
285+
{
286+
regmap_write(miig_rt, offs[slice].mac0, (u32)(mac[0] | mac[1] << 8 |
287+
mac[2] << 16 | mac[3] << 24));
288+
regmap_write(miig_rt, offs[slice].mac1, (u32)(mac[4] | mac[5] << 8));
289+
}
290+
291+
/* disable all RX traffic */
292+
void icssg_class_disable(struct regmap *miig_rt, int slice)
293+
{
294+
u32 data, offset;
295+
int n;
296+
297+
/* Enable RX_L2_G */
298+
regmap_update_bits(miig_rt, ICSSG_CFG_OFFSET, ICSSG_CFG_RX_L2_G_EN,
299+
ICSSG_CFG_RX_L2_G_EN);
300+
301+
for (n = 0; n < ICSSG_NUM_CLASSIFIERS; n++) {
302+
/* AND_EN = 0 */
303+
rx_class_set_and(miig_rt, slice, n, 0);
304+
/* OR_EN = 0 */
305+
rx_class_set_or(miig_rt, slice, n, 0);
306+
307+
/* set CFG1 to OR */
308+
rx_class_sel_set_type(miig_rt, slice, n, RX_CLASS_SEL_TYPE_OR);
309+
310+
/* configure gate */
311+
offset = RX_CLASS_GATES_N_REG(slice, n);
312+
regmap_read(miig_rt, offset, &data);
313+
/* clear class_raw so we go through filters */
314+
data &= ~RX_CLASS_GATES_RAW_MASK;
315+
/* set allow and phase mask */
316+
data |= RX_CLASS_GATES_ALLOW_MASK | RX_CLASS_GATES_PHASE_MASK;
317+
regmap_write(miig_rt, offset, data);
318+
}
319+
320+
/* FT1 Disabled */
321+
for (n = 0; n < ICSSG_NUM_FT1_SLOTS; n++) {
322+
const u8 addr[] = { 0, 0, 0, 0, 0, 0, };
323+
324+
rx_class_ft1_cfg_set_type(miig_rt, slice, n,
325+
FT1_CFG_TYPE_DISABLED);
326+
rx_class_ft1_set_da(miig_rt, slice, n, addr);
327+
rx_class_ft1_set_da_mask(miig_rt, slice, n, addr);
328+
}
329+
330+
/* clear CFG2 */
331+
regmap_write(miig_rt, offs[slice].rx_class_cfg2, 0);
332+
}
333+
334+
void icssg_class_default(struct regmap *miig_rt, int slice, bool allmulti)
335+
{
336+
u32 data;
337+
338+
/* defaults */
339+
icssg_class_disable(miig_rt, slice);
340+
341+
/* Setup Classifier */
342+
/* match on Broadcast or MAC_PRU address */
343+
data = RX_CLASS_FT_BC | RX_CLASS_FT_DA_P;
344+
345+
/* multicast */
346+
if (allmulti)
347+
data |= RX_CLASS_FT_MC;
348+
349+
rx_class_set_or(miig_rt, slice, 0, data);
350+
351+
/* set CFG1 for OR_OR_AND for classifier */
352+
rx_class_sel_set_type(miig_rt, slice, 0, RX_CLASS_SEL_TYPE_OR_OR_AND);
353+
354+
/* clear CFG2 */
355+
regmap_write(miig_rt, offs[slice].rx_class_cfg2, 0);
356+
}
357+
358+
/* required for SAV check */
359+
void icssg_ft1_set_mac_addr(struct regmap *miig_rt, int slice, u8 *mac_addr)
360+
{
361+
const u8 mask_addr[] = { 0, 0, 0, 0, 0, 0, };
362+
363+
rx_class_ft1_set_start_len(miig_rt, slice, 0, 6);
364+
rx_class_ft1_set_da(miig_rt, slice, 0, mac_addr);
365+
rx_class_ft1_set_da_mask(miig_rt, slice, 0, mask_addr);
366+
rx_class_ft1_cfg_set_type(miig_rt, slice, 0, FT1_CFG_TYPE_EQ);
367+
}

0 commit comments

Comments
 (0)