Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

gpio: brcmstb: implement .irq_mask_ack()

The .irq_mask_ack() operation is slightly more efficient than doing
.irq_mask() and .irq_ack() separately.

More importantly for this driver it bypasses the check of
irqd_irq_masked ensuring a previously masked but still active
interrupt gets remasked if unmasked at the hardware level. This
allows the driver to more efficiently unmask the wake capable
interrupts when quiescing without needing to enable the irqs
individually to clear the irqd_irq_masked state.

Reviewed-by: Linus Walleij <linusw@kernel.org>
Reviewed-by: Andy Shevchenko <andy@kernel.org>
Signed-off-by: Doug Berger <opendmb@gmail.com>
Co-developed-by: Florian Fainelli <florian.fainelli@broadcom.com>
Signed-off-by: Florian Fainelli <florian.fainelli@broadcom.com>
Link: https://patch.msgid.link/20260204164333.1146039-3-florian.fainelli@broadcom.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>

authored by

Doug Berger and committed by
Bartosz Golaszewski
66ff5094 5711ae6d

+25 -5
+25 -5
drivers/gpio/gpio-brcmstb.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0-only 2 - // Copyright (C) 2015-2017 Broadcom 2 + // Copyright (C) 2015-2017, 2026 Broadcom 3 3 4 4 #include <linux/bitops.h> 5 5 #include <linux/gpio/driver.h> ··· 95 95 return hwirq - bank->chip.gc.offset; 96 96 } 97 97 98 - static void brcmstb_gpio_set_imask(struct brcmstb_gpio_bank *bank, 99 - irq_hw_number_t hwirq, bool enable) 98 + static void __brcmstb_gpio_set_imask(struct brcmstb_gpio_bank *bank, 99 + irq_hw_number_t hwirq, bool enable) 100 100 { 101 101 struct brcmstb_gpio_priv *priv = bank->parent_priv; 102 102 u32 mask = BIT(brcmstb_gpio_hwirq_to_offset(hwirq, bank)); 103 103 u32 imask; 104 - 105 - guard(gpio_generic_lock_irqsave)(&bank->chip); 106 104 107 105 imask = gpio_generic_read_reg(&bank->chip, 108 106 priv->reg_base + GIO_MASK(bank->id)); ··· 110 112 imask &= ~mask; 111 113 gpio_generic_write_reg(&bank->chip, 112 114 priv->reg_base + GIO_MASK(bank->id), imask); 115 + } 116 + 117 + static void brcmstb_gpio_set_imask(struct brcmstb_gpio_bank *bank, 118 + irq_hw_number_t hwirq, bool enable) 119 + { 120 + guard(gpio_generic_lock_irqsave)(&bank->chip); 121 + __brcmstb_gpio_set_imask(bank, hwirq, enable); 113 122 } 114 123 115 124 static int brcmstb_gpio_to_irq(struct gpio_chip *gc, unsigned offset) ··· 138 133 struct brcmstb_gpio_bank *bank = gpiochip_get_data(gc); 139 134 140 135 brcmstb_gpio_set_imask(bank, irqd_to_hwirq(d), false); 136 + } 137 + 138 + static void brcmstb_gpio_irq_mask_ack(struct irq_data *d) 139 + { 140 + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 141 + struct brcmstb_gpio_bank *bank = gpiochip_get_data(gc); 142 + struct brcmstb_gpio_priv *priv = bank->parent_priv; 143 + irq_hw_number_t hwirq = irqd_to_hwirq(d); 144 + u32 mask = BIT(brcmstb_gpio_hwirq_to_offset(hwirq, bank)); 145 + 146 + guard(gpio_generic_lock_irqsave)(&bank->chip); 147 + __brcmstb_gpio_set_imask(bank, hwirq, false); 148 + gpio_generic_write_reg(&bank->chip, 149 + priv->reg_base + GIO_STAT(bank->id), mask); 141 150 } 142 151 143 152 static void brcmstb_gpio_irq_unmask(struct irq_data *d) ··· 490 471 priv->irq_chip.name = dev_name(dev); 491 472 priv->irq_chip.irq_disable = brcmstb_gpio_irq_mask; 492 473 priv->irq_chip.irq_mask = brcmstb_gpio_irq_mask; 474 + priv->irq_chip.irq_mask_ack = brcmstb_gpio_irq_mask_ack; 493 475 priv->irq_chip.irq_unmask = brcmstb_gpio_irq_unmask; 494 476 priv->irq_chip.irq_ack = brcmstb_gpio_irq_ack; 495 477 priv->irq_chip.irq_set_type = brcmstb_gpio_irq_set_type;