ARM: mach-shmobile: Use common INTC IRQ code on sh73a0
Magnus Damm
maintainerPATCH 6/7 ARM: mach-shmobile: Use common INTC IRQ code on sh73a0
From: Magnus Damm <[email protected]>
Improve IRQ triggering support by making use of the macro INTC_IRQ_PINS_32() for INTCA on sh73a0. Unfortunately it is not as easy as just using the macro as-is, we need to do mask and unmaks in the GIC but configure other bits and ack in INTCA. Update GPIO IRQ mappings while at it.
Signed-off-by Magnus Damm <[email protected]>
---
arch/arm/mach-shmobile/intc-sh73a0.c | 122 ++++++++++++++++++++++++++++++++++ arch/arm/mach-shmobile/pfc-sh73a0.c | 68 +++++++++--------- 2 files changed, 157 insertions(+), 33 deletions(-)
arch/arm/mach-shmobile/intc-sh73a0.c +122 -0
@@ -22,6 +22,7 @@#include <linux/irq.h> #include <linux/io.h> #include <linux/sh_intc.h> +#include <mach/intc.h> #include <asm/hardware/gic.h> #include <asm/mach-types.h> #include <asm/mach/arch.h>
@@ -255,20 +256,141 @@ static int sh73a0_set_wake(struct irq_dareturn 0 ;/* always allow wakeup */ } +#define RELOC_BASE 0x1000 + +/* INTCA IRQ pins at INTCS + 0x1000 to make space for GIC+INTC handling */ +#define INTCS_VECT_RELOC (n, vect) INTCS_VECT((n), (vect) + RELOC_BASE) + +INTC_IRQ_PINS_32 (intca_irq_pins,0xe6900000 , +INTCS_VECT_RELOC ,"sh73a0-intca-irq-pins" ); + +static int to_gic_irq (struct irq_data *data) +{ +unsigned int vect =irq2evt (data->irq) -INTCS_VECT_BASE ; + +if (vect >=0x3200 ) + vect -=0x3000 ; +else + vect -=0x0200 ; + +return gic_spi ((vect >>5 ) +1 ); +} + +static int to_intca_reloc_irq (struct irq_data *data) +{ +return data->irq + (RELOC_BASE >>5 ); +} + +#define irq_cb (cb, irq) irq_get_chip(irq)->cb(irq_get_irq_data(irq)) +#define irq_cbp(cb, irq, p...) irq_get_chip(irq)->cb(irq_get_irq_data(irq), p) + +static void intca_gic_enable (struct irq_data *data) +{ +irq_cb (irq_unmask,to_intca_reloc_irq (data)); +irq_cb (irq_unmask,to_gic_irq (data)); +} + +static void intca_gic_disable (struct irq_data *data) +{ +irq_cb (irq_mask,to_gic_irq (data)); +irq_cb (irq_mask,to_intca_reloc_irq (data)); +} + +static void intca_gic_mask_ack (struct irq_data *data) +{ +irq_cb (irq_mask,to_gic_irq (data)); +irq_cb (irq_mask_ack,to_intca_reloc_irq (data)); +} + +static void intca_gic_eoi (struct irq_data *data) +{ +irq_cb (irq_eoi,to_gic_irq (data)); +} + +static int intca_gic_set_type (struct irq_data *data,unsigned int type) +{ +return irq_cbp (irq_set_type,to_intca_reloc_irq (data), type); +} + +static int intca_gic_set_wake (struct irq_data *data,unsigned int on) +{ +return irq_cbp (irq_set_wake,to_intca_reloc_irq (data), on); +} + +#ifdef CONFIG_SMP +static int intca_gic_set_affinity (struct irq_data *data, +const struct cpumask *cpumask, +bool force) +{ +return irq_cbp (irq_set_affinity,to_gic_irq (data), cpumask, force); +} +#endif + +struct irq_chip intca_gic_irq_chip = { + .name ="INTCA-GIC" , + .irq_mask = intca_gic_disable, + .irq_unmask = intca_gic_enable, + .irq_mask_ack = intca_gic_mask_ack, + .irq_eoi = intca_gic_eoi, + .irq_enable = intca_gic_enable, + .irq_disable = intca_gic_disable, + .irq_shutdown = intca_gic_disable, + .irq_set_type = intca_gic_set_type, + .irq_set_wake = intca_gic_set_wake, +#ifdef CONFIG_SMP + .irq_set_affinity = intca_gic_set_affinity, +#endif +}; + +static int to_intc_vect (int irq) +{ +unsigned int irq_pin = irq -gic_spi (1 ); +unsigned int offs; + +if (irq_pin <16 ) + offs =0x0200 ; +else + offs =0x3000 ; + +return offs + (irq_pin <<5 ); +} + +static irqreturn_t sh73a0_irq_pin_demux (int irq,void *dev_id) +{ +generic_handle_irq (intcs_evt2irq (to_intc_vect (irq))); +return IRQ_HANDLED ; +} + +static struct irqaction sh73a0_irq_pin_cascade[32 ]; +void __init sh73a0_init_irq (void ) {void __iomem *gic_dist_base =__io (0xf0001000 );void __iomem *gic_cpu_base =__io (0xf0000100 );void __iomem *intevtsa =ioremap_nocache (0xffd20100 ,PAGE_SIZE ); +int k, n;gic_init (0 ,29 , gic_dist_base, gic_cpu_base); gic_arch_extn.irq_set_wake = sh73a0_set_wake;register_intc_controller (&intcs_desc); +register_intc_controller (&intca_irq_pins_desc);/* demux using INTEVTSA */ sh73a0_intcs_cascade.name ="INTCS cascade" ; sh73a0_intcs_cascade.handler = sh73a0_intcs_demux; sh73a0_intcs_cascade.dev_id = intevtsa;setup_irq (gic_spi (50 ), &sh73a0_intcs_cascade); + +/* IRQ pins require special handling through INTCA and GIC */ +for (k =0 ; k <32 ; k++) { + sh73a0_irq_pin_cascade[k].name ="INTCA-GIC cascade" ; + sh73a0_irq_pin_cascade[k].handler = sh73a0_irq_pin_demux; +setup_irq (gic_spi (1 + k), &sh73a0_irq_pin_cascade[k]); + + n =intcs_evt2irq (to_intc_vect (gic_spi (1 + k))); +irq_set_chip_and_handler_name (n, &intca_gic_irq_chip, + handle_level_irq,"level" ); +set_irq_flags (n,IRQF_VALID );/* yuck */ + } }
arch/arm/mach-shmobile/pfc-sh73a0.c +35 -33
76 lines not on this page · raw message