diff mbox

[RFC,19/29] xen/arm: Use device tree API in pl011 UART driver

Message ID f4b5d9c23c8e1c854398ce96d5a5f2eb48b76329.1367188423.git.julien.grall@linaro.org
State Changes Requested, archived
Headers show

Commit Message

Julien Grall April 28, 2013, 11:02 p.m. UTC
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(-)

Comments

Ian Campbell April 29, 2013, 3:54 p.m. UTC | #1
On Mon, 2013-04-29 at 00:02 +0100, Julien Grall wrote:

> -/* TODO: Parse UART config from device-tree or command-line */

I think the "or command-line" bit of this comment remains?

Otherwise: Acked-by: Ian Campbell <ian.campbell@citrix.com>
Julien Grall April 29, 2013, 5:27 p.m. UTC | #2
On 04/29/2013 04:54 PM, Ian Campbell wrote:

> On Mon, 2013-04-29 at 00:02 +0100, Julien Grall wrote:
> 
>> -/* TODO: Parse UART config from device-tree or command-line */
> 
> I think the "or command-line" bit of this comment remains?


Right. I will fix it.
diff mbox

Patch

diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
index 8085b6e..8dba4b6 100644
--- a/xen/arch/arm/gic.c
+++ b/xen/arch/arm/gic.c
@@ -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 )
diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
index e5d8724..aee491d 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -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();
 
diff --git a/xen/drivers/char/pl011.c b/xen/drivers/char/pl011.c
index 8efd08e..411aea5 100644
--- a/xen/drivers/char/pl011.c
+++ b/xen/drivers/char/pl011.c
@@ -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
diff --git a/xen/include/xen/serial.h b/xen/include/xen/serial.h
index 2579ce8..a7d4c6d 100644
--- a/xen/include/xen/serial.h
+++ b/xen/include/xen/serial.h
@@ -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 */