diff options
author | Ryan Grimm <grimm@linux.vnet.ibm.com> | 2016-02-17 11:27:36 -0500 |
---|---|---|
committer | Stewart Smith <stewart@linux.vnet.ibm.com> | 2016-03-07 19:28:30 +1100 |
commit | 687103941245c3a10ba68266aaf661d91815e773 (patch) | |
tree | 901defec58225e57e8e87510b660a08447a92113 | |
parent | 67212eb3ca9fed121432b814b5e58fb8d2cfebae (diff) | |
download | skiboot-687103941245c3a10ba68266aaf661d91815e773.zip skiboot-687103941245c3a10ba68266aaf661d91815e773.tar.gz skiboot-687103941245c3a10ba68266aaf661d91815e773.tar.bz2 |
Enable Simics UART console
The UART is a simulated ns16550 with memory mapped registers.
A /simics dt node is detected and a SIMICS_QUIRK is added to chip quirks
similar to MAMBO_CALLOUTS. It can contain an ns16550 dt node with a property
console-bar.
The LPC UART code is reused and this will work without an LPC bus in the model.
Signed-off-by: Ryan Grimm <grimm@linux.vnet.ibm.com>
Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
-rw-r--r-- | core/chip.c | 4 | ||||
-rw-r--r-- | core/init.c | 2 | ||||
-rw-r--r-- | hw/lpc-uart.c | 63 | ||||
-rw-r--r-- | include/chip.h | 1 | ||||
-rw-r--r-- | include/console.h | 1 |
5 files changed, 68 insertions, 3 deletions
diff --git a/core/chip.c b/core/chip.c index 729bccb..49d2f1f 100644 --- a/core/chip.c +++ b/core/chip.c @@ -76,6 +76,10 @@ void init_chips(void) | QUIRK_DISABLE_NAP; prlog(PR_NOTICE, "CHIP: Detected Mambo simulator\n"); } + if (dt_find_by_path(dt_root, "/simics")) { + proc_chip_quirks |= QUIRK_SIMICS; + prlog(PR_NOTICE, "CHIP: Detected Simics simulator\n"); + } if (dt_node_is_compatible(dt_root, "qemu,powernv")) { proc_chip_quirks |= QUIRK_NO_CHIPTOD | QUIRK_NO_PBA; prlog(PR_NOTICE, "CHIP: Detected Qemu simulator\n"); diff --git a/core/init.c b/core/init.c index 1d9ef70..0576f46 100644 --- a/core/init.c +++ b/core/init.c @@ -639,6 +639,8 @@ void __noreturn main_cpu_entry(const void *fdt, u32 master_cpu) init_chips(); if (chip_quirk(QUIRK_MAMBO_CALLOUTS)) enable_mambo_console(); + if (chip_quirk(QUIRK_SIMICS)) + enable_simics_console(); xscom_init(); mfsi_init(); diff --git a/hw/lpc-uart.c b/hw/lpc-uart.c index bba6354..433cdff 100644 --- a/hw/lpc-uart.c +++ b/hw/lpc-uart.c @@ -26,6 +26,7 @@ #include <timebase.h> #include <cpu.h> #include <chip.h> +#include <io.h> DEFINE_LOG_ENTRY(OPAL_RC_UART_INIT, OPAL_PLATFORM_ERR_EVT, OPAL_UART, OPAL_CEC_HARDWARE, OPAL_PREDICTIVE_ERR_GENERAL, @@ -66,6 +67,8 @@ static uint32_t uart_base; static bool has_irq, irq_ok, rx_full, tx_full; static uint8_t tx_room; static uint8_t cached_ier; +static bool simics_uart; +static void *simics_uart_base; static void uart_trace(u8 ctx, u8 cnt, u8 irq_state, u8 in_count) { @@ -80,12 +83,18 @@ static void uart_trace(u8 ctx, u8 cnt, u8 irq_state, u8 in_count) static inline uint8_t uart_read(unsigned int reg) { - return lpc_inb(uart_base + reg); + if (simics_uart) + return in_8(simics_uart_base + reg); + else + return lpc_inb(uart_base + reg); } static inline void uart_write(unsigned int reg, uint8_t val) { - lpc_outb(val, uart_base + reg); + if (simics_uart) + out_8(simics_uart_base + reg, val); + else + lpc_outb(val, uart_base + reg); } static void uart_check_tx_room(void) @@ -137,7 +146,7 @@ static size_t uart_con_write(const char *buf, size_t len) size_t written = 0; /* If LPC bus is bad, we just swallow data */ - if (!lpc_ok()) + if (!lpc_ok() && !simics_uart) return written; lock(&uart_lock); @@ -547,3 +556,51 @@ void uart_init(bool use_interrupt) } else has_irq = false; } + +static bool simics_con_poll_read(void) { + uint8_t lsr = uart_read(REG_LSR); + return ((lsr & LSR_DR) != 0); +} + +static size_t simics_con_read(char *buf, size_t len) +{ + size_t count = 0; + while (count < len) { + if (!simics_con_poll_read()) + break; + *(buf++) = uart_read(REG_RBR); + count++; + } + return count; +} + +static struct con_ops simics_con_driver = { + .poll_read = simics_con_poll_read, + .read = simics_con_read, + .write = uart_con_write, +}; + +void enable_simics_console() { + struct dt_node *n; + + printf("Enabling Simics console\n"); + + n = dt_find_compatible_node(dt_root, NULL, "ns16550"); + if (!n) { + prerror("UART: cannot find ns16550\n"); + return; + } + + simics_uart_base = (void *)dt_prop_get_u64(n, "console-bar"); + simics_uart = 1; + has_irq = false; + + if (!uart_init_hw(dt_prop_get_u32(n, "current-speed"), + dt_prop_get_u32(n, "clock-frequency"))) { + prerror("UART: Initialization failed\n"); + dt_add_property_strings(n, "status", "bad"); + return; + } + + set_console(&simics_con_driver); +} diff --git a/include/chip.h b/include/chip.h index 5109e25..9e50f7a 100644 --- a/include/chip.h +++ b/include/chip.h @@ -99,6 +99,7 @@ enum proc_chip_quirks { QUIRK_NO_PBA = 0x00000008, QUIRK_NO_OCC_IRQ = 0x00000010, QUIRK_DISABLE_NAP = 0x00000020, + QUIRK_SIMICS = 0x00000040, } proc_chip_quirks; static inline bool chip_quirk(unsigned int q) diff --git a/include/console.h b/include/console.h index b6fc8bf..ecb18c4 100644 --- a/include/console.h +++ b/include/console.h @@ -67,6 +67,7 @@ extern void console_complete_flush(void); extern int mambo_read(void); extern void mambo_write(const char *buf, size_t count); extern void enable_mambo_console(void); +extern void enable_simics_console(void); ssize_t console_write(bool flush_to_drivers, const void *buf, size_t count); |