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