xref: /optee_os/core/drivers/imx_lpuart.c (revision 601976a55d4cf036f46c90c1274340605c85fb43)
1*601976a5SPeng Fan // SPDX-License-Identifier: BSD-2-Clause
2*601976a5SPeng Fan /*
3*601976a5SPeng Fan  * Copyright 2017-2019 NXP
4*601976a5SPeng Fan  */
5*601976a5SPeng Fan 
6*601976a5SPeng Fan #include <assert.h>
7*601976a5SPeng Fan #include <drivers/imx_uart.h>
8*601976a5SPeng Fan #include <io.h>
9*601976a5SPeng Fan #include <keep.h>
10*601976a5SPeng Fan #include <util.h>
11*601976a5SPeng Fan 
12*601976a5SPeng Fan #define STAT		0x14
13*601976a5SPeng Fan #define DATA		0x1C
14*601976a5SPeng Fan #define STAT_TDRE	BIT(23)
15*601976a5SPeng Fan #define STAT_RDRF	BIT(21)
16*601976a5SPeng Fan #define STAT_OR		BIT(19)
17*601976a5SPeng Fan 
18*601976a5SPeng Fan static vaddr_t chip_to_base(struct serial_chip *chip)
19*601976a5SPeng Fan {
20*601976a5SPeng Fan 	struct imx_uart_data *pd =
21*601976a5SPeng Fan 		container_of(chip, struct imx_uart_data, chip);
22*601976a5SPeng Fan 
23*601976a5SPeng Fan 	return io_pa_or_va(&pd->base);
24*601976a5SPeng Fan }
25*601976a5SPeng Fan 
26*601976a5SPeng Fan static void imx_lpuart_flush(struct serial_chip *chip __unused)
27*601976a5SPeng Fan {
28*601976a5SPeng Fan }
29*601976a5SPeng Fan 
30*601976a5SPeng Fan static int imx_lpuart_getchar(struct serial_chip *chip)
31*601976a5SPeng Fan {
32*601976a5SPeng Fan 	int ch = 0;
33*601976a5SPeng Fan 	vaddr_t base = chip_to_base(chip);
34*601976a5SPeng Fan 
35*601976a5SPeng Fan 	while (io_read32(base + STAT) & STAT_RDRF)
36*601976a5SPeng Fan 		;
37*601976a5SPeng Fan 
38*601976a5SPeng Fan 	ch = io_read32(base + DATA) & 0x3ff;
39*601976a5SPeng Fan 
40*601976a5SPeng Fan 	if (io_read32(base + STAT) & STAT_OR)
41*601976a5SPeng Fan 		io_write32(base + STAT, STAT_OR);
42*601976a5SPeng Fan 
43*601976a5SPeng Fan 	return ch;
44*601976a5SPeng Fan }
45*601976a5SPeng Fan 
46*601976a5SPeng Fan static void imx_lpuart_putc(struct serial_chip *chip, int ch)
47*601976a5SPeng Fan {
48*601976a5SPeng Fan 	vaddr_t base = chip_to_base(chip);
49*601976a5SPeng Fan 
50*601976a5SPeng Fan 	while (!(io_read32(base + STAT) & STAT_TDRE))
51*601976a5SPeng Fan 		;
52*601976a5SPeng Fan 
53*601976a5SPeng Fan 	io_write32(base + DATA, ch);
54*601976a5SPeng Fan }
55*601976a5SPeng Fan 
56*601976a5SPeng Fan static const struct serial_ops imx_lpuart_ops = {
57*601976a5SPeng Fan 	.flush = imx_lpuart_flush,
58*601976a5SPeng Fan 	.getchar = imx_lpuart_getchar,
59*601976a5SPeng Fan 	.putc = imx_lpuart_putc,
60*601976a5SPeng Fan };
61*601976a5SPeng Fan KEEP_PAGER(imx_lpuart_ops);
62*601976a5SPeng Fan 
63*601976a5SPeng Fan void imx_uart_init(struct imx_uart_data *pd, paddr_t base)
64*601976a5SPeng Fan {
65*601976a5SPeng Fan 	pd->base.pa = base;
66*601976a5SPeng Fan 	pd->chip.ops = &imx_lpuart_ops;
67*601976a5SPeng Fan 
68*601976a5SPeng Fan 	/*
69*601976a5SPeng Fan 	 * Do nothing, debug uart(sc lpuart) shared with normal world,
70*601976a5SPeng Fan 	 * everything for uart initialization is done in bootloader.
71*601976a5SPeng Fan 	 */
72*601976a5SPeng Fan }
73