示例#1
0
文件: irq.c 项目: CSCLOG/beaglebone
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;
}
示例#2
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;
}
示例#3
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;
}
示例#5
0
文件: irq.c 项目: mozzwald/linux-2.6
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;
}
示例#6
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;
}
示例#7
0
文件: irq.c 项目: 08opt/linux
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;
}
示例#8
0
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;
}
示例#9
0
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;
}
示例#10
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;
}
示例#12
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;
}
示例#14
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);
		}
示例#15
0
文件: gpio-ep93xx.c 项目: 7799/linux
/*
 * 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;
}
示例#16
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;
}
示例#17
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;
}