Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/ncsw/Peripherals/FM/MAC/fman_memac.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
34
#include "fsl_fman_memac.h"
35
36
37
uint32_t fman_memac_get_event(struct memac_regs *regs, uint32_t ev_mask)
38
{
39
return ioread32be(&regs->ievent) & ev_mask;
40
}
41
42
uint32_t fman_memac_get_interrupt_mask(struct memac_regs *regs)
43
{
44
return ioread32be(&regs->imask);
45
}
46
47
void fman_memac_ack_event(struct memac_regs *regs, uint32_t ev_mask)
48
{
49
iowrite32be(ev_mask, &regs->ievent);
50
}
51
52
void fman_memac_set_promiscuous(struct memac_regs *regs, bool val)
53
{
54
uint32_t tmp;
55
56
tmp = ioread32be(&regs->command_config);
57
58
if (val)
59
tmp |= CMD_CFG_PROMIS_EN;
60
else
61
tmp &= ~CMD_CFG_PROMIS_EN;
62
63
iowrite32be(tmp, &regs->command_config);
64
}
65
66
void fman_memac_clear_addr_in_paddr(struct memac_regs *regs,
67
uint8_t paddr_num)
68
{
69
if (paddr_num == 0) {
70
iowrite32be(0, &regs->mac_addr0.mac_addr_l);
71
iowrite32be(0, &regs->mac_addr0.mac_addr_u);
72
} else {
73
iowrite32be(0x0, &regs->mac_addr[paddr_num - 1].mac_addr_l);
74
iowrite32be(0x0, &regs->mac_addr[paddr_num - 1].mac_addr_u);
75
}
76
}
77
78
void fman_memac_add_addr_in_paddr(struct memac_regs *regs,
79
uint8_t *adr,
80
uint8_t paddr_num)
81
{
82
uint32_t tmp0, tmp1;
83
84
tmp0 = (uint32_t)(adr[0] |
85
adr[1] << 8 |
86
adr[2] << 16 |
87
adr[3] << 24);
88
tmp1 = (uint32_t)(adr[4] | adr[5] << 8);
89
90
if (paddr_num == 0) {
91
iowrite32be(tmp0, &regs->mac_addr0.mac_addr_l);
92
iowrite32be(tmp1, &regs->mac_addr0.mac_addr_u);
93
} else {
94
iowrite32be(tmp0, &regs->mac_addr[paddr_num-1].mac_addr_l);
95
iowrite32be(tmp1, &regs->mac_addr[paddr_num-1].mac_addr_u);
96
}
97
}
98
99
void fman_memac_enable(struct memac_regs *regs, bool apply_rx, bool apply_tx)
100
{
101
uint32_t tmp;
102
103
tmp = ioread32be(&regs->command_config);
104
105
if (apply_rx)
106
tmp |= CMD_CFG_RX_EN;
107
108
if (apply_tx)
109
tmp |= CMD_CFG_TX_EN;
110
111
iowrite32be(tmp, &regs->command_config);
112
}
113
114
void fman_memac_disable(struct memac_regs *regs, bool apply_rx, bool apply_tx)
115
{
116
uint32_t tmp;
117
118
tmp = ioread32be(&regs->command_config);
119
120
if (apply_rx)
121
tmp &= ~CMD_CFG_RX_EN;
122
123
if (apply_tx)
124
tmp &= ~CMD_CFG_TX_EN;
125
126
iowrite32be(tmp, &regs->command_config);
127
}
128
129
void fman_memac_reset_stat(struct memac_regs *regs)
130
{
131
uint32_t tmp;
132
133
tmp = ioread32be(&regs->statn_config);
134
135
tmp |= STATS_CFG_CLR;
136
137
iowrite32be(tmp, &regs->statn_config);
138
139
while (ioread32be(&regs->statn_config) & STATS_CFG_CLR);
140
}
141
142
void fman_memac_reset(struct memac_regs *regs)
143
{
144
uint32_t tmp;
145
146
tmp = ioread32be(&regs->command_config);
147
148
tmp |= CMD_CFG_SW_RESET;
149
150
iowrite32be(tmp, &regs->command_config);
151
152
while (ioread32be(&regs->command_config) & CMD_CFG_SW_RESET);
153
}
154
155
int fman_memac_init(struct memac_regs *regs,
156
struct memac_cfg *cfg,
157
enum enet_interface enet_interface,
158
enum enet_speed enet_speed,
159
bool slow_10g_if,
160
uint32_t exceptions)
161
{
162
uint32_t tmp;
163
164
/* Config */
165
tmp = 0;
166
if (cfg->wan_mode_enable)
167
tmp |= CMD_CFG_WAN_MODE;
168
if (cfg->promiscuous_mode_enable)
169
tmp |= CMD_CFG_PROMIS_EN;
170
if (cfg->pause_forward_enable)
171
tmp |= CMD_CFG_PAUSE_FWD;
172
if (cfg->pause_ignore)
173
tmp |= CMD_CFG_PAUSE_IGNORE;
174
if (cfg->tx_addr_ins_enable)
175
tmp |= CMD_CFG_TX_ADDR_INS;
176
if (cfg->loopback_enable)
177
tmp |= CMD_CFG_LOOPBACK_EN;
178
if (cfg->cmd_frame_enable)
179
tmp |= CMD_CFG_CNT_FRM_EN;
180
if (cfg->send_idle_enable)
181
tmp |= CMD_CFG_SEND_IDLE;
182
if (cfg->no_length_check_enable)
183
tmp |= CMD_CFG_NO_LEN_CHK;
184
if (cfg->rx_sfd_any)
185
tmp |= CMD_CFG_SFD_ANY;
186
if (cfg->pad_enable)
187
tmp |= CMD_CFG_TX_PAD_EN;
188
if (cfg->wake_on_lan)
189
tmp |= CMD_CFG_MG;
190
191
tmp |= CMD_CFG_CRC_FWD;
192
193
iowrite32be(tmp, &regs->command_config);
194
195
/* Max Frame Length */
196
iowrite32be((uint32_t)cfg->max_frame_length, &regs->maxfrm);
197
198
/* Pause Time */
199
iowrite32be((uint32_t)cfg->pause_quanta, &regs->pause_quanta[0]);
200
iowrite32be((uint32_t)0, &regs->pause_thresh[0]);
201
202
/* IF_MODE */
203
tmp = 0;
204
switch (enet_interface) {
205
case E_ENET_IF_XGMII:
206
case E_ENET_IF_XFI:
207
tmp |= IF_MODE_XGMII;
208
break;
209
default:
210
tmp |= IF_MODE_GMII;
211
if (enet_interface == E_ENET_IF_RGMII && !cfg->loopback_enable)
212
tmp |= IF_MODE_RGMII | IF_MODE_RGMII_AUTO;
213
}
214
iowrite32be(tmp, &regs->if_mode);
215
216
/* TX_FIFO_SECTIONS */
217
tmp = 0;
218
if (enet_interface == E_ENET_IF_XGMII ||
219
enet_interface == E_ENET_IF_XFI) {
220
if(slow_10g_if) {
221
tmp |= (TX_FIFO_SECTIONS_TX_AVAIL_SLOW_10G |
222
TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_10G);
223
} else {
224
tmp |= (TX_FIFO_SECTIONS_TX_AVAIL_10G |
225
TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_10G);
226
}
227
} else {
228
tmp |= (TX_FIFO_SECTIONS_TX_AVAIL_1G |
229
TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_1G);
230
}
231
iowrite32be(tmp, &regs->tx_fifo_sections);
232
233
/* clear all pending events and set-up interrupts */
234
fman_memac_ack_event(regs, 0xffffffff);
235
fman_memac_set_exception(regs, exceptions, TRUE);
236
237
return 0;
238
}
239
240
void fman_memac_set_exception(struct memac_regs *regs, uint32_t val, bool enable)
241
{
242
uint32_t tmp;
243
244
tmp = ioread32be(&regs->imask);
245
if (enable)
246
tmp |= val;
247
else
248
tmp &= ~val;
249
250
iowrite32be(tmp, &regs->imask);
251
}
252
253
void fman_memac_reset_filter_table(struct memac_regs *regs)
254
{
255
uint32_t i;
256
for (i = 0; i < 64; i++)
257
iowrite32be(i & ~HASH_CTRL_MCAST_EN, &regs->hashtable_ctrl);
258
}
259
260
void fman_memac_set_hash_table_entry(struct memac_regs *regs, uint32_t crc)
261
{
262
iowrite32be(crc | HASH_CTRL_MCAST_EN, &regs->hashtable_ctrl);
263
}
264
265
void fman_memac_set_hash_table(struct memac_regs *regs, uint32_t val)
266
{
267
iowrite32be(val, &regs->hashtable_ctrl);
268
}
269
270
uint16_t fman_memac_get_max_frame_len(struct memac_regs *regs)
271
{
272
uint32_t tmp;
273
274
tmp = ioread32be(&regs->maxfrm);
275
276
return(uint16_t)tmp;
277
}
278
279
280
void fman_memac_set_tx_pause_frames(struct memac_regs *regs,
281
uint8_t priority,
282
uint16_t pause_time,
283
uint16_t thresh_time)
284
{
285
uint32_t tmp;
286
287
tmp = ioread32be(&regs->tx_fifo_sections);
288
289
if (priority == 0xff) {
290
GET_TX_EMPTY_DEFAULT_VALUE(tmp);
291
iowrite32be(tmp, &regs->tx_fifo_sections);
292
293
tmp = ioread32be(&regs->command_config);
294
tmp &= ~CMD_CFG_PFC_MODE;
295
priority = 0;
296
} else {
297
GET_TX_EMPTY_PFC_VALUE(tmp);
298
iowrite32be(tmp, &regs->tx_fifo_sections);
299
300
tmp = ioread32be(&regs->command_config);
301
tmp |= CMD_CFG_PFC_MODE;
302
}
303
304
iowrite32be(tmp, &regs->command_config);
305
306
tmp = ioread32be(&regs->pause_quanta[priority / 2]);
307
if (priority % 2)
308
tmp &= 0x0000FFFF;
309
else
310
tmp &= 0xFFFF0000;
311
tmp |= ((uint32_t)pause_time << (16 * (priority % 2)));
312
iowrite32be(tmp, &regs->pause_quanta[priority / 2]);
313
314
tmp = ioread32be(&regs->pause_thresh[priority / 2]);
315
if (priority % 2)
316
tmp &= 0x0000FFFF;
317
else
318
tmp &= 0xFFFF0000;
319
tmp |= ((uint32_t)thresh_time<<(16 * (priority % 2)));
320
iowrite32be(tmp, &regs->pause_thresh[priority / 2]);
321
}
322
323
void fman_memac_set_rx_ignore_pause_frames(struct memac_regs *regs,bool enable)
324
{
325
uint32_t tmp;
326
327
tmp = ioread32be(&regs->command_config);
328
if (enable)
329
tmp |= CMD_CFG_PAUSE_IGNORE;
330
else
331
tmp &= ~CMD_CFG_PAUSE_IGNORE;
332
333
iowrite32be(tmp, &regs->command_config);
334
}
335
336
void fman_memac_set_wol(struct memac_regs *regs, bool enable)
337
{
338
uint32_t tmp;
339
340
tmp = ioread32be(&regs->command_config);
341
342
if (enable)
343
tmp |= CMD_CFG_MG;
344
else
345
tmp &= ~CMD_CFG_MG;
346
347
iowrite32be(tmp, &regs->command_config);
348
}
349
350
#define GET_MEMAC_CNTR_64(bn) \
351
(ioread32be(&regs->bn ## _l) | \
352
((uint64_t)ioread32be(&regs->bn ## _u) << 32))
353
354
uint64_t fman_memac_get_counter(struct memac_regs *regs,
355
enum memac_counters reg_name)
356
{
357
uint64_t ret_val;
358
359
switch (reg_name) {
360
case E_MEMAC_COUNTER_R64:
361
ret_val = GET_MEMAC_CNTR_64(r64);
362
break;
363
case E_MEMAC_COUNTER_R127:
364
ret_val = GET_MEMAC_CNTR_64(r127);
365
break;
366
case E_MEMAC_COUNTER_R255:
367
ret_val = GET_MEMAC_CNTR_64(r255);
368
break;
369
case E_MEMAC_COUNTER_R511:
370
ret_val = GET_MEMAC_CNTR_64(r511);
371
break;
372
case E_MEMAC_COUNTER_R1023:
373
ret_val = GET_MEMAC_CNTR_64(r1023);
374
break;
375
case E_MEMAC_COUNTER_R1518:
376
ret_val = GET_MEMAC_CNTR_64(r1518);
377
break;
378
case E_MEMAC_COUNTER_R1519X:
379
ret_val = GET_MEMAC_CNTR_64(r1519x);
380
break;
381
case E_MEMAC_COUNTER_RFRG:
382
ret_val = GET_MEMAC_CNTR_64(rfrg);
383
break;
384
case E_MEMAC_COUNTER_RJBR:
385
ret_val = GET_MEMAC_CNTR_64(rjbr);
386
break;
387
case E_MEMAC_COUNTER_RDRP:
388
ret_val = GET_MEMAC_CNTR_64(rdrp);
389
break;
390
case E_MEMAC_COUNTER_RALN:
391
ret_val = GET_MEMAC_CNTR_64(raln);
392
break;
393
case E_MEMAC_COUNTER_TUND:
394
ret_val = GET_MEMAC_CNTR_64(tund);
395
break;
396
case E_MEMAC_COUNTER_ROVR:
397
ret_val = GET_MEMAC_CNTR_64(rovr);
398
break;
399
case E_MEMAC_COUNTER_RXPF:
400
ret_val = GET_MEMAC_CNTR_64(rxpf);
401
break;
402
case E_MEMAC_COUNTER_TXPF:
403
ret_val = GET_MEMAC_CNTR_64(txpf);
404
break;
405
case E_MEMAC_COUNTER_ROCT:
406
ret_val = GET_MEMAC_CNTR_64(roct);
407
break;
408
case E_MEMAC_COUNTER_RMCA:
409
ret_val = GET_MEMAC_CNTR_64(rmca);
410
break;
411
case E_MEMAC_COUNTER_RBCA:
412
ret_val = GET_MEMAC_CNTR_64(rbca);
413
break;
414
case E_MEMAC_COUNTER_RPKT:
415
ret_val = GET_MEMAC_CNTR_64(rpkt);
416
break;
417
case E_MEMAC_COUNTER_RUCA:
418
ret_val = GET_MEMAC_CNTR_64(ruca);
419
break;
420
case E_MEMAC_COUNTER_RERR:
421
ret_val = GET_MEMAC_CNTR_64(rerr);
422
break;
423
case E_MEMAC_COUNTER_TOCT:
424
ret_val = GET_MEMAC_CNTR_64(toct);
425
break;
426
case E_MEMAC_COUNTER_TMCA:
427
ret_val = GET_MEMAC_CNTR_64(tmca);
428
break;
429
case E_MEMAC_COUNTER_TBCA:
430
ret_val = GET_MEMAC_CNTR_64(tbca);
431
break;
432
case E_MEMAC_COUNTER_TUCA:
433
ret_val = GET_MEMAC_CNTR_64(tuca);
434
break;
435
case E_MEMAC_COUNTER_TERR:
436
ret_val = GET_MEMAC_CNTR_64(terr);
437
break;
438
default:
439
ret_val = 0;
440
}
441
442
return ret_val;
443
}
444
445
void fman_memac_adjust_link(struct memac_regs *regs,
446
enum enet_interface iface_mode,
447
enum enet_speed speed, bool full_dx)
448
{
449
uint32_t tmp;
450
451
tmp = ioread32be(&regs->if_mode);
452
453
if (full_dx)
454
tmp &= ~IF_MODE_HD;
455
else
456
tmp |= IF_MODE_HD;
457
458
if (iface_mode == E_ENET_IF_RGMII) {
459
/* Configure RGMII in manual mode */
460
tmp &= ~IF_MODE_RGMII_AUTO;
461
tmp &= ~IF_MODE_RGMII_SP_MASK;
462
463
if (full_dx)
464
tmp |= IF_MODE_RGMII_FD;
465
else
466
tmp &= ~IF_MODE_RGMII_FD;
467
468
switch (speed) {
469
case E_ENET_SPEED_1000:
470
tmp |= IF_MODE_RGMII_1000;
471
break;
472
case E_ENET_SPEED_100:
473
tmp |= IF_MODE_RGMII_100;
474
break;
475
case E_ENET_SPEED_10:
476
tmp |= IF_MODE_RGMII_10;
477
break;
478
default:
479
break;
480
}
481
}
482
483
iowrite32be(tmp, &regs->if_mode);
484
}
485
486
void fman_memac_defconfig(struct memac_cfg *cfg)
487
{
488
cfg->reset_on_init = FALSE;
489
cfg->wan_mode_enable = FALSE;
490
cfg->promiscuous_mode_enable = FALSE;
491
cfg->pause_forward_enable = FALSE;
492
cfg->pause_ignore = FALSE;
493
cfg->tx_addr_ins_enable = FALSE;
494
cfg->loopback_enable = FALSE;
495
cfg->cmd_frame_enable = FALSE;
496
cfg->rx_error_discard = FALSE;
497
cfg->send_idle_enable = FALSE;
498
cfg->no_length_check_enable = TRUE;
499
cfg->lgth_check_nostdr = FALSE;
500
cfg->time_stamp_enable = FALSE;
501
cfg->tx_ipg_length = DEFAULT_TX_IPG_LENGTH;
502
cfg->max_frame_length = DEFAULT_FRAME_LENGTH;
503
cfg->pause_quanta = DEFAULT_PAUSE_QUANTA;
504
cfg->pad_enable = TRUE;
505
cfg->phy_tx_ena_on = FALSE;
506
cfg->rx_sfd_any = FALSE;
507
cfg->rx_pbl_fwd = FALSE;
508
cfg->tx_pbl_fwd = FALSE;
509
cfg->debug_mode = FALSE;
510
cfg->wake_on_lan = FALSE;
511
}
512
513