From mboxrd@z Thu Jan 1 00:00:00 1970 From: Julien Grall Subject: [PATCH V4 20/32] xen/arm: Use device tree API in pl011 UART driver Date: Fri, 10 May 2013 16:11:59 +0100 Message-ID: <1368198723-24639-8-git-send-email-julien.grall@linaro.org> References: <1368198723-24639-1-git-send-email-julien.grall@linaro.org> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: In-Reply-To: <1368198723-24639-1-git-send-email-julien.grall@linaro.org> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org To: xen-devel@lists.xen.org Cc: patches@linaro.org, ian.campbell@citrix.com, Julien Grall , Stefano.Stabellini@eu.citrix.com List-Id: xen-devel@lists.xenproject.org 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 Acked-by: Ian Campbell Changes in v4: - Use ioremap_nocache instead of ioremap_attr(..., PAGE_HYPERVISOR_NOCACHE) - Print a warning if config != "" Changes in v3: - Remove the usage of serial_arm_defaults - Get the base address from the DT and map it with ioremap_attr - Allow only 1 PL011 assigned to SERHND_DTUART - Replace DT_USED_BY_XEN by DOMID_XEN Changes in v2: - Rework TODO - Use the new function setup_dt_irq --- xen/arch/arm/gic.c | 4 --- xen/arch/arm/setup.c | 4 --- xen/drivers/char/pl011.c | 88 +++++++++++++++++++++++++++++++++++++--------- xen/include/xen/serial.h | 1 - 4 files changed, 72 insertions(+), 25 deletions(-) diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c index 761f570..648b1a0 100644 --- a/xen/arch/arm/gic.c +++ b/xen/arch/arm/gic.c @@ -505,10 +505,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 2e331d3..e5f4459 100644 --- a/xen/arch/arm/setup.c +++ b/xen/arch/arm/setup.c @@ -433,10 +433,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 dt_uart_init(); console_init_preirq(); diff --git a/xen/drivers/char/pl011.c b/xen/drivers/char/pl011.c index 8efd08e..05b5ef1 100644 --- a/xen/drivers/char/pl011.c +++ b/xen/drivers/char/pl011.c @@ -22,9 +22,16 @@ #include #include #include +#include +#include +#include +#include +#include +#include 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; @@ -32,7 +39,7 @@ static struct pl011 { /* struct timer timer; */ /* unsigned int timeout_ms; */ /* bool_t probing, intr_works; */ -} pl011_com[2] = {{0}}; +} pl011_com = {0}; /* PL011 register addresses */ #define DR (0x00/4) @@ -163,13 +170,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_dt_irq(&uart->irq, &uart->irqaction)) != 0 ) + printk("ERROR: Failed to allocate pl011 IRQ %d\n", uart->irq.irq); } /* Clear pending error interrupts */ @@ -215,7 +222,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 +241,74 @@ 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) +/* TODO: Parse UART config from the command line */ +static int __init pl011_uart_init(struct dt_device_node *dev, + const void *data) { + const char *config = data; struct pl011 *uart; + int res; + u64 addr, size; - if ( (index < 0) || (index > 1) ) - return; + if ( strcmp(config, "") ) + { + early_printk("WARNING: UART configuration is not supported\n"); + } - uart = &pl011_com[index]; + uart = &pl011_com; 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; + + res = dt_device_get_address(dev, 0, &addr, &size); + if ( res ) + { + early_printk("pl011: Unable to retrieve the base" + " address of the UART\n"); + return res; + } + + uart->regs = ioremap_attr(addr, size, PAGE_HYPERVISOR_NOCACHE); + if ( !uart->regs ) + { + early_printk("pl011: Unable to map the UART memory\n"); + + return -ENOMEM; + } + + 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); + serial_register_uart(SERHND_DTUART, &pl011_driver, uart); + + dt_device_set_used_by(dev, DOMID_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 8af3bc4..9caf776 100644 --- a/xen/include/xen/serial.h +++ b/xen/include/xen/serial.h @@ -157,7 +157,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); void __init dt_uart_init(void); struct physdev_dbgp_op; -- 1.7.10.4