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> Reviewed-on: http://review.coreboot.org/5309 Tested-by: build bot (Jenkins) Reviewed-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
This commit is contained in:
parent
e5760af398
commit
c2610a4a18
|
@ -28,9 +28,6 @@
|
||||||
#define RX_FIFO_FULL_MASK (1 << 8)
|
#define RX_FIFO_FULL_MASK (1 << 8)
|
||||||
#define TX_FIFO_FULL_MASK (1 << 24)
|
#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
|
* The coefficient, used to calculate the baudrate on S5P UARTs is
|
||||||
|
@ -58,9 +55,8 @@ static const int udivslot[] = {
|
||||||
0xffdf,
|
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 uclk;
|
||||||
u32 val;
|
u32 val;
|
||||||
|
|
||||||
|
@ -87,10 +83,8 @@ static void serial_setbrg_dev(void)
|
||||||
* Initialise the serial port with the given baudrate. The settings
|
* Initialise the serial port with the given baudrate. The settings
|
||||||
* are always 8 data bits, no parity, 1 stop bit, no start bits.
|
* 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.
|
// TODO initialize with correct peripheral id by base_port.
|
||||||
exynos_pinmux_uart3();
|
exynos_pinmux_uart3();
|
||||||
|
|
||||||
|
@ -102,12 +96,11 @@ static void exynos5_init_dev(void)
|
||||||
/* No interrupts, no DMA, pure polling */
|
/* No interrupts, no DMA, pure polling */
|
||||||
writel(0x245, &uart->ucon);
|
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;
|
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
|
* otherwise. When the function is successful, the character read is
|
||||||
* written into its argument c.
|
* 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 */
|
/* wait for character to arrive */
|
||||||
while (!(readl(&uart->ufstat) & (RX_FIFO_COUNT_MASK |
|
while (!(readl(&uart->ufstat) & (RX_FIFO_COUNT_MASK |
|
||||||
RX_FIFO_FULL_MASK))) {
|
RX_FIFO_FULL_MASK))) {
|
||||||
if (exynos5_uart_err_check(0))
|
if (exynos5_uart_err_check(uart, 0))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,49 +138,54 @@ static unsigned char exynos5_uart_rx_byte(void)
|
||||||
/*
|
/*
|
||||||
* Output a single byte to the serial port.
|
* 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 */
|
/* wait for room in the tx FIFO */
|
||||||
while ((readl(&uart->ufstat) & TX_FIFO_FULL_MASK)) {
|
while ((readl(&uart->ufstat) & TX_FIFO_FULL_MASK)) {
|
||||||
if (exynos5_uart_err_check(1))
|
if (exynos5_uart_err_check(uart, 1))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
writeb(data, &uart->utxh);
|
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);
|
while (readl(&uart->ufstat) & 0x1ff0000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int uart_platform_base(int idx)
|
||||||
|
{
|
||||||
|
return CONFIG_CONSOLE_SERIAL_UART_ADDRESS;
|
||||||
|
}
|
||||||
|
|
||||||
#if !defined(__PRE_RAM__)
|
#if !defined(__PRE_RAM__)
|
||||||
uint32_t uartmem_getbaseaddr(void)
|
uint32_t uartmem_getbaseaddr(void)
|
||||||
{
|
{
|
||||||
return base_port;
|
return uart_platform_base(0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void uart_init(void)
|
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)
|
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)
|
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)
|
void uart_tx_flush(void)
|
||||||
{
|
{
|
||||||
exynos5_uart_tx_flush();
|
struct s5p_uart *uart = uart_platform_baseptr(0);
|
||||||
|
exynos5_uart_tx_flush(uart);
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,9 +28,6 @@
|
||||||
#define RX_FIFO_FULL_MASK (1 << 8)
|
#define RX_FIFO_FULL_MASK (1 << 8)
|
||||||
#define TX_FIFO_FULL_MASK (1 << 24)
|
#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
|
* The coefficient, used to calculate the baudrate on S5P UARTs is
|
||||||
|
@ -58,9 +55,8 @@ static const int udivslot[] = {
|
||||||
0xffdf,
|
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 uclk;
|
||||||
u32 val;
|
u32 val;
|
||||||
|
|
||||||
|
@ -87,10 +83,8 @@ static void serial_setbrg_dev(void)
|
||||||
* Initialise the serial port with the given baudrate. The settings
|
* Initialise the serial port with the given baudrate. The settings
|
||||||
* are always 8 data bits, no parity, 1 stop bit, no start bits.
|
* 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 */
|
/* enable FIFOs */
|
||||||
writel(0x1, &uart->ufcon);
|
writel(0x1, &uart->ufcon);
|
||||||
writel(0, &uart->umcon);
|
writel(0, &uart->umcon);
|
||||||
|
@ -99,12 +93,11 @@ static void exynos5_init_dev(void)
|
||||||
/* No interrupts, no DMA, pure polling */
|
/* No interrupts, no DMA, pure polling */
|
||||||
writel(0x245, &uart->ucon);
|
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;
|
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
|
* otherwise. When the function is succesfull, the character read is
|
||||||
* written into its argument c.
|
* 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 */
|
/* wait for character to arrive */
|
||||||
while (!(readl(&uart->ufstat) & (RX_FIFO_COUNT_MASK |
|
while (!(readl(&uart->ufstat) & (RX_FIFO_COUNT_MASK |
|
||||||
RX_FIFO_FULL_MASK))) {
|
RX_FIFO_FULL_MASK))) {
|
||||||
if (exynos5_uart_err_check(0))
|
if (exynos5_uart_err_check(uart, 0))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,41 +135,48 @@ static unsigned char exynos5_uart_rx_byte(void)
|
||||||
/*
|
/*
|
||||||
* Output a single byte to the serial port.
|
* 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 */
|
/* wait for room in the tx FIFO */
|
||||||
while ((readl(&uart->ufstat) & TX_FIFO_FULL_MASK)) {
|
while ((readl(&uart->ufstat) & TX_FIFO_FULL_MASK)) {
|
||||||
if (exynos5_uart_err_check(1))
|
if (exynos5_uart_err_check(uart, 1))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
writeb(data, &uart->utxh);
|
writeb(data, &uart->utxh);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int uart_platform_base(int idx)
|
||||||
|
{
|
||||||
|
return CONFIG_CONSOLE_SERIAL_UART_ADDRESS;
|
||||||
|
}
|
||||||
|
|
||||||
#if !defined(__PRE_RAM__)
|
#if !defined(__PRE_RAM__)
|
||||||
uint32_t uartmem_getbaseaddr(void)
|
uint32_t uartmem_getbaseaddr(void)
|
||||||
{
|
{
|
||||||
return base_port;
|
return uart_platform_base(0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void uart_init(void)
|
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)
|
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)
|
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)
|
void uart_tx_flush(void)
|
||||||
{
|
{
|
||||||
|
/* Exynos5250 implements this too. */
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,10 +35,8 @@
|
||||||
* Initialise the serial port with the given baudrate divisor. The settings
|
* Initialise the serial port with the given baudrate divisor. The settings
|
||||||
* are always 8 data bits, no parity, 1 stop bit, no start bits.
|
* 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;
|
uint16_t lcr_orig, efr_orig, mcr_orig;
|
||||||
|
|
||||||
/* reset the UART */
|
/* 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
|
* otherwise. When the function is successful, the character read is
|
||||||
* written into its argument c.
|
* 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));
|
while (!(read16(&uart->lsr) & LSR_RXFIFOE));
|
||||||
|
|
||||||
return read8(&uart->rhr);
|
return read8(&uart->rhr);
|
||||||
|
@ -144,11 +139,8 @@ static unsigned char am335x_uart_rx_byte(void)
|
||||||
/*
|
/*
|
||||||
* Output a single byte to the serial port.
|
* 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));
|
while (!(read16(&uart->lsr) & LSR_TXFIFOE));
|
||||||
|
|
||||||
return write8(data, &uart->thr);
|
return write8(data, &uart->thr);
|
||||||
|
@ -159,28 +151,36 @@ unsigned int uart_platform_refclk(void)
|
||||||
return 48000000;
|
return 48000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int uart_platform_base(int idx)
|
||||||
|
{
|
||||||
|
return CONFIG_CONSOLE_SERIAL_UART_ADDRESS;
|
||||||
|
}
|
||||||
|
|
||||||
#if !defined(__PRE_RAM__)
|
#if !defined(__PRE_RAM__)
|
||||||
uint32_t uartmem_getbaseaddr(void)
|
uint32_t uartmem_getbaseaddr(void)
|
||||||
{
|
{
|
||||||
return CONFIG_CONSOLE_SERIAL_UART_ADDRESS;
|
return uart_platform_base(0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void uart_init(void)
|
void uart_init(void)
|
||||||
{
|
{
|
||||||
|
struct am335x_uart *uart = uart_platform_baseptr(0);
|
||||||
uint16_t div = (uint16_t) uart_baudrate_divisor(
|
uint16_t div = (uint16_t) uart_baudrate_divisor(
|
||||||
default_baudrate(), uart_platform_refclk(), 16);
|
default_baudrate(), uart_platform_refclk(), 16);
|
||||||
am335x_uart_init(div);
|
am335x_uart_init(uart, div);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char uart_rx_byte(void)
|
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)
|
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)
|
void uart_tx_flush(void)
|
||||||
|
|
|
@ -15,12 +15,14 @@
|
||||||
|
|
||||||
#include <console/uart.h>
|
#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 =
|
*uart_base = (unsigned int)data;
|
||||||
(unsigned int *) CONFIG_CONSOLE_SERIAL_UART_ADDRESS;
|
}
|
||||||
|
|
||||||
*uart0_address = (unsigned int)data;
|
unsigned int uart_platform_base(int idx)
|
||||||
|
{
|
||||||
|
return CONFIG_CONSOLE_SERIAL_UART_ADDRESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(__PRE_RAM__)
|
#if !defined(__PRE_RAM__)
|
||||||
|
@ -36,7 +38,8 @@ void uart_init(void)
|
||||||
|
|
||||||
void uart_tx_byte(unsigned char data)
|
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)
|
void uart_tx_flush(void)
|
||||||
|
|
|
@ -48,6 +48,13 @@ int uart_can_rx_byte(void);
|
||||||
unsigned int uart_platform_base(int idx);
|
unsigned int uart_platform_base(int idx);
|
||||||
uint32_t uartmem_getbaseaddr(void);
|
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_init(void);
|
||||||
void oxford_remap(unsigned int new_base);
|
void oxford_remap(unsigned int new_base);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue