Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/ncsw/Peripherals/FM/Pcd/fman_kg.c
48524 views
1
/*
2
* Copyright 2008-2012 Freescale Semiconductor Inc.
3
*
4
* Redistribution and use in source and binary forms, with or without
5
* modification, are permitted provided that the following conditions are met:
6
* * Redistributions of source code must retain the above copyright
7
* notice, this list of conditions and the following disclaimer.
8
* * Redistributions in binary form must reproduce the above copyright
9
* notice, this list of conditions and the following disclaimer in the
10
* documentation and/or other materials provided with the distribution.
11
* * Neither the name of Freescale Semiconductor nor the
12
* names of its contributors may be used to endorse or promote products
13
* derived from this software without specific prior written permission.
14
*
15
*
16
* ALTERNATIVELY, this software may be distributed under the terms of the
17
* GNU General Public License ("GPL") as published by the Free Software
18
* Foundation, either version 2 of that License or (at your option) any
19
* later version.
20
*
21
* THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
22
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24
* DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
25
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
*/
32
33
#include "fsl_fman_kg.h"
34
35
/****************************************/
36
/* static functions */
37
/****************************************/
38
39
40
static uint32_t build_ar_bind_scheme(uint8_t hwport_id, bool write)
41
{
42
uint32_t rw;
43
44
rw = write ? (uint32_t)FM_KG_KGAR_WRITE : (uint32_t)FM_KG_KGAR_READ;
45
46
return (uint32_t)(FM_KG_KGAR_GO |
47
rw |
48
FM_PCD_KG_KGAR_SEL_PORT_ENTRY |
49
hwport_id |
50
FM_PCD_KG_KGAR_SEL_PORT_WSEL_SP);
51
}
52
53
static void clear_pe_all_scheme(struct fman_kg_regs *regs, uint8_t hwport_id)
54
{
55
uint32_t ar;
56
57
fman_kg_write_sp(regs, 0xffffffff, 0);
58
59
ar = build_ar_bind_scheme(hwport_id, TRUE);
60
fman_kg_write_ar_wait(regs, ar);
61
}
62
63
static uint32_t build_ar_bind_cls_plan(uint8_t hwport_id, bool write)
64
{
65
uint32_t rw;
66
67
rw = write ? (uint32_t)FM_KG_KGAR_WRITE : (uint32_t)FM_KG_KGAR_READ;
68
69
return (uint32_t)(FM_KG_KGAR_GO |
70
rw |
71
FM_PCD_KG_KGAR_SEL_PORT_ENTRY |
72
hwport_id |
73
FM_PCD_KG_KGAR_SEL_PORT_WSEL_CPP);
74
}
75
76
static void clear_pe_all_cls_plan(struct fman_kg_regs *regs, uint8_t hwport_id)
77
{
78
uint32_t ar;
79
80
fman_kg_write_cpp(regs, 0);
81
82
ar = build_ar_bind_cls_plan(hwport_id, TRUE);
83
fman_kg_write_ar_wait(regs, ar);
84
}
85
86
static uint8_t get_gen_ht_code(enum fman_kg_gen_extract_src src,
87
bool no_validation,
88
uint8_t *offset)
89
{
90
int code;
91
92
switch (src) {
93
case E_FMAN_KG_GEN_EXTRACT_ETH:
94
code = no_validation ? 0x73 : 0x3;
95
break;
96
97
case E_FMAN_KG_GEN_EXTRACT_ETYPE:
98
code = no_validation ? 0x77 : 0x7;
99
break;
100
101
case E_FMAN_KG_GEN_EXTRACT_SNAP:
102
code = no_validation ? 0x74 : 0x4;
103
break;
104
105
case E_FMAN_KG_GEN_EXTRACT_VLAN_TCI_1:
106
code = no_validation ? 0x75 : 0x5;
107
break;
108
109
case E_FMAN_KG_GEN_EXTRACT_VLAN_TCI_N:
110
code = no_validation ? 0x76 : 0x6;
111
break;
112
113
case E_FMAN_KG_GEN_EXTRACT_PPPoE:
114
code = no_validation ? 0x78 : 0x8;
115
break;
116
117
case E_FMAN_KG_GEN_EXTRACT_MPLS_1:
118
code = no_validation ? 0x79 : 0x9;
119
break;
120
121
case E_FMAN_KG_GEN_EXTRACT_MPLS_2:
122
code = no_validation ? FM_KG_SCH_GEN_HT_INVALID : 0x19;
123
break;
124
125
case E_FMAN_KG_GEN_EXTRACT_MPLS_3:
126
code = no_validation ? FM_KG_SCH_GEN_HT_INVALID : 0x29;
127
break;
128
129
case E_FMAN_KG_GEN_EXTRACT_MPLS_N:
130
code = no_validation ? 0x7a : 0xa;
131
break;
132
133
case E_FMAN_KG_GEN_EXTRACT_IPv4_1:
134
code = no_validation ? 0x7b : 0xb;
135
break;
136
137
case E_FMAN_KG_GEN_EXTRACT_IPv6_1:
138
code = no_validation ? 0x7b : 0x1b;
139
break;
140
141
case E_FMAN_KG_GEN_EXTRACT_IPv4_2:
142
code = no_validation ? 0x7c : 0xc;
143
break;
144
145
case E_FMAN_KG_GEN_EXTRACT_IPv6_2:
146
code = no_validation ? 0x7c : 0x1c;
147
break;
148
149
case E_FMAN_KG_GEN_EXTRACT_MINENCAP:
150
code = no_validation ? 0x7c : 0x2c;
151
break;
152
153
case E_FMAN_KG_GEN_EXTRACT_IP_PID:
154
code = no_validation ? 0x72 : 0x2;
155
break;
156
157
case E_FMAN_KG_GEN_EXTRACT_GRE:
158
code = no_validation ? 0x7d : 0xd;
159
break;
160
161
case E_FMAN_KG_GEN_EXTRACT_TCP:
162
code = no_validation ? 0x7e : 0xe;
163
break;
164
165
case E_FMAN_KG_GEN_EXTRACT_UDP:
166
code = no_validation ? 0x7e : 0x1e;
167
break;
168
169
case E_FMAN_KG_GEN_EXTRACT_SCTP:
170
code = no_validation ? 0x7e : 0x3e;
171
break;
172
173
case E_FMAN_KG_GEN_EXTRACT_DCCP:
174
code = no_validation ? 0x7e : 0x4e;
175
break;
176
177
case E_FMAN_KG_GEN_EXTRACT_IPSEC_AH:
178
code = no_validation ? 0x7e : 0x2e;
179
break;
180
181
case E_FMAN_KG_GEN_EXTRACT_IPSEC_ESP:
182
code = no_validation ? 0x7e : 0x6e;
183
break;
184
185
case E_FMAN_KG_GEN_EXTRACT_SHIM_1:
186
code = 0x70;
187
break;
188
189
case E_FMAN_KG_GEN_EXTRACT_SHIM_2:
190
code = 0x71;
191
break;
192
193
case E_FMAN_KG_GEN_EXTRACT_FROM_DFLT:
194
code = 0x10;
195
break;
196
197
case E_FMAN_KG_GEN_EXTRACT_FROM_FRAME_START:
198
code = 0x40;
199
break;
200
201
case E_FMAN_KG_GEN_EXTRACT_FROM_PARSE_RESULT:
202
code = 0x20;
203
break;
204
205
case E_FMAN_KG_GEN_EXTRACT_FROM_END_OF_PARSE:
206
code = 0x7f;
207
break;
208
209
case E_FMAN_KG_GEN_EXTRACT_FROM_FQID:
210
code = 0x20;
211
*offset += 0x20;
212
break;
213
214
default:
215
code = FM_KG_SCH_GEN_HT_INVALID;
216
}
217
218
return (uint8_t)code;
219
}
220
221
static uint32_t build_ar_scheme(uint8_t scheme,
222
uint8_t hwport_id,
223
bool update_counter,
224
bool write)
225
{
226
uint32_t rw;
227
228
rw = (uint32_t)(write ? FM_KG_KGAR_WRITE : FM_KG_KGAR_READ);
229
230
return (uint32_t)(FM_KG_KGAR_GO |
231
rw |
232
FM_KG_KGAR_SEL_SCHEME_ENTRY |
233
hwport_id |
234
((uint32_t)scheme << FM_KG_KGAR_NUM_SHIFT) |
235
(update_counter ? FM_KG_KGAR_SCM_WSEL_UPDATE_CNT : 0));
236
}
237
238
static uint32_t build_ar_cls_plan(uint8_t grp,
239
uint8_t entries_mask,
240
uint8_t hwport_id,
241
bool write)
242
{
243
uint32_t rw;
244
245
rw = (uint32_t)(write ? FM_KG_KGAR_WRITE : FM_KG_KGAR_READ);
246
247
return (uint32_t)(FM_KG_KGAR_GO |
248
rw |
249
FM_PCD_KG_KGAR_SEL_CLS_PLAN_ENTRY |
250
hwport_id |
251
((uint32_t)grp << FM_KG_KGAR_NUM_SHIFT) |
252
((uint32_t)entries_mask << FM_KG_KGAR_WSEL_SHIFT));
253
}
254
255
int fman_kg_write_ar_wait(struct fman_kg_regs *regs, uint32_t fmkg_ar)
256
{
257
iowrite32be(fmkg_ar, &regs->fmkg_ar);
258
/* Wait for GO to be idle and read error */
259
while ((fmkg_ar = ioread32be(&regs->fmkg_ar)) & FM_KG_KGAR_GO) ;
260
if (fmkg_ar & FM_PCD_KG_KGAR_ERR)
261
return -EINVAL;
262
return 0;
263
}
264
265
void fman_kg_write_sp(struct fman_kg_regs *regs, uint32_t sp, bool add)
266
{
267
268
struct fman_kg_pe_regs *kgpe_regs;
269
uint32_t tmp;
270
271
kgpe_regs = (struct fman_kg_pe_regs *)&(regs->fmkg_indirect[0]);
272
tmp = ioread32be(&kgpe_regs->fmkg_pe_sp);
273
274
if (add)
275
tmp |= sp;
276
else /* clear */
277
tmp &= ~sp;
278
279
iowrite32be(tmp, &kgpe_regs->fmkg_pe_sp);
280
281
}
282
283
void fman_kg_write_cpp(struct fman_kg_regs *regs, uint32_t cpp)
284
{
285
struct fman_kg_pe_regs *kgpe_regs;
286
287
kgpe_regs = (struct fman_kg_pe_regs *)&(regs->fmkg_indirect[0]);
288
289
iowrite32be(cpp, &kgpe_regs->fmkg_pe_cpp);
290
}
291
292
void fman_kg_get_event(struct fman_kg_regs *regs,
293
uint32_t *event,
294
uint32_t *scheme_idx)
295
{
296
uint32_t mask, force;
297
298
*event = ioread32be(&regs->fmkg_eer);
299
mask = ioread32be(&regs->fmkg_eeer);
300
*scheme_idx = ioread32be(&regs->fmkg_seer);
301
*scheme_idx &= ioread32be(&regs->fmkg_seeer);
302
303
*event &= mask;
304
305
/* clear the forced events */
306
force = ioread32be(&regs->fmkg_feer);
307
if (force & *event)
308
iowrite32be(force & ~*event ,&regs->fmkg_feer);
309
310
iowrite32be(*event, &regs->fmkg_eer);
311
iowrite32be(*scheme_idx, &regs->fmkg_seer);
312
}
313
314
315
void fman_kg_init(struct fman_kg_regs *regs,
316
uint32_t exceptions,
317
uint32_t dflt_nia)
318
{
319
uint32_t tmp;
320
int i;
321
322
iowrite32be(FM_EX_KG_DOUBLE_ECC | FM_EX_KG_KEYSIZE_OVERFLOW,
323
&regs->fmkg_eer);
324
325
tmp = 0;
326
if (exceptions & FM_EX_KG_DOUBLE_ECC)
327
tmp |= FM_EX_KG_DOUBLE_ECC;
328
329
if (exceptions & FM_EX_KG_KEYSIZE_OVERFLOW)
330
tmp |= FM_EX_KG_KEYSIZE_OVERFLOW;
331
332
iowrite32be(tmp, &regs->fmkg_eeer);
333
iowrite32be(0, &regs->fmkg_fdor);
334
iowrite32be(0, &regs->fmkg_gdv0r);
335
iowrite32be(0, &regs->fmkg_gdv1r);
336
iowrite32be(dflt_nia, &regs->fmkg_gcr);
337
338
/* Clear binding between ports to schemes and classification plans
339
* so that all ports are not bound to any scheme/classification plan */
340
for (i = 0; i < FMAN_MAX_NUM_OF_HW_PORTS; i++) {
341
clear_pe_all_scheme(regs, (uint8_t)i);
342
clear_pe_all_cls_plan(regs, (uint8_t)i);
343
}
344
}
345
346
void fman_kg_enable_scheme_interrupts(struct fman_kg_regs *regs)
347
{
348
/* enable and enable all scheme interrupts */
349
iowrite32be(0xFFFFFFFF, &regs->fmkg_seer);
350
iowrite32be(0xFFFFFFFF, &regs->fmkg_seeer);
351
}
352
353
void fman_kg_enable(struct fman_kg_regs *regs)
354
{
355
iowrite32be(ioread32be(&regs->fmkg_gcr) | FM_KG_KGGCR_EN,
356
&regs->fmkg_gcr);
357
}
358
359
void fman_kg_disable(struct fman_kg_regs *regs)
360
{
361
iowrite32be(ioread32be(&regs->fmkg_gcr) & ~FM_KG_KGGCR_EN,
362
&regs->fmkg_gcr);
363
}
364
365
void fman_kg_set_data_after_prs(struct fman_kg_regs *regs, uint8_t offset)
366
{
367
iowrite32be(offset, &regs->fmkg_fdor);
368
}
369
370
void fman_kg_set_dflt_val(struct fman_kg_regs *regs,
371
uint8_t def_id,
372
uint32_t val)
373
{
374
if(def_id == 0)
375
iowrite32be(val, &regs->fmkg_gdv0r);
376
else
377
iowrite32be(val, &regs->fmkg_gdv1r);
378
}
379
380
381
void fman_kg_set_exception(struct fman_kg_regs *regs,
382
uint32_t exception,
383
bool enable)
384
{
385
uint32_t tmp;
386
387
tmp = ioread32be(&regs->fmkg_eeer);
388
389
if (enable) {
390
tmp |= exception;
391
} else {
392
tmp &= ~exception;
393
}
394
395
iowrite32be(tmp, &regs->fmkg_eeer);
396
}
397
398
void fman_kg_get_exception(struct fman_kg_regs *regs,
399
uint32_t *events,
400
uint32_t *scheme_ids,
401
bool clear)
402
{
403
uint32_t mask;
404
405
*events = ioread32be(&regs->fmkg_eer);
406
mask = ioread32be(&regs->fmkg_eeer);
407
*events &= mask;
408
409
*scheme_ids = 0;
410
411
if (*events & FM_EX_KG_KEYSIZE_OVERFLOW) {
412
*scheme_ids = ioread32be(&regs->fmkg_seer);
413
mask = ioread32be(&regs->fmkg_seeer);
414
*scheme_ids &= mask;
415
}
416
417
if (clear) {
418
iowrite32be(*scheme_ids, &regs->fmkg_seer);
419
iowrite32be(*events, &regs->fmkg_eer);
420
}
421
}
422
423
void fman_kg_get_capture(struct fman_kg_regs *regs,
424
struct fman_kg_ex_ecc_attr *ecc_attr,
425
bool clear)
426
{
427
uint32_t tmp;
428
429
tmp = ioread32be(&regs->fmkg_serc);
430
431
if (tmp & KG_FMKG_SERC_CAP) {
432
/* Captured data is valid */
433
ecc_attr->valid = TRUE;
434
ecc_attr->double_ecc =
435
(bool)((tmp & KG_FMKG_SERC_CET) ? TRUE : FALSE);
436
ecc_attr->single_ecc_count =
437
(uint8_t)((tmp & KG_FMKG_SERC_CNT_MSK) >>
438
KG_FMKG_SERC_CNT_SHIFT);
439
ecc_attr->addr = (uint16_t)(tmp & KG_FMKG_SERC_ADDR_MSK);
440
441
if (clear)
442
iowrite32be(KG_FMKG_SERC_CAP, &regs->fmkg_serc);
443
} else {
444
/* No ECC error is captured */
445
ecc_attr->valid = FALSE;
446
}
447
}
448
449
int fman_kg_build_scheme(struct fman_kg_scheme_params *params,
450
struct fman_kg_scheme_regs *scheme_regs)
451
{
452
struct fman_kg_extract_params *extract_params;
453
struct fman_kg_gen_extract_params *gen_params;
454
uint32_t tmp_reg, i, select, mask, fqb;
455
uint8_t offset, shift, ht;
456
457
/* Zero out all registers so no need to care about unused ones */
458
memset(scheme_regs, 0, sizeof(struct fman_kg_scheme_regs));
459
460
/* Mode register */
461
tmp_reg = fm_kg_build_nia(params->next_engine,
462
params->next_engine_action);
463
if (tmp_reg == KG_NIA_INVALID) {
464
return -EINVAL;
465
}
466
467
if (params->next_engine == E_FMAN_PCD_PLCR) {
468
tmp_reg |= FMAN_KG_SCH_MODE_NIA_PLCR;
469
}
470
else if (params->next_engine == E_FMAN_PCD_CC) {
471
tmp_reg |= (uint32_t)params->cc_params.base_offset <<
472
FMAN_KG_SCH_MODE_CCOBASE_SHIFT;
473
}
474
475
tmp_reg |= FMAN_KG_SCH_MODE_EN;
476
scheme_regs->kgse_mode = tmp_reg;
477
478
/* Match vector */
479
scheme_regs->kgse_mv = params->match_vector;
480
481
extract_params = &params->extract_params;
482
483
/* Scheme default values registers */
484
scheme_regs->kgse_dv0 = extract_params->def_scheme_0;
485
scheme_regs->kgse_dv1 = extract_params->def_scheme_1;
486
487
/* Extract Known Fields Command register */
488
scheme_regs->kgse_ekfc = extract_params->known_fields;
489
490
/* Entry Extract Known Default Value register */
491
tmp_reg = 0;
492
tmp_reg |= extract_params->known_fields_def.mac_addr <<
493
FMAN_KG_SCH_DEF_MAC_ADDR_SHIFT;
494
tmp_reg |= extract_params->known_fields_def.vlan_tci <<
495
FMAN_KG_SCH_DEF_VLAN_TCI_SHIFT;
496
tmp_reg |= extract_params->known_fields_def.etype <<
497
FMAN_KG_SCH_DEF_ETYPE_SHIFT;
498
tmp_reg |= extract_params->known_fields_def.ppp_sid <<
499
FMAN_KG_SCH_DEF_PPP_SID_SHIFT;
500
tmp_reg |= extract_params->known_fields_def.ppp_pid <<
501
FMAN_KG_SCH_DEF_PPP_PID_SHIFT;
502
tmp_reg |= extract_params->known_fields_def.mpls <<
503
FMAN_KG_SCH_DEF_MPLS_SHIFT;
504
tmp_reg |= extract_params->known_fields_def.ip_addr <<
505
FMAN_KG_SCH_DEF_IP_ADDR_SHIFT;
506
tmp_reg |= extract_params->known_fields_def.ptype <<
507
FMAN_KG_SCH_DEF_PTYPE_SHIFT;
508
tmp_reg |= extract_params->known_fields_def.ip_tos_tc <<
509
FMAN_KG_SCH_DEF_IP_TOS_TC_SHIFT;
510
tmp_reg |= extract_params->known_fields_def.ipv6_fl <<
511
FMAN_KG_SCH_DEF_IPv6_FL_SHIFT;
512
tmp_reg |= extract_params->known_fields_def.ipsec_spi <<
513
FMAN_KG_SCH_DEF_IPSEC_SPI_SHIFT;
514
tmp_reg |= extract_params->known_fields_def.l4_port <<
515
FMAN_KG_SCH_DEF_L4_PORT_SHIFT;
516
tmp_reg |= extract_params->known_fields_def.tcp_flg <<
517
FMAN_KG_SCH_DEF_TCP_FLG_SHIFT;
518
519
scheme_regs->kgse_ekdv = tmp_reg;
520
521
/* Generic extract registers */
522
if (extract_params->gen_extract_num > FM_KG_NUM_OF_GENERIC_REGS) {
523
return -EINVAL;
524
}
525
526
for (i = 0; i < extract_params->gen_extract_num; i++) {
527
gen_params = extract_params->gen_extract + i;
528
529
tmp_reg = FMAN_KG_SCH_GEN_VALID;
530
tmp_reg |= (uint32_t)gen_params->def_val <<
531
FMAN_KG_SCH_GEN_DEF_SHIFT;
532
533
if (gen_params->type == E_FMAN_KG_HASH_EXTRACT) {
534
if ((gen_params->extract > FMAN_KG_SCH_GEN_SIZE_MAX) ||
535
(gen_params->extract == 0)) {
536
return -EINVAL;
537
}
538
} else {
539
tmp_reg |= FMAN_KG_SCH_GEN_OR;
540
}
541
542
tmp_reg |= (uint32_t)gen_params->extract <<
543
FMAN_KG_SCH_GEN_SIZE_SHIFT;
544
tmp_reg |= (uint32_t)gen_params->mask <<
545
FMAN_KG_SCH_GEN_MASK_SHIFT;
546
547
offset = gen_params->offset;
548
ht = get_gen_ht_code(gen_params->src,
549
gen_params->no_validation,
550
&offset);
551
tmp_reg |= (uint32_t)ht << FMAN_KG_SCH_GEN_HT_SHIFT;
552
tmp_reg |= offset;
553
554
scheme_regs->kgse_gec[i] = tmp_reg;
555
}
556
557
/* Masks registers */
558
if (extract_params->masks_num > FM_KG_EXTRACT_MASKS_NUM) {
559
return -EINVAL;
560
}
561
562
select = 0;
563
mask = 0;
564
fqb = 0;
565
for (i = 0; i < extract_params->masks_num; i++) {
566
/* MCSx fields */
567
KG_GET_MASK_SEL_SHIFT(shift, i);
568
if (extract_params->masks[i].is_known) {
569
/* Mask known field */
570
select |= extract_params->masks[i].field_or_gen_idx <<
571
shift;
572
} else {
573
/* Mask generic extract */
574
select |= (extract_params->masks[i].field_or_gen_idx +
575
FM_KG_MASK_SEL_GEN_BASE) << shift;
576
}
577
578
/* MOx fields - spread between se_bmch and se_fqb registers */
579
KG_GET_MASK_OFFSET_SHIFT(shift, i);
580
if (i < 2) {
581
select |= (uint32_t)extract_params->masks[i].offset <<
582
shift;
583
} else {
584
fqb |= (uint32_t)extract_params->masks[i].offset <<
585
shift;
586
}
587
588
/* BMx fields */
589
KG_GET_MASK_SHIFT(shift, i);
590
mask |= (uint32_t)extract_params->masks[i].mask << shift;
591
}
592
593
/* Finish with rest of BMx fileds -
594
* don't mask bits for unused masks by setting
595
* corresponding BMx field = 0xFF */
596
for (i = extract_params->masks_num; i < FM_KG_EXTRACT_MASKS_NUM; i++) {
597
KG_GET_MASK_SHIFT(shift, i);
598
mask |= 0xFF << shift;
599
}
600
601
scheme_regs->kgse_bmch = select;
602
scheme_regs->kgse_bmcl = mask;
603
604
/* Finish with FQB register initialization.
605
* Check fqid is 24-bit value. */
606
if (params->base_fqid & ~0x00FFFFFF) {
607
return -EINVAL;
608
}
609
610
fqb |= params->base_fqid;
611
scheme_regs->kgse_fqb = fqb;
612
613
/* Hash Configuration register */
614
tmp_reg = 0;
615
if (params->hash_params.use_hash) {
616
/* Check hash mask is 24-bit value */
617
if (params->hash_params.mask & ~0x00FFFFFF) {
618
return -EINVAL;
619
}
620
621
/* Hash function produces 64-bit value, 24 bits of that
622
* are used to generate fq_id and policer profile.
623
* Thus, maximal shift is 40 bits to allow 24 bits out of 64.
624
*/
625
if (params->hash_params.shift_r > FMAN_KG_SCH_HASH_HSHIFT_MAX) {
626
return -EINVAL;
627
}
628
629
tmp_reg |= params->hash_params.mask;
630
tmp_reg |= (uint32_t)params->hash_params.shift_r <<
631
FMAN_KG_SCH_HASH_HSHIFT_SHIFT;
632
633
if (params->hash_params.sym) {
634
tmp_reg |= FMAN_KG_SCH_HASH_SYM;
635
}
636
637
}
638
639
if (params->bypass_fqid_gen) {
640
tmp_reg |= FMAN_KG_SCH_HASH_NO_FQID_GEN;
641
}
642
643
scheme_regs->kgse_hc = tmp_reg;
644
645
/* Policer Profile register */
646
if (params->policer_params.bypass_pp_gen) {
647
tmp_reg = 0;
648
} else {
649
/* Lower 8 bits of 24-bits extracted from hash result
650
* are used for policer profile generation.
651
* That leaves maximum shift value = 23. */
652
if (params->policer_params.shift > FMAN_KG_SCH_PP_SHIFT_MAX) {
653
return -EINVAL;
654
}
655
656
tmp_reg = params->policer_params.base;
657
tmp_reg |= ((uint32_t)params->policer_params.shift <<
658
FMAN_KG_SCH_PP_SH_SHIFT) &
659
FMAN_KG_SCH_PP_SH_MASK;
660
tmp_reg |= ((uint32_t)params->policer_params.shift <<
661
FMAN_KG_SCH_PP_SL_SHIFT) &
662
FMAN_KG_SCH_PP_SL_MASK;
663
tmp_reg |= (uint32_t)params->policer_params.mask <<
664
FMAN_KG_SCH_PP_MASK_SHIFT;
665
}
666
667
scheme_regs->kgse_ppc = tmp_reg;
668
669
/* Coarse Classification Bit Select register */
670
if (params->next_engine == E_FMAN_PCD_CC) {
671
scheme_regs->kgse_ccbs = params->cc_params.qlcv_bits_sel;
672
}
673
674
/* Packets Counter register */
675
if (params->update_counter) {
676
scheme_regs->kgse_spc = params->counter_value;
677
}
678
679
return 0;
680
}
681
682
int fman_kg_write_scheme(struct fman_kg_regs *regs,
683
uint8_t scheme_id,
684
uint8_t hwport_id,
685
struct fman_kg_scheme_regs *scheme_regs,
686
bool update_counter)
687
{
688
struct fman_kg_scheme_regs *kgse_regs;
689
uint32_t tmp_reg;
690
int err, i;
691
692
/* Write indirect scheme registers */
693
kgse_regs = (struct fman_kg_scheme_regs *)&(regs->fmkg_indirect[0]);
694
695
iowrite32be(scheme_regs->kgse_mode, &kgse_regs->kgse_mode);
696
iowrite32be(scheme_regs->kgse_ekfc, &kgse_regs->kgse_ekfc);
697
iowrite32be(scheme_regs->kgse_ekdv, &kgse_regs->kgse_ekdv);
698
iowrite32be(scheme_regs->kgse_bmch, &kgse_regs->kgse_bmch);
699
iowrite32be(scheme_regs->kgse_bmcl, &kgse_regs->kgse_bmcl);
700
iowrite32be(scheme_regs->kgse_fqb, &kgse_regs->kgse_fqb);
701
iowrite32be(scheme_regs->kgse_hc, &kgse_regs->kgse_hc);
702
iowrite32be(scheme_regs->kgse_ppc, &kgse_regs->kgse_ppc);
703
iowrite32be(scheme_regs->kgse_spc, &kgse_regs->kgse_spc);
704
iowrite32be(scheme_regs->kgse_dv0, &kgse_regs->kgse_dv0);
705
iowrite32be(scheme_regs->kgse_dv1, &kgse_regs->kgse_dv1);
706
iowrite32be(scheme_regs->kgse_ccbs, &kgse_regs->kgse_ccbs);
707
iowrite32be(scheme_regs->kgse_mv, &kgse_regs->kgse_mv);
708
709
for (i = 0 ; i < FM_KG_NUM_OF_GENERIC_REGS ; i++)
710
iowrite32be(scheme_regs->kgse_gec[i], &kgse_regs->kgse_gec[i]);
711
712
/* Write AR (Action register) */
713
tmp_reg = build_ar_scheme(scheme_id, hwport_id, update_counter, TRUE);
714
err = fman_kg_write_ar_wait(regs, tmp_reg);
715
return err;
716
}
717
718
int fman_kg_delete_scheme(struct fman_kg_regs *regs,
719
uint8_t scheme_id,
720
uint8_t hwport_id)
721
{
722
struct fman_kg_scheme_regs *kgse_regs;
723
uint32_t tmp_reg;
724
int err, i;
725
726
kgse_regs = (struct fman_kg_scheme_regs *)&(regs->fmkg_indirect[0]);
727
728
/* Clear all registers including enable bit in mode register */
729
for (i = 0; i < (sizeof(struct fman_kg_scheme_regs)) / 4; ++i) {
730
iowrite32be(0, ((uint32_t *)kgse_regs + i));
731
}
732
733
/* Write AR (Action register) */
734
tmp_reg = build_ar_scheme(scheme_id, hwport_id, FALSE, TRUE);
735
err = fman_kg_write_ar_wait(regs, tmp_reg);
736
return err;
737
}
738
739
int fman_kg_get_scheme_counter(struct fman_kg_regs *regs,
740
uint8_t scheme_id,
741
uint8_t hwport_id,
742
uint32_t *counter)
743
{
744
struct fman_kg_scheme_regs *kgse_regs;
745
uint32_t tmp_reg;
746
int err;
747
748
kgse_regs = (struct fman_kg_scheme_regs *)&(regs->fmkg_indirect[0]);
749
750
tmp_reg = build_ar_scheme(scheme_id, hwport_id, TRUE, FALSE);
751
err = fman_kg_write_ar_wait(regs, tmp_reg);
752
753
if (err != 0)
754
return err;
755
756
*counter = ioread32be(&kgse_regs->kgse_spc);
757
758
return 0;
759
}
760
761
int fman_kg_set_scheme_counter(struct fman_kg_regs *regs,
762
uint8_t scheme_id,
763
uint8_t hwport_id,
764
uint32_t counter)
765
{
766
struct fman_kg_scheme_regs *kgse_regs;
767
uint32_t tmp_reg;
768
int err;
769
770
kgse_regs = (struct fman_kg_scheme_regs *)&(regs->fmkg_indirect[0]);
771
772
tmp_reg = build_ar_scheme(scheme_id, hwport_id, TRUE, FALSE);
773
774
err = fman_kg_write_ar_wait(regs, tmp_reg);
775
if (err != 0)
776
return err;
777
778
/* Keygen indirect access memory contains all scheme_id registers
779
* by now. Change only counter value. */
780
iowrite32be(counter, &kgse_regs->kgse_spc);
781
782
/* Write back scheme registers */
783
tmp_reg = build_ar_scheme(scheme_id, hwport_id, TRUE, TRUE);
784
err = fman_kg_write_ar_wait(regs, tmp_reg);
785
786
return err;
787
}
788
789
uint32_t fman_kg_get_schemes_total_counter(struct fman_kg_regs *regs)
790
{
791
return ioread32be(&regs->fmkg_tpc);
792
}
793
794
int fman_kg_build_cls_plan(struct fman_kg_cls_plan_params *params,
795
struct fman_kg_cp_regs *cls_plan_regs)
796
{
797
uint8_t entries_set, entry_bit;
798
int i;
799
800
/* Zero out all group's register */
801
memset(cls_plan_regs, 0, sizeof(struct fman_kg_cp_regs));
802
803
/* Go over all classification entries in params->entries_mask and
804
* configure the corresponding cpe register */
805
entries_set = params->entries_mask;
806
for (i = 0; entries_set; i++) {
807
entry_bit = (uint8_t)(0x80 >> i);
808
if ((entry_bit & entries_set) == 0)
809
continue;
810
entries_set ^= entry_bit;
811
cls_plan_regs->kgcpe[i] = params->mask_vector[i];
812
}
813
814
return 0;
815
}
816
817
int fman_kg_write_cls_plan(struct fman_kg_regs *regs,
818
uint8_t grp_id,
819
uint8_t entries_mask,
820
uint8_t hwport_id,
821
struct fman_kg_cp_regs *cls_plan_regs)
822
{
823
struct fman_kg_cp_regs *kgcpe_regs;
824
uint32_t tmp_reg;
825
int i, err;
826
827
/* Check group index is valid and the group isn't empty */
828
if (grp_id >= FM_KG_CLS_PLAN_GRPS_NUM)
829
return -EINVAL;
830
831
/* Write indirect classification plan registers */
832
kgcpe_regs = (struct fman_kg_cp_regs *)&(regs->fmkg_indirect[0]);
833
834
for (i = 0; i < FM_KG_NUM_CLS_PLAN_ENTR; i++) {
835
iowrite32be(cls_plan_regs->kgcpe[i], &kgcpe_regs->kgcpe[i]);
836
}
837
838
tmp_reg = build_ar_cls_plan(grp_id, entries_mask, hwport_id, TRUE);
839
err = fman_kg_write_ar_wait(regs, tmp_reg);
840
return err;
841
}
842
843
int fman_kg_write_bind_schemes(struct fman_kg_regs *regs,
844
uint8_t hwport_id,
845
uint32_t schemes)
846
{
847
struct fman_kg_pe_regs *kg_pe_regs;
848
uint32_t tmp_reg;
849
int err;
850
851
kg_pe_regs = (struct fman_kg_pe_regs *)&(regs->fmkg_indirect[0]);
852
853
iowrite32be(schemes, &kg_pe_regs->fmkg_pe_sp);
854
855
tmp_reg = build_ar_bind_scheme(hwport_id, TRUE);
856
err = fman_kg_write_ar_wait(regs, tmp_reg);
857
return err;
858
}
859
860
int fman_kg_build_bind_cls_plans(uint8_t grp_base,
861
uint8_t grp_mask,
862
uint32_t *bind_cls_plans)
863
{
864
/* Check grp_base and grp_mask are 5-bits values */
865
if ((grp_base & ~0x0000001F) || (grp_mask & ~0x0000001F))
866
return -EINVAL;
867
868
*bind_cls_plans = (uint32_t) ((grp_mask << FMAN_KG_PE_CPP_MASK_SHIFT) | grp_base);
869
return 0;
870
}
871
872
873
int fman_kg_write_bind_cls_plans(struct fman_kg_regs *regs,
874
uint8_t hwport_id,
875
uint32_t bind_cls_plans)
876
{
877
struct fman_kg_pe_regs *kg_pe_regs;
878
uint32_t tmp_reg;
879
int err;
880
881
kg_pe_regs = (struct fman_kg_pe_regs *)&(regs->fmkg_indirect[0]);
882
883
iowrite32be(bind_cls_plans, &kg_pe_regs->fmkg_pe_cpp);
884
885
tmp_reg = build_ar_bind_cls_plan(hwport_id, TRUE);
886
err = fman_kg_write_ar_wait(regs, tmp_reg);
887
return err;
888
}
889
890