From: Sander Vanheule <sander@svanheule.net>
To: linux-gpio@vger.kernel.org, devicetree@vger.kernel.org
Cc: Linus Walleij <linus.walleij@linaro.org>,
Bartosz Golaszewski <brgl@bgdev.pl>,
Rob Herring <robh+dt@kernel.org>,
Krzysztof Kozlowski <krzk+dt@kernel.org>,
Sander Vanheule <sander@svanheule.net>,
Bert Vermeulen <bert@biot.com>,
linux-kernel@vger.kernel.org
Subject: [PATCH v1 3/6] gpio: realtek-otto: Support per-cpu interrupts
Date: Sat, 9 Apr 2022 21:55:48 +0200 [thread overview]
Message-ID: <8d4e0848f233c2c1b98aa141741c61d95cd3843f.1649533972.git.sander@svanheule.net> (raw)
In-Reply-To: <cover.1649533972.git.sander@svanheule.net>
On SoCs with multiple cores, it is possible that the GPIO interrupt
controller supports assigning specific pins to one or more cores.
IRQ balancing can be performed on a line-by-line basis if the parent
interrupt is routed to all available cores, which is the default upon
initialisation.
Signed-off-by: Sander Vanheule <sander@svanheule.net>
---
drivers/gpio/gpio-realtek-otto.c | 75 +++++++++++++++++++++++++++++++-
1 file changed, 74 insertions(+), 1 deletion(-)
diff --git a/drivers/gpio/gpio-realtek-otto.c b/drivers/gpio/gpio-realtek-otto.c
index c838ad8ce55f..dd1b7656d23a 100644
--- a/drivers/gpio/gpio-realtek-otto.c
+++ b/drivers/gpio/gpio-realtek-otto.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
#include <linux/gpio/driver.h>
+#include <linux/cpumask.h>
#include <linux/irq.h>
#include <linux/minmax.h>
#include <linux/mod_devicetable.h>
@@ -55,6 +56,8 @@
struct realtek_gpio_ctrl {
struct gpio_chip gc;
void __iomem *base;
+ void __iomem *cpumask_base;
+ struct cpumask cpu_irq_maskable;
raw_spinlock_t lock;
u16 intr_mask[REALTEK_GPIO_PORTS_PER_BANK];
u16 intr_type[REALTEK_GPIO_PORTS_PER_BANK];
@@ -76,6 +79,11 @@ enum realtek_gpio_flags {
* fields, and [BA, DC] for 2-bit fields.
*/
GPIO_PORTS_REVERSED = BIT(1),
+ /*
+ * Interrupts can be enabled per cpu. This requires a secondary IO
+ * range, where the per-cpu enable masks are located.
+ */
+ GPIO_INTERRUPTS_PER_CPU = BIT(2),
};
static struct realtek_gpio_ctrl *irq_data_to_ctrl(struct irq_data *data)
@@ -247,14 +255,61 @@ static void realtek_gpio_irq_handler(struct irq_desc *desc)
chained_irq_exit(irq_chip, desc);
}
+static inline void __iomem *realtek_gpio_irq_cpu_mask(struct realtek_gpio_ctrl *ctrl,
+ unsigned int port, int cpu)
+{
+ return ctrl->cpumask_base + ctrl->port_offset_u8(port) +
+ REALTEK_GPIO_PORTS_PER_BANK * cpu;
+}
+
+static int realtek_gpio_irq_set_affinity(struct irq_data *data,
+ const struct cpumask *dest, bool force)
+{
+ struct realtek_gpio_ctrl *ctrl = irq_data_to_ctrl(data);
+ unsigned int line = irqd_to_hwirq(data);
+ unsigned int port = line / 8;
+ unsigned int port_pin = line % 8;
+ void __iomem *irq_cpu_mask;
+ unsigned long flags;
+ int cpu;
+ u8 v;
+
+ if (!ctrl->cpumask_base)
+ return -ENXIO;
+
+ raw_spin_lock_irqsave(&ctrl->lock, flags);
+
+ for_each_cpu(cpu, &ctrl->cpu_irq_maskable) {
+ irq_cpu_mask = realtek_gpio_irq_cpu_mask(ctrl, port, cpu);
+ v = ioread8(irq_cpu_mask);
+
+ if (cpumask_test_cpu(cpu, dest))
+ v |= BIT(port_pin);
+ else
+ v &= ~BIT(port_pin);
+
+ iowrite8(v, irq_cpu_mask);
+ }
+
+ raw_spin_unlock_irqrestore(&ctrl->lock, flags);
+
+ irq_data_update_effective_affinity(data, dest);
+
+ return 0;
+}
+
static int realtek_gpio_irq_init(struct gpio_chip *gc)
{
struct realtek_gpio_ctrl *ctrl = gpiochip_get_data(gc);
unsigned int port;
+ int cpu;
for (port = 0; (port * 8) < gc->ngpio; port++) {
realtek_gpio_write_imr(ctrl, port, 0, 0);
realtek_gpio_clear_isr(ctrl, port, GENMASK(7, 0));
+
+ for_each_cpu(cpu, &ctrl->cpu_irq_maskable)
+ iowrite8(GENMASK(7, 0), realtek_gpio_irq_cpu_mask(ctrl, port, cpu));
}
return 0;
@@ -266,6 +321,7 @@ static struct irq_chip realtek_gpio_irq_chip = {
.irq_mask = realtek_gpio_irq_mask,
.irq_unmask = realtek_gpio_irq_unmask,
.irq_set_type = realtek_gpio_irq_set_type,
+ .irq_set_affinity = realtek_gpio_irq_set_affinity,
};
static const struct of_device_id realtek_gpio_of_match[] = {
@@ -290,8 +346,10 @@ static int realtek_gpio_probe(struct platform_device *pdev)
unsigned int dev_flags;
struct gpio_irq_chip *girq;
struct realtek_gpio_ctrl *ctrl;
+ struct resource *res;
u32 ngpios;
- int err, irq;
+ unsigned int nr_cpus;
+ int cpu, err, irq;
ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL);
if (!ctrl)
@@ -352,6 +410,21 @@ static int realtek_gpio_probe(struct platform_device *pdev)
girq->init_hw = realtek_gpio_irq_init;
}
+ cpumask_clear(&ctrl->cpu_irq_maskable);
+
+ if ((dev_flags & GPIO_INTERRUPTS_PER_CPU) && irq > 0) {
+ ctrl->cpumask_base = devm_platform_get_and_ioremap_resource(pdev, 1, &res);
+ if (IS_ERR(ctrl->cpumask_base))
+ return dev_err_probe(dev, PTR_ERR(ctrl->cpumask_base),
+ "missing CPU IRQ mask registers");
+
+ nr_cpus = resource_size(res) / REALTEK_GPIO_PORTS_PER_BANK;
+ nr_cpus = min(nr_cpus, num_present_cpus());
+
+ for (cpu = 0; cpu < nr_cpus; cpu++)
+ cpumask_set_cpu(cpu, &ctrl->cpu_irq_maskable);
+ }
+
return devm_gpiochip_add_data(dev, &ctrl->gc, ctrl);
}
--
2.35.1
next prev parent reply other threads:[~2022-04-09 20:05 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-04-09 19:55 [PATCH v1 0/6] Support for RTL930x/RTL931x GPIOs Sander Vanheule
2022-04-09 19:55 ` [PATCH v1 1/6] dt-bindings: gpio: realtek-otto: Add rtl9300 compatible Sander Vanheule
2022-04-10 14:16 ` Krzysztof Kozlowski
2022-04-10 14:34 ` Sander Vanheule
2022-04-09 19:55 ` [PATCH v1 2/6] gpio: realtek-otto: Support reversed port layouts Sander Vanheule
2022-04-20 23:01 ` Linus Walleij
2022-04-21 7:55 ` Sander Vanheule
2022-04-22 21:14 ` Linus Walleij
2022-04-09 19:55 ` Sander Vanheule [this message]
2022-04-20 23:04 ` [PATCH v1 3/6] gpio: realtek-otto: Support per-cpu interrupts Linus Walleij
2022-04-21 9:48 ` Marc Zyngier
2022-04-22 7:04 ` Sander Vanheule
2022-04-22 20:40 ` Sander Vanheule
2022-04-09 19:55 ` [PATCH v1 4/6] gpio: realtek-otto: Add RTL930x support Sander Vanheule
2022-04-09 19:55 ` [PATCH v1 5/6] dt-bindings: gpio: realtek-otto: Add rtl9310 compatible Sander Vanheule
2022-04-10 14:16 ` Krzysztof Kozlowski
2022-04-09 19:55 ` [PATCH v1 6/6] gpio: realtek-otto: Add RTL931x support Sander Vanheule
2022-04-11 12:31 ` [PATCH v1 0/6] Support for RTL930x/RTL931x GPIOs Bartosz Golaszewski
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=8d4e0848f233c2c1b98aa141741c61d95cd3843f.1649533972.git.sander@svanheule.net \
--to=sander@svanheule.net \
--cc=bert@biot.com \
--cc=brgl@bgdev.pl \
--cc=devicetree@vger.kernel.org \
--cc=krzk+dt@kernel.org \
--cc=linus.walleij@linaro.org \
--cc=linux-gpio@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=robh+dt@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®