gpio: ath79: use the generic GPIO chip lock for IRQ handling
This driver uses its own raw spinlock in interrupt routines while the generic GPIO chip callbacks use a separate one. This is, of course, racy so use the fact that the lock in generic GPIO chip is also a raw spinlock and convert the interrupt handling functions in this module to using the provided generic GPIO chip locking API. Reviewed-by: Linus Walleij <linus.walleij@linaro.org> Link: https://lore.kernel.org/r/20250910-gpio-mmio-gpio-conv-part4-v2-5-f3d1a4c57124@linaro.org Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
This commit is contained in:
parent
551a097118
commit
e7a3a1be11
|
@ -31,7 +31,6 @@
|
||||||
struct ath79_gpio_ctrl {
|
struct ath79_gpio_ctrl {
|
||||||
struct gpio_generic_chip chip;
|
struct gpio_generic_chip chip;
|
||||||
void __iomem *base;
|
void __iomem *base;
|
||||||
raw_spinlock_t lock;
|
|
||||||
unsigned long both_edges;
|
unsigned long both_edges;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -72,23 +71,22 @@ static void ath79_gpio_irq_unmask(struct irq_data *data)
|
||||||
{
|
{
|
||||||
struct ath79_gpio_ctrl *ctrl = irq_data_to_ath79_gpio(data);
|
struct ath79_gpio_ctrl *ctrl = irq_data_to_ath79_gpio(data);
|
||||||
u32 mask = BIT(irqd_to_hwirq(data));
|
u32 mask = BIT(irqd_to_hwirq(data));
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
gpiochip_enable_irq(&ctrl->chip.gc, irqd_to_hwirq(data));
|
gpiochip_enable_irq(&ctrl->chip.gc, irqd_to_hwirq(data));
|
||||||
raw_spin_lock_irqsave(&ctrl->lock, flags);
|
|
||||||
|
guard(gpio_generic_lock_irqsave)(&ctrl->chip);
|
||||||
|
|
||||||
ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_MASK, mask, mask);
|
ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_MASK, mask, mask);
|
||||||
raw_spin_unlock_irqrestore(&ctrl->lock, flags);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ath79_gpio_irq_mask(struct irq_data *data)
|
static void ath79_gpio_irq_mask(struct irq_data *data)
|
||||||
{
|
{
|
||||||
struct ath79_gpio_ctrl *ctrl = irq_data_to_ath79_gpio(data);
|
struct ath79_gpio_ctrl *ctrl = irq_data_to_ath79_gpio(data);
|
||||||
u32 mask = BIT(irqd_to_hwirq(data));
|
u32 mask = BIT(irqd_to_hwirq(data));
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
raw_spin_lock_irqsave(&ctrl->lock, flags);
|
scoped_guard(gpio_generic_lock_irqsave, &ctrl->chip)
|
||||||
ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_MASK, mask, 0);
|
ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_MASK, mask, 0);
|
||||||
raw_spin_unlock_irqrestore(&ctrl->lock, flags);
|
|
||||||
gpiochip_disable_irq(&ctrl->chip.gc, irqd_to_hwirq(data));
|
gpiochip_disable_irq(&ctrl->chip.gc, irqd_to_hwirq(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,24 +94,20 @@ static void ath79_gpio_irq_enable(struct irq_data *data)
|
||||||
{
|
{
|
||||||
struct ath79_gpio_ctrl *ctrl = irq_data_to_ath79_gpio(data);
|
struct ath79_gpio_ctrl *ctrl = irq_data_to_ath79_gpio(data);
|
||||||
u32 mask = BIT(irqd_to_hwirq(data));
|
u32 mask = BIT(irqd_to_hwirq(data));
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
raw_spin_lock_irqsave(&ctrl->lock, flags);
|
guard(gpio_generic_lock_irqsave)(&ctrl->chip);
|
||||||
ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_ENABLE, mask, mask);
|
ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_ENABLE, mask, mask);
|
||||||
ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_MASK, mask, mask);
|
ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_MASK, mask, mask);
|
||||||
raw_spin_unlock_irqrestore(&ctrl->lock, flags);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ath79_gpio_irq_disable(struct irq_data *data)
|
static void ath79_gpio_irq_disable(struct irq_data *data)
|
||||||
{
|
{
|
||||||
struct ath79_gpio_ctrl *ctrl = irq_data_to_ath79_gpio(data);
|
struct ath79_gpio_ctrl *ctrl = irq_data_to_ath79_gpio(data);
|
||||||
u32 mask = BIT(irqd_to_hwirq(data));
|
u32 mask = BIT(irqd_to_hwirq(data));
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
raw_spin_lock_irqsave(&ctrl->lock, flags);
|
guard(gpio_generic_lock_irqsave)(&ctrl->chip);
|
||||||
ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_MASK, mask, 0);
|
ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_MASK, mask, 0);
|
||||||
ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_ENABLE, mask, 0);
|
ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_ENABLE, mask, 0);
|
||||||
raw_spin_unlock_irqrestore(&ctrl->lock, flags);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ath79_gpio_irq_set_type(struct irq_data *data,
|
static int ath79_gpio_irq_set_type(struct irq_data *data,
|
||||||
|
@ -122,7 +116,6 @@ static int ath79_gpio_irq_set_type(struct irq_data *data,
|
||||||
struct ath79_gpio_ctrl *ctrl = irq_data_to_ath79_gpio(data);
|
struct ath79_gpio_ctrl *ctrl = irq_data_to_ath79_gpio(data);
|
||||||
u32 mask = BIT(irqd_to_hwirq(data));
|
u32 mask = BIT(irqd_to_hwirq(data));
|
||||||
u32 type = 0, polarity = 0;
|
u32 type = 0, polarity = 0;
|
||||||
unsigned long flags;
|
|
||||||
bool disabled;
|
bool disabled;
|
||||||
|
|
||||||
switch (flow_type) {
|
switch (flow_type) {
|
||||||
|
@ -144,7 +137,7 @@ static int ath79_gpio_irq_set_type(struct irq_data *data,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
raw_spin_lock_irqsave(&ctrl->lock, flags);
|
guard(gpio_generic_lock_irqsave)(&ctrl->chip);
|
||||||
|
|
||||||
if (flow_type == IRQ_TYPE_EDGE_BOTH) {
|
if (flow_type == IRQ_TYPE_EDGE_BOTH) {
|
||||||
ctrl->both_edges |= mask;
|
ctrl->both_edges |= mask;
|
||||||
|
@ -169,8 +162,6 @@ static int ath79_gpio_irq_set_type(struct irq_data *data,
|
||||||
ath79_gpio_update_bits(
|
ath79_gpio_update_bits(
|
||||||
ctrl, AR71XX_GPIO_REG_INT_ENABLE, mask, mask);
|
ctrl, AR71XX_GPIO_REG_INT_ENABLE, mask, mask);
|
||||||
|
|
||||||
raw_spin_unlock_irqrestore(&ctrl->lock, flags);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,14 +183,13 @@ static void ath79_gpio_irq_handler(struct irq_desc *desc)
|
||||||
struct gpio_generic_chip *gen_gc = to_gpio_generic_chip(gc);
|
struct gpio_generic_chip *gen_gc = to_gpio_generic_chip(gc);
|
||||||
struct ath79_gpio_ctrl *ctrl =
|
struct ath79_gpio_ctrl *ctrl =
|
||||||
container_of(gen_gc, struct ath79_gpio_ctrl, chip);
|
container_of(gen_gc, struct ath79_gpio_ctrl, chip);
|
||||||
unsigned long flags, pending;
|
unsigned long pending;
|
||||||
u32 both_edges, state;
|
u32 both_edges, state;
|
||||||
int irq;
|
int irq;
|
||||||
|
|
||||||
chained_irq_enter(irqchip, desc);
|
chained_irq_enter(irqchip, desc);
|
||||||
|
|
||||||
raw_spin_lock_irqsave(&ctrl->lock, flags);
|
scoped_guard(gpio_generic_lock_irqsave, &ctrl->chip) {
|
||||||
|
|
||||||
pending = ath79_gpio_read(ctrl, AR71XX_GPIO_REG_INT_PENDING);
|
pending = ath79_gpio_read(ctrl, AR71XX_GPIO_REG_INT_PENDING);
|
||||||
|
|
||||||
/* Update the polarity of the both edges irqs */
|
/* Update the polarity of the both edges irqs */
|
||||||
|
@ -209,8 +199,7 @@ static void ath79_gpio_irq_handler(struct irq_desc *desc)
|
||||||
ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_POLARITY,
|
ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_POLARITY,
|
||||||
both_edges, ~state);
|
both_edges, ~state);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
raw_spin_unlock_irqrestore(&ctrl->lock, flags);
|
|
||||||
|
|
||||||
for_each_set_bit(irq, &pending, gc->ngpio)
|
for_each_set_bit(irq, &pending, gc->ngpio)
|
||||||
generic_handle_domain_irq(gc->irq.domain, irq);
|
generic_handle_domain_irq(gc->irq.domain, irq);
|
||||||
|
@ -256,8 +245,6 @@ static int ath79_gpio_probe(struct platform_device *pdev)
|
||||||
if (IS_ERR(ctrl->base))
|
if (IS_ERR(ctrl->base))
|
||||||
return PTR_ERR(ctrl->base);
|
return PTR_ERR(ctrl->base);
|
||||||
|
|
||||||
raw_spin_lock_init(&ctrl->lock);
|
|
||||||
|
|
||||||
config = (struct gpio_generic_chip_config) {
|
config = (struct gpio_generic_chip_config) {
|
||||||
.dev = dev,
|
.dev = dev,
|
||||||
.sz = 4,
|
.sz = 4,
|
||||||
|
|
Loading…
Reference in New Issue