1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2006 Freescale Semiconductor, Inc.
4  *
5  * Dave Liu <daveliu@freescale.com>
6  * based on source code of Shlomi Gridish
7  */
8 
9 #include <common.h>
10 #include <malloc.h>
11 #include <linux/errno.h>
12 #include <asm/io.h>
13 #include <linux/immap_qe.h>
14 #include "uccf.h"
15 #include <fsl_qe.h>
16 
ucc_fast_transmit_on_demand(struct ucc_fast_priv * uccf)17 void ucc_fast_transmit_on_demand(struct ucc_fast_priv *uccf)
18 {
19 	out_be16(&uccf->uf_regs->utodr, UCC_FAST_TOD);
20 }
21 
ucc_fast_get_qe_cr_subblock(int ucc_num)22 u32 ucc_fast_get_qe_cr_subblock(int ucc_num)
23 {
24 	switch (ucc_num) {
25 	case 0:
26 		return QE_CR_SUBBLOCK_UCCFAST1;
27 	case 1:
28 		return QE_CR_SUBBLOCK_UCCFAST2;
29 	case 2:
30 		return QE_CR_SUBBLOCK_UCCFAST3;
31 	case 3:
32 		return QE_CR_SUBBLOCK_UCCFAST4;
33 	case 4:
34 		return QE_CR_SUBBLOCK_UCCFAST5;
35 	case 5:
36 		return QE_CR_SUBBLOCK_UCCFAST6;
37 	case 6:
38 		return QE_CR_SUBBLOCK_UCCFAST7;
39 	case 7:
40 		return QE_CR_SUBBLOCK_UCCFAST8;
41 	default:
42 		return QE_CR_SUBBLOCK_INVALID;
43 	}
44 }
45 
ucc_get_cmxucr_reg(int ucc_num,u32 ** p_cmxucr,u8 * reg_num,u8 * shift)46 static void ucc_get_cmxucr_reg(int ucc_num, u32 **p_cmxucr,
47 			       u8 *reg_num, u8 *shift)
48 {
49 	switch (ucc_num) {
50 	case 0:	/* UCC1 */
51 		*p_cmxucr  = &qe_immr->qmx.cmxucr1;
52 		*reg_num = 1;
53 		*shift  = 16;
54 		break;
55 	case 2:	/* UCC3 */
56 		*p_cmxucr  = &qe_immr->qmx.cmxucr1;
57 		*reg_num = 1;
58 		*shift  = 0;
59 		break;
60 	case 4:	/* UCC5 */
61 		*p_cmxucr  = &qe_immr->qmx.cmxucr2;
62 		*reg_num = 2;
63 		*shift  = 16;
64 		break;
65 	case 6:	/* UCC7 */
66 		*p_cmxucr  = &qe_immr->qmx.cmxucr2;
67 		*reg_num = 2;
68 		*shift  = 0;
69 		break;
70 	case 1:	/* UCC2 */
71 		*p_cmxucr  = &qe_immr->qmx.cmxucr3;
72 		*reg_num = 3;
73 		*shift  = 16;
74 		break;
75 	case 3:	/* UCC4 */
76 		*p_cmxucr  = &qe_immr->qmx.cmxucr3;
77 		*reg_num = 3;
78 		*shift  = 0;
79 		break;
80 	case 5:	/* UCC6 */
81 		*p_cmxucr  = &qe_immr->qmx.cmxucr4;
82 		*reg_num = 4;
83 		*shift  = 16;
84 		break;
85 	case 7:	/* UCC8 */
86 		*p_cmxucr  = &qe_immr->qmx.cmxucr4;
87 		*reg_num = 4;
88 		*shift  = 0;
89 		break;
90 	default:
91 		break;
92 	}
93 }
94 
ucc_set_clk_src(int ucc_num,qe_clock_e clock,comm_dir_e mode)95 static int ucc_set_clk_src(int ucc_num, qe_clock_e clock, comm_dir_e mode)
96 {
97 	u32	*p_cmxucr = NULL;
98 	u8	reg_num = 0;
99 	u8	shift = 0;
100 	u32	clk_bits;
101 	u32	clk_mask;
102 	int	source = -1;
103 
104 	/* check if the UCC number is in range. */
105 	if ((ucc_num > UCC_MAX_NUM - 1) || ucc_num < 0)
106 		return -EINVAL;
107 
108 	if (!(mode == COMM_DIR_RX || mode == COMM_DIR_TX)) {
109 		printf("%s: bad comm mode type passed\n", __func__);
110 		return -EINVAL;
111 	}
112 
113 	ucc_get_cmxucr_reg(ucc_num, &p_cmxucr, &reg_num, &shift);
114 
115 	switch (reg_num) {
116 	case 1:
117 		switch (clock) {
118 		case QE_BRG1:
119 			source = 1;
120 			break;
121 		case QE_BRG2:
122 			source = 2;
123 			break;
124 		case QE_BRG7:
125 			source = 3;
126 			break;
127 		case QE_BRG8:
128 			source = 4;
129 			break;
130 		case QE_CLK9:
131 			source = 5;
132 			break;
133 		case QE_CLK10:
134 			source = 6;
135 			break;
136 		case QE_CLK11:
137 			source = 7;
138 			break;
139 		case QE_CLK12:
140 			source = 8;
141 			break;
142 		case QE_CLK15:
143 			source = 9;
144 			break;
145 		case QE_CLK16:
146 			source = 10;
147 			break;
148 		default:
149 			source = -1;
150 			break;
151 		}
152 		break;
153 	case 2:
154 		switch (clock) {
155 		case QE_BRG5:
156 			source = 1;
157 			break;
158 		case QE_BRG6:
159 			source = 2;
160 			break;
161 		case QE_BRG7:
162 			source = 3;
163 			break;
164 		case QE_BRG8:
165 			source = 4;
166 			break;
167 		case QE_CLK13:
168 			source = 5;
169 			break;
170 		case QE_CLK14:
171 			source = 6;
172 			break;
173 		case QE_CLK19:
174 			source = 7;
175 			break;
176 		case QE_CLK20:
177 			source = 8;
178 			break;
179 		case QE_CLK15:
180 			source = 9;
181 			break;
182 		case QE_CLK16:
183 			source = 10;
184 			break;
185 		default:
186 			source = -1;
187 			break;
188 		}
189 		break;
190 	case 3:
191 		switch (clock) {
192 		case QE_BRG9:
193 			source = 1;
194 			break;
195 		case QE_BRG10:
196 			source = 2;
197 			break;
198 		case QE_BRG15:
199 			source = 3;
200 			break;
201 		case QE_BRG16:
202 			source = 4;
203 			break;
204 		case QE_CLK3:
205 			source = 5;
206 			break;
207 		case QE_CLK4:
208 			source = 6;
209 			break;
210 		case QE_CLK17:
211 			source = 7;
212 			break;
213 		case QE_CLK18:
214 			source = 8;
215 			break;
216 		case QE_CLK7:
217 			source = 9;
218 			break;
219 		case QE_CLK8:
220 			source = 10;
221 			break;
222 		case QE_CLK16:
223 			source = 11;
224 			break;
225 		default:
226 			source = -1;
227 			break;
228 		}
229 		break;
230 	case 4:
231 		switch (clock) {
232 		case QE_BRG13:
233 			source = 1;
234 			break;
235 		case QE_BRG14:
236 			source = 2;
237 			break;
238 		case QE_BRG15:
239 			source = 3;
240 			break;
241 		case QE_BRG16:
242 			source = 4;
243 			break;
244 		case QE_CLK5:
245 			source = 5;
246 			break;
247 		case QE_CLK6:
248 			source = 6;
249 			break;
250 		case QE_CLK21:
251 			source = 7;
252 			break;
253 		case QE_CLK22:
254 			source = 8;
255 			break;
256 		case QE_CLK7:
257 			source = 9;
258 			break;
259 		case QE_CLK8:
260 			source = 10;
261 			break;
262 		case QE_CLK16:
263 			source = 11;
264 			break;
265 		default:
266 			source = -1;
267 			break;
268 		}
269 		break;
270 	default:
271 		source = -1;
272 		break;
273 	}
274 
275 	if (source == -1) {
276 		printf("%s: Bad combination of clock and UCC\n", __func__);
277 		return -ENOENT;
278 	}
279 
280 	clk_bits = (u32)source;
281 	clk_mask = QE_CMXUCR_TX_CLK_SRC_MASK;
282 	if (mode == COMM_DIR_RX) {
283 		clk_bits <<= 4; /* Rx field is 4 bits to left of Tx field */
284 		clk_mask <<= 4; /* Rx field is 4 bits to left of Tx field */
285 	}
286 	clk_bits <<= shift;
287 	clk_mask <<= shift;
288 
289 	out_be32(p_cmxucr, (in_be32(p_cmxucr) & ~clk_mask) | clk_bits);
290 
291 	return 0;
292 }
293 
ucc_get_reg_baseaddr(int ucc_num)294 static uint ucc_get_reg_baseaddr(int ucc_num)
295 {
296 	uint base = 0;
297 
298 	/* check if the UCC number is in range */
299 	if ((ucc_num > UCC_MAX_NUM - 1) || ucc_num < 0) {
300 		printf("%s: the UCC num not in ranges\n", __func__);
301 		return 0;
302 	}
303 
304 	switch (ucc_num) {
305 	case 0:
306 		base = 0x00002000;
307 		break;
308 	case 1:
309 		base = 0x00003000;
310 		break;
311 	case 2:
312 		base = 0x00002200;
313 		break;
314 	case 3:
315 		base = 0x00003200;
316 		break;
317 	case 4:
318 		base = 0x00002400;
319 		break;
320 	case 5:
321 		base = 0x00003400;
322 		break;
323 	case 6:
324 		base = 0x00002600;
325 		break;
326 	case 7:
327 		base = 0x00003600;
328 		break;
329 	default:
330 		break;
331 	}
332 
333 	base = (uint)qe_immr + base;
334 	return base;
335 }
336 
ucc_fast_enable(struct ucc_fast_priv * uccf,comm_dir_e mode)337 void ucc_fast_enable(struct ucc_fast_priv *uccf, comm_dir_e mode)
338 {
339 	ucc_fast_t	*uf_regs;
340 	u32		gumr;
341 
342 	uf_regs = uccf->uf_regs;
343 
344 	/* Enable reception and/or transmission on this UCC. */
345 	gumr = in_be32(&uf_regs->gumr);
346 	if (mode & COMM_DIR_TX) {
347 		gumr |= UCC_FAST_GUMR_ENT;
348 		uccf->enabled_tx = 1;
349 	}
350 	if (mode & COMM_DIR_RX) {
351 		gumr |= UCC_FAST_GUMR_ENR;
352 		uccf->enabled_rx = 1;
353 	}
354 	out_be32(&uf_regs->gumr, gumr);
355 }
356 
ucc_fast_disable(struct ucc_fast_priv * uccf,comm_dir_e mode)357 void ucc_fast_disable(struct ucc_fast_priv *uccf, comm_dir_e mode)
358 {
359 	ucc_fast_t	*uf_regs;
360 	u32		gumr;
361 
362 	uf_regs = uccf->uf_regs;
363 
364 	/* Disable reception and/or transmission on this UCC. */
365 	gumr = in_be32(&uf_regs->gumr);
366 	if (mode & COMM_DIR_TX) {
367 		gumr &= ~UCC_FAST_GUMR_ENT;
368 		uccf->enabled_tx = 0;
369 	}
370 	if (mode & COMM_DIR_RX) {
371 		gumr &= ~UCC_FAST_GUMR_ENR;
372 		uccf->enabled_rx = 0;
373 	}
374 	out_be32(&uf_regs->gumr, gumr);
375 }
376 
ucc_fast_init(struct ucc_fast_inf * uf_info,struct ucc_fast_priv ** uccf_ret)377 int ucc_fast_init(struct ucc_fast_inf *uf_info,
378 		  struct ucc_fast_priv **uccf_ret)
379 {
380 	struct ucc_fast_priv	*uccf;
381 	ucc_fast_t		*uf_regs;
382 
383 	if (!uf_info)
384 		return -EINVAL;
385 
386 	if (uf_info->ucc_num < 0 || (uf_info->ucc_num > UCC_MAX_NUM - 1)) {
387 		printf("%s: Illagal UCC number!\n", __func__);
388 		return -EINVAL;
389 	}
390 
391 	uccf = (struct ucc_fast_priv *)malloc(sizeof(struct ucc_fast_priv));
392 	if (!uccf) {
393 		printf("%s: No memory for UCC fast data structure!\n",
394 		       __func__);
395 		return -ENOMEM;
396 	}
397 	memset(uccf, 0, sizeof(struct ucc_fast_priv));
398 
399 	/* Save fast UCC structure */
400 	uccf->uf_info	= uf_info;
401 	uccf->uf_regs	= (ucc_fast_t *)ucc_get_reg_baseaddr(uf_info->ucc_num);
402 
403 	if (!uccf->uf_regs) {
404 		printf("%s: No memory map for UCC fast controller!\n",
405 		       __func__);
406 		return -ENOMEM;
407 	}
408 
409 	uccf->enabled_tx	= 0;
410 	uccf->enabled_rx	= 0;
411 
412 	uf_regs			= uccf->uf_regs;
413 	uccf->p_ucce		= (u32 *)&uf_regs->ucce;
414 	uccf->p_uccm		= (u32 *)&uf_regs->uccm;
415 
416 	/* Init GUEMR register, UCC both Rx and Tx is Fast protocol */
417 	out_8(&uf_regs->guemr, UCC_GUEMR_SET_RESERVED3 | UCC_GUEMR_MODE_FAST_RX
418 				 | UCC_GUEMR_MODE_FAST_TX);
419 
420 	/* Set GUMR, disable UCC both Rx and Tx, Ethernet protocol */
421 	out_be32(&uf_regs->gumr, UCC_FAST_GUMR_ETH);
422 
423 	/* Set the Giga ethernet VFIFO stuff */
424 	if (uf_info->eth_type == GIGA_ETH) {
425 		/* Allocate memory for Tx Virtual Fifo */
426 		uccf->ucc_fast_tx_virtual_fifo_base_offset =
427 		qe_muram_alloc(UCC_GETH_UTFS_GIGA_INIT,
428 			       UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT);
429 
430 		/* Allocate memory for Rx Virtual Fifo */
431 		uccf->ucc_fast_rx_virtual_fifo_base_offset =
432 		qe_muram_alloc(UCC_GETH_URFS_GIGA_INIT +
433 			       UCC_FAST_RX_VIRTUAL_FIFO_SIZE_PAD,
434 			       UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT);
435 
436 		/* utfb, urfb are offsets from MURAM base */
437 		out_be32(&uf_regs->utfb,
438 			 uccf->ucc_fast_tx_virtual_fifo_base_offset);
439 		out_be32(&uf_regs->urfb,
440 			 uccf->ucc_fast_rx_virtual_fifo_base_offset);
441 
442 		/* Set Virtual Fifo registers */
443 		out_be16(&uf_regs->urfs, UCC_GETH_URFS_GIGA_INIT);
444 		out_be16(&uf_regs->urfet, UCC_GETH_URFET_GIGA_INIT);
445 		out_be16(&uf_regs->urfset, UCC_GETH_URFSET_GIGA_INIT);
446 		out_be16(&uf_regs->utfs, UCC_GETH_UTFS_GIGA_INIT);
447 		out_be16(&uf_regs->utfet, UCC_GETH_UTFET_GIGA_INIT);
448 		out_be16(&uf_regs->utftt, UCC_GETH_UTFTT_GIGA_INIT);
449 	}
450 
451 	/* Set the Fast ethernet VFIFO stuff */
452 	if (uf_info->eth_type == FAST_ETH) {
453 		/* Allocate memory for Tx Virtual Fifo */
454 		uccf->ucc_fast_tx_virtual_fifo_base_offset =
455 		qe_muram_alloc(UCC_GETH_UTFS_INIT,
456 			       UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT);
457 
458 		/* Allocate memory for Rx Virtual Fifo */
459 		uccf->ucc_fast_rx_virtual_fifo_base_offset =
460 		qe_muram_alloc(UCC_GETH_URFS_INIT +
461 				 UCC_FAST_RX_VIRTUAL_FIFO_SIZE_PAD,
462 				UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT);
463 
464 		/* utfb, urfb are offsets from MURAM base */
465 		out_be32(&uf_regs->utfb,
466 			 uccf->ucc_fast_tx_virtual_fifo_base_offset);
467 		out_be32(&uf_regs->urfb,
468 			 uccf->ucc_fast_rx_virtual_fifo_base_offset);
469 
470 		/* Set Virtual Fifo registers */
471 		out_be16(&uf_regs->urfs, UCC_GETH_URFS_INIT);
472 		out_be16(&uf_regs->urfet, UCC_GETH_URFET_INIT);
473 		out_be16(&uf_regs->urfset, UCC_GETH_URFSET_INIT);
474 		out_be16(&uf_regs->utfs, UCC_GETH_UTFS_INIT);
475 		out_be16(&uf_regs->utfet, UCC_GETH_UTFET_INIT);
476 		out_be16(&uf_regs->utftt, UCC_GETH_UTFTT_INIT);
477 	}
478 
479 	/* Rx clock routing */
480 	if (uf_info->rx_clock != QE_CLK_NONE) {
481 		if (ucc_set_clk_src(uf_info->ucc_num,
482 				    uf_info->rx_clock, COMM_DIR_RX)) {
483 			printf("%s: Illegal value for parameter 'RxClock'.\n",
484 			       __func__);
485 			return -EINVAL;
486 		}
487 	}
488 
489 	/* Tx clock routing */
490 	if (uf_info->tx_clock != QE_CLK_NONE) {
491 		if (ucc_set_clk_src(uf_info->ucc_num,
492 				    uf_info->tx_clock, COMM_DIR_TX)) {
493 			printf("%s: Illegal value for parameter 'TxClock'.\n",
494 			       __func__);
495 			return -EINVAL;
496 		}
497 	}
498 
499 	/* Clear interrupt mask register to disable all of interrupts */
500 	out_be32(&uf_regs->uccm, 0x0);
501 
502 	/* Writing '1' to clear all of envents */
503 	out_be32(&uf_regs->ucce, 0xffffffff);
504 
505 	*uccf_ret = uccf;
506 	return 0;
507 }
508