hv: uart: make uart base address more readable

Now if the uart is mapped to a PIO address space, the uart base address is a physical
PIO address; if it's mapped to a MMIO address space, the uart base address is a
virtual MMIO address. Add union uart_addr structure to imply this.
And define a console_uart structure to add all uart related fields into this structure.

Tracked-On: #2987
Signed-off-by: Li, Fei1 <fei1.li@intel.com>
This commit is contained in:
Li, Fei1 2019-07-24 17:31:20 +08:00 committed by ACRN System Integration
parent 49e60ae151
commit 18ecdc123a

View File

@ -14,27 +14,35 @@
#define MAX_BDF_LEN 8 #define MAX_BDF_LEN 8
struct console_uart {
bool enabled;
bool serial_port_mapped;
union {
uint16_t port_address;
void *mmio_base_vaddr;
};
spinlock_t rx_lock;
spinlock_t tx_lock;
};
#if defined(CONFIG_SERIAL_PIO_BASE) #if defined(CONFIG_SERIAL_PIO_BASE)
static bool serial_port_mapped = true; static struct console_uart uart = {
static bool uart_enabled = true; .enabled = true,
static uint64_t uart_base_address = CONFIG_SERIAL_PIO_BASE; .serial_port_mapped = true,
.port_address = CONFIG_SERIAL_PIO_BASE,
};
static char pci_bdf_info[MAX_BDF_LEN + 1U]; static char pci_bdf_info[MAX_BDF_LEN + 1U];
#elif defined(CONFIG_SERIAL_PCI_BDF) #elif defined(CONFIG_SERIAL_PCI_BDF)
static bool serial_port_mapped; static struct console_uart uart = {
static bool uart_enabled = true; .enabled = true,
static uint64_t uart_base_address; };
static char pci_bdf_info[MAX_BDF_LEN + 1U] = CONFIG_SERIAL_PCI_BDF; static char pci_bdf_info[MAX_BDF_LEN + 1U] = CONFIG_SERIAL_PCI_BDF;
#else #else
static bool serial_port_mapped; static struct console_uart uart;
static bool uart_enabled;
static uint64_t uart_base_address;
static char pci_bdf_info[MAX_BDF_LEN + 1U]; static char pci_bdf_info[MAX_BDF_LEN + 1U];
#endif #endif
typedef uint32_t uart_reg_t; typedef uint32_t uart_reg_t;
static spinlock_t uart_rx_lock;
static spinlock_t uart_tx_lock;
static union pci_bdf serial_pci_bdf; static union pci_bdf serial_pci_bdf;
/* PCI BDF must follow format: bus:dev.func, for example 0:18.2 */ /* PCI BDF must follow format: bus:dev.func, for example 0:18.2 */
@ -64,26 +72,26 @@ static uint16_t get_pci_bdf_value(char *bdf)
} }
/** /**
* @pre uart_enabled == true * @pre uart->enabled == true
*/ */
static inline uint32_t uart16550_read_reg(uint64_t base, uint16_t reg_idx) static inline uint32_t uart16550_read_reg(struct console_uart uart, uint16_t reg_idx)
{ {
if (serial_port_mapped) { if (uart.serial_port_mapped) {
return pio_read8((uint16_t)base + reg_idx); return pio_read8(uart.port_address + reg_idx);
} else { } else {
return mmio_read32((void *)((uint32_t *)hpa2hva(base) + reg_idx)); return mmio_read32((uint32_t *)uart.mmio_base_vaddr + reg_idx);
} }
} }
/** /**
* @pre uart_enabled == true * @pre uart->enabled == true
*/ */
static inline void uart16550_write_reg(uint64_t base, uint32_t val, uint16_t reg_idx) static inline void uart16550_write_reg(struct console_uart uart, uint32_t val, uint16_t reg_idx)
{ {
if (serial_port_mapped) { if (uart.serial_port_mapped) {
pio_write8((uint8_t)val, (uint16_t)base + reg_idx); pio_write8(val, uart.port_address + reg_idx);
} else { } else {
mmio_write32(val, (void *)((uint32_t *)hpa2hva(base) + reg_idx)); mmio_write32(val, (uint32_t *)uart.mmio_base_vaddr + reg_idx);
} }
} }
@ -99,7 +107,7 @@ static void uart16550_calc_baud_div(uint32_t ref_freq, uint32_t *baud_div_ptr, u
} }
/** /**
* @pre uart_enabled == true * @pre uart->enabled == true
*/ */
static void uart16550_set_baud_rate(uint32_t baud_rate) static void uart16550_set_baud_rate(uint32_t baud_rate)
{ {
@ -110,75 +118,76 @@ static void uart16550_set_baud_rate(uint32_t baud_rate)
uart16550_calc_baud_div(duart_clock, &baud_div, baud_rate); uart16550_calc_baud_div(duart_clock, &baud_div, baud_rate);
/* Enable DLL and DLM registers for setting the Divisor */ /* Enable DLL and DLM registers for setting the Divisor */
temp_reg = uart16550_read_reg(uart_base_address, UART16550_LCR); temp_reg = uart16550_read_reg(uart, UART16550_LCR);
temp_reg |= LCR_DLAB; temp_reg |= LCR_DLAB;
uart16550_write_reg(uart_base_address, temp_reg, UART16550_LCR); uart16550_write_reg(uart, temp_reg, UART16550_LCR);
/* Write the appropriate divisor value */ /* Write the appropriate divisor value */
uart16550_write_reg(uart_base_address, ((baud_div >> 8U) & 0xFFU), UART16550_DLM); uart16550_write_reg(uart, ((baud_div >> 8U) & 0xFFU), UART16550_DLM);
uart16550_write_reg(uart_base_address, (baud_div & 0xFFU), UART16550_DLL); uart16550_write_reg(uart, (baud_div & 0xFFU), UART16550_DLL);
/* Disable DLL and DLM registers */ /* Disable DLL and DLM registers */
temp_reg &= ~LCR_DLAB; temp_reg &= ~LCR_DLAB;
uart16550_write_reg(uart_base_address, temp_reg, UART16550_LCR); uart16550_write_reg(uart, temp_reg, UART16550_LCR);
} }
void uart16550_init(void) void uart16550_init(void)
{ {
if (!uart_enabled) { if (!uart.enabled) {
return; return;
} }
/* if configure serial PCI BDF, get its base MMIO address */ /* if configure serial PCI BDF, get its base MMIO address */
if (!serial_port_mapped) { if (!uart.serial_port_mapped) {
serial_pci_bdf.value = get_pci_bdf_value(pci_bdf_info); serial_pci_bdf.value = get_pci_bdf_value(pci_bdf_info);
uart_base_address = pci_pdev_read_cfg(serial_pci_bdf, pci_bar_offset(0), 4U) & PCIM_BAR_MEM_BASE; uart.mmio_base_vaddr =
hpa2hva(pci_pdev_read_cfg(serial_pci_bdf, pci_bar_offset(0), 4U) & PCIM_BAR_MEM_BASE);
} }
if (!serial_port_mapped) { if (!uart.serial_port_mapped) {
hv_access_memory_region_update(uart_base_address, PDE_SIZE); hv_access_memory_region_update((uint64_t)uart.mmio_base_vaddr, PDE_SIZE);
} }
spinlock_init(&uart_rx_lock); spinlock_init(&uart.rx_lock);
spinlock_init(&uart_tx_lock); spinlock_init(&uart.tx_lock);
/* Enable TX and RX FIFOs */ /* Enable TX and RX FIFOs */
uart16550_write_reg(uart_base_address, FCR_FIFOE | FCR_RFR | FCR_TFR, UART16550_FCR); uart16550_write_reg(uart, FCR_FIFOE | FCR_RFR | FCR_TFR, UART16550_FCR);
/* Set-up data bits / parity / stop bits. */ /* Set-up data bits / parity / stop bits. */
uart16550_write_reg(uart_base_address, (LCR_WL8 | LCR_NB_STOP_BITS_1 | LCR_PARITY_NONE), UART16550_LCR); uart16550_write_reg(uart, (LCR_WL8 | LCR_NB_STOP_BITS_1 | LCR_PARITY_NONE), UART16550_LCR);
/* Disable interrupts (we use polling) */ /* Disable interrupts (we use polling) */
uart16550_write_reg(uart_base_address, UART_IER_DISABLE_ALL, UART16550_IER); uart16550_write_reg(uart, UART_IER_DISABLE_ALL, UART16550_IER);
/* Set baud rate */ /* Set baud rate */
uart16550_set_baud_rate(BAUD_115200); uart16550_set_baud_rate(BAUD_115200);
/* Data terminal ready + Request to send */ /* Data terminal ready + Request to send */
uart16550_write_reg(uart_base_address, MCR_RTS | MCR_DTR, UART16550_MCR); uart16550_write_reg(uart, MCR_RTS | MCR_DTR, UART16550_MCR);
} }
char uart16550_getc(void) char uart16550_getc(void)
{ {
char ret = -1; char ret = -1;
if (!uart_enabled) { if (!uart.enabled) {
return ret; return ret;
} }
spinlock_obtain(&uart_rx_lock); spinlock_obtain(&uart.rx_lock);
/* If a character has been received, read it */ /* If a character has been received, read it */
if ((uart16550_read_reg(uart_base_address, UART16550_LSR) & LSR_DR) == LSR_DR) { if ((uart16550_read_reg(uart, UART16550_LSR) & LSR_DR) == LSR_DR) {
/* Read a character */ /* Read a character */
ret = uart16550_read_reg(uart_base_address, UART16550_RBR); ret = uart16550_read_reg(uart, UART16550_RBR);
} }
spinlock_release(&uart_rx_lock); spinlock_release(&uart.rx_lock);
return ret; return ret;
} }
/** /**
* @pre uart_enabled == true * @pre uart->enabled == true
*/ */
static void uart16550_putc(char c) static void uart16550_putc(char c)
{ {
@ -187,21 +196,21 @@ static void uart16550_putc(char c)
/* Ensure there are no further Transmit buffer write requests */ /* Ensure there are no further Transmit buffer write requests */
do { do {
reg = uart16550_read_reg(uart_base_address, UART16550_LSR); reg = uart16550_read_reg(uart, UART16550_LSR);
} while ((reg & LSR_THRE) == 0U || (reg & LSR_TEMT) == 0U); } while ((reg & LSR_THRE) == 0U || (reg & LSR_TEMT) == 0U);
temp = (uint8_t)c; temp = (uint8_t)c;
/* Transmit the character. */ /* Transmit the character. */
uart16550_write_reg(uart_base_address, (uint32_t)temp, UART16550_THR); uart16550_write_reg(uart, (uint32_t)temp, UART16550_THR);
} }
size_t uart16550_puts(const char *buf, uint32_t len) size_t uart16550_puts(const char *buf, uint32_t len)
{ {
uint32_t i; uint32_t i;
if (!uart_enabled) { if (!uart.enabled) {
return len; return len;
} }
spinlock_obtain(&uart_tx_lock); spinlock_obtain(&uart.tx_lock);
for (i = 0U; i < len; i++) { for (i = 0U; i < len; i++) {
/* Transmit character */ /* Transmit character */
uart16550_putc(*buf); uart16550_putc(*buf);
@ -211,17 +220,17 @@ size_t uart16550_puts(const char *buf, uint32_t len)
} }
buf++; buf++;
} }
spinlock_release(&uart_tx_lock); spinlock_release(&uart.tx_lock);
return len; return len;
} }
void uart16550_set_property(bool enabled, bool port_mapped, uint64_t base_addr) void uart16550_set_property(bool enabled, bool port_mapped, uint64_t base_addr)
{ {
uart_enabled = enabled; uart.enabled = enabled;
serial_port_mapped = port_mapped; uart.serial_port_mapped = port_mapped;
if (port_mapped) { if (port_mapped) {
uart_base_address = base_addr; uart.port_address = base_addr;
} else { } else {
const char *bdf = (const char *)base_addr; const char *bdf = (const char *)base_addr;
strncpy_s(pci_bdf_info, MAX_BDF_LEN + 1U, bdf, MAX_BDF_LEN); strncpy_s(pci_bdf_info, MAX_BDF_LEN + 1U, bdf, MAX_BDF_LEN);
@ -232,7 +241,7 @@ bool is_pci_dbg_uart(union pci_bdf bdf_value)
{ {
bool ret = false; bool ret = false;
if (uart_enabled && !serial_port_mapped) { if (uart.enabled && !uart.serial_port_mapped) {
if (bdf_value.value == serial_pci_bdf.value) { if (bdf_value.value == serial_pci_bdf.value) {
ret = true; ret = true;
} }