xref: /optee_os/core/drivers/amlogic_uart.c (revision b6afa13a5fe7d94666ba7a5e2c98ba78dc22092d)
1*b6afa13aSCarlo Caione // SPDX-License-Identifier: BSD-2-Clause
2*b6afa13aSCarlo Caione /*
3*b6afa13aSCarlo Caione  * Copyright (c) 2020 Carlo Caione <ccaione@baylibre.com>
4*b6afa13aSCarlo Caione  */
5*b6afa13aSCarlo Caione 
6*b6afa13aSCarlo Caione #include <assert.h>
7*b6afa13aSCarlo Caione #include <drivers/amlogic_uart.h>
8*b6afa13aSCarlo Caione #include <io.h>
9*b6afa13aSCarlo Caione #include <keep.h>
10*b6afa13aSCarlo Caione #include <util.h>
11*b6afa13aSCarlo Caione 
12*b6afa13aSCarlo Caione /* Registers */
13*b6afa13aSCarlo Caione #define AML_UART_WFIFO		0x0000
14*b6afa13aSCarlo Caione #define AML_UART_RFIFO		0x0004
15*b6afa13aSCarlo Caione #define AML_UART_CONTROL	0x0008
16*b6afa13aSCarlo Caione #define AML_UART_STATUS		0x000C
17*b6afa13aSCarlo Caione #define AML_UART_MISC		0x0010
18*b6afa13aSCarlo Caione 
19*b6afa13aSCarlo Caione /* AML_UART_STATUS bits */
20*b6afa13aSCarlo Caione #define AML_UART_RX_EMPTY	BIT(20)
21*b6afa13aSCarlo Caione #define AML_UART_TX_FULL	BIT(21)
22*b6afa13aSCarlo Caione #define AML_UART_TX_EMPTY	BIT(22)
23*b6afa13aSCarlo Caione 
24*b6afa13aSCarlo Caione static vaddr_t chip_to_base(struct serial_chip *chip)
25*b6afa13aSCarlo Caione {
26*b6afa13aSCarlo Caione 	struct amlogic_uart_data *pd =
27*b6afa13aSCarlo Caione 		container_of(chip, struct amlogic_uart_data, chip);
28*b6afa13aSCarlo Caione 
29*b6afa13aSCarlo Caione 	return io_pa_or_va(&pd->base);
30*b6afa13aSCarlo Caione }
31*b6afa13aSCarlo Caione 
32*b6afa13aSCarlo Caione static void amlogic_uart_flush(struct serial_chip *chip)
33*b6afa13aSCarlo Caione {
34*b6afa13aSCarlo Caione 	vaddr_t base = chip_to_base(chip);
35*b6afa13aSCarlo Caione 
36*b6afa13aSCarlo Caione 	while (!(io_read32(base + AML_UART_STATUS) & AML_UART_TX_EMPTY))
37*b6afa13aSCarlo Caione 		;
38*b6afa13aSCarlo Caione }
39*b6afa13aSCarlo Caione 
40*b6afa13aSCarlo Caione static int amlogic_uart_getchar(struct serial_chip *chip)
41*b6afa13aSCarlo Caione {
42*b6afa13aSCarlo Caione 	vaddr_t base = chip_to_base(chip);
43*b6afa13aSCarlo Caione 
44*b6afa13aSCarlo Caione 	if (io_read32(base + AML_UART_STATUS) & AML_UART_RX_EMPTY)
45*b6afa13aSCarlo Caione 		return -1;
46*b6afa13aSCarlo Caione 
47*b6afa13aSCarlo Caione 	return io_read32(base + AML_UART_RFIFO) & 0xff;
48*b6afa13aSCarlo Caione }
49*b6afa13aSCarlo Caione 
50*b6afa13aSCarlo Caione static void amlogic_uart_putc(struct serial_chip *chip, int ch)
51*b6afa13aSCarlo Caione {
52*b6afa13aSCarlo Caione 	vaddr_t base = chip_to_base(chip);
53*b6afa13aSCarlo Caione 
54*b6afa13aSCarlo Caione 	while (io_read32(base + AML_UART_STATUS) & AML_UART_TX_FULL)
55*b6afa13aSCarlo Caione 		;
56*b6afa13aSCarlo Caione 
57*b6afa13aSCarlo Caione 	io_write32(base + AML_UART_WFIFO, ch);
58*b6afa13aSCarlo Caione }
59*b6afa13aSCarlo Caione 
60*b6afa13aSCarlo Caione static const struct serial_ops amlogic_uart_ops = {
61*b6afa13aSCarlo Caione 	.flush = amlogic_uart_flush,
62*b6afa13aSCarlo Caione 	.getchar = amlogic_uart_getchar,
63*b6afa13aSCarlo Caione 	.putc = amlogic_uart_putc,
64*b6afa13aSCarlo Caione };
65*b6afa13aSCarlo Caione 
66*b6afa13aSCarlo Caione void amlogic_uart_init(struct amlogic_uart_data *pd, paddr_t base)
67*b6afa13aSCarlo Caione {
68*b6afa13aSCarlo Caione 	pd->base.pa = base;
69*b6afa13aSCarlo Caione 	pd->chip.ops = &amlogic_uart_ops;
70*b6afa13aSCarlo Caione 
71*b6afa13aSCarlo Caione 	/*
72*b6afa13aSCarlo Caione 	 * Do nothing, debug uart (AO) shared with normal world, everything for
73*b6afa13aSCarlo Caione 	 * uart initialization is done in bootloader.
74*b6afa13aSCarlo Caione 	 */
75*b6afa13aSCarlo Caione }
76