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
fman_memac_get_event(struct memac_regs * regs,uint32_t ev_mask)37 uint32_t fman_memac_get_event(struct memac_regs *regs, uint32_t ev_mask)
38 {
39 return ioread32be(®s->ievent) & ev_mask;
40 }
41
fman_memac_get_interrupt_mask(struct memac_regs * regs)42 uint32_t fman_memac_get_interrupt_mask(struct memac_regs *regs)
43 {
44 return ioread32be(®s->imask);
45 }
46
fman_memac_ack_event(struct memac_regs * regs,uint32_t ev_mask)47 void fman_memac_ack_event(struct memac_regs *regs, uint32_t ev_mask)
48 {
49 iowrite32be(ev_mask, ®s->ievent);
50 }
51
fman_memac_set_promiscuous(struct memac_regs * regs,bool val)52 void fman_memac_set_promiscuous(struct memac_regs *regs, bool val)
53 {
54 uint32_t tmp;
55
56 tmp = ioread32be(®s->command_config);
57
58 if (val)
59 tmp |= CMD_CFG_PROMIS_EN;
60 else
61 tmp &= ~CMD_CFG_PROMIS_EN;
62
63 iowrite32be(tmp, ®s->command_config);
64 }
65
fman_memac_clear_addr_in_paddr(struct memac_regs * regs,uint8_t paddr_num)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, ®s->mac_addr0.mac_addr_l);
71 iowrite32be(0, ®s->mac_addr0.mac_addr_u);
72 } else {
73 iowrite32be(0x0, ®s->mac_addr[paddr_num - 1].mac_addr_l);
74 iowrite32be(0x0, ®s->mac_addr[paddr_num - 1].mac_addr_u);
75 }
76 }
77
fman_memac_add_addr_in_paddr(struct memac_regs * regs,uint8_t * adr,uint8_t paddr_num)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, ®s->mac_addr0.mac_addr_l);
92 iowrite32be(tmp1, ®s->mac_addr0.mac_addr_u);
93 } else {
94 iowrite32be(tmp0, ®s->mac_addr[paddr_num-1].mac_addr_l);
95 iowrite32be(tmp1, ®s->mac_addr[paddr_num-1].mac_addr_u);
96 }
97 }
98
fman_memac_enable(struct memac_regs * regs,bool apply_rx,bool apply_tx)99 void fman_memac_enable(struct memac_regs *regs, bool apply_rx, bool apply_tx)
100 {
101 uint32_t tmp;
102
103 tmp = ioread32be(®s->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, ®s->command_config);
112 }
113
fman_memac_disable(struct memac_regs * regs,bool apply_rx,bool apply_tx)114 void fman_memac_disable(struct memac_regs *regs, bool apply_rx, bool apply_tx)
115 {
116 uint32_t tmp;
117
118 tmp = ioread32be(®s->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, ®s->command_config);
127 }
128
fman_memac_reset_stat(struct memac_regs * regs)129 void fman_memac_reset_stat(struct memac_regs *regs)
130 {
131 uint32_t tmp;
132
133 tmp = ioread32be(®s->statn_config);
134
135 tmp |= STATS_CFG_CLR;
136
137 iowrite32be(tmp, ®s->statn_config);
138
139 while (ioread32be(®s->statn_config) & STATS_CFG_CLR);
140 }
141
fman_memac_reset(struct memac_regs * regs)142 void fman_memac_reset(struct memac_regs *regs)
143 {
144 uint32_t tmp;
145
146 tmp = ioread32be(®s->command_config);
147
148 tmp |= CMD_CFG_SW_RESET;
149
150 iowrite32be(tmp, ®s->command_config);
151
152 while (ioread32be(®s->command_config) & CMD_CFG_SW_RESET);
153 }
154
fman_memac_init(struct memac_regs * regs,struct memac_cfg * cfg,enum enet_interface enet_interface,enum enet_speed enet_speed,bool slow_10g_if,uint32_t exceptions)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, ®s->command_config);
194
195 /* Max Frame Length */
196 iowrite32be((uint32_t)cfg->max_frame_length, ®s->maxfrm);
197
198 /* Pause Time */
199 iowrite32be((uint32_t)cfg->pause_quanta, ®s->pause_quanta[0]);
200 iowrite32be((uint32_t)0, ®s->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, ®s->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, ®s->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
fman_memac_set_exception(struct memac_regs * regs,uint32_t val,bool enable)240 void fman_memac_set_exception(struct memac_regs *regs, uint32_t val, bool enable)
241 {
242 uint32_t tmp;
243
244 tmp = ioread32be(®s->imask);
245 if (enable)
246 tmp |= val;
247 else
248 tmp &= ~val;
249
250 iowrite32be(tmp, ®s->imask);
251 }
252
fman_memac_reset_filter_table(struct memac_regs * regs)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, ®s->hashtable_ctrl);
258 }
259
fman_memac_set_hash_table_entry(struct memac_regs * regs,uint32_t crc)260 void fman_memac_set_hash_table_entry(struct memac_regs *regs, uint32_t crc)
261 {
262 iowrite32be(crc | HASH_CTRL_MCAST_EN, ®s->hashtable_ctrl);
263 }
264
fman_memac_set_hash_table(struct memac_regs * regs,uint32_t val)265 void fman_memac_set_hash_table(struct memac_regs *regs, uint32_t val)
266 {
267 iowrite32be(val, ®s->hashtable_ctrl);
268 }
269
fman_memac_get_max_frame_len(struct memac_regs * regs)270 uint16_t fman_memac_get_max_frame_len(struct memac_regs *regs)
271 {
272 uint32_t tmp;
273
274 tmp = ioread32be(®s->maxfrm);
275
276 return(uint16_t)tmp;
277 }
278
279
fman_memac_set_tx_pause_frames(struct memac_regs * regs,uint8_t priority,uint16_t pause_time,uint16_t thresh_time)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(®s->tx_fifo_sections);
288
289 if (priority == 0xff) {
290 GET_TX_EMPTY_DEFAULT_VALUE(tmp);
291 iowrite32be(tmp, ®s->tx_fifo_sections);
292
293 tmp = ioread32be(®s->command_config);
294 tmp &= ~CMD_CFG_PFC_MODE;
295 priority = 0;
296 } else {
297 GET_TX_EMPTY_PFC_VALUE(tmp);
298 iowrite32be(tmp, ®s->tx_fifo_sections);
299
300 tmp = ioread32be(®s->command_config);
301 tmp |= CMD_CFG_PFC_MODE;
302 }
303
304 iowrite32be(tmp, ®s->command_config);
305
306 tmp = ioread32be(®s->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, ®s->pause_quanta[priority / 2]);
313
314 tmp = ioread32be(®s->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, ®s->pause_thresh[priority / 2]);
321 }
322
fman_memac_set_rx_ignore_pause_frames(struct memac_regs * regs,bool enable)323 void fman_memac_set_rx_ignore_pause_frames(struct memac_regs *regs,bool enable)
324 {
325 uint32_t tmp;
326
327 tmp = ioread32be(®s->command_config);
328 if (enable)
329 tmp |= CMD_CFG_PAUSE_IGNORE;
330 else
331 tmp &= ~CMD_CFG_PAUSE_IGNORE;
332
333 iowrite32be(tmp, ®s->command_config);
334 }
335
fman_memac_set_wol(struct memac_regs * regs,bool enable)336 void fman_memac_set_wol(struct memac_regs *regs, bool enable)
337 {
338 uint32_t tmp;
339
340 tmp = ioread32be(®s->command_config);
341
342 if (enable)
343 tmp |= CMD_CFG_MG;
344 else
345 tmp &= ~CMD_CFG_MG;
346
347 iowrite32be(tmp, ®s->command_config);
348 }
349
350 #define GET_MEMAC_CNTR_64(bn) \
351 (ioread32be(®s->bn ## _l) | \
352 ((uint64_t)ioread32be(®s->bn ## _u) << 32))
353
fman_memac_get_counter(struct memac_regs * regs,enum memac_counters reg_name)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
fman_memac_adjust_link(struct memac_regs * regs,enum enet_interface iface_mode,enum enet_speed speed,bool full_dx)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(®s->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, ®s->if_mode);
484 }
485
fman_memac_defconfig(struct memac_cfg * cfg)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