• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright 2019 NXP
4  * Copyright 2013 Freescale Semiconductor, Inc.
5  */
6 
7 #include <common.h>
8 #include <clk.h>
9 #include <dm.h>
10 #include <fsl_lpuart.h>
11 #include <watchdog.h>
12 #include <asm/io.h>
13 #include <serial.h>
14 #include <linux/compiler.h>
15 #include <asm/arch/imx-regs.h>
16 #include <asm/arch/clock.h>
17 
18 #define US1_TDRE	(1 << 7)
19 #define US1_RDRF	(1 << 5)
20 #define US1_OR		(1 << 3)
21 #define UC2_TE		(1 << 3)
22 #define UC2_RE		(1 << 2)
23 #define CFIFO_TXFLUSH	(1 << 7)
24 #define CFIFO_RXFLUSH	(1 << 6)
25 #define SFIFO_RXOF	(1 << 2)
26 #define SFIFO_RXUF	(1 << 0)
27 
28 #define STAT_LBKDIF	(1 << 31)
29 #define STAT_RXEDGIF	(1 << 30)
30 #define STAT_TDRE	(1 << 23)
31 #define STAT_RDRF	(1 << 21)
32 #define STAT_IDLE	(1 << 20)
33 #define STAT_OR		(1 << 19)
34 #define STAT_NF		(1 << 18)
35 #define STAT_FE		(1 << 17)
36 #define STAT_PF		(1 << 16)
37 #define STAT_MA1F	(1 << 15)
38 #define STAT_MA2F	(1 << 14)
39 #define STAT_FLAGS	(STAT_LBKDIF | STAT_RXEDGIF | STAT_IDLE | STAT_OR | \
40 			 STAT_NF | STAT_FE | STAT_PF | STAT_MA1F | STAT_MA2F)
41 
42 #define CTRL_TE		(1 << 19)
43 #define CTRL_RE		(1 << 18)
44 
45 #define FIFO_RXFLUSH		BIT(14)
46 #define FIFO_TXFLUSH		BIT(15)
47 #define FIFO_TXSIZE_MASK	0x70
48 #define FIFO_TXSIZE_OFF	4
49 #define FIFO_RXSIZE_MASK	0x7
50 #define FIFO_RXSIZE_OFF	0
51 #define FIFO_TXFE		0x80
52 #ifdef CONFIG_ARCH_IMX8
53 #define FIFO_RXFE		0x08
54 #else
55 #define FIFO_RXFE		0x40
56 #endif
57 
58 #define WATER_TXWATER_OFF	0
59 #define WATER_RXWATER_OFF	16
60 
61 DECLARE_GLOBAL_DATA_PTR;
62 
63 #define LPUART_FLAG_REGMAP_32BIT_REG	BIT(0)
64 #define LPUART_FLAG_REGMAP_ENDIAN_BIG	BIT(1)
65 
66 enum lpuart_devtype {
67 	DEV_VF610 = 1,
68 	DEV_LS1021A,
69 	DEV_MX7ULP,
70 	DEV_IMX8
71 };
72 
73 struct lpuart_serial_platdata {
74 	void *reg;
75 	enum lpuart_devtype devtype;
76 	ulong flags;
77 };
78 
lpuart_read32(u32 flags,u32 * addr,u32 * val)79 static void lpuart_read32(u32 flags, u32 *addr, u32 *val)
80 {
81 	if (flags & LPUART_FLAG_REGMAP_32BIT_REG) {
82 		if (flags & LPUART_FLAG_REGMAP_ENDIAN_BIG)
83 			*(u32 *)val = in_be32(addr);
84 		else
85 			*(u32 *)val = in_le32(addr);
86 	}
87 }
88 
lpuart_write32(u32 flags,u32 * addr,u32 val)89 static void lpuart_write32(u32 flags, u32 *addr, u32 val)
90 {
91 	if (flags & LPUART_FLAG_REGMAP_32BIT_REG) {
92 		if (flags & LPUART_FLAG_REGMAP_ENDIAN_BIG)
93 			out_be32(addr, val);
94 		else
95 			out_le32(addr, val);
96 	}
97 }
98 
99 
100 #ifndef CONFIG_SYS_CLK_FREQ
101 #define CONFIG_SYS_CLK_FREQ	0
102 #endif
103 
get_lpuart_clk(void)104 u32 __weak get_lpuart_clk(void)
105 {
106 	return CONFIG_SYS_CLK_FREQ;
107 }
108 
109 #if CONFIG_IS_ENABLED(CLK)
get_lpuart_clk_rate(struct udevice * dev,u32 * clk)110 static int get_lpuart_clk_rate(struct udevice *dev, u32 *clk)
111 {
112 	struct clk per_clk;
113 	ulong rate;
114 	int ret;
115 
116 	ret = clk_get_by_name(dev, "per", &per_clk);
117 	if (ret) {
118 		dev_err(dev, "Failed to get per clk: %d\n", ret);
119 		return ret;
120 	}
121 
122 	rate = clk_get_rate(&per_clk);
123 	if ((long)rate <= 0) {
124 		dev_err(dev, "Failed to get per clk rate: %ld\n", (long)rate);
125 		return ret;
126 	}
127 	*clk = rate;
128 	return 0;
129 }
130 #else
get_lpuart_clk_rate(struct udevice * dev,u32 * clk)131 static inline int get_lpuart_clk_rate(struct udevice *dev, u32 *clk)
132 { return -ENOSYS; }
133 #endif
134 
is_lpuart32(struct udevice * dev)135 static bool is_lpuart32(struct udevice *dev)
136 {
137 	struct lpuart_serial_platdata *plat = dev->platdata;
138 
139 	return plat->flags & LPUART_FLAG_REGMAP_32BIT_REG;
140 }
141 
_lpuart_serial_setbrg(struct udevice * dev,int baudrate)142 static void _lpuart_serial_setbrg(struct udevice *dev,
143 				  int baudrate)
144 {
145 	struct lpuart_serial_platdata *plat = dev_get_platdata(dev);
146 	struct lpuart_fsl *base = plat->reg;
147 	u32 clk;
148 	u16 sbr;
149 	int ret;
150 
151 	if (CONFIG_IS_ENABLED(CLK)) {
152 		ret = get_lpuart_clk_rate(dev, &clk);
153 		if (ret)
154 			return;
155 	} else {
156 		clk = get_lpuart_clk();
157 	}
158 
159 	sbr = (u16)(clk / (16 * baudrate));
160 
161 	/* place adjustment later - n/32 BRFA */
162 	__raw_writeb(sbr >> 8, &base->ubdh);
163 	__raw_writeb(sbr & 0xff, &base->ubdl);
164 }
165 
_lpuart_serial_getc(struct lpuart_serial_platdata * plat)166 static int _lpuart_serial_getc(struct lpuart_serial_platdata *plat)
167 {
168 	struct lpuart_fsl *base = plat->reg;
169 	while (!(__raw_readb(&base->us1) & (US1_RDRF | US1_OR)))
170 		WATCHDOG_RESET();
171 
172 	barrier();
173 
174 	return __raw_readb(&base->ud);
175 }
176 
_lpuart_serial_putc(struct lpuart_serial_platdata * plat,const char c)177 static void _lpuart_serial_putc(struct lpuart_serial_platdata *plat,
178 				const char c)
179 {
180 	struct lpuart_fsl *base = plat->reg;
181 
182 	while (!(__raw_readb(&base->us1) & US1_TDRE))
183 		WATCHDOG_RESET();
184 
185 	__raw_writeb(c, &base->ud);
186 }
187 
188 /* Test whether a character is in the RX buffer */
_lpuart_serial_tstc(struct lpuart_serial_platdata * plat)189 static int _lpuart_serial_tstc(struct lpuart_serial_platdata *plat)
190 {
191 	struct lpuart_fsl *base = plat->reg;
192 
193 	if (__raw_readb(&base->urcfifo) == 0)
194 		return 0;
195 
196 	return 1;
197 }
198 
199 /*
200  * Initialise the serial port with the given baudrate. The settings
201  * are always 8 data bits, no parity, 1 stop bit, no start bits.
202  */
_lpuart_serial_init(struct udevice * dev)203 static int _lpuart_serial_init(struct udevice *dev)
204 {
205 	struct lpuart_serial_platdata *plat = dev_get_platdata(dev);
206 	struct lpuart_fsl *base = (struct lpuart_fsl *)plat->reg;
207 	u8 ctrl;
208 
209 	ctrl = __raw_readb(&base->uc2);
210 	ctrl &= ~UC2_RE;
211 	ctrl &= ~UC2_TE;
212 	__raw_writeb(ctrl, &base->uc2);
213 
214 	__raw_writeb(0, &base->umodem);
215 	__raw_writeb(0, &base->uc1);
216 
217 	/* Disable FIFO and flush buffer */
218 	__raw_writeb(0x0, &base->upfifo);
219 	__raw_writeb(0x0, &base->utwfifo);
220 	__raw_writeb(0x1, &base->urwfifo);
221 	__raw_writeb(CFIFO_TXFLUSH | CFIFO_RXFLUSH, &base->ucfifo);
222 
223 	/* provide data bits, parity, stop bit, etc */
224 	_lpuart_serial_setbrg(dev, gd->baudrate);
225 
226 	__raw_writeb(UC2_RE | UC2_TE, &base->uc2);
227 
228 	return 0;
229 }
230 
_lpuart32_serial_setbrg_7ulp(struct udevice * dev,int baudrate)231 static void _lpuart32_serial_setbrg_7ulp(struct udevice *dev,
232 					 int baudrate)
233 {
234 	struct lpuart_serial_platdata *plat = dev_get_platdata(dev);
235 	struct lpuart_fsl_reg32 *base = plat->reg;
236 	u32 sbr, osr, baud_diff, tmp_osr, tmp_sbr, tmp_diff, tmp;
237 	u32 clk;
238 	int ret;
239 
240 	if (CONFIG_IS_ENABLED(CLK)) {
241 		ret = get_lpuart_clk_rate(dev, &clk);
242 		if (ret)
243 			return;
244 	} else {
245 		clk = get_lpuart_clk();
246 	}
247 
248 	baud_diff = baudrate;
249 	osr = 0;
250 	sbr = 0;
251 
252 	for (tmp_osr = 4; tmp_osr <= 32; tmp_osr++) {
253 		tmp_sbr = (clk / (baudrate * tmp_osr));
254 
255 		if (tmp_sbr == 0)
256 			tmp_sbr = 1;
257 
258 		/*calculate difference in actual buad w/ current values */
259 		tmp_diff = (clk / (tmp_osr * tmp_sbr));
260 		tmp_diff = tmp_diff - baudrate;
261 
262 		/* select best values between sbr and sbr+1 */
263 		if (tmp_diff > (baudrate - (clk / (tmp_osr * (tmp_sbr + 1))))) {
264 			tmp_diff = baudrate - (clk / (tmp_osr * (tmp_sbr + 1)));
265 			tmp_sbr++;
266 		}
267 
268 		if (tmp_diff <= baud_diff) {
269 			baud_diff = tmp_diff;
270 			osr = tmp_osr;
271 			sbr = tmp_sbr;
272 		}
273 	}
274 
275 	/*
276 	 * TODO: handle buadrate outside acceptable rate
277 	 * if (baudDiff > ((config->baudRate_Bps / 100) * 3))
278 	 * {
279 	 *   Unacceptable baud rate difference of more than 3%
280 	 *   return kStatus_LPUART_BaudrateNotSupport;
281 	 * }
282 	 */
283 	tmp = in_le32(&base->baud);
284 
285 	if ((osr > 3) && (osr < 8))
286 		tmp |= LPUART_BAUD_BOTHEDGE_MASK;
287 
288 	tmp &= ~LPUART_BAUD_OSR_MASK;
289 	tmp |= LPUART_BAUD_OSR(osr-1);
290 
291 	tmp &= ~LPUART_BAUD_SBR_MASK;
292 	tmp |= LPUART_BAUD_SBR(sbr);
293 
294 	/* explicitly disable 10 bit mode & set 1 stop bit */
295 	tmp &= ~(LPUART_BAUD_M10_MASK | LPUART_BAUD_SBNS_MASK);
296 
297 	out_le32(&base->baud, tmp);
298 }
299 
_lpuart32_serial_setbrg(struct udevice * dev,int baudrate)300 static void _lpuart32_serial_setbrg(struct udevice *dev,
301 				    int baudrate)
302 {
303 	struct lpuart_serial_platdata *plat = dev_get_platdata(dev);
304 	struct lpuart_fsl_reg32 *base = plat->reg;
305 	u32 clk;
306 	u32 sbr;
307 	int ret;
308 
309 	if (CONFIG_IS_ENABLED(CLK)) {
310 		ret = get_lpuart_clk_rate(dev, &clk);
311 		if (ret)
312 			return;
313 	} else {
314 		clk = get_lpuart_clk();
315 	}
316 
317 	sbr = (clk / (16 * baudrate));
318 
319 	/* place adjustment later - n/32 BRFA */
320 	lpuart_write32(plat->flags, &base->baud, sbr);
321 }
322 
_lpuart32_serial_getc(struct lpuart_serial_platdata * plat)323 static int _lpuart32_serial_getc(struct lpuart_serial_platdata *plat)
324 {
325 	struct lpuart_fsl_reg32 *base = plat->reg;
326 	u32 stat, val;
327 
328 	lpuart_read32(plat->flags, &base->stat, &stat);
329 	while ((stat & STAT_RDRF) == 0) {
330 		lpuart_write32(plat->flags, &base->stat, STAT_FLAGS);
331 		WATCHDOG_RESET();
332 		lpuart_read32(plat->flags, &base->stat, &stat);
333 	}
334 
335 	lpuart_read32(plat->flags, &base->data, &val);
336 
337 	lpuart_read32(plat->flags, &base->stat, &stat);
338 	if (stat & STAT_OR)
339 		lpuart_write32(plat->flags, &base->stat, STAT_OR);
340 
341 	return val & 0x3ff;
342 }
343 
_lpuart32_serial_putc(struct lpuart_serial_platdata * plat,const char c)344 static void _lpuart32_serial_putc(struct lpuart_serial_platdata *plat,
345 				  const char c)
346 {
347 	struct lpuart_fsl_reg32 *base = plat->reg;
348 	u32 stat;
349 
350 	if (c == '\n')
351 		serial_putc('\r');
352 
353 	while (true) {
354 		lpuart_read32(plat->flags, &base->stat, &stat);
355 
356 		if ((stat & STAT_TDRE))
357 			break;
358 
359 		WATCHDOG_RESET();
360 	}
361 
362 	lpuart_write32(plat->flags, &base->data, c);
363 }
364 
365 /* Test whether a character is in the RX buffer */
_lpuart32_serial_tstc(struct lpuart_serial_platdata * plat)366 static int _lpuart32_serial_tstc(struct lpuart_serial_platdata *plat)
367 {
368 	struct lpuart_fsl_reg32 *base = plat->reg;
369 	u32 water;
370 
371 	lpuart_read32(plat->flags, &base->water, &water);
372 
373 	if ((water >> 24) == 0)
374 		return 0;
375 
376 	return 1;
377 }
378 
379 /*
380  * Initialise the serial port with the given baudrate. The settings
381  * are always 8 data bits, no parity, 1 stop bit, no start bits.
382  */
_lpuart32_serial_init(struct udevice * dev)383 static int _lpuart32_serial_init(struct udevice *dev)
384 {
385 	struct lpuart_serial_platdata *plat = dev_get_platdata(dev);
386 	struct lpuart_fsl_reg32 *base = (struct lpuart_fsl_reg32 *)plat->reg;
387 	u32 val, tx_fifo_size;
388 
389 	lpuart_read32(plat->flags, &base->ctrl, &val);
390 	val &= ~CTRL_RE;
391 	val &= ~CTRL_TE;
392 	lpuart_write32(plat->flags, &base->ctrl, val);
393 
394 	lpuart_write32(plat->flags, &base->modir, 0);
395 
396 	lpuart_read32(plat->flags, &base->fifo, &val);
397 	tx_fifo_size = (val & FIFO_TXSIZE_MASK) >> FIFO_TXSIZE_OFF;
398 	/* Set the TX water to half of FIFO size */
399 	if (tx_fifo_size > 1)
400 		tx_fifo_size = tx_fifo_size >> 1;
401 
402 	/* Set RX water to 0, to be triggered by any receive data */
403 	lpuart_write32(plat->flags, &base->water,
404 		       (tx_fifo_size << WATER_TXWATER_OFF));
405 
406 	/* Enable TX and RX FIFO */
407 	val |= (FIFO_TXFE | FIFO_RXFE | FIFO_TXFLUSH | FIFO_RXFLUSH);
408 	lpuart_write32(plat->flags, &base->fifo, val);
409 
410 	lpuart_write32(plat->flags, &base->match, 0);
411 
412 	if (plat->devtype == DEV_MX7ULP || plat->devtype == DEV_IMX8) {
413 		_lpuart32_serial_setbrg_7ulp(dev, gd->baudrate);
414 	} else {
415 		/* provide data bits, parity, stop bit, etc */
416 		_lpuart32_serial_setbrg(dev, gd->baudrate);
417 	}
418 
419 	lpuart_write32(plat->flags, &base->ctrl, CTRL_RE | CTRL_TE);
420 
421 	return 0;
422 }
423 
lpuart_serial_setbrg(struct udevice * dev,int baudrate)424 static int lpuart_serial_setbrg(struct udevice *dev, int baudrate)
425 {
426 	struct lpuart_serial_platdata *plat = dev_get_platdata(dev);
427 
428 	if (is_lpuart32(dev)) {
429 		if (plat->devtype == DEV_MX7ULP || plat->devtype == DEV_IMX8)
430 			_lpuart32_serial_setbrg_7ulp(dev, baudrate);
431 		else
432 			_lpuart32_serial_setbrg(dev, baudrate);
433 	} else {
434 		_lpuart_serial_setbrg(dev, baudrate);
435 	}
436 
437 	return 0;
438 }
439 
lpuart_serial_getc(struct udevice * dev)440 static int lpuart_serial_getc(struct udevice *dev)
441 {
442 	struct lpuart_serial_platdata *plat = dev->platdata;
443 
444 	if (is_lpuart32(dev))
445 		return _lpuart32_serial_getc(plat);
446 
447 	return _lpuart_serial_getc(plat);
448 }
449 
lpuart_serial_putc(struct udevice * dev,const char c)450 static int lpuart_serial_putc(struct udevice *dev, const char c)
451 {
452 	struct lpuart_serial_platdata *plat = dev->platdata;
453 
454 	if (is_lpuart32(dev))
455 		_lpuart32_serial_putc(plat, c);
456 	else
457 		_lpuart_serial_putc(plat, c);
458 
459 	return 0;
460 }
461 
lpuart_serial_pending(struct udevice * dev,bool input)462 static int lpuart_serial_pending(struct udevice *dev, bool input)
463 {
464 	struct lpuart_serial_platdata *plat = dev->platdata;
465 	struct lpuart_fsl *reg = plat->reg;
466 	struct lpuart_fsl_reg32 *reg32 = plat->reg;
467 	u32 stat;
468 
469 	if (is_lpuart32(dev)) {
470 		if (input) {
471 			return _lpuart32_serial_tstc(plat);
472 		} else {
473 			lpuart_read32(plat->flags, &reg32->stat, &stat);
474 			return stat & STAT_TDRE ? 0 : 1;
475 		}
476 	}
477 
478 	if (input)
479 		return _lpuart_serial_tstc(plat);
480 	else
481 		return __raw_readb(&reg->us1) & US1_TDRE ? 0 : 1;
482 }
483 
lpuart_serial_probe(struct udevice * dev)484 static int lpuart_serial_probe(struct udevice *dev)
485 {
486 	if (is_lpuart32(dev))
487 		return _lpuart32_serial_init(dev);
488 	else
489 		return _lpuart_serial_init(dev);
490 }
491 
lpuart_serial_ofdata_to_platdata(struct udevice * dev)492 static int lpuart_serial_ofdata_to_platdata(struct udevice *dev)
493 {
494 	struct lpuart_serial_platdata *plat = dev->platdata;
495 	const void *blob = gd->fdt_blob;
496 	int node = dev_of_offset(dev);
497 	fdt_addr_t addr;
498 
499 	addr = devfdt_get_addr(dev);
500 	if (addr == FDT_ADDR_T_NONE)
501 		return -EINVAL;
502 
503 	plat->reg = (void *)addr;
504 	plat->flags = dev_get_driver_data(dev);
505 
506 	if (fdtdec_get_bool(blob, node, "little-endian"))
507 		plat->flags &= ~LPUART_FLAG_REGMAP_ENDIAN_BIG;
508 
509 	if (!fdt_node_check_compatible(blob, node, "fsl,ls1021a-lpuart"))
510 		plat->devtype = DEV_LS1021A;
511 	else if (!fdt_node_check_compatible(blob, node, "fsl,imx7ulp-lpuart"))
512 		plat->devtype = DEV_MX7ULP;
513 	else if (!fdt_node_check_compatible(blob, node, "fsl,vf610-lpuart"))
514 		plat->devtype = DEV_VF610;
515 	else if (!fdt_node_check_compatible(blob, node, "fsl,imx8qm-lpuart"))
516 		plat->devtype = DEV_IMX8;
517 
518 	return 0;
519 }
520 
521 static const struct dm_serial_ops lpuart_serial_ops = {
522 	.putc = lpuart_serial_putc,
523 	.pending = lpuart_serial_pending,
524 	.getc = lpuart_serial_getc,
525 	.setbrg = lpuart_serial_setbrg,
526 };
527 
528 static const struct udevice_id lpuart_serial_ids[] = {
529 	{ .compatible = "fsl,ls1021a-lpuart", .data =
530 		LPUART_FLAG_REGMAP_32BIT_REG | LPUART_FLAG_REGMAP_ENDIAN_BIG },
531 	{ .compatible = "fsl,imx7ulp-lpuart",
532 		.data = LPUART_FLAG_REGMAP_32BIT_REG },
533 	{ .compatible = "fsl,vf610-lpuart"},
534 	{ .compatible = "fsl,imx8qm-lpuart",
535 		.data = LPUART_FLAG_REGMAP_32BIT_REG },
536 	{ }
537 };
538 
539 U_BOOT_DRIVER(serial_lpuart) = {
540 	.name	= "serial_lpuart",
541 	.id	= UCLASS_SERIAL,
542 	.of_match = lpuart_serial_ids,
543 	.ofdata_to_platdata = lpuart_serial_ofdata_to_platdata,
544 	.platdata_auto_alloc_size = sizeof(struct lpuart_serial_platdata),
545 	.probe = lpuart_serial_probe,
546 	.ops	= &lpuart_serial_ops,
547 };
548