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_tgec.h"
35 
36 
37 void fman_tgec_set_mac_address(struct tgec_regs *regs, uint8_t *adr)
38 {
39 	uint32_t tmp0, tmp1;
40 
41 	tmp0 = (uint32_t)(adr[0] |
42 			adr[1] << 8 |
43 			adr[2] << 16 |
44 			adr[3] << 24);
45 	tmp1 = (uint32_t)(adr[4] | adr[5] << 8);
46 	iowrite32be(tmp0, &regs->mac_addr_0);
47 	iowrite32be(tmp1, &regs->mac_addr_1);
48 }
49 
50 void fman_tgec_reset_stat(struct tgec_regs *regs)
51 {
52 	uint32_t tmp;
53 
54 	tmp = ioread32be(&regs->command_config);
55 
56 	tmp |= CMD_CFG_STAT_CLR;
57 
58 	iowrite32be(tmp, &regs->command_config);
59 
60 	while (ioread32be(&regs->command_config) & CMD_CFG_STAT_CLR) ;
61 }
62 
63 #define GET_TGEC_CNTR_64(bn) \
64 	(((uint64_t)ioread32be(&regs->bn ## _u) << 32) | \
65 			ioread32be(&regs->bn ## _l))
66 
67 uint64_t fman_tgec_get_counter(struct tgec_regs *regs, enum tgec_counters reg_name)
68 {
69 	uint64_t ret_val;
70 
71 	switch (reg_name) {
72 	case E_TGEC_COUNTER_R64:
73 		ret_val = GET_TGEC_CNTR_64(r64);
74 		break;
75 	case E_TGEC_COUNTER_R127:
76 		ret_val = GET_TGEC_CNTR_64(r127);
77 		break;
78 	case E_TGEC_COUNTER_R255:
79 		ret_val = GET_TGEC_CNTR_64(r255);
80 		break;
81 	case E_TGEC_COUNTER_R511:
82 		ret_val = GET_TGEC_CNTR_64(r511);
83 		break;
84 	case E_TGEC_COUNTER_R1023:
85 		ret_val = GET_TGEC_CNTR_64(r1023);
86 		break;
87 	case E_TGEC_COUNTER_R1518:
88 		ret_val = GET_TGEC_CNTR_64(r1518);
89 		break;
90 	case E_TGEC_COUNTER_R1519X:
91 		ret_val = GET_TGEC_CNTR_64(r1519x);
92 		break;
93 	case E_TGEC_COUNTER_TRFRG:
94 		ret_val = GET_TGEC_CNTR_64(trfrg);
95 		break;
96 	case E_TGEC_COUNTER_TRJBR:
97 		ret_val = GET_TGEC_CNTR_64(trjbr);
98 		break;
99 	case E_TGEC_COUNTER_RDRP:
100 		ret_val = GET_TGEC_CNTR_64(rdrp);
101 		break;
102 	case E_TGEC_COUNTER_RALN:
103 		ret_val = GET_TGEC_CNTR_64(raln);
104 		break;
105 	case E_TGEC_COUNTER_TRUND:
106 		ret_val = GET_TGEC_CNTR_64(trund);
107 		break;
108 	case E_TGEC_COUNTER_TROVR:
109 		ret_val = GET_TGEC_CNTR_64(trovr);
110 		break;
111 	case E_TGEC_COUNTER_RXPF:
112 		ret_val = GET_TGEC_CNTR_64(rxpf);
113 		break;
114 	case E_TGEC_COUNTER_TXPF:
115 		ret_val = GET_TGEC_CNTR_64(txpf);
116 		break;
117 	case E_TGEC_COUNTER_ROCT:
118 		ret_val = GET_TGEC_CNTR_64(roct);
119 		break;
120 	case E_TGEC_COUNTER_RMCA:
121 		ret_val = GET_TGEC_CNTR_64(rmca);
122 		break;
123 	case E_TGEC_COUNTER_RBCA:
124 		ret_val = GET_TGEC_CNTR_64(rbca);
125 		break;
126 	case E_TGEC_COUNTER_RPKT:
127 		ret_val = GET_TGEC_CNTR_64(rpkt);
128 		break;
129 	case E_TGEC_COUNTER_RUCA:
130 		ret_val = GET_TGEC_CNTR_64(ruca);
131 		break;
132 	case E_TGEC_COUNTER_RERR:
133 		ret_val = GET_TGEC_CNTR_64(rerr);
134 		break;
135 	case E_TGEC_COUNTER_TOCT:
136 		ret_val = GET_TGEC_CNTR_64(toct);
137 		break;
138 	case E_TGEC_COUNTER_TMCA:
139 		ret_val = GET_TGEC_CNTR_64(tmca);
140 		break;
141 	case E_TGEC_COUNTER_TBCA:
142 		ret_val = GET_TGEC_CNTR_64(tbca);
143 		break;
144 	case E_TGEC_COUNTER_TUCA:
145 		ret_val = GET_TGEC_CNTR_64(tuca);
146 		break;
147 	case E_TGEC_COUNTER_TERR:
148 		ret_val = GET_TGEC_CNTR_64(terr);
149 		break;
150 	default:
151 		ret_val = 0;
152 	}
153 
154 	return ret_val;
155 }
156 
157 void fman_tgec_enable(struct tgec_regs *regs, bool apply_rx, bool apply_tx)
158 {
159 	uint32_t tmp;
160 
161 	tmp = ioread32be(&regs->command_config);
162 	if (apply_rx)
163 		tmp |= CMD_CFG_RX_EN;
164 	if (apply_tx)
165 		tmp |= CMD_CFG_TX_EN;
166 	iowrite32be(tmp, &regs->command_config);
167 }
168 
169 void fman_tgec_disable(struct tgec_regs *regs, bool apply_rx, bool apply_tx)
170 {
171 	uint32_t tmp_reg_32;
172 
173 	tmp_reg_32 = ioread32be(&regs->command_config);
174 	if (apply_rx)
175 		tmp_reg_32 &= ~CMD_CFG_RX_EN;
176 	if (apply_tx)
177 		tmp_reg_32 &= ~CMD_CFG_TX_EN;
178 	iowrite32be(tmp_reg_32, &regs->command_config);
179 }
180 
181 void fman_tgec_set_promiscuous(struct tgec_regs *regs, bool val)
182 {
183 	uint32_t tmp;
184 
185 	tmp = ioread32be(&regs->command_config);
186 	if (val)
187 		tmp |= CMD_CFG_PROMIS_EN;
188 	else
189 		tmp &= ~CMD_CFG_PROMIS_EN;
190 	iowrite32be(tmp, &regs->command_config);
191 }
192 
193 void fman_tgec_reset_filter_table(struct tgec_regs *regs)
194 {
195 	uint32_t i;
196 	for (i = 0; i < 512; i++)
197 		iowrite32be(i & ~TGEC_HASH_MCAST_EN, &regs->hashtable_ctrl);
198 }
199 
200 void fman_tgec_set_hash_table_entry(struct tgec_regs *regs, uint32_t crc)
201 {
202     uint32_t hash = (crc >> TGEC_HASH_MCAST_SHIFT) & TGEC_HASH_ADR_MSK;        /* Take 9 MSB bits */
203 	iowrite32be(hash | TGEC_HASH_MCAST_EN, &regs->hashtable_ctrl);
204 }
205 
206 void fman_tgec_set_hash_table(struct tgec_regs *regs, uint32_t value)
207 {
208 	iowrite32be(value, &regs->hashtable_ctrl);
209 }
210 
211 void fman_tgec_set_tx_pause_frames(struct tgec_regs *regs, uint16_t pause_time)
212 {
213 	iowrite32be((uint32_t)pause_time, &regs->pause_quant);
214 }
215 
216 void fman_tgec_set_rx_ignore_pause_frames(struct tgec_regs *regs, bool en)
217 {
218 	uint32_t tmp;
219 
220 	tmp = ioread32be(&regs->command_config);
221 	if (en)
222 		tmp |= CMD_CFG_PAUSE_IGNORE;
223 	else
224 		tmp &= ~CMD_CFG_PAUSE_IGNORE;
225 	iowrite32be(tmp, &regs->command_config);
226 }
227 
228 void fman_tgec_enable_1588_time_stamp(struct tgec_regs *regs, bool en)
229 {
230 	uint32_t tmp;
231 
232 	tmp = ioread32be(&regs->command_config);
233 	if (en)
234 		tmp |= CMD_CFG_EN_TIMESTAMP;
235 	else
236 		tmp &= ~CMD_CFG_EN_TIMESTAMP;
237 	iowrite32be(tmp, &regs->command_config);
238 }
239 
240 uint32_t fman_tgec_get_event(struct tgec_regs *regs, uint32_t ev_mask)
241 {
242 	return ioread32be(&regs->ievent) & ev_mask;
243 }
244 
245 void fman_tgec_ack_event(struct tgec_regs *regs, uint32_t ev_mask)
246 {
247 	iowrite32be(ev_mask, &regs->ievent);
248 }
249 
250 uint32_t fman_tgec_get_interrupt_mask(struct tgec_regs *regs)
251 {
252 	return ioread32be(&regs->imask);
253 }
254 
255 void fman_tgec_add_addr_in_paddr(struct tgec_regs *regs, uint8_t *adr)
256 {
257 	uint32_t tmp0, tmp1;
258 
259 	tmp0 = (uint32_t)(adr[0] |
260 			adr[1] << 8 |
261 			adr[2] << 16 |
262 			adr[3] << 24);
263 	tmp1 = (uint32_t)(adr[4] | adr[5] << 8);
264 	iowrite32be(tmp0, &regs->mac_addr_2);
265 	iowrite32be(tmp1, &regs->mac_addr_3);
266 }
267 
268 void fman_tgec_clear_addr_in_paddr(struct tgec_regs *regs)
269 {
270 	iowrite32be(0, &regs->mac_addr_2);
271 	iowrite32be(0, &regs->mac_addr_3);
272 }
273 
274 uint32_t fman_tgec_get_revision(struct tgec_regs *regs)
275 {
276 	return ioread32be(&regs->tgec_id);
277 }
278 
279 void fman_tgec_enable_interrupt(struct tgec_regs *regs, uint32_t ev_mask)
280 {
281 	iowrite32be(ioread32be(&regs->imask) | ev_mask, &regs->imask);
282 }
283 
284 void fman_tgec_disable_interrupt(struct tgec_regs *regs, uint32_t ev_mask)
285 {
286 	iowrite32be(ioread32be(&regs->imask) & ~ev_mask, &regs->imask);
287 }
288 
289 uint16_t fman_tgec_get_max_frame_len(struct tgec_regs *regs)
290 {
291 	return (uint16_t) ioread32be(&regs->maxfrm);
292 }
293 
294 void fman_tgec_defconfig(struct tgec_cfg *cfg)
295 {
296 	cfg->wan_mode_enable = DEFAULT_WAN_MODE_ENABLE;
297 	cfg->promiscuous_mode_enable = DEFAULT_PROMISCUOUS_MODE_ENABLE;
298 	cfg->pause_forward_enable = DEFAULT_PAUSE_FORWARD_ENABLE;
299 	cfg->pause_ignore = DEFAULT_PAUSE_IGNORE;
300 	cfg->tx_addr_ins_enable = DEFAULT_TX_ADDR_INS_ENABLE;
301 	cfg->loopback_enable = DEFAULT_LOOPBACK_ENABLE;
302 	cfg->cmd_frame_enable = DEFAULT_CMD_FRAME_ENABLE;
303 	cfg->rx_error_discard = DEFAULT_RX_ERROR_DISCARD;
304 	cfg->send_idle_enable = DEFAULT_SEND_IDLE_ENABLE;
305 	cfg->no_length_check_enable = DEFAULT_NO_LENGTH_CHECK_ENABLE;
306 	cfg->lgth_check_nostdr = DEFAULT_LGTH_CHECK_NOSTDR;
307 	cfg->time_stamp_enable = DEFAULT_TIME_STAMP_ENABLE;
308 	cfg->tx_ipg_length = DEFAULT_TX_IPG_LENGTH;
309 	cfg->max_frame_length = DEFAULT_MAX_FRAME_LENGTH;
310 	cfg->pause_quant = DEFAULT_PAUSE_QUANT;
311 #ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004
312 	cfg->skip_fman11_workaround = FALSE;
313 #endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */
314 }
315 
316 int fman_tgec_init(struct tgec_regs *regs, struct tgec_cfg *cfg,
317 		uint32_t exception_mask)
318 {
319 	uint32_t tmp;
320 
321 	/* Config */
322 	tmp = 0x40; /* CRC forward */
323 	if (cfg->wan_mode_enable)
324 		tmp |= CMD_CFG_WAN_MODE;
325 	if (cfg->promiscuous_mode_enable)
326 		tmp |= CMD_CFG_PROMIS_EN;
327 	if (cfg->pause_forward_enable)
328 		tmp |= CMD_CFG_PAUSE_FWD;
329 	if (cfg->pause_ignore)
330 		tmp |= CMD_CFG_PAUSE_IGNORE;
331 	if (cfg->tx_addr_ins_enable)
332 		tmp |= CMD_CFG_TX_ADDR_INS;
333 	if (cfg->loopback_enable)
334 		tmp |= CMD_CFG_LOOPBACK_EN;
335 	if (cfg->cmd_frame_enable)
336 		tmp |= CMD_CFG_CMD_FRM_EN;
337 	if (cfg->rx_error_discard)
338 		tmp |= CMD_CFG_RX_ER_DISC;
339 	if (cfg->send_idle_enable)
340 		tmp |= CMD_CFG_SEND_IDLE;
341 	if (cfg->no_length_check_enable)
342 		tmp |= CMD_CFG_NO_LEN_CHK;
343 	if (cfg->time_stamp_enable)
344 		tmp |= CMD_CFG_EN_TIMESTAMP;
345 	iowrite32be(tmp, &regs->command_config);
346 
347 	/* Max Frame Length */
348 	iowrite32be((uint32_t)cfg->max_frame_length, &regs->maxfrm);
349 	/* Pause Time */
350 	iowrite32be(cfg->pause_quant, &regs->pause_quant);
351 
352 	/* clear all pending events and set-up interrupts */
353 	fman_tgec_ack_event(regs, 0xffffffff);
354 	fman_tgec_enable_interrupt(regs, exception_mask);
355 
356 	return 0;
357 }
358 
359 void fman_tgec_set_erratum_tx_fifo_corruption_10gmac_a007(struct tgec_regs *regs)
360 {
361 	uint32_t tmp;
362 
363 	/* restore the default tx ipg Length */
364 	tmp = (ioread32be(&regs->tx_ipg_len) & ~TGEC_TX_IPG_LENGTH_MASK) | 12;
365 
366 	iowrite32be(tmp, &regs->tx_ipg_len);
367 }
368