On Thu, Jan 28, 2016 at 8:44 PM, Alban Bedel <albeu@xxxxxxx> wrote: > Add support for the interrupt controller using GPIOLIB_IRQCHIP. > Both edges isn't supported by the chip and has to be emulated > by switching the polarity on each interrupt. > > Signed-off-by: Alban Bedel <albeu@xxxxxxx> Patch applied (you know this better than me and I assume you have tested it), but look into the following: > +static struct ath79_gpio_ctrl *irq_data_to_ath79_gpio(struct irq_data *data) > +{ > + struct gpio_chip *gc = irq_data_get_irq_chip_data(data); > + > + return container_of(gc, struct ath79_gpio_ctrl, gc); That looks like it could be return gpiochip_get_data(gc); > +static u32 ath79_gpio_read(struct ath79_gpio_ctrl *ctrl, unsigned reg) > +{ > + return readl(ctrl->base + reg); > +} > + > +static void ath79_gpio_write(struct ath79_gpio_ctrl *ctrl, > + unsigned reg, u32 val) > +{ > + return writel(val, ctrl->base + reg); > +} Do you really need these wrappers? I would just inline the functions. No strong preference but please consider. > +static bool ath79_gpio_update_bits( > + struct ath79_gpio_ctrl *ctrl, unsigned reg, u32 mask, u32 bits) > +{ > + u32 old_val, new_val; > + > + old_val = ath79_gpio_read(ctrl, reg); > + new_val = (old_val & ~mask) | (bits & mask); > + > + if (new_val != old_val) > + ath79_gpio_write(ctrl, reg, new_val); > + > + return new_val != old_val; > +} This is starting to look like regmap. One thing it provides is caching. Look at my commit 179c8fb3c2a6cc86cc746e6d071be00f611328de "clk: versatile-icst: convert to use regmap" for example. Very light suggestion, but regmap has regmap_update_bits(). I would rather just read-modify-write the register. > +static int ath79_gpio_irq_set_type(struct irq_data *data, > + unsigned int flow_type) > +{ > + struct ath79_gpio_ctrl *ctrl = irq_data_to_ath79_gpio(data); > + u32 mask = BIT(irqd_to_hwirq(data)); > + u32 type = 0, polarity = 0; > + unsigned long flags; > + bool disabled; > + > + switch (flow_type) { > + case IRQ_TYPE_EDGE_RISING: > + polarity |= mask; > + case IRQ_TYPE_EDGE_FALLING: > + case IRQ_TYPE_EDGE_BOTH: > + break; > + > + case IRQ_TYPE_LEVEL_HIGH: > + polarity |= mask; > + case IRQ_TYPE_LEVEL_LOW: > + type |= mask; Some more comments on edge handling below... > + break; > + > + default: > + return -EINVAL; > + } > + > + spin_lock_irqsave(&ctrl->lock, flags); > + > + if (flow_type == IRQ_TYPE_EDGE_BOTH) { > + ctrl->both_edges |= mask; > + polarity = ~ath79_gpio_read(ctrl, AR71XX_GPIO_REG_IN); > + } else { > + ctrl->both_edges &= ~mask; > + } Maybe insert a comment about the trick used to toggle the detection edge? > +static struct irq_chip ath79_gpio_irqchip = { > + .name = "gpio-ath79", > + .irq_enable = ath79_gpio_irq_enable, > + .irq_disable = ath79_gpio_irq_disable, > + .irq_mask = ath79_gpio_irq_mask, > + .irq_unmask = ath79_gpio_irq_unmask, > + .irq_set_type = ath79_gpio_irq_set_type, > +}; Hm no .irq_ack... even though using edge irqs. See below. > +static void ath79_gpio_irq_handler(struct irq_desc *desc) > +{ > + struct gpio_chip *gc = irq_desc_get_handler_data(desc); > + struct irq_chip *irqchip = irq_desc_get_chip(desc); > + struct ath79_gpio_ctrl *ctrl = > + container_of(gc, struct ath79_gpio_ctrl, gc); > + unsigned long flags, pending; > + u32 both_edges, state; > + int irq; > + > + chained_irq_enter(irqchip, desc); > + > + spin_lock_irqsave(&ctrl->lock, flags); > + > + pending = ath79_gpio_read(ctrl, AR71XX_GPIO_REG_INT_PENDING); > + > + /* Update the polarity of the both edges irqs */ > + both_edges = ctrl->both_edges & pending; > + if (both_edges) { > + state = ath79_gpio_read(ctrl, AR71XX_GPIO_REG_IN); > + ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_POLARITY, > + both_edges, ~state); > + } > + > + spin_unlock_irqrestore(&ctrl->lock, flags); > + > + if (pending) { > + for_each_set_bit(irq, &pending, gc->ngpio) > + generic_handle_irq( > + irq_linear_revmap(gc->irqdomain, irq)); > + } > + > + chained_irq_exit(irqchip, desc); > +} This is an edge-only handler, this should not be used for level IRQs. Have you really tested level IRQs? > + err = gpiochip_irqchip_add(&ctrl->gc, &ath79_gpio_irqchip, 0, > + handle_simple_irq, IRQ_TYPE_NONE); > + if (err) { > + dev_err(&pdev->dev, "failed to add gpiochip_irqchip\n"); > + goto gpiochip_remove; > + } Doesn't the chip requireq ACKing the level IRQs in some register? If it happens automagically when issueing ath79_gpio_read(ctrl, AR71XX_GPIO_REG_INT_PENDING); then it's OK like this I guess. Usually we use handle_edge_irq() and requires defining an .irq_ack() callback in the irqchip that ACKs the irqs. But if they are ACKed by the register read like that, it is not needed. Yours, Linus Walleij -- To unsubscribe from this list: send the line "unsubscribe linux-gpio" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html