1
2
3
4#include "sja1105.h"
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98#define SJA1105_SIZE_DYN_CMD 4
99
100#define SJA1105ET_SIZE_VL_LOOKUP_DYN_CMD \
101 SJA1105_SIZE_DYN_CMD
102
103#define SJA1105PQRS_SIZE_VL_LOOKUP_DYN_CMD \
104 (SJA1105_SIZE_DYN_CMD + SJA1105_SIZE_VL_LOOKUP_ENTRY)
105
106#define SJA1105ET_SIZE_MAC_CONFIG_DYN_ENTRY \
107 SJA1105_SIZE_DYN_CMD
108
109#define SJA1105ET_SIZE_L2_LOOKUP_DYN_CMD \
110 (SJA1105_SIZE_DYN_CMD + SJA1105ET_SIZE_L2_LOOKUP_ENTRY)
111
112#define SJA1105PQRS_SIZE_L2_LOOKUP_DYN_CMD \
113 (SJA1105_SIZE_DYN_CMD + SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY)
114
115#define SJA1105_SIZE_VLAN_LOOKUP_DYN_CMD \
116 (SJA1105_SIZE_DYN_CMD + 4 + SJA1105_SIZE_VLAN_LOOKUP_ENTRY)
117
118#define SJA1105_SIZE_L2_FORWARDING_DYN_CMD \
119 (SJA1105_SIZE_DYN_CMD + SJA1105_SIZE_L2_FORWARDING_ENTRY)
120
121#define SJA1105ET_SIZE_MAC_CONFIG_DYN_CMD \
122 (SJA1105_SIZE_DYN_CMD + SJA1105ET_SIZE_MAC_CONFIG_DYN_ENTRY)
123
124#define SJA1105PQRS_SIZE_MAC_CONFIG_DYN_CMD \
125 (SJA1105_SIZE_DYN_CMD + SJA1105PQRS_SIZE_MAC_CONFIG_ENTRY)
126
127#define SJA1105ET_SIZE_L2_LOOKUP_PARAMS_DYN_CMD \
128 SJA1105_SIZE_DYN_CMD
129
130#define SJA1105PQRS_SIZE_L2_LOOKUP_PARAMS_DYN_CMD \
131 (SJA1105_SIZE_DYN_CMD + SJA1105PQRS_SIZE_L2_LOOKUP_PARAMS_ENTRY)
132
133#define SJA1105ET_SIZE_GENERAL_PARAMS_DYN_CMD \
134 SJA1105_SIZE_DYN_CMD
135
136#define SJA1105PQRS_SIZE_GENERAL_PARAMS_DYN_CMD \
137 (SJA1105_SIZE_DYN_CMD + SJA1105PQRS_SIZE_GENERAL_PARAMS_ENTRY)
138
139#define SJA1105PQRS_SIZE_AVB_PARAMS_DYN_CMD \
140 (SJA1105_SIZE_DYN_CMD + SJA1105PQRS_SIZE_AVB_PARAMS_ENTRY)
141
142#define SJA1105_SIZE_RETAGGING_DYN_CMD \
143 (SJA1105_SIZE_DYN_CMD + SJA1105_SIZE_RETAGGING_ENTRY)
144
145#define SJA1105ET_SIZE_CBS_DYN_CMD \
146 (SJA1105_SIZE_DYN_CMD + SJA1105ET_SIZE_CBS_ENTRY)
147
148#define SJA1105PQRS_SIZE_CBS_DYN_CMD \
149 (SJA1105_SIZE_DYN_CMD + SJA1105PQRS_SIZE_CBS_ENTRY)
150
151#define SJA1105_MAX_DYN_CMD_SIZE \
152 SJA1105PQRS_SIZE_GENERAL_PARAMS_DYN_CMD
153
154struct sja1105_dyn_cmd {
155 bool search;
156 u64 valid;
157 u64 rdwrset;
158 u64 errors;
159 u64 valident;
160 u64 index;
161};
162
163enum sja1105_hostcmd {
164 SJA1105_HOSTCMD_SEARCH = 1,
165 SJA1105_HOSTCMD_READ = 2,
166 SJA1105_HOSTCMD_WRITE = 3,
167 SJA1105_HOSTCMD_INVALIDATE = 4,
168};
169
170static void
171sja1105_vl_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
172 enum packing_op op)
173{
174 const int size = SJA1105_SIZE_DYN_CMD;
175
176 sja1105_packing(buf, &cmd->valid, 31, 31, size, op);
177 sja1105_packing(buf, &cmd->errors, 30, 30, size, op);
178 sja1105_packing(buf, &cmd->rdwrset, 29, 29, size, op);
179 sja1105_packing(buf, &cmd->index, 9, 0, size, op);
180}
181
182static size_t sja1105et_vl_lookup_entry_packing(void *buf, void *entry_ptr,
183 enum packing_op op)
184{
185 struct sja1105_vl_lookup_entry *entry = entry_ptr;
186 const int size = SJA1105ET_SIZE_VL_LOOKUP_DYN_CMD;
187
188 sja1105_packing(buf, &entry->egrmirr, 21, 17, size, op);
189 sja1105_packing(buf, &entry->ingrmirr, 16, 16, size, op);
190 return size;
191}
192
193static void
194sja1105pqrs_l2_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
195 enum packing_op op)
196{
197 u8 *p = buf + SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY;
198 const int size = SJA1105_SIZE_DYN_CMD;
199 u64 hostcmd;
200
201 sja1105_packing(p, &cmd->valid, 31, 31, size, op);
202 sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op);
203 sja1105_packing(p, &cmd->errors, 29, 29, size, op);
204 sja1105_packing(p, &cmd->valident, 27, 27, size, op);
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227 if (cmd->rdwrset == SPI_READ) {
228 if (cmd->search)
229 hostcmd = SJA1105_HOSTCMD_SEARCH;
230 else
231 hostcmd = SJA1105_HOSTCMD_READ;
232 } else {
233
234 if (cmd->valident)
235 hostcmd = SJA1105_HOSTCMD_WRITE;
236 else
237 hostcmd = SJA1105_HOSTCMD_INVALIDATE;
238 }
239 sja1105_packing(p, &hostcmd, 25, 23, size, op);
240
241
242
243
244
245
246
247
248
249 sja1105_packing(buf, &cmd->index, 15, 6,
250 SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY, op);
251}
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298static size_t
299sja1105pqrs_dyn_l2_lookup_entry_packing(void *buf, void *entry_ptr,
300 enum packing_op op)
301{
302 struct sja1105_l2_lookup_entry *entry = entry_ptr;
303 u8 *cmd = buf + SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY;
304 const int size = SJA1105_SIZE_DYN_CMD;
305
306 sja1105_packing(cmd, &entry->lockeds, 28, 28, size, op);
307
308 return sja1105pqrs_l2_lookup_entry_packing(buf, entry_ptr, op);
309}
310
311static void
312sja1105et_l2_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
313 enum packing_op op)
314{
315 u8 *p = buf + SJA1105ET_SIZE_L2_LOOKUP_ENTRY;
316 const int size = SJA1105_SIZE_DYN_CMD;
317
318 sja1105_packing(p, &cmd->valid, 31, 31, size, op);
319 sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op);
320 sja1105_packing(p, &cmd->errors, 29, 29, size, op);
321 sja1105_packing(p, &cmd->valident, 27, 27, size, op);
322
323 sja1105_packing(buf, &cmd->index, 29, 20,
324 SJA1105ET_SIZE_L2_LOOKUP_ENTRY, op);
325}
326
327static size_t sja1105et_dyn_l2_lookup_entry_packing(void *buf, void *entry_ptr,
328 enum packing_op op)
329{
330 struct sja1105_l2_lookup_entry *entry = entry_ptr;
331 u8 *cmd = buf + SJA1105ET_SIZE_L2_LOOKUP_ENTRY;
332 const int size = SJA1105_SIZE_DYN_CMD;
333
334 sja1105_packing(cmd, &entry->lockeds, 28, 28, size, op);
335
336 return sja1105et_l2_lookup_entry_packing(buf, entry_ptr, op);
337}
338
339static void
340sja1105et_mgmt_route_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
341 enum packing_op op)
342{
343 u8 *p = buf + SJA1105ET_SIZE_L2_LOOKUP_ENTRY;
344 u64 mgmtroute = 1;
345
346 sja1105et_l2_lookup_cmd_packing(buf, cmd, op);
347 if (op == PACK)
348 sja1105_pack(p, &mgmtroute, 26, 26, SJA1105_SIZE_DYN_CMD);
349}
350
351static size_t sja1105et_mgmt_route_entry_packing(void *buf, void *entry_ptr,
352 enum packing_op op)
353{
354 struct sja1105_mgmt_entry *entry = entry_ptr;
355 const size_t size = SJA1105ET_SIZE_L2_LOOKUP_ENTRY;
356
357
358
359
360
361
362
363 sja1105_packing(buf, &entry->tsreg, 85, 85, size, op);
364 sja1105_packing(buf, &entry->takets, 84, 84, size, op);
365 sja1105_packing(buf, &entry->macaddr, 83, 36, size, op);
366 sja1105_packing(buf, &entry->destports, 35, 31, size, op);
367 sja1105_packing(buf, &entry->enfport, 30, 30, size, op);
368 return size;
369}
370
371static void
372sja1105pqrs_mgmt_route_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
373 enum packing_op op)
374{
375 u8 *p = buf + SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY;
376 u64 mgmtroute = 1;
377
378 sja1105pqrs_l2_lookup_cmd_packing(buf, cmd, op);
379 if (op == PACK)
380 sja1105_pack(p, &mgmtroute, 26, 26, SJA1105_SIZE_DYN_CMD);
381}
382
383static size_t sja1105pqrs_mgmt_route_entry_packing(void *buf, void *entry_ptr,
384 enum packing_op op)
385{
386 const size_t size = SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY;
387 struct sja1105_mgmt_entry *entry = entry_ptr;
388
389
390
391
392
393 sja1105_packing(buf, &entry->tsreg, 71, 71, size, op);
394 sja1105_packing(buf, &entry->takets, 70, 70, size, op);
395 sja1105_packing(buf, &entry->macaddr, 69, 22, size, op);
396 sja1105_packing(buf, &entry->destports, 21, 17, size, op);
397 sja1105_packing(buf, &entry->enfport, 16, 16, size, op);
398 return size;
399}
400
401
402
403
404
405static void
406sja1105_vlan_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
407 enum packing_op op)
408{
409 u8 *p = buf + SJA1105_SIZE_VLAN_LOOKUP_ENTRY + 4;
410 const int size = SJA1105_SIZE_DYN_CMD;
411
412 sja1105_packing(p, &cmd->valid, 31, 31, size, op);
413 sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op);
414 sja1105_packing(p, &cmd->valident, 27, 27, size, op);
415
416
417
418 sja1105_packing(buf, &cmd->index, 38, 27,
419 SJA1105_SIZE_VLAN_LOOKUP_ENTRY, op);
420}
421
422static void
423sja1105_l2_forwarding_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
424 enum packing_op op)
425{
426 u8 *p = buf + SJA1105_SIZE_L2_FORWARDING_ENTRY;
427 const int size = SJA1105_SIZE_DYN_CMD;
428
429 sja1105_packing(p, &cmd->valid, 31, 31, size, op);
430 sja1105_packing(p, &cmd->errors, 30, 30, size, op);
431 sja1105_packing(p, &cmd->rdwrset, 29, 29, size, op);
432 sja1105_packing(p, &cmd->index, 4, 0, size, op);
433}
434
435static void
436sja1105et_mac_config_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
437 enum packing_op op)
438{
439 const int size = SJA1105_SIZE_DYN_CMD;
440
441 u8 *reg1 = buf + 4;
442
443 sja1105_packing(reg1, &cmd->valid, 31, 31, size, op);
444 sja1105_packing(reg1, &cmd->index, 26, 24, size, op);
445}
446
447static size_t sja1105et_mac_config_entry_packing(void *buf, void *entry_ptr,
448 enum packing_op op)
449{
450 const int size = SJA1105ET_SIZE_MAC_CONFIG_DYN_ENTRY;
451 struct sja1105_mac_config_entry *entry = entry_ptr;
452
453 u8 *reg1 = buf + 4;
454 u8 *reg2 = buf;
455
456 sja1105_packing(reg1, &entry->speed, 30, 29, size, op);
457 sja1105_packing(reg1, &entry->drpdtag, 23, 23, size, op);
458 sja1105_packing(reg1, &entry->drpuntag, 22, 22, size, op);
459 sja1105_packing(reg1, &entry->retag, 21, 21, size, op);
460 sja1105_packing(reg1, &entry->dyn_learn, 20, 20, size, op);
461 sja1105_packing(reg1, &entry->egress, 19, 19, size, op);
462 sja1105_packing(reg1, &entry->ingress, 18, 18, size, op);
463 sja1105_packing(reg1, &entry->ing_mirr, 17, 17, size, op);
464 sja1105_packing(reg1, &entry->egr_mirr, 16, 16, size, op);
465 sja1105_packing(reg1, &entry->vlanprio, 14, 12, size, op);
466 sja1105_packing(reg1, &entry->vlanid, 11, 0, size, op);
467 sja1105_packing(reg2, &entry->tp_delin, 31, 16, size, op);
468 sja1105_packing(reg2, &entry->tp_delout, 15, 0, size, op);
469
470
471
472
473 return 0;
474}
475
476static void
477sja1105pqrs_mac_config_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
478 enum packing_op op)
479{
480 const int size = SJA1105ET_SIZE_MAC_CONFIG_DYN_ENTRY;
481 u8 *p = buf + SJA1105PQRS_SIZE_MAC_CONFIG_ENTRY;
482
483 sja1105_packing(p, &cmd->valid, 31, 31, size, op);
484 sja1105_packing(p, &cmd->errors, 30, 30, size, op);
485 sja1105_packing(p, &cmd->rdwrset, 29, 29, size, op);
486 sja1105_packing(p, &cmd->index, 2, 0, size, op);
487}
488
489static void
490sja1105et_l2_lookup_params_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
491 enum packing_op op)
492{
493 sja1105_packing(buf, &cmd->valid, 31, 31,
494 SJA1105ET_SIZE_L2_LOOKUP_PARAMS_DYN_CMD, op);
495}
496
497static size_t
498sja1105et_l2_lookup_params_entry_packing(void *buf, void *entry_ptr,
499 enum packing_op op)
500{
501 struct sja1105_l2_lookup_params_entry *entry = entry_ptr;
502
503 sja1105_packing(buf, &entry->poly, 7, 0,
504 SJA1105ET_SIZE_L2_LOOKUP_PARAMS_DYN_CMD, op);
505
506 return 0;
507}
508
509static void
510sja1105pqrs_l2_lookup_params_cmd_packing(void *buf,
511 struct sja1105_dyn_cmd *cmd,
512 enum packing_op op)
513{
514 u8 *p = buf + SJA1105PQRS_SIZE_L2_LOOKUP_PARAMS_ENTRY;
515 const int size = SJA1105_SIZE_DYN_CMD;
516
517 sja1105_packing(p, &cmd->valid, 31, 31, size, op);
518 sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op);
519}
520
521static void
522sja1105et_general_params_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
523 enum packing_op op)
524{
525 const int size = SJA1105ET_SIZE_GENERAL_PARAMS_DYN_CMD;
526
527 sja1105_packing(buf, &cmd->valid, 31, 31, size, op);
528 sja1105_packing(buf, &cmd->errors, 30, 30, size, op);
529}
530
531static size_t
532sja1105et_general_params_entry_packing(void *buf, void *entry_ptr,
533 enum packing_op op)
534{
535 struct sja1105_general_params_entry *entry = entry_ptr;
536 const int size = SJA1105ET_SIZE_GENERAL_PARAMS_DYN_CMD;
537
538 sja1105_packing(buf, &entry->mirr_port, 2, 0, size, op);
539
540 return 0;
541}
542
543static void
544sja1105pqrs_general_params_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
545 enum packing_op op)
546{
547 u8 *p = buf + SJA1105PQRS_SIZE_GENERAL_PARAMS_ENTRY;
548 const int size = SJA1105_SIZE_DYN_CMD;
549
550 sja1105_packing(p, &cmd->valid, 31, 31, size, op);
551 sja1105_packing(p, &cmd->errors, 30, 30, size, op);
552 sja1105_packing(p, &cmd->rdwrset, 28, 28, size, op);
553}
554
555static void
556sja1105pqrs_avb_params_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
557 enum packing_op op)
558{
559 u8 *p = buf + SJA1105PQRS_SIZE_AVB_PARAMS_ENTRY;
560 const int size = SJA1105_SIZE_DYN_CMD;
561
562 sja1105_packing(p, &cmd->valid, 31, 31, size, op);
563 sja1105_packing(p, &cmd->errors, 30, 30, size, op);
564 sja1105_packing(p, &cmd->rdwrset, 29, 29, size, op);
565}
566
567static void
568sja1105_retagging_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
569 enum packing_op op)
570{
571 u8 *p = buf + SJA1105_SIZE_RETAGGING_ENTRY;
572 const int size = SJA1105_SIZE_DYN_CMD;
573
574 sja1105_packing(p, &cmd->valid, 31, 31, size, op);
575 sja1105_packing(p, &cmd->errors, 30, 30, size, op);
576 sja1105_packing(p, &cmd->valident, 29, 29, size, op);
577 sja1105_packing(p, &cmd->rdwrset, 28, 28, size, op);
578 sja1105_packing(p, &cmd->index, 5, 0, size, op);
579}
580
581static void sja1105et_cbs_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
582 enum packing_op op)
583{
584 u8 *p = buf + SJA1105ET_SIZE_CBS_ENTRY;
585 const int size = SJA1105_SIZE_DYN_CMD;
586
587 sja1105_packing(p, &cmd->valid, 31, 31, size, op);
588 sja1105_packing(p, &cmd->index, 19, 16, size, op);
589}
590
591static size_t sja1105et_cbs_entry_packing(void *buf, void *entry_ptr,
592 enum packing_op op)
593{
594 const size_t size = SJA1105ET_SIZE_CBS_ENTRY;
595 struct sja1105_cbs_entry *entry = entry_ptr;
596 u8 *cmd = buf + size;
597 u32 *p = buf;
598
599 sja1105_packing(cmd, &entry->port, 5, 3, SJA1105_SIZE_DYN_CMD, op);
600 sja1105_packing(cmd, &entry->prio, 2, 0, SJA1105_SIZE_DYN_CMD, op);
601 sja1105_packing(p + 3, &entry->credit_lo, 31, 0, size, op);
602 sja1105_packing(p + 2, &entry->credit_hi, 31, 0, size, op);
603 sja1105_packing(p + 1, &entry->send_slope, 31, 0, size, op);
604 sja1105_packing(p + 0, &entry->idle_slope, 31, 0, size, op);
605 return size;
606}
607
608static void sja1105pqrs_cbs_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
609 enum packing_op op)
610{
611 u8 *p = buf + SJA1105PQRS_SIZE_CBS_ENTRY;
612 const int size = SJA1105_SIZE_DYN_CMD;
613
614 sja1105_packing(p, &cmd->valid, 31, 31, size, op);
615 sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op);
616 sja1105_packing(p, &cmd->errors, 29, 29, size, op);
617 sja1105_packing(p, &cmd->index, 3, 0, size, op);
618}
619
620static size_t sja1105pqrs_cbs_entry_packing(void *buf, void *entry_ptr,
621 enum packing_op op)
622{
623 const size_t size = SJA1105PQRS_SIZE_CBS_ENTRY;
624 struct sja1105_cbs_entry *entry = entry_ptr;
625
626 sja1105_packing(buf, &entry->port, 159, 157, size, op);
627 sja1105_packing(buf, &entry->prio, 156, 154, size, op);
628 sja1105_packing(buf, &entry->credit_lo, 153, 122, size, op);
629 sja1105_packing(buf, &entry->credit_hi, 121, 90, size, op);
630 sja1105_packing(buf, &entry->send_slope, 89, 58, size, op);
631 sja1105_packing(buf, &entry->idle_slope, 57, 26, size, op);
632 return size;
633}
634
635#define OP_READ BIT(0)
636#define OP_WRITE BIT(1)
637#define OP_DEL BIT(2)
638#define OP_SEARCH BIT(3)
639
640
641const struct sja1105_dynamic_table_ops sja1105et_dyn_ops[BLK_IDX_MAX_DYN] = {
642 [BLK_IDX_VL_LOOKUP] = {
643 .entry_packing = sja1105et_vl_lookup_entry_packing,
644 .cmd_packing = sja1105_vl_lookup_cmd_packing,
645 .access = OP_WRITE,
646 .max_entry_count = SJA1105_MAX_VL_LOOKUP_COUNT,
647 .packed_size = SJA1105ET_SIZE_VL_LOOKUP_DYN_CMD,
648 .addr = 0x35,
649 },
650 [BLK_IDX_L2_LOOKUP] = {
651 .entry_packing = sja1105et_dyn_l2_lookup_entry_packing,
652 .cmd_packing = sja1105et_l2_lookup_cmd_packing,
653 .access = (OP_READ | OP_WRITE | OP_DEL),
654 .max_entry_count = SJA1105_MAX_L2_LOOKUP_COUNT,
655 .packed_size = SJA1105ET_SIZE_L2_LOOKUP_DYN_CMD,
656 .addr = 0x20,
657 },
658 [BLK_IDX_MGMT_ROUTE] = {
659 .entry_packing = sja1105et_mgmt_route_entry_packing,
660 .cmd_packing = sja1105et_mgmt_route_cmd_packing,
661 .access = (OP_READ | OP_WRITE),
662 .max_entry_count = SJA1105_NUM_PORTS,
663 .packed_size = SJA1105ET_SIZE_L2_LOOKUP_DYN_CMD,
664 .addr = 0x20,
665 },
666 [BLK_IDX_VLAN_LOOKUP] = {
667 .entry_packing = sja1105_vlan_lookup_entry_packing,
668 .cmd_packing = sja1105_vlan_lookup_cmd_packing,
669 .access = (OP_WRITE | OP_DEL),
670 .max_entry_count = SJA1105_MAX_VLAN_LOOKUP_COUNT,
671 .packed_size = SJA1105_SIZE_VLAN_LOOKUP_DYN_CMD,
672 .addr = 0x27,
673 },
674 [BLK_IDX_L2_FORWARDING] = {
675 .entry_packing = sja1105_l2_forwarding_entry_packing,
676 .cmd_packing = sja1105_l2_forwarding_cmd_packing,
677 .max_entry_count = SJA1105_MAX_L2_FORWARDING_COUNT,
678 .access = OP_WRITE,
679 .packed_size = SJA1105_SIZE_L2_FORWARDING_DYN_CMD,
680 .addr = 0x24,
681 },
682 [BLK_IDX_MAC_CONFIG] = {
683 .entry_packing = sja1105et_mac_config_entry_packing,
684 .cmd_packing = sja1105et_mac_config_cmd_packing,
685 .max_entry_count = SJA1105_MAX_MAC_CONFIG_COUNT,
686 .access = OP_WRITE,
687 .packed_size = SJA1105ET_SIZE_MAC_CONFIG_DYN_CMD,
688 .addr = 0x36,
689 },
690 [BLK_IDX_L2_LOOKUP_PARAMS] = {
691 .entry_packing = sja1105et_l2_lookup_params_entry_packing,
692 .cmd_packing = sja1105et_l2_lookup_params_cmd_packing,
693 .max_entry_count = SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT,
694 .access = OP_WRITE,
695 .packed_size = SJA1105ET_SIZE_L2_LOOKUP_PARAMS_DYN_CMD,
696 .addr = 0x38,
697 },
698 [BLK_IDX_GENERAL_PARAMS] = {
699 .entry_packing = sja1105et_general_params_entry_packing,
700 .cmd_packing = sja1105et_general_params_cmd_packing,
701 .max_entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT,
702 .access = OP_WRITE,
703 .packed_size = SJA1105ET_SIZE_GENERAL_PARAMS_DYN_CMD,
704 .addr = 0x34,
705 },
706 [BLK_IDX_RETAGGING] = {
707 .entry_packing = sja1105_retagging_entry_packing,
708 .cmd_packing = sja1105_retagging_cmd_packing,
709 .max_entry_count = SJA1105_MAX_RETAGGING_COUNT,
710 .access = (OP_WRITE | OP_DEL),
711 .packed_size = SJA1105_SIZE_RETAGGING_DYN_CMD,
712 .addr = 0x31,
713 },
714 [BLK_IDX_CBS] = {
715 .entry_packing = sja1105et_cbs_entry_packing,
716 .cmd_packing = sja1105et_cbs_cmd_packing,
717 .max_entry_count = SJA1105ET_MAX_CBS_COUNT,
718 .access = OP_WRITE,
719 .packed_size = SJA1105ET_SIZE_CBS_DYN_CMD,
720 .addr = 0x2c,
721 },
722};
723
724
725const struct sja1105_dynamic_table_ops sja1105pqrs_dyn_ops[BLK_IDX_MAX_DYN] = {
726 [BLK_IDX_VL_LOOKUP] = {
727 .entry_packing = sja1105_vl_lookup_entry_packing,
728 .cmd_packing = sja1105_vl_lookup_cmd_packing,
729 .access = (OP_READ | OP_WRITE),
730 .max_entry_count = SJA1105_MAX_VL_LOOKUP_COUNT,
731 .packed_size = SJA1105PQRS_SIZE_VL_LOOKUP_DYN_CMD,
732 .addr = 0x47,
733 },
734 [BLK_IDX_L2_LOOKUP] = {
735 .entry_packing = sja1105pqrs_dyn_l2_lookup_entry_packing,
736 .cmd_packing = sja1105pqrs_l2_lookup_cmd_packing,
737 .access = (OP_READ | OP_WRITE | OP_DEL | OP_SEARCH),
738 .max_entry_count = SJA1105_MAX_L2_LOOKUP_COUNT,
739 .packed_size = SJA1105PQRS_SIZE_L2_LOOKUP_DYN_CMD,
740 .addr = 0x24,
741 },
742 [BLK_IDX_MGMT_ROUTE] = {
743 .entry_packing = sja1105pqrs_mgmt_route_entry_packing,
744 .cmd_packing = sja1105pqrs_mgmt_route_cmd_packing,
745 .access = (OP_READ | OP_WRITE | OP_DEL | OP_SEARCH),
746 .max_entry_count = SJA1105_NUM_PORTS,
747 .packed_size = SJA1105PQRS_SIZE_L2_LOOKUP_DYN_CMD,
748 .addr = 0x24,
749 },
750 [BLK_IDX_VLAN_LOOKUP] = {
751 .entry_packing = sja1105_vlan_lookup_entry_packing,
752 .cmd_packing = sja1105_vlan_lookup_cmd_packing,
753 .access = (OP_READ | OP_WRITE | OP_DEL),
754 .max_entry_count = SJA1105_MAX_VLAN_LOOKUP_COUNT,
755 .packed_size = SJA1105_SIZE_VLAN_LOOKUP_DYN_CMD,
756 .addr = 0x2D,
757 },
758 [BLK_IDX_L2_FORWARDING] = {
759 .entry_packing = sja1105_l2_forwarding_entry_packing,
760 .cmd_packing = sja1105_l2_forwarding_cmd_packing,
761 .max_entry_count = SJA1105_MAX_L2_FORWARDING_COUNT,
762 .access = OP_WRITE,
763 .packed_size = SJA1105_SIZE_L2_FORWARDING_DYN_CMD,
764 .addr = 0x2A,
765 },
766 [BLK_IDX_MAC_CONFIG] = {
767 .entry_packing = sja1105pqrs_mac_config_entry_packing,
768 .cmd_packing = sja1105pqrs_mac_config_cmd_packing,
769 .max_entry_count = SJA1105_MAX_MAC_CONFIG_COUNT,
770 .access = (OP_READ | OP_WRITE),
771 .packed_size = SJA1105PQRS_SIZE_MAC_CONFIG_DYN_CMD,
772 .addr = 0x4B,
773 },
774 [BLK_IDX_L2_LOOKUP_PARAMS] = {
775 .entry_packing = sja1105pqrs_l2_lookup_params_entry_packing,
776 .cmd_packing = sja1105pqrs_l2_lookup_params_cmd_packing,
777 .max_entry_count = SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT,
778 .access = (OP_READ | OP_WRITE),
779 .packed_size = SJA1105PQRS_SIZE_L2_LOOKUP_PARAMS_DYN_CMD,
780 .addr = 0x54,
781 },
782 [BLK_IDX_AVB_PARAMS] = {
783 .entry_packing = sja1105pqrs_avb_params_entry_packing,
784 .cmd_packing = sja1105pqrs_avb_params_cmd_packing,
785 .max_entry_count = SJA1105_MAX_AVB_PARAMS_COUNT,
786 .access = (OP_READ | OP_WRITE),
787 .packed_size = SJA1105PQRS_SIZE_AVB_PARAMS_DYN_CMD,
788 .addr = 0x8003,
789 },
790 [BLK_IDX_GENERAL_PARAMS] = {
791 .entry_packing = sja1105pqrs_general_params_entry_packing,
792 .cmd_packing = sja1105pqrs_general_params_cmd_packing,
793 .max_entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT,
794 .access = (OP_READ | OP_WRITE),
795 .packed_size = SJA1105PQRS_SIZE_GENERAL_PARAMS_DYN_CMD,
796 .addr = 0x3B,
797 },
798 [BLK_IDX_RETAGGING] = {
799 .entry_packing = sja1105_retagging_entry_packing,
800 .cmd_packing = sja1105_retagging_cmd_packing,
801 .max_entry_count = SJA1105_MAX_RETAGGING_COUNT,
802 .access = (OP_READ | OP_WRITE | OP_DEL),
803 .packed_size = SJA1105_SIZE_RETAGGING_DYN_CMD,
804 .addr = 0x38,
805 },
806 [BLK_IDX_CBS] = {
807 .entry_packing = sja1105pqrs_cbs_entry_packing,
808 .cmd_packing = sja1105pqrs_cbs_cmd_packing,
809 .max_entry_count = SJA1105PQRS_MAX_CBS_COUNT,
810 .access = OP_WRITE,
811 .packed_size = SJA1105PQRS_SIZE_CBS_DYN_CMD,
812 .addr = 0x32,
813 },
814};
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834int sja1105_dynamic_config_read(struct sja1105_private *priv,
835 enum sja1105_blk_idx blk_idx,
836 int index, void *entry)
837{
838 const struct sja1105_dynamic_table_ops *ops;
839 struct sja1105_dyn_cmd cmd = {0};
840
841 u8 packed_buf[SJA1105_MAX_DYN_CMD_SIZE] = {0};
842 int retries = 3;
843 int rc;
844
845 if (blk_idx >= BLK_IDX_MAX_DYN)
846 return -ERANGE;
847
848 ops = &priv->info->dyn_ops[blk_idx];
849
850 if (index >= 0 && index >= ops->max_entry_count)
851 return -ERANGE;
852 if (index < 0 && !(ops->access & OP_SEARCH))
853 return -EOPNOTSUPP;
854 if (!(ops->access & OP_READ))
855 return -EOPNOTSUPP;
856 if (ops->packed_size > SJA1105_MAX_DYN_CMD_SIZE)
857 return -ERANGE;
858 if (!ops->cmd_packing)
859 return -EOPNOTSUPP;
860 if (!ops->entry_packing)
861 return -EOPNOTSUPP;
862
863 cmd.valid = true;
864 cmd.rdwrset = SPI_READ;
865 if (index < 0) {
866
867 cmd.index = 0;
868 cmd.search = true;
869 } else {
870 cmd.index = index;
871 cmd.search = false;
872 }
873 cmd.valident = true;
874 ops->cmd_packing(packed_buf, &cmd, PACK);
875
876 if (cmd.search)
877 ops->entry_packing(packed_buf, entry, PACK);
878
879
880 rc = sja1105_xfer_buf(priv, SPI_WRITE, ops->addr, packed_buf,
881 ops->packed_size);
882 if (rc < 0)
883 return rc;
884
885
886
887
888 do {
889 memset(packed_buf, 0, ops->packed_size);
890
891
892 rc = sja1105_xfer_buf(priv, SPI_READ, ops->addr, packed_buf,
893 ops->packed_size);
894 if (rc < 0)
895 return rc;
896
897 cmd = (struct sja1105_dyn_cmd) {0};
898 ops->cmd_packing(packed_buf, &cmd, UNPACK);
899
900
901
902
903 if (!cmd.valident && blk_idx != BLK_IDX_MGMT_ROUTE)
904 return -ENOENT;
905 cpu_relax();
906 } while (cmd.valid && --retries);
907
908 if (cmd.valid)
909 return -ETIMEDOUT;
910
911
912
913
914 if (entry)
915 ops->entry_packing(packed_buf, entry, UNPACK);
916 return 0;
917}
918
919int sja1105_dynamic_config_write(struct sja1105_private *priv,
920 enum sja1105_blk_idx blk_idx,
921 int index, void *entry, bool keep)
922{
923 const struct sja1105_dynamic_table_ops *ops;
924 struct sja1105_dyn_cmd cmd = {0};
925
926 u8 packed_buf[SJA1105_MAX_DYN_CMD_SIZE] = {0};
927 int rc;
928
929 if (blk_idx >= BLK_IDX_MAX_DYN)
930 return -ERANGE;
931
932 ops = &priv->info->dyn_ops[blk_idx];
933
934 if (index >= ops->max_entry_count)
935 return -ERANGE;
936 if (index < 0)
937 return -ERANGE;
938 if (!(ops->access & OP_WRITE))
939 return -EOPNOTSUPP;
940 if (!keep && !(ops->access & OP_DEL))
941 return -EOPNOTSUPP;
942 if (ops->packed_size > SJA1105_MAX_DYN_CMD_SIZE)
943 return -ERANGE;
944
945 cmd.valident = keep;
946 cmd.valid = true;
947 cmd.rdwrset = SPI_WRITE;
948 cmd.index = index;
949
950 if (!ops->cmd_packing)
951 return -EOPNOTSUPP;
952 ops->cmd_packing(packed_buf, &cmd, PACK);
953
954 if (!ops->entry_packing)
955 return -EOPNOTSUPP;
956
957
958
959
960
961 if (keep)
962 ops->entry_packing(packed_buf, entry, PACK);
963
964
965 rc = sja1105_xfer_buf(priv, SPI_WRITE, ops->addr, packed_buf,
966 ops->packed_size);
967 if (rc < 0)
968 return rc;
969
970 cmd = (struct sja1105_dyn_cmd) {0};
971 ops->cmd_packing(packed_buf, &cmd, UNPACK);
972 if (cmd.errors)
973 return -EINVAL;
974
975 return 0;
976}
977
978static u8 sja1105_crc8_add(u8 crc, u8 byte, u8 poly)
979{
980 int i;
981
982 for (i = 0; i < 8; i++) {
983 if ((crc ^ byte) & (1 << 7)) {
984 crc <<= 1;
985 crc ^= poly;
986 } else {
987 crc <<= 1;
988 }
989 byte <<= 1;
990 }
991 return crc;
992}
993
994
995
996
997
998
999
1000u8 sja1105et_fdb_hash(struct sja1105_private *priv, const u8 *addr, u16 vid)
1001{
1002 struct sja1105_l2_lookup_params_entry *l2_lookup_params =
1003 priv->static_config.tables[BLK_IDX_L2_LOOKUP_PARAMS].entries;
1004 u64 poly_koopman = l2_lookup_params->poly;
1005
1006 u8 poly = (u8)(1 + (poly_koopman << 1));
1007 u64 vlanid = l2_lookup_params->shared_learn ? 0 : vid;
1008 u64 input = (vlanid << 48) | ether_addr_to_u64(addr);
1009 u8 crc = 0;
1010 int i;
1011
1012
1013 for (i = 56; i >= 0; i -= 8) {
1014 u8 byte = (input & (0xffull << i)) >> i;
1015
1016 crc = sja1105_crc8_add(crc, byte, poly);
1017 }
1018 return crc;
1019}
1020