diff options
Diffstat (limited to 'arch/sh/kernel/cpu/irq/ipr.c')
| -rw-r--r-- | arch/sh/kernel/cpu/irq/ipr.c | 154 |
1 files changed, 45 insertions, 109 deletions
diff --git a/arch/sh/kernel/cpu/irq/ipr.c b/arch/sh/kernel/cpu/irq/ipr.c index a0089563cbf..5de6dff5c21 100644 --- a/arch/sh/kernel/cpu/irq/ipr.c +++ b/arch/sh/kernel/cpu/irq/ipr.c @@ -8,7 +8,7 @@ * * Supported system: * On-chip supporting modules (TMU, RTC, etc.). - * On-chip supporting modules for SH7709/SH7709A/SH7729/SH7300. + * On-chip supporting modules for SH7709/SH7709A/SH7729. * Hitachi SolutionEngine external I/O: * MS7709SE01, MS7709ASE01, and MS7750SE01 * @@ -17,131 +17,67 @@ * for more details. */ #include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/io.h> #include <linux/irq.h> +#include <linux/kernel.h> #include <linux/module.h> -#include <asm/system.h> -#include <asm/io.h> -#include <asm/machvec.h> +#include <linux/topology.h> +static inline struct ipr_desc *get_ipr_desc(struct irq_data *data) +{ + struct irq_chip *chip = irq_data_get_irq_chip(data); + return container_of(chip, struct ipr_desc, chip); +} -static void disable_ipr_irq(unsigned int irq) +static void disable_ipr_irq(struct irq_data *data) { - struct ipr_data *p = get_irq_chip_data(irq); - int shift = p->shift*4; + struct ipr_data *p = irq_data_get_irq_chip_data(data); + unsigned long addr = get_ipr_desc(data)->ipr_offsets[p->ipr_idx]; /* Set the priority in IPR to 0 */ - ctrl_outw(ctrl_inw(p->addr) & (0xffff ^ (0xf << shift)), p->addr); + __raw_writew(__raw_readw(addr) & (0xffff ^ (0xf << p->shift)), addr); + (void)__raw_readw(addr); /* Read back to flush write posting */ } -static void enable_ipr_irq(unsigned int irq) +static void enable_ipr_irq(struct irq_data *data) { - struct ipr_data *p = get_irq_chip_data(irq); - int shift = p->shift*4; + struct ipr_data *p = irq_data_get_irq_chip_data(data); + unsigned long addr = get_ipr_desc(data)->ipr_offsets[p->ipr_idx]; /* Set priority in IPR back to original value */ - ctrl_outw(ctrl_inw(p->addr) | (p->priority << shift), p->addr); + __raw_writew(__raw_readw(addr) | (p->priority << p->shift), addr); } -static struct irq_chip ipr_irq_chip = { - .name = "IPR", - .mask = disable_ipr_irq, - .unmask = enable_ipr_irq, - .mask_ack = disable_ipr_irq, -}; - -void make_ipr_irq(struct ipr_data *table, unsigned int nr_irqs) +/* + * The shift value is now the number of bits to shift, not the number of + * bits/4. This is to make it easier to read the value directly from the + * datasheets. The IPR address is calculated using the ipr_offset table. + */ +void register_ipr_controller(struct ipr_desc *desc) { int i; - for (i = 0; i < nr_irqs; i++) { - unsigned int irq = table[i].irq; - disable_irq_nosync(irq); - set_irq_chip_and_handler_name(irq, &ipr_irq_chip, - handle_level_irq, "level"); - set_irq_chip_data(irq, &table[i]); - enable_ipr_irq(irq); - } -} -EXPORT_SYMBOL(make_ipr_irq); - -static struct ipr_data sys_ipr_map[] = { -#ifndef CONFIG_CPU_SUBTYPE_SH7780 - { TIMER_IRQ, TIMER_IPR_ADDR, TIMER_IPR_POS, TIMER_PRIORITY }, - { TIMER1_IRQ, TIMER1_IPR_ADDR, TIMER1_IPR_POS, TIMER1_PRIORITY }, -#ifdef RTC_IRQ - { RTC_IRQ, RTC_IPR_ADDR, RTC_IPR_POS, RTC_PRIORITY }, -#endif -#ifdef SCI_ERI_IRQ - { SCI_ERI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY }, - { SCI_RXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY }, - { SCI_TXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY }, -#endif -#ifdef SCIF1_ERI_IRQ - { SCIF1_ERI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY }, - { SCIF1_RXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY }, - { SCIF1_BRI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY }, - { SCIF1_TXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY }, -#endif -#if defined(CONFIG_CPU_SUBTYPE_SH7300) - { SCIF0_IRQ, SCIF0_IPR_ADDR, SCIF0_IPR_POS, SCIF0_PRIORITY }, - { DMTE2_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY }, - { DMTE3_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY }, - { VIO_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY }, -#endif -#ifdef SCIF_ERI_IRQ - { SCIF_ERI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY }, - { SCIF_RXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY }, - { SCIF_BRI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY }, - { SCIF_TXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY }, -#endif -#ifdef IRDA_ERI_IRQ - { IRDA_ERI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY }, - { IRDA_RXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY }, - { IRDA_BRI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY }, - { IRDA_TXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY }, -#endif -#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) || \ - defined(CONFIG_CPU_SUBTYPE_SH7706) || \ - defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705) - /* - * Initialize the Interrupt Controller (INTC) - * registers to their power on values - */ - - /* - * Enable external irq (INTC IRQ mode). - * You should set corresponding bits of PFC to "00" - * to enable these interrupts. - */ - { IRQ0_IRQ, IRQ0_IPR_ADDR, IRQ0_IPR_POS, IRQ0_PRIORITY }, - { IRQ1_IRQ, IRQ1_IPR_ADDR, IRQ1_IPR_POS, IRQ1_PRIORITY }, - { IRQ2_IRQ, IRQ2_IPR_ADDR, IRQ2_IPR_POS, IRQ2_PRIORITY }, - { IRQ3_IRQ, IRQ3_IPR_ADDR, IRQ3_IPR_POS, IRQ3_PRIORITY }, - { IRQ4_IRQ, IRQ4_IPR_ADDR, IRQ4_IPR_POS, IRQ4_PRIORITY }, - { IRQ5_IRQ, IRQ5_IPR_ADDR, IRQ5_IPR_POS, IRQ5_PRIORITY }, -#endif -#endif -}; + desc->chip.irq_mask = disable_ipr_irq; + desc->chip.irq_unmask = enable_ipr_irq; -void __init init_IRQ(void) -{ - make_ipr_irq(sys_ipr_map, ARRAY_SIZE(sys_ipr_map)); + for (i = 0; i < desc->nr_irqs; i++) { + struct ipr_data *p = desc->ipr_data + i; + int res; -#ifdef CONFIG_CPU_HAS_PINT_IRQ - init_IRQ_pint(); -#endif + BUG_ON(p->ipr_idx >= desc->nr_offsets); + BUG_ON(!desc->ipr_offsets[p->ipr_idx]); -#ifdef CONFIG_CPU_HAS_INTC2_IRQ - init_IRQ_intc2(); -#endif - /* Perform the machine specific initialisation */ - if (sh_mv.mv_init_irq != NULL) - sh_mv.mv_init_irq(); + res = irq_alloc_desc_at(p->irq, numa_node_id()); + if (unlikely(res != p->irq && res != -EEXIST)) { + printk(KERN_INFO "can not get irq_desc for %d\n", + p->irq); + continue; + } - irq_ctx_init(smp_processor_id()); -} - -#if !defined(CONFIG_CPU_HAS_PINT_IRQ) -int ipr_irq_demux(int irq) -{ - return irq; + disable_irq_nosync(p->irq); + irq_set_chip_and_handler_name(p->irq, &desc->chip, + handle_level_irq, "level"); + irq_set_chip_data(p->irq, p); + disable_ipr_irq(irq_get_irq_data(p->irq)); + } } -#endif +EXPORT_SYMBOL(register_ipr_controller); |
