aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyan Grimm <grimm@linux.vnet.ibm.com>2016-02-17 11:27:36 -0500
committerStewart Smith <stewart@linux.vnet.ibm.com>2016-03-07 19:28:30 +1100
commit687103941245c3a10ba68266aaf661d91815e773 (patch)
tree901defec58225e57e8e87510b660a08447a92113
parent67212eb3ca9fed121432b814b5e58fb8d2cfebae (diff)
downloadskiboot-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.c4
-rw-r--r--core/init.c2
-rw-r--r--hw/lpc-uart.c63
-rw-r--r--include/chip.h1
-rw-r--r--include/console.h1
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);