From c2610a4a186c6e5a05f6518c2c7a734fde8f6cfd Mon Sep 17 00:00:00 2001 From: Kyösti Mälkki Date: Mon, 24 Feb 2014 20:51:30 +0200 Subject: uart: Prepare to support multiple base addresses MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prepare low-level register access to take UART base address as a parameter. This is done to support a list of base addresses defined in the platform. Change-Id: Ie630e55f2562f099b0ba9eb94b08c92d26dfdf2e Signed-off-by: Kyösti Mälkki Reviewed-on: http://review.coreboot.org/5309 Tested-by: build bot (Jenkins) Reviewed-by: Alexandru Gagniuc --- src/cpu/samsung/exynos5250/uart.c | 50 ++++++++++++++++++--------------------- src/cpu/samsung/exynos5420/uart.c | 44 ++++++++++++++++------------------ src/cpu/ti/am335x/uart.c | 30 +++++++++++------------ src/drivers/uart/pl011.c | 13 ++++++---- src/include/console/uart.h | 7 ++++++ 5 files changed, 74 insertions(+), 70 deletions(-) diff --git a/src/cpu/samsung/exynos5250/uart.c b/src/cpu/samsung/exynos5250/uart.c index 14d140c4dc..860d020a92 100644 --- a/src/cpu/samsung/exynos5250/uart.c +++ b/src/cpu/samsung/exynos5250/uart.c @@ -28,9 +28,6 @@ #define RX_FIFO_FULL_MASK (1 << 8) #define TX_FIFO_FULL_MASK (1 << 24) -/* FIXME(dhendrix): exynos5 has 4 UARTs and its functions in u-boot take a - base_port argument. However console_driver functions do not. */ -static uint32_t base_port = CONFIG_CONSOLE_SERIAL_UART_ADDRESS; /* * The coefficient, used to calculate the baudrate on S5P UARTs is @@ -58,9 +55,8 @@ static const int udivslot[] = { 0xffdf, }; -static void serial_setbrg_dev(void) +static void serial_setbrg_dev(struct s5p_uart *uart) { - struct s5p_uart *uart = (struct s5p_uart *)base_port; u32 uclk; u32 val; @@ -87,10 +83,8 @@ static void serial_setbrg_dev(void) * Initialise the serial port with the given baudrate. The settings * are always 8 data bits, no parity, 1 stop bit, no start bits. */ -static void exynos5_init_dev(void) +static void exynos5_init_dev(struct s5p_uart *uart) { - struct s5p_uart *uart = (struct s5p_uart *)base_port; - // TODO initialize with correct peripheral id by base_port. exynos_pinmux_uart3(); @@ -102,12 +96,11 @@ static void exynos5_init_dev(void) /* No interrupts, no DMA, pure polling */ writel(0x245, &uart->ucon); - serial_setbrg_dev(); + serial_setbrg_dev(uart); } -static int exynos5_uart_err_check(int op) +static int exynos5_uart_err_check(struct s5p_uart *uart, int op) { - struct s5p_uart *uart = (struct s5p_uart *)base_port; unsigned int mask; /* @@ -130,14 +123,12 @@ static int exynos5_uart_err_check(int op) * otherwise. When the function is successful, the character read is * written into its argument c. */ -static unsigned char exynos5_uart_rx_byte(void) +static unsigned char exynos5_uart_rx_byte(struct s5p_uart *uart) { - struct s5p_uart *uart = (struct s5p_uart *)base_port; - /* wait for character to arrive */ while (!(readl(&uart->ufstat) & (RX_FIFO_COUNT_MASK | RX_FIFO_FULL_MASK))) { - if (exynos5_uart_err_check(0)) + if (exynos5_uart_err_check(uart, 0)) return 0; } @@ -147,49 +138,54 @@ static unsigned char exynos5_uart_rx_byte(void) /* * Output a single byte to the serial port. */ -static void exynos5_uart_tx_byte(unsigned char data) +static void exynos5_uart_tx_byte(struct s5p_uart *uart, unsigned char data) { - struct s5p_uart *uart = (struct s5p_uart *)base_port; - /* wait for room in the tx FIFO */ while ((readl(&uart->ufstat) & TX_FIFO_FULL_MASK)) { - if (exynos5_uart_err_check(1)) + if (exynos5_uart_err_check(uart, 1)) return; } writeb(data, &uart->utxh); } -static void exynos5_uart_tx_flush(void) +static void exynos5_uart_tx_flush(struct s5p_uart *uart) { - struct s5p_uart *uart = (struct s5p_uart *)base_port; - while (readl(&uart->ufstat) & 0x1ff0000); } +unsigned int uart_platform_base(int idx) +{ + return CONFIG_CONSOLE_SERIAL_UART_ADDRESS; +} + #if !defined(__PRE_RAM__) uint32_t uartmem_getbaseaddr(void) { - return base_port; + return uart_platform_base(0); } #endif void uart_init(void) { - exynos5_init_dev(); + struct s5p_uart *uart = uart_platform_baseptr(0); + exynos5_init_dev(uart); } unsigned char uart_rx_byte(void) { - return exynos5_uart_rx_byte(); + struct s5p_uart *uart = uart_platform_baseptr(0); + return exynos5_uart_rx_byte(uart); } void uart_tx_byte(unsigned char data) { - exynos5_uart_tx_byte(data); + struct s5p_uart *uart = uart_platform_baseptr(0); + exynos5_uart_tx_byte(uart, data); } void uart_tx_flush(void) { - exynos5_uart_tx_flush(); + struct s5p_uart *uart = uart_platform_baseptr(0); + exynos5_uart_tx_flush(uart); } diff --git a/src/cpu/samsung/exynos5420/uart.c b/src/cpu/samsung/exynos5420/uart.c index d05adcd903..82b1265972 100644 --- a/src/cpu/samsung/exynos5420/uart.c +++ b/src/cpu/samsung/exynos5420/uart.c @@ -28,9 +28,6 @@ #define RX_FIFO_FULL_MASK (1 << 8) #define TX_FIFO_FULL_MASK (1 << 24) -/* FIXME(dhendrix): exynos5 has 4 UARTs and its functions in u-boot take a - base_port argument. However console_driver functions do not. */ -static uint32_t base_port = CONFIG_CONSOLE_SERIAL_UART_ADDRESS; /* * The coefficient, used to calculate the baudrate on S5P UARTs is @@ -58,9 +55,8 @@ static const int udivslot[] = { 0xffdf, }; -static void serial_setbrg_dev(void) +static void serial_setbrg_dev(struct s5p_uart *uart) { - struct s5p_uart *uart = (struct s5p_uart *)base_port; u32 uclk; u32 val; @@ -87,10 +83,8 @@ static void serial_setbrg_dev(void) * Initialise the serial port with the given baudrate. The settings * are always 8 data bits, no parity, 1 stop bit, no start bits. */ -static void exynos5_init_dev(void) +static void exynos5_init_dev(struct s5p_uart *uart) { - struct s5p_uart *uart = (struct s5p_uart *)base_port; - /* enable FIFOs */ writel(0x1, &uart->ufcon); writel(0, &uart->umcon); @@ -99,12 +93,11 @@ static void exynos5_init_dev(void) /* No interrupts, no DMA, pure polling */ writel(0x245, &uart->ucon); - serial_setbrg_dev(); + serial_setbrg_dev(uart); } -static int exynos5_uart_err_check(int op) +static int exynos5_uart_err_check(struct s5p_uart *uart, int op) { - struct s5p_uart *uart = (struct s5p_uart *)base_port; unsigned int mask; /* @@ -127,14 +120,12 @@ static int exynos5_uart_err_check(int op) * otherwise. When the function is succesfull, the character read is * written into its argument c. */ -static unsigned char exynos5_uart_rx_byte(void) +static unsigned char exynos5_uart_rx_byte(struct s5p_uart *uart) { - struct s5p_uart *uart = (struct s5p_uart *)base_port; - /* wait for character to arrive */ while (!(readl(&uart->ufstat) & (RX_FIFO_COUNT_MASK | RX_FIFO_FULL_MASK))) { - if (exynos5_uart_err_check(0)) + if (exynos5_uart_err_check(uart, 0)) return 0; } @@ -144,41 +135,48 @@ static unsigned char exynos5_uart_rx_byte(void) /* * Output a single byte to the serial port. */ -static void exynos5_uart_tx_byte(unsigned char data) +static void exynos5_uart_tx_byte(struct s5p_uart *uart, unsigned char data) { - struct s5p_uart *uart = (struct s5p_uart *)base_port; - /* wait for room in the tx FIFO */ while ((readl(&uart->ufstat) & TX_FIFO_FULL_MASK)) { - if (exynos5_uart_err_check(1)) + if (exynos5_uart_err_check(uart, 1)) return; } writeb(data, &uart->utxh); } +unsigned int uart_platform_base(int idx) +{ + return CONFIG_CONSOLE_SERIAL_UART_ADDRESS; +} + #if !defined(__PRE_RAM__) uint32_t uartmem_getbaseaddr(void) { - return base_port; + return uart_platform_base(0); } #endif void uart_init(void) { - exynos5_init_dev(); + struct s5p_uart *uart = uart_platform_baseptr(0); + exynos5_init_dev(uart); } unsigned char uart_rx_byte(void) { - return exynos5_uart_rx_byte(); + struct s5p_uart *uart = uart_platform_baseptr(0); + return exynos5_uart_rx_byte(uart); } void uart_tx_byte(unsigned char data) { - exynos5_uart_tx_byte(data); + struct s5p_uart *uart = uart_platform_baseptr(0); + exynos5_uart_tx_byte(uart, data); } void uart_tx_flush(void) { + /* Exynos5250 implements this too. */ } diff --git a/src/cpu/ti/am335x/uart.c b/src/cpu/ti/am335x/uart.c index 27051ea2cc..09bb96ece3 100644 --- a/src/cpu/ti/am335x/uart.c +++ b/src/cpu/ti/am335x/uart.c @@ -35,10 +35,8 @@ * Initialise the serial port with the given baudrate divisor. The settings * are always 8 data bits, no parity, 1 stop bit, no start bits. */ -static void am335x_uart_init(uint16_t div) +static void am335x_uart_init(struct am335x_uart *uart, uint16_t div) { - struct am335x_uart *uart = (struct am335x_uart *) - CONFIG_CONSOLE_SERIAL_UART_ADDRESS; uint16_t lcr_orig, efr_orig, mcr_orig; /* reset the UART */ @@ -131,11 +129,8 @@ static void am335x_uart_init(uint16_t div) * otherwise. When the function is successful, the character read is * written into its argument c. */ -static unsigned char am335x_uart_rx_byte(void) +static unsigned char am335x_uart_rx_byte(struct am335x_uart *uart) { - struct am335x_uart *uart = - (struct am335x_uart *)CONFIG_CONSOLE_SERIAL_UART_ADDRESS; - while (!(read16(&uart->lsr) & LSR_RXFIFOE)); return read8(&uart->rhr); @@ -144,11 +139,8 @@ static unsigned char am335x_uart_rx_byte(void) /* * Output a single byte to the serial port. */ -static void am335x_uart_tx_byte(unsigned char data) +static void am335x_uart_tx_byte(struct am335x_uart *uart, unsigned char data) { - struct am335x_uart *uart = - (struct am335x_uart *)CONFIG_CONSOLE_SERIAL_UART_ADDRESS; - while (!(read16(&uart->lsr) & LSR_TXFIFOE)); return write8(data, &uart->thr); @@ -159,28 +151,36 @@ unsigned int uart_platform_refclk(void) return 48000000; } +unsigned int uart_platform_base(int idx) +{ + return CONFIG_CONSOLE_SERIAL_UART_ADDRESS; +} + #if !defined(__PRE_RAM__) uint32_t uartmem_getbaseaddr(void) { - return CONFIG_CONSOLE_SERIAL_UART_ADDRESS; + return uart_platform_base(0); } #endif void uart_init(void) { + struct am335x_uart *uart = uart_platform_baseptr(0); uint16_t div = (uint16_t) uart_baudrate_divisor( default_baudrate(), uart_platform_refclk(), 16); - am335x_uart_init(div); + am335x_uart_init(uart, div); } unsigned char uart_rx_byte(void) { - return am335x_uart_rx_byte(); + struct am335x_uart *uart = uart_platform_baseptr(0); + return am335x_uart_rx_byte(uart); } void uart_tx_byte(unsigned char data) { - am335x_uart_tx_byte(data); + struct am335x_uart *uart = uart_platform_baseptr(0); + am335x_uart_tx_byte(uart, data); } void uart_tx_flush(void) diff --git a/src/drivers/uart/pl011.c b/src/drivers/uart/pl011.c index 2202de755d..e4bfdc6136 100644 --- a/src/drivers/uart/pl011.c +++ b/src/drivers/uart/pl011.c @@ -15,12 +15,14 @@ #include -static void pl011_uart_tx_byte(unsigned char data) +static void pl011_uart_tx_byte(unsigned int *uart_base, unsigned char data) { - static volatile unsigned int *uart0_address = - (unsigned int *) CONFIG_CONSOLE_SERIAL_UART_ADDRESS; + *uart_base = (unsigned int)data; +} - *uart0_address = (unsigned int)data; +unsigned int uart_platform_base(int idx) +{ + return CONFIG_CONSOLE_SERIAL_UART_ADDRESS; } #if !defined(__PRE_RAM__) @@ -36,7 +38,8 @@ void uart_init(void) void uart_tx_byte(unsigned char data) { - pl011_uart_tx_byte(data); + unsigned int *uart_base = uart_platform_baseptr(0); + pl011_uart_tx_byte(uart_base, data); } void uart_tx_flush(void) diff --git a/src/include/console/uart.h b/src/include/console/uart.h index f0371a2a98..6a1251e5d0 100644 --- a/src/include/console/uart.h +++ b/src/include/console/uart.h @@ -48,6 +48,13 @@ int uart_can_rx_byte(void); unsigned int uart_platform_base(int idx); uint32_t uartmem_getbaseaddr(void); +#if !defined(__ROMCC__) +static inline void *uart_platform_baseptr(int idx) +{ + return (void *)uart_platform_base(idx); +} +#endif + void oxford_init(void); void oxford_remap(unsigned int new_base); -- cgit v1.2.3