arm: msm: Convert sirc to generic irq chip
Abhijeet Dharmapurikar
adharmap at codeaurora.org
Thu Apr 21 11:13:31 EDT 2011
On 04/16/2011 02:14 PM, Thomas Gleixner wrote:
> Signed-off-by: Thomas Gleixner<tglx at linutronix.de>
> ---
> arch/arm/mach-msm/include/mach/sirc.h | 43 +++-----
> arch/arm/mach-msm/sirc.c | 166 ++++++++++------------------------
> 2 files changed, 68 insertions(+), 141 deletions(-)
>
> Index: linux-2.6/arch/arm/mach-msm/include/mach/sirc.h
> ===================================================================
> --- linux-2.6.orig/arch/arm/mach-msm/include/mach/sirc.h
> +++ linux-2.6/arch/arm/mach-msm/include/mach/sirc.h
> @@ -13,18 +13,13 @@
> #ifndef __ASM_ARCH_MSM_SIRC_H
> #define __ASM_ARCH_MSM_SIRC_H
>
> -struct sirc_regs_t {
> - void *int_enable;
> - void *int_enable_clear;
> - void *int_enable_set;
> - void *int_type;
> - void *int_polarity;
> - void *int_clear;
> -};
> -
> struct sirc_cascade_regs {
> - void *int_status;
> - unsigned int cascade_irq;
> + void __iomem *reg_base;
> + unsigned long int_status;
> + u32 status_mask;
> + unsigned int irq_base;
> + unsigned int irq_cnt;
> + unsigned int cascade_irq;
> };
>
> void msm_init_sirc(void);
> @@ -78,20 +73,18 @@ void msm_sirc_exit_sleep(void);
> #define SIRC_MASK 0x007FFFFF
> #endif
>
> -#define LAST_SIRC_IRQ (FIRST_SIRC_IRQ + NR_SIRC_IRQS - 1)
> -
> -#define SPSS_SIRC_INT_SELECT (MSM_SIRC_BASE + 0x00)
> -#define SPSS_SIRC_INT_ENABLE (MSM_SIRC_BASE + 0x04)
> -#define SPSS_SIRC_INT_ENABLE_CLEAR (MSM_SIRC_BASE + 0x08)
> -#define SPSS_SIRC_INT_ENABLE_SET (MSM_SIRC_BASE + 0x0C)
> -#define SPSS_SIRC_INT_TYPE (MSM_SIRC_BASE + 0x10)
> -#define SPSS_SIRC_INT_POLARITY (MSM_SIRC_BASE + 0x14)
> -#define SPSS_SIRC_SECURITY (MSM_SIRC_BASE + 0x18)
> -#define SPSS_SIRC_IRQ_STATUS (MSM_SIRC_BASE + 0x1C)
> -#define SPSS_SIRC_IRQ1_STATUS (MSM_SIRC_BASE + 0x20)
> -#define SPSS_SIRC_RAW_STATUS (MSM_SIRC_BASE + 0x24)
> -#define SPSS_SIRC_INT_CLEAR (MSM_SIRC_BASE + 0x28)
> -#define SPSS_SIRC_SOFT_INT (MSM_SIRC_BASE + 0x2C)
> +#define SPSS_SIRC_INT_SELECT 0x00
> +#define SPSS_SIRC_INT_ENABLE 0x04
> +#define SPSS_SIRC_INT_ENABLE_CLEAR 0x08
> +#define SPSS_SIRC_INT_ENABLE_SET 0x0C
> +#define SPSS_SIRC_INT_TYPE 0x10
> +#define SPSS_SIRC_INT_POLARITY 0x14
> +#define SPSS_SIRC_SECURITY 0x18
> +#define SPSS_SIRC_IRQ_STATUS 0x1C
> +#define SPSS_SIRC_IRQ1_STATUS 0x20
> +#define SPSS_SIRC_RAW_STATUS 0x24
> +#define SPSS_SIRC_INT_CLEAR 0x28
> +#define SPSS_SIRC_SOFT_INT 0x2C
>
> #endif
>
> Index: linux-2.6/arch/arm/mach-msm/sirc.c
> ===================================================================
> --- linux-2.6.orig/arch/arm/mach-msm/sirc.c
> +++ linux-2.6/arch/arm/mach-msm/sirc.c
> @@ -15,158 +15,92 @@
> * 02110-1301, USA.
> *
> */
> -
> -#include<linux/io.h>
> -#include<linux/irq.h>
> #include<linux/interrupt.h>
> -#include<asm/irq.h>
> -
> -static unsigned int int_enable;
> -static unsigned int wake_enable;
> +#include<linux/irq.h>
> +#include<linux/io.h>
>
> -static struct sirc_regs_t sirc_regs = {
> - .int_enable = SPSS_SIRC_INT_ENABLE,
> - .int_enable_clear = SPSS_SIRC_INT_ENABLE_CLEAR,
> - .int_enable_set = SPSS_SIRC_INT_ENABLE_SET,
> - .int_type = SPSS_SIRC_INT_TYPE,
> - .int_polarity = SPSS_SIRC_INT_POLARITY,
> - .int_clear = SPSS_SIRC_INT_CLEAR,
> -};
> +#include<asm/irq.h>
>
> static struct sirc_cascade_regs sirc_reg_table[] = {
> {
> + .reg_base = MSM_SIRC_BASE,
> .int_status = SPSS_SIRC_IRQ_STATUS,
> + .status_mask = SIRC_MASK,
> + .irq_base = FIRST_SIRC_IRQ,
> + .irq_cnt = NR_SIRC_IRQS,
> .cascade_irq = INT_SIRC_0,
> }
> };
>
> -/* Mask off the given interrupt. Keep the int_enable mask in sync with
> - the enable reg, so it can be restored after power collapse. */
> -static void sirc_irq_mask(struct irq_data *d)
> -{
> - unsigned int mask;
> -
> - mask = 1<< (d->irq - FIRST_SIRC_IRQ);
> - writel(mask, sirc_regs.int_enable_clear);
> - int_enable&= ~mask;
> - return;
> -}
> -
> -/* Unmask the given interrupt. Keep the int_enable mask in sync with
> - the enable reg, so it can be restored after power collapse. */
> -static void sirc_irq_unmask(struct irq_data *d)
> -{
> - unsigned int mask;
> -
> - mask = 1<< (d->irq - FIRST_SIRC_IRQ);
> - writel(mask, sirc_regs.int_enable_set);
> - int_enable |= mask;
> - return;
> -}
> -
> -static void sirc_irq_ack(struct irq_data *d)
> -{
> - unsigned int mask;
> -
> - mask = 1<< (d->irq - FIRST_SIRC_IRQ);
> - writel(mask, sirc_regs.int_clear);
> - return;
> -}
> -
> -static int sirc_irq_set_wake(struct irq_data *d, unsigned int on)
> -{
> - unsigned int mask;
> -
> - /* Used to set the interrupt enable mask during power collapse. */
> - mask = 1<< (d->irq - FIRST_SIRC_IRQ);
> - if (on)
> - wake_enable |= mask;
> - else
> - wake_enable&= ~mask;
> -
> - return 0;
> -}
> -
> static int sirc_irq_set_type(struct irq_data *d, unsigned int flow_type)
> {
> - unsigned int mask;
> - unsigned int val;
> -
> - mask = 1<< (d->irq - FIRST_SIRC_IRQ);
> - val = readl(sirc_regs.int_polarity);
> + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
> + u32 mask = 1<< (d->irq - gc->irq_base);
>
> if (flow_type& (IRQF_TRIGGER_LOW | IRQF_TRIGGER_FALLING))
> - val |= mask;
> + gc->polarity_cache |= mask;
> else
> - val&= ~mask;
> -
> - writel(val, sirc_regs.int_polarity);
> + gc->polarity_cache&= ~mask;
> + writel(gc->polarity_cache, gc->reg_base + gc->chip_types->regs.type);
>
> - val = readl(sirc_regs.int_type);
> if (flow_type& (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
> - val |= mask;
> + gc->type_cache |= mask;
> __irq_set_handler_locked(d->irq, handle_edge_irq);
> } else {
> - val&= ~mask;
> + gc->type_cache&= ~mask;
> __irq_set_handler_locked(d->irq, handle_level_irq);
> }
> -
> - writel(val, sirc_regs.int_type);
> -
> + writel(gc->type_cache, gc->reg_base + gc->chip_types->regs.polarity);
> return 0;
> }
>
> /* Finds the pending interrupt on the passed cascade irq and redrives it */
> static void sirc_irq_handler(unsigned int irq, struct irq_desc *desc)
> {
> - unsigned int reg = 0;
> - unsigned int sirq;
> - unsigned int status;
> -
> - while ((reg< ARRAY_SIZE(sirc_reg_table))&&
> - (sirc_reg_table[reg].cascade_irq != irq))
> - reg++;
> -
> - status = readl(sirc_reg_table[reg].int_status);
> - status&= SIRC_MASK;
> - if (status == 0)
> + struct sirc_cascade_regs *cr = irq_desc_get_handler_data(desc);
> + u32 status;
> +
> + status = readl(cr->reg_base + cr->int_status);
> + status&= cr->status_mask;
> + if (!status)
> return;
>
> - for (sirq = 0;
> - (sirq< NR_SIRC_IRQS)&& ((status& (1U<< sirq)) == 0);
> - sirq++)
> - ;
> - generic_handle_irq(sirq+FIRST_SIRC_IRQ);
> + generic_handle_irq(cr->irq_base + __ffs(status));
>
> desc->irq_data.chip->irq_ack(&desc->irq_data);
> }
>
> -static struct irq_chip sirc_irq_chip = {
> - .name = "sirc",
> - .irq_ack = sirc_irq_ack,
> - .irq_mask = sirc_irq_mask,
> - .irq_unmask = sirc_irq_unmask,
> - .irq_set_wake = sirc_irq_set_wake,
> - .irq_set_type = sirc_irq_set_type,
> -};
> +static void msm_init_one_sirc(struct sirc_cascade_regs *cr)
> +{
> + struct irq_chip_generic *gc;
> + struct irq_chip_type *ct;
> +
> + gc = irq_alloc_generic_chip("sirc", 1, cr->irq_base, cr->reg_base,
> + handle_level_irq);
> + ct = gc->chip_types;
> + ct->chip.irq_ack = irq_gc_ack;
> + ct->chip.irq_mask = irq_gc_mask_disable_reg;
> + ct->chip.irq_unmask = irq_gc_unmask_enable_reg;
> + ct->chip.irq_set_wake = irq_gc_set_wake;
> + ct->chip.irq_set_type = sirc_irq_set_type;
> + ct->regs.ack = SPSS_SIRC_INT_CLEAR;
> + ct->regs.disable = SPSS_SIRC_INT_ENABLE_CLEAR;
> + ct->regs.enable = SPSS_SIRC_INT_ENABLE_SET;
> + ct->regs.type = SPSS_SIRC_INT_TYPE;
> + ct->regs.polarity = SPSS_SIRC_INT_POLARITY;
> +
> + irq_setup_generic_chip(gc, IRQ_MSK(sirc->irq_cnt),
> + IRQ_NOREQUEST | IRQ_NOPROBE, 0);
> +
> + irq_set_chained_handler(cr->cascade_irq, sirc_irq_handler);
> + irq_set_handler_data(cr->cascade_irq, cr);
> + irq_set_irq_wake(cr->cascade_irq, 1);
> +}
>
> void __init msm_init_sirc(void)
> {
> int i;
>
> - int_enable = 0;
> - wake_enable = 0;
> -
> - for (i = FIRST_SIRC_IRQ; i< LAST_SIRC_IRQ; i++) {
> - irq_set_chip_and_handler(i,&sirc_irq_chip, handle_edge_irq);
> - set_irq_flags(i, IRQF_VALID);
> - }
> -
> - for (i = 0; i< ARRAY_SIZE(sirc_reg_table); i++) {
> - irq_set_chained_handler(sirc_reg_table[i].cascade_irq,
> - sirc_irq_handler);
> - irq_set_irq_wake(sirc_reg_table[i].cascade_irq, 1);
> - }
> - return;
> + for (i = 0; i< ARRAY_SIZE(sirc_reg_table); i++)
> + msm_init_one_sirc(sirc_reg_table + i);
> }
This looks good to me. Thanks a ton for cleaning it up.
Abhijeet
--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
More information about the linux-arm-kernel
mailing list