diff mbox

[V2,16/33] xen/arm: Retrieve timer interrupts from the device tree

Message ID 3ac08fff0490b6d88a2609beae4b608c49f748dd.1367979526.git.julien.grall@linaro.org
State Changes Requested, archived
Headers show

Commit Message

Julien Grall May 8, 2013, 2:33 a.m. UTC
Signed-off-by: Julien Grall <julien.grall@linaro.org>

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(-)

Comments

Ian Campbell May 8, 2013, 1:50 p.m. UTC | #1
> @@ -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);

It occurs to me that this guy (and the underlying function) should
probably take a cpumask_t. Not now though.

> +}
> +
>  /* 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);

Why the change to flags == 2 here?

Ian.
Julien Grall May 8, 2013, 3:53 p.m. UTC | #2
On 05/08/2013 02:50 PM, Ian Campbell wrote:

>> @@ -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);
> 
> It occurs to me that this guy (and the underlying function) should
> probably take a cpumask_t. Not now though.
> 
>> +}
>> +
>>  /* 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);
> 
> Why the change to flags == 2 here?


It's a mistake. I will fix it on the next patch series.
diff mbox

Patch

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);