[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH V2 16/33] xen/arm: Retrieve timer interrupts from the device tree
Signed-off-by: Julien Grall <julien.grall@xxxxxxxxxx> Changes in v2: - Hardcode ppi_nr value - Use the new function request_dt_irq --- xen/arch/arm/gic.c | 9 ++----- xen/arch/arm/time.c | 59 +++++++++++++++++++++++++++++++++++++++----- xen/include/asm-arm/time.h | 3 +++ 3 files changed, 58 insertions(+), 13 deletions(-) diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c index 34304b3..91348b6 100644 --- a/xen/arch/arm/gic.c +++ b/xen/arch/arm/gic.c @@ -484,15 +484,10 @@ void gic_disable_cpu(void) void gic_route_ppis(void) { - /* XXX should get these from DT */ /* GIC maintenance */ gic_route_dt_irq(&gic.maintenance, 1u << smp_processor_id(), 0xa0); - /* Hypervisor Timer */ - gic_route_irq(26, 1, 1u << smp_processor_id(), 0xa0); - /* Virtual Timer */ - gic_route_irq(27, 1, 1u << smp_processor_id(), 0xa0); - /* Physical Timer */ - gic_route_irq(30, 1, 1u << smp_processor_id(), 0xa0); + /* Route timer interrupt */ + route_timer_interrupt(); } void gic_route_spis(void) diff --git a/xen/arch/arm/time.c b/xen/arch/arm/time.c index 82f69d2..bfc41c2 100644 --- a/xen/arch/arm/time.c +++ b/xen/arch/arm/time.c @@ -19,6 +19,7 @@ #include <xen/config.h> #include <xen/console.h> +#include <xen/device_tree.h> #include <xen/init.h> #include <xen/irq.h> #include <xen/lib.h> @@ -46,6 +47,18 @@ uint64_t __read_mostly boot_count; * register-mapped time source in the SoC. */ unsigned long __read_mostly cpu_khz; /* CPU clock frequency in kHz. */ +/* List of timer's IRQ */ +enum ppi_nr +{ + PHYS_SECURE_PPI = 0, + PHYS_NONSECURE_PPI = 1, + VIRT_PPI = 2, + HYP_PPI = 3, + MAX_TIMER_PPI = 4, +}; + +static struct dt_irq timer_irq[MAX_TIMER_PPI]; + /*static inline*/ s_time_t ticks_to_ns(uint64_t ticks) { return muldiv64(ticks, SECONDS(1), 1000 * cpu_khz); @@ -90,6 +103,28 @@ static uint32_t calibrate_timer(void) /* Set up the timer on the boot CPU */ int __init init_xen_time(void) { + struct dt_device_node *dev; + int res; + unsigned int i; + + dev = dt_find_compatible_node(NULL, NULL, "arm,armv7-timer"); + if ( !dev ) + panic("Unable to find a compatible timer in the device tree\n"); + + dt_device_set_used_by(dev, DT_USED_BY_XEN); + + /* Retrieve all IRQs for the timer */ + for ( i = PHYS_SECURE_PPI; i < MAX_TIMER_PPI; i++ ) + { + res = dt_device_get_irq(dev, i, &timer_irq[i]); + if ( res ) + panic("Timer: Unable to retrieve IRQ %u from the device tree\n", i); + } + + printk("Generic Timer IRQ: phys=%u hyp=%u virt=%u\n", + timer_irq[PHYS_NONSECURE_PPI].irq, timer_irq[HYP_PPI].irq, + timer_irq[VIRT_PPI].irq); + /* Check that this CPU supports the Generic Timer interface */ if ( !cpu_has_gentimer ) panic("CPU does not support the Generic Timer v1 interface.\n"); @@ -143,7 +178,8 @@ int reprogram_timer(s_time_t timeout) /* Handle the firing timer */ static void timer_interrupt(int irq, void *dev_id, struct cpu_user_regs *regs) { - if ( irq == 26 && READ_SYSREG32(CNTHP_CTL_EL2) & CNTx_CTL_PENDING ) + if ( irq == (timer_irq[HYP_PPI].irq) && + READ_SYSREG32(CNTHP_CTL_EL2) & CNTx_CTL_PENDING ) { /* Signal the generic timer code to do its work */ raise_softirq(TIMER_SOFTIRQ); @@ -151,7 +187,8 @@ static void timer_interrupt(int irq, void *dev_id, struct cpu_user_regs *regs) WRITE_SYSREG32(0, CNTHP_CTL_EL2); } - if (irq == 30 && READ_SYSREG32(CNTP_CTL_EL0) & CNTx_CTL_PENDING ) + if ( irq == (timer_irq[PHYS_NONSECURE_PPI].irq) && + READ_SYSREG32(CNTP_CTL_EL0) & CNTx_CTL_PENDING ) { /* Signal the generic timer code to do its work */ raise_softirq(TIMER_SOFTIRQ); @@ -167,6 +204,15 @@ static void vtimer_interrupt(int irq, void *dev_id, struct cpu_user_regs *regs) vgic_vcpu_inject_irq(current, irq, 1); } +/* Route timer's IRQ on this CPU */ +void __cpuinit route_timer_interrupt(void) +{ + gic_route_dt_irq(&timer_irq[PHYS_NONSECURE_PPI], + 1u << smp_processor_id(), 0xa0); + gic_route_dt_irq(&timer_irq[HYP_PPI], 1u << smp_processor_id(), 0xa0); + gic_route_dt_irq(&timer_irq[VIRT_PPI], 1u << smp_processor_id(), 0xa0); +} + /* Set up the timer interrupt on this CPU */ void __cpuinit init_timer_interrupt(void) { @@ -184,10 +230,11 @@ void __cpuinit init_timer_interrupt(void) WRITE_SYSREG32(0, CNTHP_CTL_EL2); /* Hypervisor's timer disabled */ isb(); - /* XXX Need to find this IRQ number from devicetree? */ - request_irq(26, timer_interrupt, 0, "hyptimer", NULL); - request_irq(27, vtimer_interrupt, 0, "virtimer", NULL); - request_irq(30, timer_interrupt, 0, "phytimer", NULL); + request_dt_irq(&timer_irq[HYP_PPI], timer_interrupt, 0, "hyptimer", NULL); + request_dt_irq(&timer_irq[VIRT_PPI], vtimer_interrupt, 0, + "virtimer", NULL); + request_dt_irq(&timer_irq[PHYS_NONSECURE_PPI], timer_interrupt, 2, + "phytimer", NULL); } /* Wait a set number of microseconds */ diff --git a/xen/include/asm-arm/time.h b/xen/include/asm-arm/time.h index c16bf08..467bf91 100644 --- a/xen/include/asm-arm/time.h +++ b/xen/include/asm-arm/time.h @@ -12,6 +12,9 @@ struct tm; struct tm wallclock_time(void); +/* Route timer's IRQ on this CPU */ +extern void __cpuinit route_timer_interrupt(void); + /* Set up the timer interrupt on this CPU */ extern void __cpuinit init_timer_interrupt(void); -- Julien Grall _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |