diff mbox

[RFC,12/29] xen/arm: Introduce gic_irq_xlate

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

Commit Message

Julien Grall April 28, 2013, 11:01 p.m. UTC
This function translates an interrupt specifier to an IRQ number and IRQ
type (ie: level trigger, edge trigger,...). It's GIC specific.

Signed-off-by: Julien Grall <julien.grall@linaro.org>
---
 xen/arch/arm/gic.c        |   20 ++++++++++++++++++++
 xen/arch/arm/setup.c      |    1 +
 xen/include/asm-arm/gic.h |    4 ++++
 3 files changed, 25 insertions(+)

Comments

Ian Campbell April 29, 2013, 3:31 p.m. UTC | #1
On Mon, 2013-04-29 at 00:01 +0100, Julien Grall wrote:
> This function translates an interrupt specifier to an IRQ number and IRQ
> type (ie: level trigger, edge trigger,...). It's GIC specific.
> 
> Signed-off-by: Julien Grall <julien.grall@linaro.org>
> ---
>  xen/arch/arm/gic.c        |   20 ++++++++++++++++++++
>  xen/arch/arm/setup.c      |    1 +
>  xen/include/asm-arm/gic.h |    4 ++++
>  3 files changed, 25 insertions(+)
> 
> diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
> index e03bb67..1f44fea 100644
> --- a/xen/arch/arm/gic.c
> +++ b/xen/arch/arm/gic.c
> @@ -329,6 +329,26 @@ static void __cpuinit gic_hyp_disable(void)
>      GICH[GICH_HCR] = 0;
>  }
>  
> +int gic_irq_xlate(const u32 *intspec, unsigned int intsize,
> +                  unsigned int *out_hwirq,
> +                  unsigned int *out_type)
> +{
> +    if ( intsize < 3 )
> +        return -EINVAL;
> +
> +    /* Get the interrupt number and add 16 to skip over SGIs */
> +    *out_hwirq = intspec[1] + 16;
> +
> +    /* For SPIs, we need to add 16 more to get the GIC irq ID number */
> +    if ( !intspec[0] )
> +        *out_hwirq += 16;
> +
> +    if ( out_type )
> +        *out_type = intspec[2] & IRQ_TYPE_SENSE_MASK;

These defines could replace the hardcoded 0xf08 in make_hypervisor_node?
Super!

> +
> +    return 0;
> +}
> +
>  /* Set up the GIC */
>  void __init gic_init(void)
>  {
> diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
> index 77d0879..51f4bba 100644
> --- a/xen/arch/arm/setup.c
> +++ b/xen/arch/arm/setup.c
> @@ -429,6 +429,7 @@ void __init start_xen(unsigned long boot_phys_offset,
>      setup_mm(fdt_paddr, fdt_size);
>  
>      dt_unflatten_host_device_tree();
> +    dt_irq_xlate = gic_irq_xlate;

It feels like this ought to belong in a gic_init function of some sort?

>  
>  #ifdef EARLY_UART_ADDRESS
>      /* TODO Need to get device tree or command line for UART address */
> diff --git a/xen/include/asm-arm/gic.h b/xen/include/asm-arm/gic.h
> index 2fac673..945e8db 100644
> --- a/xen/include/asm-arm/gic.h
> +++ b/xen/include/asm-arm/gic.h
> @@ -187,6 +187,10 @@ extern void send_SGI_allbutself(enum gic_sgi sgi);
>  /* print useful debug info */
>  extern void gic_dump_info(struct vcpu *v);
>  
> +/* IRQ translation function for the device tree */
> +int gic_irq_xlate(const u32 *intspec, unsigned int intsize,
> +                  unsigned int *out_hwirq, unsigned int *out_type);
> +
>  #endif /* __ASSEMBLY__ */
>  #endif
>
Julien Grall April 29, 2013, 3:52 p.m. UTC | #2
On 04/29/2013 04:31 PM, Ian Campbell wrote:

> On Mon, 2013-04-29 at 00:01 +0100, Julien Grall wrote:
>> This function translates an interrupt specifier to an IRQ number and IRQ
>> type (ie: level trigger, edge trigger,...). It's GIC specific.
>>
>> Signed-off-by: Julien Grall <julien.grall@linaro.org>
>> ---
>>  xen/arch/arm/gic.c        |   20 ++++++++++++++++++++
>>  xen/arch/arm/setup.c      |    1 +
>>  xen/include/asm-arm/gic.h |    4 ++++
>>  3 files changed, 25 insertions(+)
>>
>> diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
>> index e03bb67..1f44fea 100644
>> --- a/xen/arch/arm/gic.c
>> +++ b/xen/arch/arm/gic.c
>> @@ -329,6 +329,26 @@ static void __cpuinit gic_hyp_disable(void)
>>      GICH[GICH_HCR] = 0;
>>  }
>>  
>> +int gic_irq_xlate(const u32 *intspec, unsigned int intsize,
>> +                  unsigned int *out_hwirq,
>> +                  unsigned int *out_type)
>> +{
>> +    if ( intsize < 3 )
>> +        return -EINVAL;
>> +
>> +    /* Get the interrupt number and add 16 to skip over SGIs */
>> +    *out_hwirq = intspec[1] + 16;
>> +
>> +    /* For SPIs, we need to add 16 more to get the GIC irq ID number */
>> +    if ( !intspec[0] )
>> +        *out_hwirq += 16;
>> +
>> +    if ( out_type )
>> +        *out_type = intspec[2] & IRQ_TYPE_SENSE_MASK;
> 
> These defines could replace the hardcoded 0xf08 in make_hypervisor_node?
> Super!

Right.

>> +
>> +    return 0;
>> +}
>> +
>>  /* Set up the GIC */
>>  void __init gic_init(void)
>>  {
>> diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
>> index 77d0879..51f4bba 100644
>> --- a/xen/arch/arm/setup.c
>> +++ b/xen/arch/arm/setup.c
>> @@ -429,6 +429,7 @@ void __init start_xen(unsigned long boot_phys_offset,
>>      setup_mm(fdt_paddr, fdt_size);
>>  
>>      dt_unflatten_host_device_tree();
>> +    dt_irq_xlate = gic_irq_xlate;
> 
> It feels like this ought to belong in a gic_init function of some sort?


The device tree needs this function to translate interrupt for the UART
driver. The GIC is initialized too late (few lines after serial setup).

Is there a drawback to move gic initialization before the serial setup?
The only one I have found is we must use early printk in the function.
So most of the time the user can't see the output, assuming he doesn't
compile Xen with CONFIG_EARLY_PRINTK.
diff mbox

Patch

diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
index e03bb67..1f44fea 100644
--- a/xen/arch/arm/gic.c
+++ b/xen/arch/arm/gic.c
@@ -329,6 +329,26 @@  static void __cpuinit gic_hyp_disable(void)
     GICH[GICH_HCR] = 0;
 }
 
+int gic_irq_xlate(const u32 *intspec, unsigned int intsize,
+                  unsigned int *out_hwirq,
+                  unsigned int *out_type)
+{
+    if ( intsize < 3 )
+        return -EINVAL;
+
+    /* Get the interrupt number and add 16 to skip over SGIs */
+    *out_hwirq = intspec[1] + 16;
+
+    /* For SPIs, we need to add 16 more to get the GIC irq ID number */
+    if ( !intspec[0] )
+        *out_hwirq += 16;
+
+    if ( out_type )
+        *out_type = intspec[2] & IRQ_TYPE_SENSE_MASK;
+
+    return 0;
+}
+
 /* Set up the GIC */
 void __init gic_init(void)
 {
diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
index 77d0879..51f4bba 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -429,6 +429,7 @@  void __init start_xen(unsigned long boot_phys_offset,
     setup_mm(fdt_paddr, fdt_size);
 
     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 */
diff --git a/xen/include/asm-arm/gic.h b/xen/include/asm-arm/gic.h
index 2fac673..945e8db 100644
--- a/xen/include/asm-arm/gic.h
+++ b/xen/include/asm-arm/gic.h
@@ -187,6 +187,10 @@  extern void send_SGI_allbutself(enum gic_sgi sgi);
 /* print useful debug info */
 extern void gic_dump_info(struct vcpu *v);
 
+/* IRQ translation function for the device tree */
+int gic_irq_xlate(const u32 *intspec, unsigned int intsize,
+                  unsigned int *out_hwirq, unsigned int *out_type);
+
 #endif /* __ASSEMBLY__ */
 #endif