diff options
Diffstat (limited to 'core/drivers/sprd_uart.c')
-rw-r--r-- | core/drivers/sprd_uart.c | 59 |
1 files changed, 38 insertions, 21 deletions
diff --git a/core/drivers/sprd_uart.c b/core/drivers/sprd_uart.c index fdaa1b6..c77f595 100644 --- a/core/drivers/sprd_uart.c +++ b/core/drivers/sprd_uart.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2016, Spreadtrum Communications Inc. + * Copyright (c) 2017, Linaro Limited * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,8 +25,10 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ -#include <io.h> #include <drivers/sprd_uart.h> +#include <io.h> +#include <keep.h> +#include <util.h> /* Register definitions */ #define UART_TXD 0x0000 @@ -36,43 +39,57 @@ #define STS1_RXF_CNT_MASK 0x00ff /* Rx FIFO data counter mask */ #define STS1_TXF_CNT_MASK 0xff00 /* Tx FIFO data counter mask */ -static uint32_t sprd_uart_read(vaddr_t base, uint32_t reg) +static vaddr_t chip_to_base(struct serial_chip *chip) { - return read32(base + reg); -} + struct sprd_uart_data *pd = + container_of(chip, struct sprd_uart_data, chip); -static void sprd_uart_write(vaddr_t base, uint32_t reg, uint32_t value) -{ - write32(value, base + reg); + return io_pa_or_va(&pd->base); } -static void sprd_uart_wait_xmit_done(vaddr_t base) +static void sprd_uart_flush(struct serial_chip *chip) { - while (sprd_uart_read(base, UART_STS1) & STS1_TXF_CNT_MASK) + vaddr_t base = chip_to_base(chip); + + while (read32(base + UART_STS1) & STS1_TXF_CNT_MASK) ; } -static void sprd_uart_wait_rx_data(vaddr_t base) +static bool sprd_uart_have_rx_data(struct serial_chip *chip) { - while (!(sprd_uart_read(base, UART_STS1) & STS1_RXF_CNT_MASK)) - ; + vaddr_t base = chip_to_base(chip); + + return !!(read32(base + UART_STS1) & STS1_RXF_CNT_MASK); } -void sprd_uart_flush(vaddr_t base) +static void sprd_uart_putc(struct serial_chip *chip, int ch) { - sprd_uart_wait_xmit_done(base); + vaddr_t base = chip_to_base(chip); + + sprd_uart_flush(chip); + write32(base + UART_TXD, ch); } -void sprd_uart_putc(vaddr_t base, unsigned char ch) +static int sprd_uart_getchar(struct serial_chip *chip) { - sprd_uart_wait_xmit_done(base); + vaddr_t base = chip_to_base(chip); + + while (!sprd_uart_have_rx_data(chip)) + ; - sprd_uart_write(base, UART_TXD, (uint32_t)ch); + return read32(base + UART_RXD) & 0xff; } -unsigned char sprd_uart_getc(vaddr_t base) -{ - sprd_uart_wait_rx_data(base); +static const struct serial_ops sprd_uart_ops = { + .flush = sprd_uart_flush, + .getchar = sprd_uart_getchar, + .have_rx_data = sprd_uart_have_rx_data, + .putc = sprd_uart_putc, +}; +KEEP_PAGER(sprd_uart_ops); - return sprd_uart_read(base, UART_RXD) & 0xff; +void sprd_uart_init(struct sprd_uart_data *pd, paddr_t base) +{ + pd->base.pa = base; + pd->chip.ops = &sprd_uart_ops; } |