static int vt8500_irq_set_type(struct irq_data *d, unsigned int flow_type) { void __iomem *base = ic_regbase; unsigned irq = d->irq; unsigned orig_irq = irq; u8 dctr; if (irq >= 64) { base = sic_regbase; irq -= 64; } dctr = readb(base + VT8500_IC_DCTR + irq); dctr &= ~VT8500_EDGE; switch (flow_type) { case IRQF_TRIGGER_LOW: return -EINVAL; case IRQF_TRIGGER_HIGH: dctr |= VT8500_TRIGGER_HIGH; __irq_set_handler_locked(orig_irq, handle_level_irq); break; case IRQF_TRIGGER_FALLING: dctr |= VT8500_TRIGGER_FALLING; __irq_set_handler_locked(orig_irq, handle_edge_irq); break; case IRQF_TRIGGER_RISING: dctr |= VT8500_TRIGGER_RISING; __irq_set_handler_locked(orig_irq, handle_edge_irq); break; } writeb(dctr, base + VT8500_IC_DCTR + irq); return 0; }
static int msm_irq_set_type(struct irq_data *d, unsigned int flow_type) { void __iomem *treg = VIC_INT_TO_REG_ADDR(VIC_INT_TYPE0, d->irq); void __iomem *preg = VIC_INT_TO_REG_ADDR(VIC_INT_POLARITY0, d->irq); unsigned index = VIC_INT_TO_REG_INDEX(d->irq); int b = 1 << (d->irq & 31); uint32_t polarity; uint32_t type; polarity = msm_irq_shadow_reg[index].int_polarity; if (flow_type & (IRQF_TRIGGER_FALLING | IRQF_TRIGGER_LOW)) polarity |= b; if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_HIGH)) polarity &= ~b; writel(polarity, preg); msm_irq_shadow_reg[index].int_polarity = polarity; type = msm_irq_shadow_reg[index].int_type; if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) { type |= b; __irq_set_handler_locked(d->irq, handle_edge_irq); } if (flow_type & (IRQF_TRIGGER_HIGH | IRQF_TRIGGER_LOW)) { type &= ~b; __irq_set_handler_locked(d->irq, handle_level_irq); } writel(type, treg); mb(); msm_irq_shadow_reg[index].int_type = type; 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); if (flow_type & (IRQF_TRIGGER_LOW | IRQF_TRIGGER_FALLING)) val |= mask; else val &= ~mask; writel(val, sirc_regs.int_polarity); val = readl(sirc_regs.int_type); if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) { val |= mask; __irq_set_handler_locked(d->irq, handle_edge_irq); } else { val &= ~mask; __irq_set_handler_locked(d->irq, handle_level_irq); } writel(val, sirc_regs.int_type); return 0; }
static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int flow_type) { unsigned long irq_flags; struct msm_gpio_chip *msm_chip = irq_get_chip_data(d->irq); unsigned offset = d->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_set_handler_locked(d->irq, handle_edge_irq); } else { __raw_writel(val & ~mask, msm_chip->regs.int_edge); __irq_set_handler_locked(d->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; }
static int vt8500_irq_set_type(struct irq_data *d, unsigned int flow_type) { struct vt8500_irq_priv *priv = (struct vt8500_irq_priv *)(d->domain->host_data); void __iomem *base = priv->base; u8 dctr; dctr = readb(base + VT8500_ICDC + d->hwirq); dctr &= ~VT8500_EDGE; switch (flow_type) { case IRQF_TRIGGER_LOW: return -EINVAL; case IRQF_TRIGGER_HIGH: dctr |= VT8500_TRIGGER_HIGH; __irq_set_handler_locked(d->irq, handle_level_irq); break; case IRQF_TRIGGER_FALLING: dctr |= VT8500_TRIGGER_FALLING; __irq_set_handler_locked(d->irq, handle_edge_irq); break; case IRQF_TRIGGER_RISING: dctr |= VT8500_TRIGGER_RISING; __irq_set_handler_locked(d->irq, handle_edge_irq); break; } writeb(dctr, base + VT8500_ICDC + d->hwirq); return 0; }
static int cpm2_set_irq_type(struct irq_data *d, unsigned int flow_type) { unsigned int src = irqd_to_hwirq(d); unsigned int vold, vnew, edibit; /* Port C interrupts are either IRQ_TYPE_EDGE_FALLING or * IRQ_TYPE_EDGE_BOTH (default). All others are IRQ_TYPE_EDGE_FALLING * or IRQ_TYPE_LEVEL_LOW (default) */ if (src >= CPM2_IRQ_PORTC15 && src <= CPM2_IRQ_PORTC0) { if (flow_type == IRQ_TYPE_NONE) flow_type = IRQ_TYPE_EDGE_BOTH; if (flow_type != IRQ_TYPE_EDGE_BOTH && flow_type != IRQ_TYPE_EDGE_FALLING) goto err_sense; } else { if (flow_type == IRQ_TYPE_NONE) flow_type = IRQ_TYPE_LEVEL_LOW; if (flow_type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_LEVEL_HIGH)) goto err_sense; } irqd_set_trigger_type(d, flow_type); if (flow_type & IRQ_TYPE_LEVEL_LOW) __irq_set_handler_locked(d->irq, handle_level_irq); else __irq_set_handler_locked(d->irq, handle_edge_irq); /* internal IRQ senses are LEVEL_LOW * EXT IRQ and Port C IRQ senses are programmable */ if (src >= CPM2_IRQ_EXT1 && src <= CPM2_IRQ_EXT7) edibit = (14 - (src - CPM2_IRQ_EXT1)); else if (src >= CPM2_IRQ_PORTC15 && src <= CPM2_IRQ_PORTC0) edibit = (31 - (CPM2_IRQ_PORTC0 - src)); else return (flow_type & IRQ_TYPE_LEVEL_LOW) ? IRQ_SET_MASK_OK_NOCOPY : -EINVAL; vold = in_be32(&cpm2_intctl->ic_siexr); if ((flow_type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_FALLING) vnew = vold | (1 << edibit); else vnew = vold & ~(1 << edibit); if (vold != vnew) out_be32(&cpm2_intctl->ic_siexr, vnew); return IRQ_SET_MASK_OK_NOCOPY; err_sense: pr_err("CPM2 PIC: sense type 0x%x not supported\n", flow_type); return -EINVAL; }
static int bcm63xx_external_irq_set_type(struct irq_data *d, unsigned int flow_type) { unsigned int irq = d->irq - IRQ_EXT_BASE; u32 reg; flow_type &= IRQ_TYPE_SENSE_MASK; if (flow_type == IRQ_TYPE_NONE) flow_type = IRQ_TYPE_LEVEL_LOW; reg = bcm_perf_readl(PERF_EXTIRQ_CFG_REG); switch (flow_type) { case IRQ_TYPE_EDGE_BOTH: reg &= ~EXTIRQ_CFG_LEVELSENSE(irq); reg |= EXTIRQ_CFG_BOTHEDGE(irq); break; case IRQ_TYPE_EDGE_RISING: reg &= ~EXTIRQ_CFG_LEVELSENSE(irq); reg |= EXTIRQ_CFG_SENSE(irq); reg &= ~EXTIRQ_CFG_BOTHEDGE(irq); break; case IRQ_TYPE_EDGE_FALLING: reg &= ~EXTIRQ_CFG_LEVELSENSE(irq); reg &= ~EXTIRQ_CFG_SENSE(irq); reg &= ~EXTIRQ_CFG_BOTHEDGE(irq); break; case IRQ_TYPE_LEVEL_HIGH: reg |= EXTIRQ_CFG_LEVELSENSE(irq); reg |= EXTIRQ_CFG_SENSE(irq); break; case IRQ_TYPE_LEVEL_LOW: reg |= EXTIRQ_CFG_LEVELSENSE(irq); reg &= ~EXTIRQ_CFG_SENSE(irq); break; default: printk(KERN_ERR "bogus flow type combination given !\n"); return -EINVAL; } bcm_perf_writel(reg, PERF_EXTIRQ_CFG_REG); irqd_set_trigger_type(d, flow_type); if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) __irq_set_handler_locked(d->irq, handle_level_irq); else __irq_set_handler_locked(d->irq, handle_edge_irq); return IRQ_SET_MASK_OK_NOCOPY; }
static int eic_set_irq_type(struct irq_data *d, unsigned int flow_type) { struct eic *eic = irq_data_get_irq_chip_data(d); unsigned int irq = d->irq; unsigned int i = irq - eic->first_irq; u32 mode, edge, level; flow_type &= IRQ_TYPE_SENSE_MASK; if (flow_type == IRQ_TYPE_NONE) flow_type = IRQ_TYPE_LEVEL_LOW; mode = eic_readl(eic, MODE); edge = eic_readl(eic, EDGE); level = eic_readl(eic, LEVEL); switch (flow_type) { case IRQ_TYPE_LEVEL_LOW: mode |= 1 << i; level &= ~(1 << i); break; case IRQ_TYPE_LEVEL_HIGH: mode |= 1 << i; level |= 1 << i; break; case IRQ_TYPE_EDGE_RISING: mode &= ~(1 << i); edge |= 1 << i; break; case IRQ_TYPE_EDGE_FALLING: mode &= ~(1 << i); edge &= ~(1 << i); break; default: return -EINVAL; } eic_writel(eic, MODE, mode); eic_writel(eic, EDGE, edge); eic_writel(eic, LEVEL, level); irqd_set_trigger_type(d, flow_type); if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) __irq_set_handler_locked(irq, handle_level_irq); else __irq_set_handler_locked(irq, handle_edge_irq); return IRQ_SET_MASK_OK_NOCOPY; }
static int mpc52xx_extirq_set_type(struct irq_data *d, unsigned int flow_type) { u32 ctrl_reg, type; int irq; int l2irq; void *handler = handle_level_irq; irq = irq_map[d->irq].hwirq; l2irq = irq & MPC52xx_IRQ_L2_MASK; pr_debug("%s: irq=%x. l2=%d flow_type=%d\n", __func__, irq, l2irq, flow_type); switch (flow_type) { case IRQF_TRIGGER_HIGH: type = 0; break; case IRQF_TRIGGER_RISING: type = 1; handler = handle_edge_irq; break; case IRQF_TRIGGER_FALLING: type = 2; handler = handle_edge_irq; break; case IRQF_TRIGGER_LOW: type = 3; break; default: type = 0; } ctrl_reg = in_be32(&intr->ctrl); ctrl_reg &= ~(0x3 << (22 - (l2irq * 2))); ctrl_reg |= (type << (22 - (l2irq * 2))); out_be32(&intr->ctrl, ctrl_reg); __irq_set_handler_locked(d->irq, handler); return 0; }
/* * mt_irq_set_type: set interrupt type * @irq: interrupt id * @flow_type: interrupt type * Always return 0. */ static int mt_irq_set_type(struct irq_data *data, unsigned int flow_type) { const unsigned int irq = data->irq; if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) { mt_irq_set_sens(irq, MT65xx_EDGE_SENSITIVE); mt_irq_set_polarity(irq, (flow_type & IRQF_TRIGGER_FALLING) ? 0 : 1); __irq_set_handler_locked(irq, handle_edge_irq); } else if (flow_type & (IRQF_TRIGGER_HIGH | IRQF_TRIGGER_LOW)) { mt_irq_set_sens(irq, MT65xx_LEVEL_SENSITIVE); mt_irq_set_polarity(irq, (flow_type & IRQF_TRIGGER_LOW) ? 0 : 1); __irq_set_handler_locked(irq, handle_level_irq); } return 0; }
static int qpnpint_irq_set_type(struct irq_data *d, unsigned int flow_type) { struct q_irq_data *irq_d = irq_data_get_irq_chip_data(d); struct q_perip_data *per_d = irq_d->per_d; int rc; u8 buf[3]; pr_debug("hwirq %lu irq: %d flow: 0x%x\n", d->hwirq, d->irq, flow_type); per_d->pol_high &= ~irq_d->mask_shift; per_d->pol_low &= ~irq_d->mask_shift; if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) { per_d->type |= irq_d->mask_shift; /* edge trig */ if (flow_type & IRQF_TRIGGER_RISING) per_d->pol_high |= irq_d->mask_shift; if (flow_type & IRQF_TRIGGER_FALLING) per_d->pol_low |= irq_d->mask_shift; } else { if ((flow_type & IRQF_TRIGGER_HIGH) && (flow_type & IRQF_TRIGGER_LOW)) return -EINVAL; per_d->type &= ~irq_d->mask_shift; /* level trig */ if (flow_type & IRQF_TRIGGER_HIGH) per_d->pol_high |= irq_d->mask_shift; else per_d->pol_low |= irq_d->mask_shift; } buf[0] = per_d->type; buf[1] = per_d->pol_high; buf[2] = per_d->pol_low; rc = qpnpint_spmi_write(irq_d, QPNPINT_REG_SET_TYPE, &buf, 3); if (rc) { pr_err("spmi failure on irq %d\n", d->irq); return rc; } if (flow_type & IRQ_TYPE_EDGE_BOTH) __irq_set_handler_locked(d->irq, handle_edge_irq); else __irq_set_handler_locked(d->irq, handle_level_irq); return 0; }
static int owl_gpio_irq_set_type(struct irq_data *d, unsigned int flow_type) { int gpio = d->hwirq; unsigned long irq_flags; unsigned int type, val, offset; spin_lock_irqsave(&owl_gpio_lock, irq_flags); if (flow_type & IRQ_TYPE_EDGE_BOTH) __irq_set_handler_locked(d->irq, handle_edge_irq); else __irq_set_handler_locked(d->irq, handle_level_irq); flow_type &= IRQ_TYPE_SENSE_MASK; switch (flow_type) { case IRQ_TYPE_EDGE_RISING: type = GPIO_INT_TYPE_RISING; break; case IRQ_TYPE_EDGE_FALLING: type = GPIO_INT_TYPE_FALLING; break; case IRQ_TYPE_LEVEL_HIGH: type = GPIO_INT_TYPE_HIGH; break; case IRQ_TYPE_LEVEL_LOW: type = GPIO_INT_TYPE_LOW; break; default: pr_err("[GPIO] %s: gpio %d, unknow irq type %d\n", __func__, gpio, flow_type); return -1; } offset = (GPIO_IN_BANK(gpio) < 16) ? 4 : 0; val = act_readl(GPIO_REG_INTC_TYPE(gpio)+offset); val &= ~(0x3 << ((gpio%16) * 2)); val |= type << ((gpio%16) * 2); act_writel(val, (GPIO_REG_INTC_TYPE(gpio)+offset)); spin_unlock_irqrestore(&owl_gpio_lock, irq_flags); return 0; }
static int sci_eic_irq_set_type(struct irq_data *data, unsigned int flow_type) { struct gpio_chip *chip = (struct gpio_chip *)data->chip_data; int offset = sci_irq_to_gpio(chip, data->irq); pr_debug("%s %d+%d %d\n", __FUNCTION__, chip->base, offset, flow_type); switch (flow_type) { case IRQ_TYPE_LEVEL_HIGH: sci_gpio_write(chip, offset, REG_EIC_IEV, 1); __irq_set_handler_locked(data->irq, handle_level_irq); break; case IRQ_TYPE_LEVEL_LOW: sci_gpio_write(chip, offset, REG_EIC_IEV, 0); __irq_set_handler_locked(data->irq, handle_level_irq); break; default: return -EINVAL; } return 0; }
static int mpc8xx_set_irq_type(struct irq_data *d, unsigned int flow_type) { if (flow_type & IRQ_TYPE_EDGE_FALLING) { irq_hw_number_t hw = (unsigned int)irqd_to_hwirq(d); unsigned int siel = in_be32(&siu_reg->sc_siel); /* only external IRQ senses are programmable */ if ((hw & 1) == 0) { siel |= (0x80000000 >> hw); out_be32(&siu_reg->sc_siel, siel); __irq_set_handler_locked(d->irq, handle_edge_irq); }
/* * gpio_int_type1 controls whether the interrupt is level (0) or * edge (1) triggered, while gpio_int_type2 controls whether it * triggers on low/falling (0) or high/rising (1). */ static int ep93xx_gpio_irq_type(struct irq_data *d, unsigned int type) { const int gpio = irq_to_gpio(d->irq); const int port = gpio >> 3; const int port_mask = 1 << (gpio & 7); irq_flow_handler_t handler; gpio_direction_input(gpio); switch (type) { case IRQ_TYPE_EDGE_RISING: gpio_int_type1[port] |= port_mask; gpio_int_type2[port] |= port_mask; handler = handle_edge_irq; break; case IRQ_TYPE_EDGE_FALLING: gpio_int_type1[port] |= port_mask; gpio_int_type2[port] &= ~port_mask; handler = handle_edge_irq; break; case IRQ_TYPE_LEVEL_HIGH: gpio_int_type1[port] &= ~port_mask; gpio_int_type2[port] |= port_mask; handler = handle_level_irq; break; case IRQ_TYPE_LEVEL_LOW: gpio_int_type1[port] &= ~port_mask; gpio_int_type2[port] &= ~port_mask; handler = handle_level_irq; break; case IRQ_TYPE_EDGE_BOTH: gpio_int_type1[port] |= port_mask; /* set initial polarity based on current input level */ if (gpio_get_value(gpio)) gpio_int_type2[port] &= ~port_mask; /* falling */ else gpio_int_type2[port] |= port_mask; /* rising */ handler = handle_edge_irq; break; default: return -EINVAL; } __irq_set_handler_locked(d->irq, handler); gpio_int_enabled[port] |= port_mask; ep93xx_gpio_update_int_params(port); return 0; }
static int rk30_gpio_irq_set_type(struct irq_data *d, unsigned int type) { struct rk30_gpio_bank *bank = irq_data_get_irq_chip_data(d); u32 bit = gpio_to_bit(irq_to_gpio(d->irq)); eGPIOIntType_t int_type; unsigned long flags; switch (type) { case IRQ_TYPE_EDGE_RISING: int_type = GPIOEdgelRising; break; case IRQ_TYPE_EDGE_FALLING: int_type = GPIOEdgelFalling; break; case IRQ_TYPE_LEVEL_HIGH: int_type = GPIOLevelHigh; break; case IRQ_TYPE_LEVEL_LOW: int_type = GPIOLevelLow; break; default: return -EINVAL; } spin_lock_irqsave(&bank->lock, flags); //设置为中断之前,必须先设置为输入状态 GPIOSetPinDirection(bank->regbase, bit, GPIO_IN); GPIOSetIntrType(bank->regbase, bit, int_type); spin_unlock_irqrestore(&bank->lock, flags); if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) __irq_set_handler_locked(d->irq, handle_level_irq); else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) __irq_set_handler_locked(d->irq, handle_edge_irq); return 0; }
static int bcm63xx_external_irq_set_type(struct irq_data *d, unsigned int flow_type) { unsigned int irq = d->irq - IRQ_EXTERNAL_BASE; u32 reg, regaddr; int levelsense, sense, bothedge; flow_type &= IRQ_TYPE_SENSE_MASK; if (flow_type == IRQ_TYPE_NONE) flow_type = IRQ_TYPE_LEVEL_LOW; levelsense = sense = bothedge = 0; switch (flow_type) { case IRQ_TYPE_EDGE_BOTH: bothedge = 1; break; case IRQ_TYPE_EDGE_RISING: sense = 1; break; case IRQ_TYPE_EDGE_FALLING: break; case IRQ_TYPE_LEVEL_HIGH: levelsense = 1; sense = 1; break; case IRQ_TYPE_LEVEL_LOW: levelsense = 1; break; default: printk(KERN_ERR "bogus flow type combination given !\n"); return -EINVAL; } regaddr = get_ext_irq_perf_reg(irq); reg = bcm_perf_readl(regaddr); irq %= 4; switch (bcm63xx_get_cpu_id()) { case BCM6348_CPU_ID: if (levelsense) reg |= EXTIRQ_CFG_LEVELSENSE_6348(irq); else reg &= ~EXTIRQ_CFG_LEVELSENSE_6348(irq); if (sense) reg |= EXTIRQ_CFG_SENSE_6348(irq); else reg &= ~EXTIRQ_CFG_SENSE_6348(irq); if (bothedge) reg |= EXTIRQ_CFG_BOTHEDGE_6348(irq); else reg &= ~EXTIRQ_CFG_BOTHEDGE_6348(irq); break; case BCM6328_CPU_ID: case BCM6338_CPU_ID: case BCM6345_CPU_ID: case BCM6358_CPU_ID: case BCM6368_CPU_ID: if (levelsense) reg |= EXTIRQ_CFG_LEVELSENSE(irq); else reg &= ~EXTIRQ_CFG_LEVELSENSE(irq); if (sense) reg |= EXTIRQ_CFG_SENSE(irq); else reg &= ~EXTIRQ_CFG_SENSE(irq); if (bothedge) reg |= EXTIRQ_CFG_BOTHEDGE(irq); else reg &= ~EXTIRQ_CFG_BOTHEDGE(irq); break; default: BUG(); } bcm_perf_writel(reg, regaddr); irqd_set_trigger_type(d, flow_type); if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) __irq_set_handler_locked(d->irq, handle_level_irq); else __irq_set_handler_locked(d->irq, handle_edge_irq); return IRQ_SET_MASK_OK_NOCOPY; }