/* * The interrupt controller is setup such that it doesn't work well with * the level interrupt handler in the kernel because the handler acks the * interrupt before calling the application interrupt handler. To deal with * that, we use 2 different irq chips so that different functions can be * used for level and edge type interrupts. * * IRQ Chip common (across level and edge) operations */ static void xilinx_intc_mask(unsigned int virq) { int irq = virq_to_hw(virq); void * regs = get_irq_chip_data(virq); pr_debug("mask: %d\n", irq); out_be32(regs + XINTC_CIE, 1 << irq); }
static void adp5588_irq_unmask(unsigned int irq) { struct adp5588_gpio *dev = get_irq_chip_data(irq); unsigned gpio = irq - dev->irq_base; dev->irq_mask[ADP5588_BANK(gpio)] |= ADP5588_BIT(gpio); }
static void xilinx_intc_edge_ack(unsigned int virq) { int irq = virq_to_hw(virq); void * regs = get_irq_chip_data(virq); pr_debug("ack: %d\n", irq); out_be32(regs + XINTC_IAR, 1 << irq); }
static int set_type_ilc_irq(unsigned int irq, unsigned int flow_type) { struct ilc *ilc = get_irq_chip_data(irq); int input = irq - ilc->first_irq; int mode; switch (flow_type) { case IRQ_TYPE_EDGE_RISING: mode = ILC_TRIGGERMODE_RISING; break; case IRQ_TYPE_EDGE_FALLING: mode = ILC_TRIGGERMODE_FALLING; break; case IRQ_TYPE_EDGE_BOTH: mode = ILC_TRIGGERMODE_ANY; break; case IRQ_TYPE_LEVEL_HIGH: mode = ILC_TRIGGERMODE_HIGH; break; case IRQ_TYPE_LEVEL_LOW: mode = ILC_TRIGGERMODE_LOW; break; default: return -EINVAL; } ILC_SET_TRIGMODE(ilc->base, input, mode); ilc->irqs[input].trigger_mode = (unsigned char)mode; return 0; }
static void shutdown_ilc_irq(unsigned int irq) { struct ilc *ilc = get_irq_chip_data(irq); struct ilc_irq *ilc_irq; unsigned int priority; unsigned long flags; int input = irq - ilc->first_irq; DPRINTK("%s: irq %d\n", __func__, irq); WARN_ON(!ilc_is_used(&ilc->irqs[input])); if ((input < 0) || (input >= ilc->inputs_num)) return; ilc_irq = &ilc->irqs[input]; priority = ilc_irq->priority; ILC_CLR_ENABLE(ilc->base, input); ILC_SET_PRI(ilc->base, input, 0); spin_lock_irqsave(&ilc->lock, flags); ilc_set_disabled(ilc_irq); ilc_set_unused(ilc_irq); ilc->priority[priority][_BANK(input)] &= ~(_BIT(input)); spin_unlock_irqrestore(&ilc->lock, flags); }
static int adp5588_irq_set_type(unsigned int irq, unsigned int type) { struct adp5588_gpio *dev = get_irq_chip_data(irq); uint16_t gpio = irq - dev->irq_base; unsigned bank, bit; if ((type & IRQ_TYPE_EDGE_BOTH)) { dev_err(&dev->client->dev, "irq %d: unsupported type %d\n", irq, type); return -EINVAL; } bank = ADP5588_BANK(gpio); bit = ADP5588_BIT(gpio); if (type & IRQ_TYPE_LEVEL_HIGH) dev->int_lvl[bank] |= bit; else if (type & IRQ_TYPE_LEVEL_LOW) dev->int_lvl[bank] &= ~bit; else return -EINVAL; adp5588_gpio_direction_input(&dev->gpio_chip, gpio); adp5588_gpio_write(dev->client, GPIO_INT_LVL1 + bank, dev->int_lvl[bank]); return 0; }
static int vlynq_irq_type(unsigned int irq, unsigned int flow_type) { u32 val; struct vlynq_device *dev = get_irq_chip_data(irq); int virq; BUG_ON(!dev); virq = irq - dev->irq_start; val = readl(&dev->remote->int_device[virq >> 2]); switch (flow_type & IRQ_TYPE_SENSE_MASK) { case IRQ_TYPE_EDGE_RISING: case IRQ_TYPE_EDGE_FALLING: case IRQ_TYPE_EDGE_BOTH: val |= VINT_TYPE_EDGE << VINT_OFFSET(virq); val &= ~(VINT_LEVEL_LOW << VINT_OFFSET(virq)); break; case IRQ_TYPE_LEVEL_HIGH: val &= ~(VINT_TYPE_EDGE << VINT_OFFSET(virq)); val &= ~(VINT_LEVEL_LOW << VINT_OFFSET(virq)); break; case IRQ_TYPE_LEVEL_LOW: val &= ~(VINT_TYPE_EDGE << VINT_OFFSET(virq)); val |= VINT_LEVEL_LOW << VINT_OFFSET(virq); break; default: return -EINVAL; } writel(val, &dev->remote->int_device[virq >> 2]); return 0; }
static void flipper_pic_unmask(unsigned int virq) { int irq = virq_to_hw(virq); void __iomem *io_base = get_irq_chip_data(virq); setbits32(io_base + FLIPPER_IMR, 1 << irq); }
static void disable_ipr_irq(unsigned int irq) { struct ipr_data *p = get_irq_chip_data(irq); unsigned long addr = get_ipr_desc(irq)->ipr_offsets[p->ipr_idx]; /* Set the priority in IPR to 0 */ ctrl_outw(ctrl_inw(addr) & (0xffff ^ (0xf << p->shift)), addr); }
static void pcap_unmask_irq(unsigned int irq) { struct pcap_chip *pcap = get_irq_chip_data(irq); pcap->msr &= ~(1 << irq_to_pcap(pcap, irq)); queue_work(pcap->workqueue, &pcap->msr_work); }
static void nmk_gpio_irq_unmask(unsigned int irq) { int gpio; struct nmk_gpio_chip *nmk_chip; unsigned long flags; u32 bitmask, reg; gpio = NOMADIK_IRQ_TO_GPIO(irq); nmk_chip = get_irq_chip_data(irq); bitmask = nmk_gpio_get_bitmask(gpio); if (!nmk_chip) return; /* we must individually set the two edges */ spin_lock_irqsave(&nmk_chip->lock, flags); if (nmk_chip->edge_rising & bitmask) { reg = readl(nmk_chip->addr + NMK_GPIO_RWIMSC); reg |= bitmask; writel(reg, nmk_chip->addr + NMK_GPIO_RWIMSC); } if (nmk_chip->edge_falling & bitmask) { reg = readl(nmk_chip->addr + NMK_GPIO_FWIMSC); reg |= bitmask; writel(reg, nmk_chip->addr + NMK_GPIO_FWIMSC); } spin_unlock_irqrestore(&nmk_chip->lock, flags); }
static int msm_gpio_irq_set_type(unsigned int irq, unsigned int flow_type) { unsigned long irq_flags; struct msm_gpio_chip *msm_chip = get_irq_chip_data(irq); unsigned offset = irq - gpio_to_irq(msm_chip->chip.base); unsigned val, mask = BIT(offset); spin_lock_irqsave(&msm_chip->lock, irq_flags); val = __raw_readl(msm_chip->regs.int_edge); if (flow_type & IRQ_TYPE_EDGE_BOTH) { __raw_writel(val | mask, msm_chip->regs.int_edge); irq_desc[irq].handle_irq = handle_edge_irq; } else { __raw_writel(val & ~mask, msm_chip->regs.int_edge); irq_desc[irq].handle_irq = handle_level_irq; } if ((flow_type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) { msm_chip->both_edge_detect |= mask; msm_gpio_update_both_edge_detect(msm_chip); } else { msm_chip->both_edge_detect &= ~mask; val = __raw_readl(msm_chip->regs.int_pos); if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_HIGH)) __raw_writel(val | mask, msm_chip->regs.int_pos); else __raw_writel(val & ~mask, msm_chip->regs.int_pos); } mb(); spin_unlock_irqrestore(&msm_chip->lock, irq_flags); return 0; }
int ps3_irq_plug_setup(enum ps3_cpu_binding cpu, unsigned long outlet, unsigned int *virq) { int result; struct ps3_private *pd; result = ps3_virq_setup(cpu, outlet, virq); if (result) { pr_debug("%s:%d: ps3_virq_setup failed\n", __func__, __LINE__); goto fail_setup; } pd = get_irq_chip_data(*virq); /* Binds outlet to cpu + virq. */ result = lv1_connect_irq_plug_ext(pd->node, pd->cpu, *virq, outlet, 0); if (result) { pr_info("%s:%d: lv1_connect_irq_plug_ext failed: %s\n", __func__, __LINE__, ps3_result(result)); result = -EPERM; goto fail_connect; } return result; fail_connect: ps3_virq_destroy(*virq); fail_setup: return result; }
static void s5p_irq_vic_eint_unmask(unsigned int irq) { void __iomem *base = get_irq_chip_data(irq); s5p_irq_eint_unmask(irq); writel(1 << EINT_OFFSET(irq), base + VIC_INT_ENABLE); }
static void armctrl_unmask_irq(unsigned int irq) #endif { static const unsigned int enables[4] = { IO_ADDRESS(ARM_IRQ_ENBL1), IO_ADDRESS(ARM_IRQ_ENBL2), IO_ADDRESS(ARM_IRQ_ENBL3), 0 }; if(d->irq >= FIQ_START) { unsigned int data = (unsigned int)irq_get_chip_data(d->irq) - FIQ_START; writel(0x80 | data, __io(IO_ADDRESS(ARM_IRQ_FAST))); } else { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38) unsigned int data = (unsigned int)irq_get_chip_data(d->irq); #else unsigned int data = (unsigned int)get_irq_chip_data(irq); #endif writel(1 << (data & 0x1f), __io(enables[(data >> 5) & 0x3])); } }
static void max732x_irq_bus_sync_unlock(unsigned int irq) { struct max732x_chip *chip = get_irq_chip_data(irq); max732x_irq_update_mask(chip); mutex_unlock(&chip->irq_lock); }
static void max732x_irq_bus_lock(unsigned int irq) { struct max732x_chip *chip = get_irq_chip_data(irq); mutex_lock(&chip->irq_lock); chip->irq_mask_cur = chip->irq_mask; }
/* Mode functions */ int nmk_gpio_set_mode(int gpio, int gpio_mode) { struct nmk_gpio_chip *nmk_chip; unsigned long flags; u32 afunc, bfunc, bit; nmk_chip = get_irq_chip_data(NOMADIK_GPIO_TO_IRQ(gpio)); if (!nmk_chip) return -EINVAL; bit = 1 << (gpio - nmk_chip->chip.base); spin_lock_irqsave(&nmk_chip->lock, flags); afunc = readl(nmk_chip->addr + NMK_GPIO_AFSLA) & ~bit; bfunc = readl(nmk_chip->addr + NMK_GPIO_AFSLB) & ~bit; if (gpio_mode & NMK_GPIO_ALT_A) afunc |= bit; if (gpio_mode & NMK_GPIO_ALT_B) bfunc |= bit; writel(afunc, nmk_chip->addr + NMK_GPIO_AFSLA); writel(bfunc, nmk_chip->addr + NMK_GPIO_AFSLB); spin_unlock_irqrestore(&nmk_chip->lock, flags); return 0; }
static int max732x_irq_set_type(unsigned int irq, unsigned int type) { struct max732x_chip *chip = get_irq_chip_data(irq); uint16_t off = irq - chip->irq_base; uint16_t mask = 1 << off; if (!(mask & chip->dir_input)) { dev_dbg(&chip->client->dev, "%s port %d is output only\n", chip->client->name, off); return -EACCES; } if (!(type & IRQ_TYPE_EDGE_BOTH)) { dev_err(&chip->client->dev, "irq %d: unsupported type %d\n", irq, type); return -EINVAL; } if (type & IRQ_TYPE_EDGE_FALLING) chip->irq_trig_fall |= mask; else chip->irq_trig_fall &= ~mask; if (type & IRQ_TYPE_EDGE_RISING) chip->irq_trig_raise |= mask; else chip->irq_trig_raise &= ~mask; return max732x_gpio_direction_input(&chip->gpio_chip, off); }
static void enable_ipr_irq(unsigned int irq) { struct ipr_data *p = get_irq_chip_data(irq); unsigned long addr = get_ipr_desc(irq)->ipr_offsets[p->ipr_idx]; /* Set priority in IPR back to original value */ __raw_writew(__raw_readw(addr) | (p->priority << p->shift), addr); }
static int msm_gpio_irq_set_type(unsigned int irq, unsigned int flow_type) { unsigned long irq_flags; struct msm_gpio_dev *msm_gpio = get_irq_chip_data(irq); unsigned offset = irq - msm_gpio->irq_base; if ((flow_type & (IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING)) == (IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING)) return -ENOTSUPP; if ((flow_type & (IRQF_TRIGGER_HIGH | IRQF_TRIGGER_LOW)) == (IRQF_TRIGGER_HIGH | IRQF_TRIGGER_LOW)) return -ENOTSUPP; spin_lock_irqsave(&msm_gpio->lock, irq_flags); if (flow_type & (IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING)) { set_gpio_bit(offset, msm_gpio->regs.int_edge); irq_desc[irq].handle_irq = handle_edge_irq; } else { clr_gpio_bit(offset, msm_gpio->regs.int_edge); irq_desc[irq].handle_irq = handle_level_irq; } if (flow_type & (IRQF_TRIGGER_HIGH | IRQF_TRIGGER_RISING)) set_gpio_bit(offset, msm_gpio->regs.int_pos); else clr_gpio_bit(offset, msm_gpio->regs.int_pos); spin_unlock_irqrestore(&msm_gpio->lock, irq_flags); return 0; }
static void disable_ipr_irq(unsigned int irq) { struct ipr_data *p = get_irq_chip_data(irq); unsigned long addr = get_ipr_desc(irq)->ipr_offsets[p->ipr_idx]; /* Set the priority in IPR to 0 */ __raw_writew(__raw_readw(addr) & (0xffff ^ (0xf << p->shift)), addr); (void)__raw_readw(addr); /* Read back to flush write posting */ }
static void msm_gpio_irq_unmask(unsigned int irq) { unsigned long irq_flags; struct msm_gpio_chip *msm_chip = get_irq_chip_data(irq); spin_lock_irqsave(&msm_chip->chip.lock, irq_flags); msm_gpio_configure(&msm_chip->chip, irq - FIRST_GPIO_IRQ, MSM_GPIOF_ENABLE_INTERRUPT); spin_unlock_irqrestore(&msm_chip->chip.lock, irq_flags); }
static void vic_ack_irq(unsigned int irq) { void __iomem *base = get_irq_chip_data(irq); irq &= 31; writel(1 << irq, base + VIC_INT_ENABLE_CLEAR); /* moreover, clear the soft-triggered, in case it was the reason */ writel(1 << irq, base + VIC_INT_SOFT_CLEAR); }
static void msm_gpio_irq_ack(unsigned int irq) { unsigned long irq_flags; struct msm_gpio_chip *msm_chip = get_irq_chip_data(irq); spin_lock_irqsave(&msm_chip->chip.lock, irq_flags); msm_gpio_clear_detect_status(&msm_chip->chip, irq - FIRST_GPIO_IRQ); spin_unlock_irqrestore(&msm_chip->chip.lock, irq_flags); }
static void flipper_pic_ack(unsigned int virq) { int irq = virq_to_hw(virq); void __iomem *io_base = get_irq_chip_data(virq); /* this is at least needed for RSW */ out_be32(io_base + FLIPPER_ICR, 1 << irq); }
static void orion_irq_mask(u32 irq) { void __iomem *maskaddr = get_irq_chip_data(irq); u32 mask; mask = readl(maskaddr); mask &= ~(1 << (irq & 31)); writel(mask, maskaddr); }
static void asic2_unmask_kpio_irq(unsigned int irq) { struct asic2_data *asic = get_irq_chip_data(irq); u32 mask; mask = kpio_irq_mask[irq - (asic->irq_base + IPAQ_ASIC2_KPIO_IRQ_START)]; asic->kpio_int_shadow |= mask; __asic2_write_register(asic, IPAQ_ASIC2_KPIINTSTAT, asic->kpio_int_shadow); }
int gpio_configure(unsigned int gpio, unsigned long flags) { unsigned long irq_flags; struct msm_gpio_chip *msm_chip = get_irq_chip_data((gpio + FIRST_GPIO_IRQ)); spin_lock_irqsave(&msm_chip->chip.lock, irq_flags); msm_gpio_configure(&msm_chip->chip, gpio, flags); spin_unlock_irqrestore(&msm_chip->chip.lock, irq_flags); return 0; }
static void asic2_unmask_gpio_irq(unsigned int irq) { struct asic2_data *asic = get_irq_chip_data(irq); u32 val; val = __asic2_read_register(asic, IPAQ_ASIC2_GPIINTSTAT); val |= gpio_irq_mask[irq - (asic->irq_base + IPAQ_ASIC2_GPIO_IRQ_START)]; __asic2_write_register(asic, IPAQ_ASIC2_GPIINTSTAT, val); }