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