X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=arch%2Fmips%2Fbcm63xx%2Firq.c;h=f467e447bb0e42cf387acccd00ce686da4ef3e89;hb=3534b5ce0547790429d40b19bb444e099f6ba1cf;hp=1525f8a3841b946889d6553ca799d2550afb8f10;hpb=b409624ad5a99c2e84df6657bd0f7931ac470d2d;p=deliverable%2Flinux.git diff --git a/arch/mips/bcm63xx/irq.c b/arch/mips/bcm63xx/irq.c index 1525f8a3841b..f467e447bb0e 100644 --- a/arch/mips/bcm63xx/irq.c +++ b/arch/mips/bcm63xx/irq.c @@ -19,122 +19,8 @@ #include #include -static void __dispatch_internal(void) __maybe_unused; -static void __dispatch_internal_64(void) __maybe_unused; -static void __internal_irq_mask_32(unsigned int irq) __maybe_unused; -static void __internal_irq_mask_64(unsigned int irq) __maybe_unused; -static void __internal_irq_unmask_32(unsigned int irq) __maybe_unused; -static void __internal_irq_unmask_64(unsigned int irq) __maybe_unused; - -#ifndef BCMCPU_RUNTIME_DETECT -#ifdef CONFIG_BCM63XX_CPU_3368 -#define irq_stat_reg PERF_IRQSTAT_3368_REG -#define irq_mask_reg PERF_IRQMASK_3368_REG -#define irq_bits 32 -#define is_ext_irq_cascaded 0 -#define ext_irq_start 0 -#define ext_irq_end 0 -#define ext_irq_count 4 -#define ext_irq_cfg_reg1 PERF_EXTIRQ_CFG_REG_3368 -#define ext_irq_cfg_reg2 0 -#endif -#ifdef CONFIG_BCM63XX_CPU_6328 -#define irq_stat_reg PERF_IRQSTAT_6328_REG -#define irq_mask_reg PERF_IRQMASK_6328_REG -#define irq_bits 64 -#define is_ext_irq_cascaded 1 -#define ext_irq_start (BCM_6328_EXT_IRQ0 - IRQ_INTERNAL_BASE) -#define ext_irq_end (BCM_6328_EXT_IRQ3 - IRQ_INTERNAL_BASE) -#define ext_irq_count 4 -#define ext_irq_cfg_reg1 PERF_EXTIRQ_CFG_REG_6328 -#define ext_irq_cfg_reg2 0 -#endif -#ifdef CONFIG_BCM63XX_CPU_6338 -#define irq_stat_reg PERF_IRQSTAT_6338_REG -#define irq_mask_reg PERF_IRQMASK_6338_REG -#define irq_bits 32 -#define is_ext_irq_cascaded 0 -#define ext_irq_start 0 -#define ext_irq_end 0 -#define ext_irq_count 4 -#define ext_irq_cfg_reg1 PERF_EXTIRQ_CFG_REG_6338 -#define ext_irq_cfg_reg2 0 -#endif -#ifdef CONFIG_BCM63XX_CPU_6345 -#define irq_stat_reg PERF_IRQSTAT_6345_REG -#define irq_mask_reg PERF_IRQMASK_6345_REG -#define irq_bits 32 -#define is_ext_irq_cascaded 0 -#define ext_irq_start 0 -#define ext_irq_end 0 -#define ext_irq_count 4 -#define ext_irq_cfg_reg1 PERF_EXTIRQ_CFG_REG_6345 -#define ext_irq_cfg_reg2 0 -#endif -#ifdef CONFIG_BCM63XX_CPU_6348 -#define irq_stat_reg PERF_IRQSTAT_6348_REG -#define irq_mask_reg PERF_IRQMASK_6348_REG -#define irq_bits 32 -#define is_ext_irq_cascaded 0 -#define ext_irq_start 0 -#define ext_irq_end 0 -#define ext_irq_count 4 -#define ext_irq_cfg_reg1 PERF_EXTIRQ_CFG_REG_6348 -#define ext_irq_cfg_reg2 0 -#endif -#ifdef CONFIG_BCM63XX_CPU_6358 -#define irq_stat_reg PERF_IRQSTAT_6358_REG -#define irq_mask_reg PERF_IRQMASK_6358_REG -#define irq_bits 32 -#define is_ext_irq_cascaded 1 -#define ext_irq_start (BCM_6358_EXT_IRQ0 - IRQ_INTERNAL_BASE) -#define ext_irq_end (BCM_6358_EXT_IRQ3 - IRQ_INTERNAL_BASE) -#define ext_irq_count 4 -#define ext_irq_cfg_reg1 PERF_EXTIRQ_CFG_REG_6358 -#define ext_irq_cfg_reg2 0 -#endif -#ifdef CONFIG_BCM63XX_CPU_6362 -#define irq_stat_reg PERF_IRQSTAT_6362_REG -#define irq_mask_reg PERF_IRQMASK_6362_REG -#define irq_bits 64 -#define is_ext_irq_cascaded 1 -#define ext_irq_start (BCM_6362_EXT_IRQ0 - IRQ_INTERNAL_BASE) -#define ext_irq_end (BCM_6362_EXT_IRQ3 - IRQ_INTERNAL_BASE) -#define ext_irq_count 4 -#define ext_irq_cfg_reg1 PERF_EXTIRQ_CFG_REG_6362 -#define ext_irq_cfg_reg2 0 -#endif -#ifdef CONFIG_BCM63XX_CPU_6368 -#define irq_stat_reg PERF_IRQSTAT_6368_REG -#define irq_mask_reg PERF_IRQMASK_6368_REG -#define irq_bits 64 -#define is_ext_irq_cascaded 1 -#define ext_irq_start (BCM_6368_EXT_IRQ0 - IRQ_INTERNAL_BASE) -#define ext_irq_end (BCM_6368_EXT_IRQ5 - IRQ_INTERNAL_BASE) -#define ext_irq_count 6 -#define ext_irq_cfg_reg1 PERF_EXTIRQ_CFG_REG_6368 -#define ext_irq_cfg_reg2 PERF_EXTIRQ_CFG_REG2_6368 -#endif - -#if irq_bits == 32 -#define dispatch_internal __dispatch_internal -#define internal_irq_mask __internal_irq_mask_32 -#define internal_irq_unmask __internal_irq_unmask_32 -#else -#define dispatch_internal __dispatch_internal_64 -#define internal_irq_mask __internal_irq_mask_64 -#define internal_irq_unmask __internal_irq_unmask_64 -#endif - -#define irq_stat_addr (bcm63xx_regset_address(RSET_PERF) + irq_stat_reg) -#define irq_mask_addr (bcm63xx_regset_address(RSET_PERF) + irq_mask_reg) - -static inline void bcm63xx_init_irq(void) -{ -} -#else /* ! BCMCPU_RUNTIME_DETECT */ - -static u32 irq_stat_addr, irq_mask_addr; +static u32 irq_stat_addr[2]; +static u32 irq_mask_addr[2]; static void (*dispatch_internal)(void); static int is_ext_irq_cascaded; static unsigned int ext_irq_count; @@ -143,98 +29,6 @@ static unsigned int ext_irq_cfg_reg1, ext_irq_cfg_reg2; static void (*internal_irq_mask)(unsigned int irq); static void (*internal_irq_unmask)(unsigned int irq); -static void bcm63xx_init_irq(void) -{ - int irq_bits; - - irq_stat_addr = bcm63xx_regset_address(RSET_PERF); - irq_mask_addr = bcm63xx_regset_address(RSET_PERF); - - switch (bcm63xx_get_cpu_id()) { - case BCM3368_CPU_ID: - irq_stat_addr += PERF_IRQSTAT_3368_REG; - irq_mask_addr += PERF_IRQMASK_3368_REG; - irq_bits = 32; - ext_irq_count = 4; - ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_3368; - break; - case BCM6328_CPU_ID: - irq_stat_addr += PERF_IRQSTAT_6328_REG; - irq_mask_addr += PERF_IRQMASK_6328_REG; - irq_bits = 64; - ext_irq_count = 4; - is_ext_irq_cascaded = 1; - ext_irq_start = BCM_6328_EXT_IRQ0 - IRQ_INTERNAL_BASE; - ext_irq_end = BCM_6328_EXT_IRQ3 - IRQ_INTERNAL_BASE; - ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6328; - break; - case BCM6338_CPU_ID: - irq_stat_addr += PERF_IRQSTAT_6338_REG; - irq_mask_addr += PERF_IRQMASK_6338_REG; - irq_bits = 32; - ext_irq_count = 4; - ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6338; - break; - case BCM6345_CPU_ID: - irq_stat_addr += PERF_IRQSTAT_6345_REG; - irq_mask_addr += PERF_IRQMASK_6345_REG; - irq_bits = 32; - ext_irq_count = 4; - ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6345; - break; - case BCM6348_CPU_ID: - irq_stat_addr += PERF_IRQSTAT_6348_REG; - irq_mask_addr += PERF_IRQMASK_6348_REG; - irq_bits = 32; - ext_irq_count = 4; - ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6348; - break; - case BCM6358_CPU_ID: - irq_stat_addr += PERF_IRQSTAT_6358_REG; - irq_mask_addr += PERF_IRQMASK_6358_REG; - irq_bits = 32; - ext_irq_count = 4; - is_ext_irq_cascaded = 1; - ext_irq_start = BCM_6358_EXT_IRQ0 - IRQ_INTERNAL_BASE; - ext_irq_end = BCM_6358_EXT_IRQ3 - IRQ_INTERNAL_BASE; - ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6358; - break; - case BCM6362_CPU_ID: - irq_stat_addr += PERF_IRQSTAT_6362_REG; - irq_mask_addr += PERF_IRQMASK_6362_REG; - irq_bits = 64; - ext_irq_count = 4; - is_ext_irq_cascaded = 1; - ext_irq_start = BCM_6362_EXT_IRQ0 - IRQ_INTERNAL_BASE; - ext_irq_end = BCM_6362_EXT_IRQ3 - IRQ_INTERNAL_BASE; - ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6362; - break; - case BCM6368_CPU_ID: - irq_stat_addr += PERF_IRQSTAT_6368_REG; - irq_mask_addr += PERF_IRQMASK_6368_REG; - irq_bits = 64; - ext_irq_count = 6; - is_ext_irq_cascaded = 1; - ext_irq_start = BCM_6368_EXT_IRQ0 - IRQ_INTERNAL_BASE; - ext_irq_end = BCM_6368_EXT_IRQ5 - IRQ_INTERNAL_BASE; - ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6368; - ext_irq_cfg_reg2 = PERF_EXTIRQ_CFG_REG2_6368; - break; - default: - BUG(); - } - - if (irq_bits == 32) { - dispatch_internal = __dispatch_internal; - internal_irq_mask = __internal_irq_mask_32; - internal_irq_unmask = __internal_irq_unmask_32; - } else { - dispatch_internal = __dispatch_internal_64; - internal_irq_mask = __internal_irq_mask_64; - internal_irq_unmask = __internal_irq_unmask_64; - } -} -#endif /* ! BCMCPU_RUNTIME_DETECT */ static inline u32 get_ext_irq_perf_reg(int irq) { @@ -258,47 +52,65 @@ static inline void handle_internal(int intbit) * will resume the loop where it ended the last time we left this * function. */ -static void __dispatch_internal(void) -{ - u32 pending; - static int i; - - pending = bcm_readl(irq_stat_addr) & bcm_readl(irq_mask_addr); - - if (!pending) - return ; - - while (1) { - int to_call = i; - i = (i + 1) & 0x1f; - if (pending & (1 << to_call)) { - handle_internal(to_call); - break; - } - } +#define BUILD_IPIC_INTERNAL(width) \ +void __dispatch_internal_##width(void) \ +{ \ + u32 pending[width / 32]; \ + unsigned int src, tgt; \ + bool irqs_pending = false; \ + static unsigned int i; \ + \ + /* read registers in reverse order */ \ + for (src = 0, tgt = (width / 32); src < (width / 32); src++) { \ + u32 val; \ + \ + val = bcm_readl(irq_stat_addr[0] + src * sizeof(u32)); \ + val &= bcm_readl(irq_mask_addr[0] + src * sizeof(u32)); \ + pending[--tgt] = val; \ + \ + if (val) \ + irqs_pending = true; \ + } \ + \ + if (!irqs_pending) \ + return; \ + \ + while (1) { \ + unsigned int to_call = i; \ + \ + i = (i + 1) & (width - 1); \ + if (pending[to_call / 32] & (1 << (to_call & 0x1f))) { \ + handle_internal(to_call); \ + break; \ + } \ + } \ +} \ + \ +static void __internal_irq_mask_##width(unsigned int irq) \ +{ \ + u32 val; \ + unsigned reg = (irq / 32) ^ (width/32 - 1); \ + unsigned bit = irq & 0x1f; \ + \ + val = bcm_readl(irq_mask_addr[0] + reg * sizeof(u32)); \ + val &= ~(1 << bit); \ + bcm_writel(val, irq_mask_addr[0] + reg * sizeof(u32)); \ +} \ + \ +static void __internal_irq_unmask_##width(unsigned int irq) \ +{ \ + u32 val; \ + unsigned reg = (irq / 32) ^ (width/32 - 1); \ + unsigned bit = irq & 0x1f; \ + \ + val = bcm_readl(irq_mask_addr[0] + reg * sizeof(u32)); \ + val |= (1 << bit); \ + bcm_writel(val, irq_mask_addr[0] + reg * sizeof(u32)); \ } -static void __dispatch_internal_64(void) -{ - u64 pending; - static int i; - - pending = bcm_readq(irq_stat_addr) & bcm_readq(irq_mask_addr); - - if (!pending) - return ; - - while (1) { - int to_call = i; - - i = (i + 1) & 0x3f; - if (pending & (1ull << to_call)) { - handle_internal(to_call); - break; - } - } -} +BUILD_IPIC_INTERNAL(32); +BUILD_IPIC_INTERNAL(64); asmlinkage void plat_irq_dispatch(void) { @@ -335,42 +147,6 @@ asmlinkage void plat_irq_dispatch(void) * internal IRQs operations: only mask/unmask on PERF irq mask * register. */ -static void __internal_irq_mask_32(unsigned int irq) -{ - u32 mask; - - mask = bcm_readl(irq_mask_addr); - mask &= ~(1 << irq); - bcm_writel(mask, irq_mask_addr); -} - -static void __internal_irq_mask_64(unsigned int irq) -{ - u64 mask; - - mask = bcm_readq(irq_mask_addr); - mask &= ~(1ull << irq); - bcm_writeq(mask, irq_mask_addr); -} - -static void __internal_irq_unmask_32(unsigned int irq) -{ - u32 mask; - - mask = bcm_readl(irq_mask_addr); - mask |= (1 << irq); - bcm_writel(mask, irq_mask_addr); -} - -static void __internal_irq_unmask_64(unsigned int irq) -{ - u64 mask; - - mask = bcm_readq(irq_mask_addr); - mask |= (1ull << irq); - bcm_writeq(mask, irq_mask_addr); -} - static void bcm63xx_internal_irq_mask(struct irq_data *d) { internal_irq_mask(d->irq - IRQ_INTERNAL_BASE); @@ -560,6 +336,116 @@ static struct irqaction cpu_ext_cascade_action = { .flags = IRQF_NO_THREAD, }; +static void bcm63xx_init_irq(void) +{ + int irq_bits; + + irq_stat_addr[0] = bcm63xx_regset_address(RSET_PERF); + irq_mask_addr[0] = bcm63xx_regset_address(RSET_PERF); + irq_stat_addr[1] = bcm63xx_regset_address(RSET_PERF); + irq_mask_addr[1] = bcm63xx_regset_address(RSET_PERF); + + switch (bcm63xx_get_cpu_id()) { + case BCM3368_CPU_ID: + irq_stat_addr[0] += PERF_IRQSTAT_3368_REG; + irq_mask_addr[0] += PERF_IRQMASK_3368_REG; + irq_stat_addr[1] = 0; + irq_stat_addr[1] = 0; + irq_bits = 32; + ext_irq_count = 4; + ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_3368; + break; + case BCM6328_CPU_ID: + irq_stat_addr[0] += PERF_IRQSTAT_6328_REG(0); + irq_mask_addr[0] += PERF_IRQMASK_6328_REG(0); + irq_stat_addr[1] += PERF_IRQSTAT_6328_REG(1); + irq_stat_addr[1] += PERF_IRQMASK_6328_REG(1); + irq_bits = 64; + ext_irq_count = 4; + is_ext_irq_cascaded = 1; + ext_irq_start = BCM_6328_EXT_IRQ0 - IRQ_INTERNAL_BASE; + ext_irq_end = BCM_6328_EXT_IRQ3 - IRQ_INTERNAL_BASE; + ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6328; + break; + case BCM6338_CPU_ID: + irq_stat_addr[0] += PERF_IRQSTAT_6338_REG; + irq_mask_addr[0] += PERF_IRQMASK_6338_REG; + irq_stat_addr[1] = 0; + irq_mask_addr[1] = 0; + irq_bits = 32; + ext_irq_count = 4; + ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6338; + break; + case BCM6345_CPU_ID: + irq_stat_addr[0] += PERF_IRQSTAT_6345_REG; + irq_mask_addr[0] += PERF_IRQMASK_6345_REG; + irq_stat_addr[1] = 0; + irq_mask_addr[1] = 0; + irq_bits = 32; + ext_irq_count = 4; + ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6345; + break; + case BCM6348_CPU_ID: + irq_stat_addr[0] += PERF_IRQSTAT_6348_REG; + irq_mask_addr[0] += PERF_IRQMASK_6348_REG; + irq_stat_addr[1] = 0; + irq_mask_addr[1] = 0; + irq_bits = 32; + ext_irq_count = 4; + ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6348; + break; + case BCM6358_CPU_ID: + irq_stat_addr[0] += PERF_IRQSTAT_6358_REG(0); + irq_mask_addr[0] += PERF_IRQMASK_6358_REG(0); + irq_stat_addr[1] += PERF_IRQSTAT_6358_REG(1); + irq_mask_addr[1] += PERF_IRQMASK_6358_REG(1); + irq_bits = 32; + ext_irq_count = 4; + is_ext_irq_cascaded = 1; + ext_irq_start = BCM_6358_EXT_IRQ0 - IRQ_INTERNAL_BASE; + ext_irq_end = BCM_6358_EXT_IRQ3 - IRQ_INTERNAL_BASE; + ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6358; + break; + case BCM6362_CPU_ID: + irq_stat_addr[0] += PERF_IRQSTAT_6362_REG(0); + irq_mask_addr[0] += PERF_IRQMASK_6362_REG(0); + irq_stat_addr[1] += PERF_IRQSTAT_6362_REG(1); + irq_mask_addr[1] += PERF_IRQMASK_6362_REG(1); + irq_bits = 64; + ext_irq_count = 4; + is_ext_irq_cascaded = 1; + ext_irq_start = BCM_6362_EXT_IRQ0 - IRQ_INTERNAL_BASE; + ext_irq_end = BCM_6362_EXT_IRQ3 - IRQ_INTERNAL_BASE; + ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6362; + break; + case BCM6368_CPU_ID: + irq_stat_addr[0] += PERF_IRQSTAT_6368_REG(0); + irq_mask_addr[0] += PERF_IRQMASK_6368_REG(0); + irq_stat_addr[1] += PERF_IRQSTAT_6368_REG(1); + irq_mask_addr[1] += PERF_IRQMASK_6368_REG(1); + irq_bits = 64; + ext_irq_count = 6; + is_ext_irq_cascaded = 1; + ext_irq_start = BCM_6368_EXT_IRQ0 - IRQ_INTERNAL_BASE; + ext_irq_end = BCM_6368_EXT_IRQ5 - IRQ_INTERNAL_BASE; + ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6368; + ext_irq_cfg_reg2 = PERF_EXTIRQ_CFG_REG2_6368; + break; + default: + BUG(); + } + + if (irq_bits == 32) { + dispatch_internal = __dispatch_internal_32; + internal_irq_mask = __internal_irq_mask_32; + internal_irq_unmask = __internal_irq_unmask_32; + } else { + dispatch_internal = __dispatch_internal_64; + internal_irq_mask = __internal_irq_mask_64; + internal_irq_unmask = __internal_irq_unmask_64; + } +} + void __init arch_init_irq(void) { int i;