aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/drivers/gpio/gpiolib.c
diff options
context:
space:
mode:
authorYixun Lan <dlan@gentoo.org>2025-04-08 23:11:20 +0800
committerBartosz Golaszewski <bartosz.golaszewski@linaro.org>2025-04-08 18:56:19 +0200
commit27986833e8e675b6c17654d13623590a46f9033e (patch)
tree6103dd307f96e2cb75a9654254d6b22e9c2754d3 /drivers/gpio/gpiolib.c
parentMerge tag 'irqdomain-04-08-25' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip into gpio/for-next (diff)
downloadwireguard-linux-27986833e8e675b6c17654d13623590a46f9033e.tar.xz
wireguard-linux-27986833e8e675b6c17654d13623590a46f9033e.zip
gpiolib: support parsing gpio three-cell interrupts scheme
gpio irq which using three-cell scheme should always call instance_match() function to find the correct irqdomain. The select() function will be called with !DOMAIN_BUS_ANY, so for specific gpio irq driver, it need to set bus token explicitly, something like: irq_domain_update_bus_token(girq->domain, DOMAIN_BUS_WIRED); Signed-off-by: Yixun Lan <dlan@gentoo.org> Link: https://lore.kernel.org/r/20250408-04-gpio-irq-threecell-v4-1-fd170d5e2d2b@gentoo.org Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Diffstat (limited to '')
-rw-r--r--drivers/gpio/gpiolib.c22
1 files changed, 18 insertions, 4 deletions
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 8252a671d720..ed8397a88dea 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -1507,9 +1507,8 @@ static int gpiochip_hierarchy_irq_domain_translate(struct irq_domain *d,
unsigned int *type)
{
/* We support standard DT translation */
- if (is_of_node(fwspec->fwnode) && fwspec->param_count == 2) {
- return irq_domain_translate_twocell(d, fwspec, hwirq, type);
- }
+ if (is_of_node(fwspec->fwnode))
+ return irq_domain_translate_twothreecell(d, fwspec, hwirq, type);
/* This is for board files and others not using DT */
if (is_fwnode_irqchip(fwspec->fwnode)) {
@@ -1811,11 +1810,26 @@ static void gpiochip_irq_unmap(struct irq_domain *d, unsigned int irq)
irq_set_chip_data(irq, NULL);
}
+static int gpiochip_irq_select(struct irq_domain *d, struct irq_fwspec *fwspec,
+ enum irq_domain_bus_token bus_token)
+{
+ struct fwnode_handle *fwnode = fwspec->fwnode;
+ struct gpio_chip *gc = d->host_data;
+ unsigned int index = fwspec->param[0];
+
+ if (fwspec->param_count == 3 && is_of_node(fwnode))
+ return of_gpiochip_instance_match(gc, index);
+
+ /* Fallback for twocells */
+ return (fwnode && (d->fwnode == fwnode) && (d->bus_token == bus_token));
+}
+
static const struct irq_domain_ops gpiochip_domain_ops = {
.map = gpiochip_irq_map,
.unmap = gpiochip_irq_unmap,
+ .select = gpiochip_irq_select,
/* Virtually all GPIO irqchips are twocell:ed */
- .xlate = irq_domain_xlate_twocell,
+ .xlate = irq_domain_xlate_twothreecell,
};
static struct irq_domain *gpiochip_simple_create_domain(struct gpio_chip *gc)