@@ -501,10 +501,6 @@ void gic_route_spis(void)
int seridx;
const struct dt_irq *irq;
- /* XXX should get these from DT */
- /* UART */
- gic_route_irq(37, 0, 1u << smp_processor_id(), 0xa0);
-
for ( seridx = 0; seridx <= SERHND_IDX; seridx++ )
{
if ( (irq = serial_dt_irq(seridx)) == NULL )
@@ -431,10 +431,6 @@ void __init start_xen(unsigned long boot_phys_offset,
dt_unflatten_host_device_tree();
dt_irq_xlate = gic_irq_xlate;
-#ifdef EARLY_UART_ADDRESS
- /* TODO Need to get device tree or command line for UART address */
- pl011_init(0, FIXMAP_ADDR(FIXMAP_CONSOLE));
-#endif
arm_uart_init();
console_init_preirq();
@@ -22,9 +22,14 @@
#include <xen/serial.h>
#include <xen/init.h>
#include <xen/irq.h>
+#include <asm/early_printk.h>
+#include <xen/device_tree.h>
+#include <xen/errno.h>
+#include <asm/device.h>
static struct pl011 {
- unsigned int baud, clock_hz, data_bits, parity, stop_bits, irq;
+ unsigned int baud, clock_hz, data_bits, parity, stop_bits;
+ struct dt_irq irq;
volatile uint32_t *regs;
/* UART with IRQ line: interrupt-driven I/O. */
struct irqaction irqaction;
@@ -163,13 +168,13 @@ static void __init pl011_init_postirq(struct serial_port *port)
struct pl011 *uart = port->uart;
int rc;
- if ( uart->irq > 0 )
+ if ( uart->irq.irq > 0 )
{
uart->irqaction.handler = pl011_interrupt;
uart->irqaction.name = "pl011";
uart->irqaction.dev_id = port;
- if ( (rc = setup_irq(uart->irq, &uart->irqaction)) != 0 )
- printk("ERROR: Failed to allocate pl011 IRQ %d\n", uart->irq);
+ if ( (rc = setup_irq(uart->irq.irq, &uart->irqaction)) != 0 )
+ printk("ERROR: Failed to allocate pl011 IRQ %d\n", uart->irq.irq);
}
/* Clear pending error interrupts */
@@ -215,7 +220,14 @@ static int pl011_getc(struct serial_port *port, char *pc)
static int __init pl011_irq(struct serial_port *port)
{
struct pl011 *uart = port->uart;
- return ((uart->irq > 0) ? uart->irq : -1);
+ return ((uart->irq.irq > 0) ? uart->irq.irq : -1);
+}
+
+static const struct dt_irq __init *pl011_dt_irq(struct serial_port *port)
+{
+ struct pl011 *uart = port->uart;
+
+ return &uart->irq;
}
static struct uart_driver __read_mostly pl011_driver = {
@@ -227,32 +239,55 @@ static struct uart_driver __read_mostly pl011_driver = {
.tx_ready = pl011_tx_ready,
.putc = pl011_putc,
.getc = pl011_getc,
- .irq = pl011_irq
+ .irq = pl011_irq,
+ .dt_irq_get = pl011_dt_irq,
};
-/* TODO: Parse UART config from device-tree or command-line */
-
-void __init pl011_init(int index, unsigned long register_base_address)
+static int __init pl011_uart_init(struct dt_device_node *dev,
+ const void *data)
{
+ const struct serial_arm_defaults *defaults = data;
struct pl011 *uart;
+ int res;
- if ( (index < 0) || (index > 1) )
- return;
+ if ( (defaults->index < 0) || (defaults->index > 1) )
+ return -EINVAL;
- uart = &pl011_com[index];
+ uart = &pl011_com[defaults->index];
uart->clock_hz = 0x16e3600;
uart->baud = 38400;
uart->data_bits = 8;
uart->parity = PARITY_NONE;
uart->stop_bits = 1;
- uart->irq = 37; /* TODO Need to find this from devicetree */
- uart->regs = (uint32_t *) register_base_address;
+ uart->regs = (uint32_t *) defaults->register_base_address;
+
+ res = dt_device_get_irq(dev, 0, &uart->irq);
+ if ( res )
+ {
+ early_printk("pl011: Unable to retrieve the IRQ\n");
+ return res;
+ }
/* Register with generic serial driver. */
serial_register_uart(uart - pl011_com, &pl011_driver, uart);
+
+ dt_device_set_used_by(dev, DT_USED_BY_XEN);
+
+ return 0;
}
+static const char const *pl011_dt_compat[] __initdata =
+{
+ "arm,pl011",
+ NULL
+};
+
+DT_DEVICE_START(pl011, "PL011 UART", DEVICE_SERIAL)
+ .compatible = pl011_dt_compat,
+ .init = pl011_uart_init,
+DT_DEVICE_END
+
/*
* Local variables:
* mode: C
@@ -156,7 +156,6 @@ struct ns16550_defaults {
void ns16550_init(int index, struct ns16550_defaults *defaults);
void ehci_dbgp_init(void);
-void pl011_init(int index, unsigned long register_base_address);
/* Default value for UART on ARM boards */
struct serial_arm_defaults {
int index; /* Serial index */
Allow UART driver to retrieve all its information in the device tree. It's possible to choose the pl011 driver via the Xen command line. Signed-off-by: Julien Grall <julien.grall@linaro.org> --- xen/arch/arm/gic.c | 4 --- xen/arch/arm/setup.c | 4 --- xen/drivers/char/pl011.c | 63 +++++++++++++++++++++++++++++++++++----------- xen/include/xen/serial.h | 1 - 4 files changed, 49 insertions(+), 23 deletions(-)