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_MAC_CONFIG_DYN_ENTRY \
101 SJA1105_SIZE_DYN_CMD
102
103#define SJA1105ET_SIZE_L2_LOOKUP_DYN_CMD \
104 (SJA1105_SIZE_DYN_CMD + SJA1105ET_SIZE_L2_LOOKUP_ENTRY)
105
106#define SJA1105PQRS_SIZE_L2_LOOKUP_DYN_CMD \
107 (SJA1105_SIZE_DYN_CMD + SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY)
108
109#define SJA1105_SIZE_VLAN_LOOKUP_DYN_CMD \
110 (SJA1105_SIZE_DYN_CMD + 4 + SJA1105_SIZE_VLAN_LOOKUP_ENTRY)
111
112#define SJA1105_SIZE_L2_FORWARDING_DYN_CMD \
113 (SJA1105_SIZE_DYN_CMD + SJA1105_SIZE_L2_FORWARDING_ENTRY)
114
115#define SJA1105ET_SIZE_MAC_CONFIG_DYN_CMD \
116 (SJA1105_SIZE_DYN_CMD + SJA1105ET_SIZE_MAC_CONFIG_DYN_ENTRY)
117
118#define SJA1105PQRS_SIZE_MAC_CONFIG_DYN_CMD \
119 (SJA1105_SIZE_DYN_CMD + SJA1105PQRS_SIZE_MAC_CONFIG_ENTRY)
120
121#define SJA1105ET_SIZE_L2_LOOKUP_PARAMS_DYN_CMD \
122 SJA1105_SIZE_DYN_CMD
123
124#define SJA1105ET_SIZE_GENERAL_PARAMS_DYN_CMD \
125 SJA1105_SIZE_DYN_CMD
126
127#define SJA1105_MAX_DYN_CMD_SIZE \
128 SJA1105PQRS_SIZE_MAC_CONFIG_DYN_CMD
129
130struct sja1105_dyn_cmd {
131 bool search;
132 u64 valid;
133 u64 rdwrset;
134 u64 errors;
135 u64 valident;
136 u64 index;
137};
138
139enum sja1105_hostcmd {
140 SJA1105_HOSTCMD_SEARCH = 1,
141 SJA1105_HOSTCMD_READ = 2,
142 SJA1105_HOSTCMD_WRITE = 3,
143 SJA1105_HOSTCMD_INVALIDATE = 4,
144};
145
146static void
147sja1105pqrs_l2_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
148 enum packing_op op)
149{
150 u8 *p = buf + SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY;
151 const int size = SJA1105_SIZE_DYN_CMD;
152 u64 hostcmd;
153
154 sja1105_packing(p, &cmd->valid, 31, 31, size, op);
155 sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op);
156 sja1105_packing(p, &cmd->errors, 29, 29, size, op);
157 sja1105_packing(p, &cmd->valident, 27, 27, size, op);
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180 if (cmd->rdwrset == SPI_READ) {
181 if (cmd->search)
182 hostcmd = SJA1105_HOSTCMD_SEARCH;
183 else
184 hostcmd = SJA1105_HOSTCMD_READ;
185 } else {
186
187 if (cmd->valident)
188 hostcmd = SJA1105_HOSTCMD_WRITE;
189 else
190 hostcmd = SJA1105_HOSTCMD_INVALIDATE;
191 }
192 sja1105_packing(p, &hostcmd, 25, 23, size, op);
193
194
195
196
197
198
199
200
201
202 sja1105_packing(buf, &cmd->index, 15, 6,
203 SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY, op);
204}
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251static size_t
252sja1105pqrs_dyn_l2_lookup_entry_packing(void *buf, void *entry_ptr,
253 enum packing_op op)
254{
255 struct sja1105_l2_lookup_entry *entry = entry_ptr;
256 u8 *cmd = buf + SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY;
257 const int size = SJA1105_SIZE_DYN_CMD;
258
259 sja1105_packing(cmd, &entry->lockeds, 28, 28, size, op);
260
261 return sja1105pqrs_l2_lookup_entry_packing(buf, entry_ptr, op);
262}
263
264static void
265sja1105et_l2_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
266 enum packing_op op)
267{
268 u8 *p = buf + SJA1105ET_SIZE_L2_LOOKUP_ENTRY;
269 const int size = SJA1105_SIZE_DYN_CMD;
270
271 sja1105_packing(p, &cmd->valid, 31, 31, size, op);
272 sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op);
273 sja1105_packing(p, &cmd->errors, 29, 29, size, op);
274 sja1105_packing(p, &cmd->valident, 27, 27, size, op);
275
276 sja1105_packing(buf, &cmd->index, 29, 20,
277 SJA1105ET_SIZE_L2_LOOKUP_ENTRY, op);
278}
279
280static size_t sja1105et_dyn_l2_lookup_entry_packing(void *buf, void *entry_ptr,
281 enum packing_op op)
282{
283 struct sja1105_l2_lookup_entry *entry = entry_ptr;
284 u8 *cmd = buf + SJA1105ET_SIZE_L2_LOOKUP_ENTRY;
285 const int size = SJA1105_SIZE_DYN_CMD;
286
287 sja1105_packing(cmd, &entry->lockeds, 28, 28, size, op);
288
289 return sja1105et_l2_lookup_entry_packing(buf, entry_ptr, op);
290}
291
292static void
293sja1105et_mgmt_route_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
294 enum packing_op op)
295{
296 u8 *p = buf + SJA1105ET_SIZE_L2_LOOKUP_ENTRY;
297 u64 mgmtroute = 1;
298
299 sja1105et_l2_lookup_cmd_packing(buf, cmd, op);
300 if (op == PACK)
301 sja1105_pack(p, &mgmtroute, 26, 26, SJA1105_SIZE_DYN_CMD);
302}
303
304static size_t sja1105et_mgmt_route_entry_packing(void *buf, void *entry_ptr,
305 enum packing_op op)
306{
307 struct sja1105_mgmt_entry *entry = entry_ptr;
308 const size_t size = SJA1105ET_SIZE_L2_LOOKUP_ENTRY;
309
310
311
312
313
314
315
316 sja1105_packing(buf, &entry->tsreg, 85, 85, size, op);
317 sja1105_packing(buf, &entry->takets, 84, 84, size, op);
318 sja1105_packing(buf, &entry->macaddr, 83, 36, size, op);
319 sja1105_packing(buf, &entry->destports, 35, 31, size, op);
320 sja1105_packing(buf, &entry->enfport, 30, 30, size, op);
321 return size;
322}
323
324static void
325sja1105pqrs_mgmt_route_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
326 enum packing_op op)
327{
328 u8 *p = buf + SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY;
329 u64 mgmtroute = 1;
330
331 sja1105pqrs_l2_lookup_cmd_packing(buf, cmd, op);
332 if (op == PACK)
333 sja1105_pack(p, &mgmtroute, 26, 26, SJA1105_SIZE_DYN_CMD);
334}
335
336static size_t sja1105pqrs_mgmt_route_entry_packing(void *buf, void *entry_ptr,
337 enum packing_op op)
338{
339 const size_t size = SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY;
340 struct sja1105_mgmt_entry *entry = entry_ptr;
341
342
343
344
345
346 sja1105_packing(buf, &entry->tsreg, 71, 71, size, op);
347 sja1105_packing(buf, &entry->takets, 70, 70, size, op);
348 sja1105_packing(buf, &entry->macaddr, 69, 22, size, op);
349 sja1105_packing(buf, &entry->destports, 21, 17, size, op);
350 sja1105_packing(buf, &entry->enfport, 16, 16, size, op);
351 return size;
352}
353
354
355
356
357
358static void
359sja1105_vlan_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
360 enum packing_op op)
361{
362 u8 *p = buf + SJA1105_SIZE_VLAN_LOOKUP_ENTRY + 4;
363 const int size = SJA1105_SIZE_DYN_CMD;
364
365 sja1105_packing(p, &cmd->valid, 31, 31, size, op);
366 sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op);
367 sja1105_packing(p, &cmd->valident, 27, 27, size, op);
368
369
370
371 sja1105_packing(buf, &cmd->index, 38, 27,
372 SJA1105_SIZE_VLAN_LOOKUP_ENTRY, op);
373}
374
375static void
376sja1105_l2_forwarding_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
377 enum packing_op op)
378{
379 u8 *p = buf + SJA1105_SIZE_L2_FORWARDING_ENTRY;
380 const int size = SJA1105_SIZE_DYN_CMD;
381
382 sja1105_packing(p, &cmd->valid, 31, 31, size, op);
383 sja1105_packing(p, &cmd->errors, 30, 30, size, op);
384 sja1105_packing(p, &cmd->rdwrset, 29, 29, size, op);
385 sja1105_packing(p, &cmd->index, 4, 0, size, op);
386}
387
388static void
389sja1105et_mac_config_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
390 enum packing_op op)
391{
392 const int size = SJA1105_SIZE_DYN_CMD;
393
394 u8 *reg1 = buf + 4;
395
396 sja1105_packing(reg1, &cmd->valid, 31, 31, size, op);
397 sja1105_packing(reg1, &cmd->index, 26, 24, size, op);
398}
399
400static size_t sja1105et_mac_config_entry_packing(void *buf, void *entry_ptr,
401 enum packing_op op)
402{
403 const int size = SJA1105ET_SIZE_MAC_CONFIG_DYN_ENTRY;
404 struct sja1105_mac_config_entry *entry = entry_ptr;
405
406 u8 *reg1 = buf + 4;
407 u8 *reg2 = buf;
408
409 sja1105_packing(reg1, &entry->speed, 30, 29, size, op);
410 sja1105_packing(reg1, &entry->drpdtag, 23, 23, size, op);
411 sja1105_packing(reg1, &entry->drpuntag, 22, 22, size, op);
412 sja1105_packing(reg1, &entry->retag, 21, 21, size, op);
413 sja1105_packing(reg1, &entry->dyn_learn, 20, 20, size, op);
414 sja1105_packing(reg1, &entry->egress, 19, 19, size, op);
415 sja1105_packing(reg1, &entry->ingress, 18, 18, size, op);
416 sja1105_packing(reg1, &entry->ing_mirr, 17, 17, size, op);
417 sja1105_packing(reg1, &entry->egr_mirr, 16, 16, size, op);
418 sja1105_packing(reg1, &entry->vlanprio, 14, 12, size, op);
419 sja1105_packing(reg1, &entry->vlanid, 11, 0, size, op);
420 sja1105_packing(reg2, &entry->tp_delin, 31, 16, size, op);
421 sja1105_packing(reg2, &entry->tp_delout, 15, 0, size, op);
422
423
424
425
426 return 0;
427}
428
429static void
430sja1105pqrs_mac_config_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
431 enum packing_op op)
432{
433 const int size = SJA1105ET_SIZE_MAC_CONFIG_DYN_ENTRY;
434 u8 *p = buf + SJA1105PQRS_SIZE_MAC_CONFIG_ENTRY;
435
436 sja1105_packing(p, &cmd->valid, 31, 31, size, op);
437 sja1105_packing(p, &cmd->errors, 30, 30, size, op);
438 sja1105_packing(p, &cmd->rdwrset, 29, 29, size, op);
439 sja1105_packing(p, &cmd->index, 2, 0, size, op);
440}
441
442static void
443sja1105et_l2_lookup_params_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
444 enum packing_op op)
445{
446 sja1105_packing(buf, &cmd->valid, 31, 31,
447 SJA1105ET_SIZE_L2_LOOKUP_PARAMS_DYN_CMD, op);
448}
449
450static size_t
451sja1105et_l2_lookup_params_entry_packing(void *buf, void *entry_ptr,
452 enum packing_op op)
453{
454 struct sja1105_l2_lookup_params_entry *entry = entry_ptr;
455
456 sja1105_packing(buf, &entry->poly, 7, 0,
457 SJA1105ET_SIZE_L2_LOOKUP_PARAMS_DYN_CMD, op);
458
459 return 0;
460}
461
462static void
463sja1105et_general_params_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
464 enum packing_op op)
465{
466 const int size = SJA1105ET_SIZE_GENERAL_PARAMS_DYN_CMD;
467
468 sja1105_packing(buf, &cmd->valid, 31, 31, size, op);
469 sja1105_packing(buf, &cmd->errors, 30, 30, size, op);
470}
471
472static size_t
473sja1105et_general_params_entry_packing(void *buf, void *entry_ptr,
474 enum packing_op op)
475{
476 struct sja1105_general_params_entry *entry = entry_ptr;
477 const int size = SJA1105ET_SIZE_GENERAL_PARAMS_DYN_CMD;
478
479 sja1105_packing(buf, &entry->mirr_port, 2, 0, size, op);
480
481 return 0;
482}
483
484#define OP_READ BIT(0)
485#define OP_WRITE BIT(1)
486#define OP_DEL BIT(2)
487#define OP_SEARCH BIT(3)
488
489
490struct sja1105_dynamic_table_ops sja1105et_dyn_ops[BLK_IDX_MAX_DYN] = {
491 [BLK_IDX_L2_LOOKUP] = {
492 .entry_packing = sja1105et_dyn_l2_lookup_entry_packing,
493 .cmd_packing = sja1105et_l2_lookup_cmd_packing,
494 .access = (OP_READ | OP_WRITE | OP_DEL),
495 .max_entry_count = SJA1105_MAX_L2_LOOKUP_COUNT,
496 .packed_size = SJA1105ET_SIZE_L2_LOOKUP_DYN_CMD,
497 .addr = 0x20,
498 },
499 [BLK_IDX_MGMT_ROUTE] = {
500 .entry_packing = sja1105et_mgmt_route_entry_packing,
501 .cmd_packing = sja1105et_mgmt_route_cmd_packing,
502 .access = (OP_READ | OP_WRITE),
503 .max_entry_count = SJA1105_NUM_PORTS,
504 .packed_size = SJA1105ET_SIZE_L2_LOOKUP_DYN_CMD,
505 .addr = 0x20,
506 },
507 [BLK_IDX_L2_POLICING] = {0},
508 [BLK_IDX_VLAN_LOOKUP] = {
509 .entry_packing = sja1105_vlan_lookup_entry_packing,
510 .cmd_packing = sja1105_vlan_lookup_cmd_packing,
511 .access = (OP_WRITE | OP_DEL),
512 .max_entry_count = SJA1105_MAX_VLAN_LOOKUP_COUNT,
513 .packed_size = SJA1105_SIZE_VLAN_LOOKUP_DYN_CMD,
514 .addr = 0x27,
515 },
516 [BLK_IDX_L2_FORWARDING] = {
517 .entry_packing = sja1105_l2_forwarding_entry_packing,
518 .cmd_packing = sja1105_l2_forwarding_cmd_packing,
519 .max_entry_count = SJA1105_MAX_L2_FORWARDING_COUNT,
520 .access = OP_WRITE,
521 .packed_size = SJA1105_SIZE_L2_FORWARDING_DYN_CMD,
522 .addr = 0x24,
523 },
524 [BLK_IDX_MAC_CONFIG] = {
525 .entry_packing = sja1105et_mac_config_entry_packing,
526 .cmd_packing = sja1105et_mac_config_cmd_packing,
527 .max_entry_count = SJA1105_MAX_MAC_CONFIG_COUNT,
528 .access = OP_WRITE,
529 .packed_size = SJA1105ET_SIZE_MAC_CONFIG_DYN_CMD,
530 .addr = 0x36,
531 },
532 [BLK_IDX_L2_LOOKUP_PARAMS] = {
533 .entry_packing = sja1105et_l2_lookup_params_entry_packing,
534 .cmd_packing = sja1105et_l2_lookup_params_cmd_packing,
535 .max_entry_count = SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT,
536 .access = OP_WRITE,
537 .packed_size = SJA1105ET_SIZE_L2_LOOKUP_PARAMS_DYN_CMD,
538 .addr = 0x38,
539 },
540 [BLK_IDX_L2_FORWARDING_PARAMS] = {0},
541 [BLK_IDX_AVB_PARAMS] = {0},
542 [BLK_IDX_GENERAL_PARAMS] = {
543 .entry_packing = sja1105et_general_params_entry_packing,
544 .cmd_packing = sja1105et_general_params_cmd_packing,
545 .max_entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT,
546 .access = OP_WRITE,
547 .packed_size = SJA1105ET_SIZE_GENERAL_PARAMS_DYN_CMD,
548 .addr = 0x34,
549 },
550 [BLK_IDX_XMII_PARAMS] = {0},
551};
552
553
554struct sja1105_dynamic_table_ops sja1105pqrs_dyn_ops[BLK_IDX_MAX_DYN] = {
555 [BLK_IDX_L2_LOOKUP] = {
556 .entry_packing = sja1105pqrs_dyn_l2_lookup_entry_packing,
557 .cmd_packing = sja1105pqrs_l2_lookup_cmd_packing,
558 .access = (OP_READ | OP_WRITE | OP_DEL | OP_SEARCH),
559 .max_entry_count = SJA1105_MAX_L2_LOOKUP_COUNT,
560 .packed_size = SJA1105PQRS_SIZE_L2_LOOKUP_DYN_CMD,
561 .addr = 0x24,
562 },
563 [BLK_IDX_MGMT_ROUTE] = {
564 .entry_packing = sja1105pqrs_mgmt_route_entry_packing,
565 .cmd_packing = sja1105pqrs_mgmt_route_cmd_packing,
566 .access = (OP_READ | OP_WRITE | OP_DEL | OP_SEARCH),
567 .max_entry_count = SJA1105_NUM_PORTS,
568 .packed_size = SJA1105PQRS_SIZE_L2_LOOKUP_DYN_CMD,
569 .addr = 0x24,
570 },
571 [BLK_IDX_L2_POLICING] = {0},
572 [BLK_IDX_VLAN_LOOKUP] = {
573 .entry_packing = sja1105_vlan_lookup_entry_packing,
574 .cmd_packing = sja1105_vlan_lookup_cmd_packing,
575 .access = (OP_READ | OP_WRITE | OP_DEL),
576 .max_entry_count = SJA1105_MAX_VLAN_LOOKUP_COUNT,
577 .packed_size = SJA1105_SIZE_VLAN_LOOKUP_DYN_CMD,
578 .addr = 0x2D,
579 },
580 [BLK_IDX_L2_FORWARDING] = {
581 .entry_packing = sja1105_l2_forwarding_entry_packing,
582 .cmd_packing = sja1105_l2_forwarding_cmd_packing,
583 .max_entry_count = SJA1105_MAX_L2_FORWARDING_COUNT,
584 .access = OP_WRITE,
585 .packed_size = SJA1105_SIZE_L2_FORWARDING_DYN_CMD,
586 .addr = 0x2A,
587 },
588 [BLK_IDX_MAC_CONFIG] = {
589 .entry_packing = sja1105pqrs_mac_config_entry_packing,
590 .cmd_packing = sja1105pqrs_mac_config_cmd_packing,
591 .max_entry_count = SJA1105_MAX_MAC_CONFIG_COUNT,
592 .access = (OP_READ | OP_WRITE),
593 .packed_size = SJA1105PQRS_SIZE_MAC_CONFIG_DYN_CMD,
594 .addr = 0x4B,
595 },
596 [BLK_IDX_L2_LOOKUP_PARAMS] = {
597 .entry_packing = sja1105et_l2_lookup_params_entry_packing,
598 .cmd_packing = sja1105et_l2_lookup_params_cmd_packing,
599 .max_entry_count = SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT,
600 .access = (OP_READ | OP_WRITE),
601 .packed_size = SJA1105ET_SIZE_L2_LOOKUP_PARAMS_DYN_CMD,
602 .addr = 0x38,
603 },
604 [BLK_IDX_L2_FORWARDING_PARAMS] = {0},
605 [BLK_IDX_AVB_PARAMS] = {0},
606 [BLK_IDX_GENERAL_PARAMS] = {
607 .entry_packing = sja1105et_general_params_entry_packing,
608 .cmd_packing = sja1105et_general_params_cmd_packing,
609 .max_entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT,
610 .access = OP_WRITE,
611 .packed_size = SJA1105ET_SIZE_GENERAL_PARAMS_DYN_CMD,
612 .addr = 0x34,
613 },
614 [BLK_IDX_XMII_PARAMS] = {0},
615};
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635int sja1105_dynamic_config_read(struct sja1105_private *priv,
636 enum sja1105_blk_idx blk_idx,
637 int index, void *entry)
638{
639 const struct sja1105_dynamic_table_ops *ops;
640 struct sja1105_dyn_cmd cmd = {0};
641
642 u8 packed_buf[SJA1105_MAX_DYN_CMD_SIZE] = {0};
643 int retries = 3;
644 int rc;
645
646 if (blk_idx >= BLK_IDX_MAX_DYN)
647 return -ERANGE;
648
649 ops = &priv->info->dyn_ops[blk_idx];
650
651 if (index >= 0 && index >= ops->max_entry_count)
652 return -ERANGE;
653 if (index < 0 && !(ops->access & OP_SEARCH))
654 return -EOPNOTSUPP;
655 if (!(ops->access & OP_READ))
656 return -EOPNOTSUPP;
657 if (ops->packed_size > SJA1105_MAX_DYN_CMD_SIZE)
658 return -ERANGE;
659 if (!ops->cmd_packing)
660 return -EOPNOTSUPP;
661 if (!ops->entry_packing)
662 return -EOPNOTSUPP;
663
664 cmd.valid = true;
665 cmd.rdwrset = SPI_READ;
666 if (index < 0) {
667
668 cmd.index = 0;
669 cmd.search = true;
670 } else {
671 cmd.index = index;
672 cmd.search = false;
673 }
674 cmd.valident = true;
675 ops->cmd_packing(packed_buf, &cmd, PACK);
676
677 if (cmd.search)
678 ops->entry_packing(packed_buf, entry, PACK);
679
680
681 rc = sja1105_spi_send_packed_buf(priv, SPI_WRITE, ops->addr,
682 packed_buf, ops->packed_size);
683 if (rc < 0)
684 return rc;
685
686
687
688
689 do {
690 memset(packed_buf, 0, ops->packed_size);
691
692
693 rc = sja1105_spi_send_packed_buf(priv, SPI_READ, ops->addr,
694 packed_buf, ops->packed_size);
695 if (rc < 0)
696 return rc;
697
698 cmd = (struct sja1105_dyn_cmd) {0};
699 ops->cmd_packing(packed_buf, &cmd, UNPACK);
700
701
702
703
704 if (!cmd.valident && blk_idx != BLK_IDX_MGMT_ROUTE)
705 return -ENOENT;
706 cpu_relax();
707 } while (cmd.valid && --retries);
708
709 if (cmd.valid)
710 return -ETIMEDOUT;
711
712
713
714
715 if (entry)
716 ops->entry_packing(packed_buf, entry, UNPACK);
717 return 0;
718}
719
720int sja1105_dynamic_config_write(struct sja1105_private *priv,
721 enum sja1105_blk_idx blk_idx,
722 int index, void *entry, bool keep)
723{
724 const struct sja1105_dynamic_table_ops *ops;
725 struct sja1105_dyn_cmd cmd = {0};
726
727 u8 packed_buf[SJA1105_MAX_DYN_CMD_SIZE] = {0};
728 int rc;
729
730 if (blk_idx >= BLK_IDX_MAX_DYN)
731 return -ERANGE;
732
733 ops = &priv->info->dyn_ops[blk_idx];
734
735 if (index >= ops->max_entry_count)
736 return -ERANGE;
737 if (index < 0)
738 return -ERANGE;
739 if (!(ops->access & OP_WRITE))
740 return -EOPNOTSUPP;
741 if (!keep && !(ops->access & OP_DEL))
742 return -EOPNOTSUPP;
743 if (ops->packed_size > SJA1105_MAX_DYN_CMD_SIZE)
744 return -ERANGE;
745
746 cmd.valident = keep;
747 cmd.valid = true;
748 cmd.rdwrset = SPI_WRITE;
749 cmd.index = index;
750
751 if (!ops->cmd_packing)
752 return -EOPNOTSUPP;
753 ops->cmd_packing(packed_buf, &cmd, PACK);
754
755 if (!ops->entry_packing)
756 return -EOPNOTSUPP;
757
758
759
760
761
762 if (keep)
763 ops->entry_packing(packed_buf, entry, PACK);
764
765
766 rc = sja1105_spi_send_packed_buf(priv, SPI_WRITE, ops->addr,
767 packed_buf, ops->packed_size);
768 if (rc < 0)
769 return rc;
770
771 cmd = (struct sja1105_dyn_cmd) {0};
772 ops->cmd_packing(packed_buf, &cmd, UNPACK);
773 if (cmd.errors)
774 return -EINVAL;
775
776 return 0;
777}
778
779static u8 sja1105_crc8_add(u8 crc, u8 byte, u8 poly)
780{
781 int i;
782
783 for (i = 0; i < 8; i++) {
784 if ((crc ^ byte) & (1 << 7)) {
785 crc <<= 1;
786 crc ^= poly;
787 } else {
788 crc <<= 1;
789 }
790 byte <<= 1;
791 }
792 return crc;
793}
794
795
796
797
798
799
800
801u8 sja1105et_fdb_hash(struct sja1105_private *priv, const u8 *addr, u16 vid)
802{
803 struct sja1105_l2_lookup_params_entry *l2_lookup_params =
804 priv->static_config.tables[BLK_IDX_L2_LOOKUP_PARAMS].entries;
805 u64 poly_koopman = l2_lookup_params->poly;
806
807 u8 poly = (u8)(1 + (poly_koopman << 1));
808 u64 vlanid = l2_lookup_params->shared_learn ? 0 : vid;
809 u64 input = (vlanid << 48) | ether_addr_to_u64(addr);
810 u8 crc = 0;
811 int i;
812
813
814 for (i = 56; i >= 0; i -= 8) {
815 u8 byte = (input & (0xffull << i)) >> i;
816
817 crc = sja1105_crc8_add(crc, byte, poly);
818 }
819 return crc;
820}
821