Alexandru Gagniuc (mr.nuke.me@gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/5309
-gerrit
commit 80a78687cf48c7d0161ee8f918ea9923043ae36b Author: Kyösti Mälkki kyosti.malkki@gmail.com Date: Mon Feb 24 20:51:30 2014 +0200
uart: Prepare to support multiple base addresses
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 kyosti.malkki@gmail.com --- src/cpu/allwinner/a10/uart_console.c | 35 +++++++++---------------- 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 | 2 +- 6 files changed, 80 insertions(+), 94 deletions(-)
diff --git a/src/cpu/allwinner/a10/uart_console.c b/src/cpu/allwinner/a10/uart_console.c index aea1189..f0a99d8 100644 --- a/src/cpu/allwinner/a10/uart_console.c +++ b/src/cpu/allwinner/a10/uart_console.c @@ -13,28 +13,15 @@
#include <cpu/allwinner/a10/uart.h>
-static void *get_console_uart_base_addr(void) +void *uart_platform_base(int idx) { - /* This big block gets compiled to a constant, not a function call */ - if (CONFIG_CONSOLE_SERIAL_UART0) - return (void *)A1X_UART0_BASE; - else if (CONFIG_CONSOLE_SERIAL_UART1) - return (void *)A1X_UART1_BASE; - else if (CONFIG_CONSOLE_SERIAL_UART2) - return (void *)A1X_UART2_BASE; - else if (CONFIG_CONSOLE_SERIAL_UART3) - return (void *)A1X_UART3_BASE; - else if (CONFIG_CONSOLE_SERIAL_UART4) - return (void *)A1X_UART4_BASE; - else if (CONFIG_CONSOLE_SERIAL_UART5) - return (void *)A1X_UART5_BASE; - else if (CONFIG_CONSOLE_SERIAL_UART6) - return (void *)A1X_UART6_BASE; - else if (CONFIG_CONSOLE_SERIAL_UART7) - return (void *)A1X_UART7_BASE; - /* If selection is invalid, default to UART0 */ return (void *)A1X_UART0_BASE; + if (idx < 7) + idx = 0; + + /* UART blocks are mapped 0x400 bytes apart */ + return (void *)A1X_UART0_BASE + 0x400 * idx; }
/* FIXME: We assume clock is 24MHz, which may not be the case. */ @@ -45,7 +32,7 @@ unsigned int uart_platform_refclk(void)
void uart_init(void) { - void *uart_base = get_console_uart_base_addr(); + void *uart_base = (void *) uart_platform_base(0);
/* Use default 8N1 encoding */ a10_uart_configure(uart_base, default_baudrate(), @@ -55,18 +42,20 @@ void uart_init(void)
unsigned char uart_rx_byte(void) { - return a10_uart_rx_blocking(get_console_uart_base_addr()); + void *uart_base = (void *) uart_platform_base(0); + return a10_uart_rx_blocking(uart_base); }
void uart_tx_byte(unsigned char data) { - a10_uart_tx_blocking(get_console_uart_base_addr(), data); + void *uart_base = (void *) uart_platform_base(0); + a10_uart_tx_blocking(uart_base, data); }
#if !defined(__PRE_RAM__) uint32_t uartmem_getbaseaddr(void) { - return (uint32_t) get_console_uart_base_addr(); + return (uint32_t)uart_platform_base(0); } #endif
diff --git a/src/cpu/samsung/exynos5250/uart.c b/src/cpu/samsung/exynos5250/uart.c index 14d140c..b4e554f 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); }
+void *uart_platform_base(int idx) +{ + return (void *)CONFIG_CONSOLE_SERIAL_UART_ADDRESS; +} + #if !defined(__PRE_RAM__) uint32_t uartmem_getbaseaddr(void) { - return base_port; + return (uint32_t)uart_platform_base(0); } #endif
void uart_init(void) { - exynos5_init_dev(); + struct s5p_uart *uart = (struct s5p_uart *) uart_platform_base(0); + exynos5_init_dev(uart); }
unsigned char uart_rx_byte(void) { - return exynos5_uart_rx_byte(); + struct s5p_uart *uart = (struct s5p_uart *) uart_platform_base(0); + return exynos5_uart_rx_byte(uart); }
void uart_tx_byte(unsigned char data) { - exynos5_uart_tx_byte(data); + struct s5p_uart *uart = (struct s5p_uart *) uart_platform_base(0); + exynos5_uart_tx_byte(uart, data); }
void uart_tx_flush(void) { - exynos5_uart_tx_flush(); + struct s5p_uart *uart = (struct s5p_uart *) uart_platform_base(0); + exynos5_uart_tx_flush(uart); } diff --git a/src/cpu/samsung/exynos5420/uart.c b/src/cpu/samsung/exynos5420/uart.c index d05adcd..3f2fca0 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); }
+void *uart_platform_base(int idx) +{ + return (void *)CONFIG_CONSOLE_SERIAL_UART_ADDRESS; +} + #if !defined(__PRE_RAM__) uint32_t uartmem_getbaseaddr(void) { - return base_port; + return (uint32_t)uart_platform_base(0); } #endif
void uart_init(void) { - exynos5_init_dev(); + struct s5p_uart *uart = (struct s5p_uart *) uart_platform_base(0); + exynos5_init_dev(uart); }
unsigned char uart_rx_byte(void) { - return exynos5_uart_rx_byte(); + struct s5p_uart *uart = (struct s5p_uart *) uart_platform_base(0); + return exynos5_uart_rx_byte(uart); }
void uart_tx_byte(unsigned char data) { - exynos5_uart_tx_byte(data); + struct s5p_uart *uart = (struct s5p_uart *) uart_platform_base(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 27051ea..665b188 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; }
+void *uart_platform_base(int idx) +{ + return (void *)CONFIG_CONSOLE_SERIAL_UART_ADDRESS; +} + #if !defined(__PRE_RAM__) uint32_t uartmem_getbaseaddr(void) { - return CONFIG_CONSOLE_SERIAL_UART_ADDRESS; + return (uint32_t)uart_platform_base(0); } #endif
void uart_init(void) { + struct am335x_uart *uart = (struct am335x_uart *) uart_platform_base(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 = (struct am335x_uart *) uart_platform_base(0); + return am335x_uart_rx_byte(uart); }
void uart_tx_byte(unsigned char data) { - am335x_uart_tx_byte(data); + struct am335x_uart *uart = (struct am335x_uart *) uart_platform_base(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 2202de7..7a0a7aa 100644 --- a/src/drivers/uart/pl011.c +++ b/src/drivers/uart/pl011.c @@ -15,12 +15,14 @@
#include <console/uart.h>
-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; +void *uart_platform_base(int idx) +{ + return (void *)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 = (unsigned int *) uart_platform_base(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 f0371a2..f031901 100644 --- a/src/include/console/uart.h +++ b/src/include/console/uart.h @@ -45,7 +45,7 @@ void uart_tx_flush(void); unsigned char uart_rx_byte(void); int uart_can_rx_byte(void);
-unsigned int uart_platform_base(int idx); +void *uart_platform_base(int idx); uint32_t uartmem_getbaseaddr(void);
void oxford_init(void);