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