Kyösti Mälkki (kyosti.malkki@gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/5309
-gerrit
commit 32da062b514d68670bf51635bbb1ce54c68f21e7 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/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 14d140c..860d020 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 d05adcd..82b1265 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 27051ea..09bb96e 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 2202de7..e4bfdc6 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; +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 f0371a2..6a1251e 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);