aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNaresh Bhat <naresh.bhat@linaro.org>2014-08-14 12:08:15 +0530
committerNaresh Bhat <naresh.bhat@linaro.org>2014-09-03 16:48:47 +0530
commitbfc12c2d6cfe898c39f5c20a01fe174d4e9914ae (patch)
tree8e3008efaa0d69fdc0b204fc5b58a2539dc16548
parentc1d6b5b4e1ead7080f99c3c7122f06ac10f98daa (diff)
downloadxen-bfc12c2d6cfe898c39f5c20a01fe174d4e9914ae.tar.gz
pl011: Initialize serial from ACPI SPCR table
Parse ACPI SPCR (Serial Port Console Redirection table) table and initialize the serial port pl011. Signed-off-by: Naresh Bhat <naresh.bhat@linaro.org>
-rw-r--r--xen/arch/arm/setup.c6
-rw-r--r--xen/drivers/char/pl011.c84
-rw-r--r--xen/include/xen/serial.h1
3 files changed, 91 insertions, 0 deletions
diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
index d71427a187..c19d1b54fb 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -791,7 +791,13 @@ void __init start_xen(unsigned long boot_phys_offset,
init_IRQ();
+/* If ACPI enabled and ARM64 arch then UART initialization from SPCR table */
+#if defined(CONFIG_ACPI) && defined(CONFIG_ARM_64)
+ acpi_uart_init();
+#else
dt_uart_init();
+#endif
+
console_init_preirq();
system_state = SYS_STATE_boot;
diff --git a/xen/drivers/char/pl011.c b/xen/drivers/char/pl011.c
index dd19ce8c19..8a333ff3b5 100644
--- a/xen/drivers/char/pl011.c
+++ b/xen/drivers/char/pl011.c
@@ -280,6 +280,90 @@ DT_DEVICE_START(pl011, "PL011 UART", DEVICE_SERIAL)
.init = pl011_uart_init,
DT_DEVICE_END
+/* Parse the SPCR table and initialize the Serial UART */
+#if defined(CONFIG_ARM_64) && defined(CONFIG_ACPI)
+
+#include <xen/acpi.h>
+
+static int __init acpi_pl011_uart_init(struct acpi_table_header *table)
+{
+ struct pl011 *uart;
+ u64 addr, size;
+
+ struct acpi_table_spcr *spcr;
+ spcr = (struct acpi_table_spcr *)table;
+
+ printk("Looking for UART information in ACPI SPCR table \n");
+
+ printk("(I) interface_type 0=full 16550, 1=subset: %u\n", spcr->interface_type); /* 0=full 16550, 1=subset of 16550 */
+
+ printk("(I) UART at address : 0x%08lX\n", spcr->serial_port.address);
+ printk("(I) UART space_id : %u\n", spcr->serial_port.space_id);
+ printk("(I) UART bit_width : %u\n", spcr->serial_port.bit_width);
+ printk("(I) UART bit_offset : %u\n", spcr->serial_port.bit_offset);
+ printk("(I) UART access_width : %u\n", spcr->serial_port.access_width);
+
+ printk("(I) interrupt_type: %u\n", spcr->interrupt_type);
+ printk("(I) pc_interrupt : %u\n", spcr->pc_interrupt);
+ printk("(I) interrupt : %u\n", spcr->interrupt);
+ printk("(I) baud_rate : %u\n", spcr->baud_rate);
+ printk("(I) parity : %u\n", spcr->parity);
+ printk("(I) stop_bits : %u\n", spcr->stop_bits);
+ printk("(I) flow_control : %u\n", spcr->flow_control);
+ printk("(I) terminal_type : %u\n", spcr->terminal_type);
+
+ if (spcr->interface_type) {
+ printk("Interface_type 1=subset\n");
+ return ENXIO;
+ }
+ else
+ printk("Interface_type 0=full 16550\n");
+
+ uart = &pl011_com;
+
+ uart->clock_hz = 0x16e3600;
+ uart->baud = spcr->baud_rate;
+ uart->data_bits = 8;
+ uart->parity = spcr->parity;
+ uart->stop_bits = spcr->stop_bits;
+
+ if ( spcr->interrupt < 0 )
+ {
+ printk("pl011: Unable to retrieve the IRQ\n");
+ return -EINVAL;
+ }
+
+ uart->irq = spcr->interrupt;
+ addr = spcr->serial_port.address;
+ size = 0x1000;
+ uart->regs = ioremap_nocache(addr, size);
+
+ if ( !uart->regs )
+ {
+ printk("pl011: Unable to map the UART memory\n");
+ return -ENOMEM;
+ }
+
+ uart->vuart.base_addr = addr;
+ uart->vuart.size = size;
+ uart->vuart.data_off = DR;
+ uart->vuart.status_off = FR;
+ uart->vuart.status = 0;
+
+ /* Register with generic serial driver. */
+ serial_register_uart(SERHND_DTUART, &pl011_driver, uart);
+
+ return 0;
+}
+
+void __init acpi_uart_init(void)
+{
+ printk("ACPI UART Init\n");
+ acpi_table_parse(ACPI_SIG_SPCR, acpi_pl011_uart_init);
+
+}
+#endif
+
/*
* Local variables:
* mode: C
diff --git a/xen/include/xen/serial.h b/xen/include/xen/serial.h
index 9f4451bee9..99e53d47b3 100644
--- a/xen/include/xen/serial.h
+++ b/xen/include/xen/serial.h
@@ -167,6 +167,7 @@ void ns16550_init(int index, struct ns16550_defaults *defaults);
void ehci_dbgp_init(void);
void __init dt_uart_init(void);
+void __init acpi_uart_init(void);
struct physdev_dbgp_op;
int dbgp_op(const struct physdev_dbgp_op *);