diff --git a/drivers/pinctrl/intel/pinctrl-baytrail.c b/drivers/pinctrl/intel/pinctrl-baytrail.c index a24b51e47f00..f7c752b4bb6d 100644 --- a/drivers/pinctrl/intel/pinctrl-baytrail.c +++ b/drivers/pinctrl/intel/pinctrl-baytrail.c @@ -1120,41 +1120,6 @@ static int byt_gpio_request(struct gpio_chip *chip, unsigned int offset) return 0; } -static int byt_irq_type(struct irq_data *d, unsigned type) -{ - struct byt_gpio *vg = gpiochip_get_data(irq_data_get_irq_chip_data(d)); - u32 offset = irqd_to_hwirq(d); - u32 value; - unsigned long flags; - void __iomem *reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG); - - if (offset >= vg->chip.ngpio) - return -EINVAL; - - raw_spin_lock_irqsave(&vg->lock, flags); - value = readl(reg); - - WARN(value & BYT_DIRECT_IRQ_EN, - "Bad pad config for io mode, force direct_irq_en bit clearing"); - - /* For level trigges the BYT_TRIG_POS and BYT_TRIG_NEG bits - * are used to indicate high and low level triggering - */ - value &= ~(BYT_DIRECT_IRQ_EN | BYT_TRIG_POS | BYT_TRIG_NEG | - BYT_TRIG_LVL); - - writel(value, reg); - - if (type & IRQ_TYPE_EDGE_BOTH) - irq_set_handler_locked(d, handle_edge_irq); - else if (type & IRQ_TYPE_LEVEL_MASK) - irq_set_handler_locked(d, handle_level_irq); - - raw_spin_unlock_irqrestore(&vg->lock, flags); - - return 0; -} - static void byt_get_pull_strength(u32 reg, u16 *strength) { switch (reg & BYT_PULL_STR_MASK) { @@ -1565,12 +1530,23 @@ static void byt_irq_ack(struct irq_data *d) unsigned offset = irqd_to_hwirq(d); void __iomem *reg; - raw_spin_lock(&vg->lock); reg = byt_gpio_reg(vg, offset, BYT_INT_STAT_REG); + if (!reg) + return; + + raw_spin_lock(&vg->lock); writel(BIT(offset % 32), reg); raw_spin_unlock(&vg->lock); } +static void byt_irq_mask(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct byt_gpio *vg = gpiochip_get_data(gc); + + byt_gpio_clear_triggering(vg, irqd_to_hwirq(d)); +} + static void byt_irq_unmask(struct irq_data *d) { struct gpio_chip *gc = irq_data_get_irq_chip_data(d); @@ -1581,6 +1557,8 @@ static void byt_irq_unmask(struct irq_data *d) u32 value; reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG); + if (!reg) + return; raw_spin_lock_irqsave(&vg->lock, flags); value = readl(reg); @@ -1606,21 +1584,48 @@ static void byt_irq_unmask(struct irq_data *d) raw_spin_unlock_irqrestore(&vg->lock, flags); } -static void byt_irq_mask(struct irq_data *d) +static int byt_irq_type(struct irq_data *d, unsigned int type) { - struct gpio_chip *gc = irq_data_get_irq_chip_data(d); - struct byt_gpio *vg = gpiochip_get_data(gc); + struct byt_gpio *vg = gpiochip_get_data(irq_data_get_irq_chip_data(d)); + u32 offset = irqd_to_hwirq(d); + u32 value; + unsigned long flags; + void __iomem *reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG); - byt_gpio_clear_triggering(vg, irqd_to_hwirq(d)); + if (!reg || offset >= vg->chip.ngpio) + return -EINVAL; + + raw_spin_lock_irqsave(&vg->lock, flags); + value = readl(reg); + + WARN(value & BYT_DIRECT_IRQ_EN, + "Bad pad config for io mode, force direct_irq_en bit clearing"); + + /* For level trigges the BYT_TRIG_POS and BYT_TRIG_NEG bits + * are used to indicate high and low level triggering + */ + value &= ~(BYT_DIRECT_IRQ_EN | BYT_TRIG_POS | BYT_TRIG_NEG | + BYT_TRIG_LVL); + + writel(value, reg); + + if (type & IRQ_TYPE_EDGE_BOTH) + irq_set_handler_locked(d, handle_edge_irq); + else if (type & IRQ_TYPE_LEVEL_MASK) + irq_set_handler_locked(d, handle_level_irq); + + raw_spin_unlock_irqrestore(&vg->lock, flags); + + return 0; } static struct irq_chip byt_irqchip = { - .name = "BYT-GPIO", - .irq_ack = byt_irq_ack, - .irq_mask = byt_irq_mask, - .irq_unmask = byt_irq_unmask, - .irq_set_type = byt_irq_type, - .flags = IRQCHIP_SKIP_SET_WAKE, + .name = "BYT-GPIO", + .irq_ack = byt_irq_ack, + .irq_mask = byt_irq_mask, + .irq_unmask = byt_irq_unmask, + .irq_set_type = byt_irq_type, + .flags = IRQCHIP_SKIP_SET_WAKE, }; static void byt_gpio_irq_init_hw(struct byt_gpio *vg)