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