diff options
Diffstat (limited to 'core/drivers')
-rw-r--r-- | core/drivers/cdns_uart.c | 79 | ||||
-rw-r--r-- | core/drivers/hi16xx_uart.c | 82 | ||||
-rw-r--r-- | core/drivers/imx_uart.c | 51 | ||||
-rw-r--r-- | core/drivers/ns16550.c | 38 | ||||
-rw-r--r-- | core/drivers/pl011.c | 83 | ||||
-rw-r--r-- | core/drivers/pl050.c | 4 | ||||
-rw-r--r-- | core/drivers/scif.c | 44 | ||||
-rw-r--r-- | core/drivers/serial8250_uart.c | 73 | ||||
-rw-r--r-- | core/drivers/sprd_uart.c | 59 | ||||
-rw-r--r-- | core/drivers/stih_asc.c | 75 | ||||
-rw-r--r-- | core/drivers/sub.mk | 1 | ||||
-rw-r--r-- | core/drivers/sunxi_uart.c | 60 |
12 files changed, 486 insertions, 163 deletions
diff --git a/core/drivers/cdns_uart.c b/core/drivers/cdns_uart.c index 3b4e4b9..8672093 100644 --- a/core/drivers/cdns_uart.c +++ b/core/drivers/cdns_uart.c @@ -24,9 +24,11 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ -#include <compiler.h> +#include <assert.h> #include <drivers/cdns_uart.h> #include <io.h> +#include <keep.h> +#include <mm/core_mmu.h> #include <util.h> #define CDNS_UART_CONTROL 0 @@ -52,31 +54,44 @@ #define CDNS_UART_IRQ_RXTRIG BIT(0) #define CDNS_UART_IRQ_RXTOUT BIT(8) -void cdns_uart_flush(vaddr_t base) +static vaddr_t chip_to_base(struct serial_chip *chip) { + struct cdns_uart_data *pd = + container_of(chip, struct cdns_uart_data, chip); + + return io_pa_or_va(&pd->base); +} + +static void cdns_uart_flush(struct serial_chip *chip) +{ + vaddr_t base = chip_to_base(chip); + while (!(read32(base + CDNS_UART_CHANNEL_STATUS) & - CDNS_UART_CHANNEL_STATUS_TEMPTY)) + CDNS_UART_CHANNEL_STATUS_TEMPTY)) ; } -/* - * we rely on the bootloader having set up the HW correctly, we just enable - * transmitter/receiver here, just in case. - */ -void cdns_uart_init(vaddr_t base, uint32_t uart_clk, uint32_t baud_rate) +static bool cdns_uart_have_rx_data(struct serial_chip *chip) { - if (!base || !uart_clk || !baud_rate) - return; + vaddr_t base = chip_to_base(chip); - /* Enable UART and RX/TX */ - write32(CDNS_UART_CONTROL_RXEN | CDNS_UART_CONTROL_TXEN, - base + CDNS_UART_CONTROL); + return !(read32(base + CDNS_UART_CHANNEL_STATUS) & + CDNS_UART_CHANNEL_STATUS_REMPTY); +} + +static int cdns_uart_getchar(struct serial_chip *chip) +{ + vaddr_t base = chip_to_base(chip); - cdns_uart_flush(base); + while (!cdns_uart_have_rx_data(chip)) + ; + return read32(base + CDNS_UART_FIFO) & 0xff; } -void cdns_uart_putc(int ch, vaddr_t base) +static void cdns_uart_putc(struct serial_chip *chip, int ch) { + vaddr_t base = chip_to_base(chip); + /* Wait until there is space in the FIFO */ while (read32(base + CDNS_UART_CHANNEL_STATUS) & CDNS_UART_CHANNEL_STATUS_TFUL) @@ -86,15 +101,31 @@ void cdns_uart_putc(int ch, vaddr_t base) write32(ch, base + CDNS_UART_FIFO); } -bool cdns_uart_have_rx_data(vaddr_t base) -{ - return !(read32(base + CDNS_UART_CHANNEL_STATUS) & - CDNS_UART_CHANNEL_STATUS_REMPTY); -} -int cdns_uart_getchar(vaddr_t base) +static const struct serial_ops cdns_uart_ops = { + .flush = cdns_uart_flush, + .getchar = cdns_uart_getchar, + .have_rx_data = cdns_uart_have_rx_data, + .putc = cdns_uart_putc, +}; +KEEP_PAGER(cdns_uart_ops); + +/* + * we rely on the bootloader having set up the HW correctly, we just enable + * transmitter/receiver here, just in case. + */ +void cdns_uart_init(struct cdns_uart_data *pd, paddr_t base, uint32_t uart_clk, + uint32_t baud_rate) { - while (!cdns_uart_have_rx_data(base)) - ; - return read32(base + CDNS_UART_FIFO) & 0xff; + pd->base.pa = base; + pd->chip.ops = &cdns_uart_ops; + + if (!uart_clk || !baud_rate) + return; + + /* Enable UART and RX/TX */ + write32(CDNS_UART_CONTROL_RXEN | CDNS_UART_CONTROL_TXEN, + base + CDNS_UART_CONTROL); + + cdns_uart_flush(&pd->chip); } diff --git a/core/drivers/hi16xx_uart.c b/core/drivers/hi16xx_uart.c index 76e769d..3f8a3ca 100644 --- a/core/drivers/hi16xx_uart.c +++ b/core/drivers/hi16xx_uart.c @@ -24,8 +24,12 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ +#include <assert.h> #include <drivers/hi16xx_uart.h> #include <io.h> +#include <keep.h> +#include <mm/core_mmu.h> +#include <util.h> /* Register offsets */ @@ -76,16 +80,66 @@ #define UART_USR_RFNE_BIT 3 /* Receive FIFO not empty bit */ #define UART_USR_RFF_BIT 4 /* Receive FIFO full bit */ -void hi16xx_uart_flush(vaddr_t base) +static vaddr_t chip_to_base(struct serial_chip *chip) { + struct hi16xx_uart_data *pd = + container_of(chip, struct hi16xx_uart_data, chip); + + return io_pa_or_va(&pd->base); +} + +static void hi16xx_uart_flush(struct serial_chip *chip) +{ + vaddr_t base = chip_to_base(chip); + + while (!(read32(base + UART_USR) & UART_USR_TFE_BIT)) + ; +} + +static void hi16xx_uart_putc(struct serial_chip *chip, int ch) +{ + vaddr_t base = chip_to_base(chip); + + /* Wait until TX FIFO is empty */ while (!(read32(base + UART_USR) & UART_USR_TFE_BIT)) ; + + /* Put character into TX FIFO */ + write32(ch & 0xFF, base + UART_THR); +} + +static bool hi16xx_uart_have_rx_data(struct serial_chip *chip) +{ + vaddr_t base = chip_to_base(chip); + + return (read32(base + UART_USR) & UART_USR_RFNE_BIT); +} + +static int hi16xx_uart_getchar(struct serial_chip *chip) +{ + vaddr_t base = chip_to_base(chip); + + while (!hi16xx_uart_have_rx_data(chip)) + ; + return read32(base + UART_RBR) & 0xFF; } -void hi16xx_uart_init(vaddr_t base, uint32_t uart_clk, uint32_t baud_rate) +static const struct serial_ops hi16xx_uart_ops = { + .flush = hi16xx_uart_flush, + .getchar = hi16xx_uart_getchar, + .have_rx_data = hi16xx_uart_have_rx_data, + .putc = hi16xx_uart_putc, +}; +KEEP_PAGER(hi16xx_uart_ops); + +void hi16xx_uart_init(struct hi16xx_uart_data *pd, paddr_t base, + uint32_t uart_clk, uint32_t baud_rate) { uint16_t freq_div = uart_clk / (16 * baud_rate); + pd->base.pa = base; + pd->chip.ops = &hi16xx_uart_ops; + /* Enable (and clear) FIFOs */ write32(UART_FCR_FIFO_EN, base + UART_FCR); @@ -104,28 +158,6 @@ void hi16xx_uart_init(vaddr_t base, uint32_t uart_clk, uint32_t baud_rate) /* Disable interrupt mode */ write32(0, base + UART_IEL); - hi16xx_uart_flush(base); -} - -void hi16xx_uart_putc(int ch, vaddr_t base) -{ - /* Wait until TX FIFO is empty */ - while (!(read32(base + UART_USR) & UART_USR_TFE_BIT)) - ; - - /* Put character into TX FIFO */ - write32(ch & 0xFF, base + UART_THR); -} - -bool hi16xx_uart_have_rx_data(vaddr_t base) -{ - return (read32(base + UART_USR) & UART_USR_RFNE_BIT); -} - -int hi16xx_uart_getchar(vaddr_t base) -{ - while (!hi16xx_uart_have_rx_data(base)) - ; - return read32(base + UART_RBR) & 0xFF; + hi16xx_uart_flush(&pd->chip); } diff --git a/core/drivers/imx_uart.c b/core/drivers/imx_uart.c index b66d905..dd15ddb 100644 --- a/core/drivers/imx_uart.c +++ b/core/drivers/imx_uart.c @@ -25,12 +25,11 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include <platform_config.h> - +#include <assert.h> #include <drivers/imx_uart.h> -#include <console.h> #include <io.h> -#include <compiler.h> +#include <keep.h> +#include <util.h> /* Register definitions */ #define URXD 0x0 /* Receiver Register */ @@ -80,33 +79,57 @@ #define UTS_RXFULL (1<<3) /* RxFIFO full */ #define UTS_SOFTRST (1<<0) /* Software reset */ -void imx_uart_init(vaddr_t __unused vbase) +static vaddr_t chip_to_base(struct serial_chip *chip) { - /* - * Do nothing, debug uart(uart0) share with normal world, - * everything for uart0 intialization is done in bootloader. - */ + struct imx_uart_data *pd = + container_of(chip, struct imx_uart_data, chip); + + return io_pa_or_va(&pd->base); } -void imx_uart_flush_tx_fifo(vaddr_t base) +static void imx_uart_flush(struct serial_chip *chip) { + vaddr_t base = chip_to_base(chip); + while (!(read32(base + UTS) & UTS_TXEMPTY)) ; } -int imx_uart_getchar(vaddr_t base) +static int imx_uart_getchar(struct serial_chip *chip) { + vaddr_t base = chip_to_base(chip); + while (read32(base + UTS) & UTS_RXEMPTY) ; return (read32(base + URXD) & URXD_RX_DATA); } -void imx_uart_putc(const char c, vaddr_t base) +static void imx_uart_putc(struct serial_chip *chip, int ch) { - write32(c, base + UTXD); + vaddr_t base = chip_to_base(chip); + + write32(ch, base + UTXD); - /* wait until sent */ + /* Wait until sent */ while (!(read32(base + UTS) & UTS_TXEMPTY)) ; } + +static const struct serial_ops imx_uart_ops = { + .flush = imx_uart_flush, + .getchar = imx_uart_getchar, + .putc = imx_uart_putc, +}; +KEEP_PAGER(imx_uart_ops); + +void imx_uart_init(struct imx_uart_data *pd, paddr_t base) +{ + pd->base.pa = base; + pd->chip.ops = &imx_uart_ops; + + /* + * Do nothing, debug uart(uart0) share with normal world, + * everything for uart0 initialization is done in bootloader. + */ +} diff --git a/core/drivers/ns16550.c b/core/drivers/ns16550.c index 710b351..62c6d7f 100644 --- a/core/drivers/ns16550.c +++ b/core/drivers/ns16550.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2015 Freescale Semiconductor, Inc. + * Copyright (c) 2017, Linaro Limited * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -27,6 +28,8 @@ #include <drivers/ns16550.h> #include <io.h> +#include <keep.h> +#include <util.h> /* uart register defines */ #define UART_RBR 0x0 @@ -42,16 +45,45 @@ /* uart status register bits */ #define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */ -void ns16550_flush(vaddr_t base) +static vaddr_t chip_to_base(struct serial_chip *chip) { + struct ns16550_data *pd = + container_of(chip, struct ns16550_data, chip); + + return io_pa_or_va(&pd->base); +} + +static void ns16550_flush(struct serial_chip *chip) +{ + vaddr_t base = chip_to_base(chip); + while ((read8(base + UART_LSR) & UART_LSR_THRE) == 0) ; } -void ns16550_putc(int ch, vaddr_t base) +static void ns16550_putc(struct serial_chip *chip, int ch) { - ns16550_flush(base); + vaddr_t base = chip_to_base(chip); + + ns16550_flush(chip); /* write out charset to Transmit-hold-register */ write8(ch, base + UART_THR); } + +static const struct serial_ops ns16550_ops = { + .flush = ns16550_flush, + .putc = ns16550_putc, +}; +KEEP_PAGER(ns16550_ops); + +void ns16550_init(struct ns16550_data *pd, paddr_t base) +{ + pd->base.pa = base; + pd->chip.ops = &ns16550_ops; + + /* + * Do nothing, uart driver shared with normal world, + * everything for uart driver initialization is done in bootloader. + */ +} diff --git a/core/drivers/pl011.c b/core/drivers/pl011.c index 8c03090..7263707 100644 --- a/core/drivers/pl011.c +++ b/core/drivers/pl011.c @@ -24,8 +24,11 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ +#include <assert.h> #include <drivers/pl011.h> #include <io.h> +#include <keep.h> +#include <util.h> #define UART_DR 0x00 /* data register */ #define UART_RSR_ECR 0x04 /* receive status or error clear */ @@ -89,14 +92,64 @@ #define UART_IMSC_RTIM (1 << 6) #define UART_IMSC_RXIM (1 << 4) -void pl011_flush(vaddr_t base) +static vaddr_t chip_to_base(struct serial_chip *chip) { + struct pl011_data *pd = + container_of(chip, struct pl011_data, chip); + + return io_pa_or_va(&pd->base); +} + +static void pl011_flush(struct serial_chip *chip) +{ + vaddr_t base = chip_to_base(chip); + while (!(read32(base + UART_FR) & UART_FR_TXFE)) ; } -void pl011_init(vaddr_t base, uint32_t uart_clk, uint32_t baud_rate) +static bool pl011_have_rx_data(struct serial_chip *chip) +{ + vaddr_t base = chip_to_base(chip); + + return !(read32(base + UART_FR) & UART_FR_RXFE); +} + +static int pl011_getchar(struct serial_chip *chip) +{ + vaddr_t base = chip_to_base(chip); + + while (!pl011_have_rx_data(chip)) + ; + return read32(base + UART_DR) & 0xff; +} + +static void pl011_putc(struct serial_chip *chip, int ch) +{ + vaddr_t base = chip_to_base(chip); + + /* Wait until there is space in the FIFO */ + while (read32(base + UART_FR) & UART_FR_TXFF) + ; + + /* Send the character */ + write32(ch, base + UART_DR); +} + +static const struct serial_ops pl011_ops = { + .flush = pl011_flush, + .getchar = pl011_getchar, + .have_rx_data = pl011_have_rx_data, + .putc = pl011_putc, +}; +KEEP_PAGER(pl011_ops); + +void pl011_init(struct pl011_data *pd, paddr_t base, uint32_t uart_clk, + uint32_t baud_rate) { + pd->base.pa = base; + pd->chip.ops = &pl011_ops; + /* Clear all errors */ write32(0, base + UART_RSR_ECR); /* Disable everything */ @@ -118,30 +171,6 @@ void pl011_init(vaddr_t base, uint32_t uart_clk, uint32_t baud_rate) /* Enable UART and RX/TX */ write32(UART_CR_UARTEN | UART_CR_TXE | UART_CR_RXE, base + UART_CR); - pl011_flush(base); -} - -void pl011_putc(int ch, vaddr_t base) -{ - /* - * Wait until there is space in the FIFO - */ - while (read32(base + UART_FR) & UART_FR_TXFF) - ; - - /* Send the character */ - write32(ch, base + UART_DR); -} - -bool pl011_have_rx_data(vaddr_t base) -{ - return !(read32(base + UART_FR) & UART_FR_RXFE); -} - -int pl011_getchar(vaddr_t base) -{ - while (!pl011_have_rx_data(base)) - ; - return read32(base + UART_DR) & 0xff; + pl011_flush(&pd->chip); } diff --git a/core/drivers/pl050.c b/core/drivers/pl050.c index fa5feab..aedaf71 100644 --- a/core/drivers/pl050.c +++ b/core/drivers/pl050.c @@ -26,8 +26,9 @@ */ #include <compiler.h> #include <drivers/pl050.h> -#include <util.h> #include <io.h> +#include <keep.h> +#include <util.h> #define KMI_ICR 0x00 #define KMI_STAT 0x04 @@ -91,6 +92,7 @@ static const struct serial_ops pl050_ops = { .have_rx_data = pl050_have_rx_data, .getchar = pl050_getchar, }; +KEEP_PAGER(pl050_ops); void pl050_init(struct pl050_data *pd, vaddr_t base, uint32_t clk) { diff --git a/core/drivers/scif.c b/core/drivers/scif.c index 02fd49d..ff0cec8 100644 --- a/core/drivers/scif.c +++ b/core/drivers/scif.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2016, GlobalLogic + * Copyright (c) 2017, Linaro Limited * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,16 +25,18 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ -#include <compiler.h> +#include <drivers/scif.h> #include <io.h> +#include <keep.h> #include <util.h> -#include <drivers/scif.h> +#define SCIF_SCSCR (0x08) #define SCIF_SCFSR (0x10) #define SCIF_SCFTDR (0x0C) #define SCIF_SCFCR (0x18) #define SCIF_SCFDR (0x1C) +#define SCSCR_TE BIT(5) #define SCFSR_TDFE BIT(5) #define SCFSR_TEND BIT(6) @@ -41,20 +44,26 @@ #define SCIF_TX_FIFO_SIZE 16 -void scif_uart_flush(vaddr_t base) +static vaddr_t chip_to_base(struct serial_chip *chip) { - while (!(read16(base + SCIF_SCFSR) & SCFSR_TEND)) - ; + struct scif_uart_data *pd = + container_of(chip, struct scif_uart_data, chip); + + return io_pa_or_va(&pd->base); } -void scif_uart_init(vaddr_t base) +static void scif_uart_flush(struct serial_chip *chip) { - /* Bootloader should initialize device for us */ - scif_uart_flush(base); + vaddr_t base = chip_to_base(chip); + + while (!(read16(base + SCIF_SCFSR) & SCFSR_TEND)) + ; } -void scif_uart_putc(int ch, vaddr_t base) +static void scif_uart_putc(struct serial_chip *chip, int ch) { + vaddr_t base = chip_to_base(chip); + /* Wait until there is space in the FIFO */ while ((read16(base + SCIF_SCFDR) >> SCFDR_T_SHIFT) >= SCIF_TX_FIFO_SIZE) @@ -63,3 +72,20 @@ void scif_uart_putc(int ch, vaddr_t base) write16(read16(base + SCIF_SCFSR) & ~(SCFSR_TEND | SCFSR_TDFE), base + SCIF_SCFSR); } + +static const struct serial_ops scif_uart_ops = { + .flush = scif_uart_flush, + .putc = scif_uart_putc, +}; +KEEP_PAGER(scif_uart_ops); + +void scif_uart_init(struct scif_uart_data *pd, paddr_t base) +{ + pd->base.pa = base; + pd->chip.ops = &scif_uart_ops; + + /* Set Transmit Enable in Control register */ + write16(read16(base + SCIF_SCSCR) | SCSCR_TE, base + SCIF_SCSCR); + + scif_uart_flush(&pd->chip); +} diff --git a/core/drivers/serial8250_uart.c b/core/drivers/serial8250_uart.c index 1dd21de..5e86158 100644 --- a/core/drivers/serial8250_uart.c +++ b/core/drivers/serial8250_uart.c @@ -24,12 +24,13 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ -#include <platform_config.h> -#include <drivers/serial8250_uart.h> +#include <compiler.h> #include <console.h> +#include <drivers/serial8250_uart.h> #include <io.h> -#include <compiler.h> +#include <keep.h> +#include <util.h> /* uart register defines */ #define UART_RHR 0x0 @@ -49,45 +50,73 @@ #define LSR_EMPTY (LSR_TEMT | LSR_THRE) #define LSR_DR 0x01 /* DATA Ready */ -void serial8250_uart_init(vaddr_t __unused base, - uint32_t __unused uart_clk, uint32_t __unused baud_rate) +static vaddr_t chip_to_base(struct serial_chip *chip) { - /* - * do nothing, debug uart(uart0) share with normal world, - * everything for uart0 is ready now. - */ + struct serial8250_uart_data *pd = + container_of(chip, struct serial8250_uart_data, chip); + + return io_pa_or_va(&pd->base); } -void serial8250_uart_flush_tx_fifo(vaddr_t base) +static void serial8250_uart_flush(struct serial_chip *chip) { + vaddr_t base = chip_to_base(chip); + while (1) { uint8_t state = read8(base + UART_LSR); - /* waiting transmit fifo empty */ + /* Wait until transmit FIFO is empty */ if ((state & LSR_EMPTY) == LSR_EMPTY) break; } } -bool serial8250_uart_have_rx_data(vaddr_t base) +static bool serial8250_uart_have_rx_data(struct serial_chip *chip) { + vaddr_t base = chip_to_base(chip); + return (read32(base + UART_LSR) & LSR_DR); } -void serial8250_uart_putc(int ch, vaddr_t base) +static int serial8250_uart_getchar(struct serial_chip *chip) { - serial8250_uart_flush_tx_fifo(base); + vaddr_t base = chip_to_base(chip); - /* write out charset to transmit fifo */ - write8(ch, base + UART_THR); -} - -int serial8250_uart_getchar(vaddr_t base) -{ - while (!serial8250_uart_have_rx_data(base)) { - /* transmit fifo is empty, waiting again. */ + while (!serial8250_uart_have_rx_data(chip)) { + /* Transmit FIFO is empty, waiting again */ ; } return read8(base + UART_RHR); } +static void serial8250_uart_putc(struct serial_chip *chip, int ch) +{ + vaddr_t base = chip_to_base(chip); + + serial8250_uart_flush(chip); + + /* Write out character to transmit FIFO */ + write8(ch, base + UART_THR); +} + +static const struct serial_ops serial8250_uart_ops = { + .flush = serial8250_uart_flush, + .getchar = serial8250_uart_getchar, + .have_rx_data = serial8250_uart_have_rx_data, + .putc = serial8250_uart_putc, +}; +KEEP_PAGER(serial8250_uart_ops); + +void serial8250_uart_init(struct serial8250_uart_data *pd, paddr_t base, + uint32_t __unused uart_clk, + uint32_t __unused baud_rate) + +{ + pd->base.pa = base; + pd->chip.ops = &serial8250_uart_ops; + + /* + * do nothing, debug uart(uart0) share with normal world, + * everything for uart0 is ready now. + */ +} 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; } diff --git a/core/drivers/stih_asc.c b/core/drivers/stih_asc.c new file mode 100644 index 0000000..7f69ce7 --- /dev/null +++ b/core/drivers/stih_asc.c @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2017, Linaro Limited + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include <drivers/stih_asc.h> +#include <io.h> +#include <keep.h> +#include <util.h> + +#define ASC_BAUDRATE 0x00 +#define ASC_TXBUFFER 0x04 +#define ASC_STATUS 0x14 + +#define ASC_STATUS_TX_EMPTY BIT(1) +#define ASC_STATUS_TX_HALF_EMPTY BIT(2) + +static vaddr_t chip_to_base(struct serial_chip *chip) +{ + struct stih_asc_pd *pd = + container_of(chip, struct stih_asc_pd, chip); + + return io_pa_or_va(&pd->base); +} + +static void stih_asc_flush(struct serial_chip *chip) +{ + vaddr_t base = chip_to_base(chip); + + while (!(read32(base + ASC_STATUS) & ASC_STATUS_TX_EMPTY)) + ; +} + +static void stih_asc_putc(struct serial_chip *chip, int ch) +{ + vaddr_t base = chip_to_base(chip); + + while (!(read32(base + ASC_STATUS) & ASC_STATUS_TX_HALF_EMPTY)) + ; + + write32(ch, base + ASC_TXBUFFER); +} + +static const struct serial_ops stih_asc_ops = { + .flush = stih_asc_flush, + .putc = stih_asc_putc, +}; +KEEP_PAGER(stih_asc_ops); + +void stih_asc_init(struct stih_asc_pd *pd, vaddr_t base) +{ + pd->base.pa = base; + pd->chip.ops = &stih_asc_ops; +} diff --git a/core/drivers/sub.mk b/core/drivers/sub.mk index 609b378..015f5c3 100644 --- a/core/drivers/sub.mk +++ b/core/drivers/sub.mk @@ -17,3 +17,4 @@ srcs-$(CFG_HI16XX_UART) += hi16xx_uart.c srcs-$(CFG_HI16XX_RNG) += hi16xx_rng.c srcs-$(CFG_SCIF) += scif.c srcs-$(CFG_DRA7_RNG) += dra7_rng.c +srcs-$(CFG_STIH_UART) += stih_asc.c diff --git a/core/drivers/sunxi_uart.c b/core/drivers/sunxi_uart.c index 433c423..b83da02 100644 --- a/core/drivers/sunxi_uart.c +++ b/core/drivers/sunxi_uart.c @@ -24,11 +24,10 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ -#include <platform_config.h> - #include <drivers/sunxi_uart.h> #include <io.h> -#include <compiler.h> +#include <keep.h> +#include <util.h> /* uart register defines */ #define UART_REG_RBR (0x00) @@ -55,28 +54,46 @@ #define UART_REG_USR_RFNE (0x1 << 0x3) #define UART_REG_USR_RFF (0x1 << 0x4) -void sunxi_uart_init(vaddr_t __unused base) +static vaddr_t chip_to_base(struct serial_chip *chip) { - /* do nothing, debug uart(uart0) share with normal world, - * everything for uart0 is ready now. - */ + struct sunxi_uart_data *pd = + container_of(chip, struct sunxi_uart_data, chip); + + return io_pa_or_va(&pd->base); } -void sunxi_uart_flush(vaddr_t base) +static void sunxi_uart_flush(struct serial_chip *chip) { + vaddr_t base = chip_to_base(chip); + while (read32(base + UART_REG_TFL)) { /* waiting transmit fifo empty */ ; } } -bool sunxi_uart_have_rx_data(vaddr_t base) +static bool sunxi_uart_have_rx_data(struct serial_chip *chip) { + vaddr_t base = chip_to_base(chip); + return read32(base + UART_REG_RFL); } -void sunxi_uart_putc(int ch, vaddr_t base) +static int sunxi_uart_getchar(struct serial_chip *chip) +{ + vaddr_t base = chip_to_base(chip); + + while (!sunxi_uart_have_rx_data(chip)) { + /* transmit fifo is empty, waiting again. */ + ; + } + return read32(base + UART_REG_RBR) & 0xff; +} + +static void sunxi_uart_putc(struct serial_chip *chip, int ch) { + vaddr_t base = chip_to_base(chip); + while (!(read32(base + UART_REG_USR) & UART_REG_USR_TFNF)) { /* transmit fifo is full, waiting again. */ ; @@ -86,12 +103,21 @@ void sunxi_uart_putc(int ch, vaddr_t base) write8(ch, base + UART_REG_THR); } -int sunxi_uart_getchar(vaddr_t base) +static const struct serial_ops sunxi_uart_ops = { + .flush = sunxi_uart_flush, + .getchar = sunxi_uart_getchar, + .have_rx_data = sunxi_uart_have_rx_data, + .putc = sunxi_uart_putc, +}; +KEEP_PAGER(sunxi_uart_ops); + +void sunxi_uart_init(struct sunxi_uart_data *pd, paddr_t base) { - while (!sunxi_uart_have_rx_data(base)) { - /* transmit fifo is empty, waiting again. */ - ; - } - return read32(base + UART_REG_RBR) & 0xff; -} + pd->base.pa = base; + pd->chip.ops = &sunxi_uart_ops; + /* + * Do nothing, debug uart(uart0) share with normal world, + * everything for uart0 is ready now. + */ +} |