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