Skip to content

Commit

Permalink
bcm27xx: bcm2712: backport RP1 interrupt affinity
Browse files Browse the repository at this point in the history
Support for setting the CPU affinity on RP1 has been added to RPi linux v6.6

Signed-off-by: Álvaro Fernández Rojas <[email protected]>
  • Loading branch information
Noltari committed Apr 7, 2024
1 parent 20fe7e6 commit 6512333
Show file tree
Hide file tree
Showing 5 changed files with 195 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
From 877cf6ae71c8eb9315014b3b379d9519ae6401b4 Mon Sep 17 00:00:00 2001
From: Phil Elwell <[email protected]>
Date: Wed, 3 Apr 2024 23:15:28 +0100
Subject: [PATCH 1/5] mfd: rp1: Support interrupt CPU affinity

See: https://github.com/raspberrypi/linux/issues/6077

Signed-off-by: Phil Elwell <[email protected]>
---
drivers/mfd/rp1.c | 9 +++++++++
1 file changed, 9 insertions(+)

--- a/drivers/mfd/rp1.c
+++ b/drivers/mfd/rp1.c
@@ -141,11 +141,20 @@ static int rp1_irq_set_type(struct irq_d
return ret;
}

+static int rp1_irq_set_affinity(struct irq_data *irqd, const struct cpumask *dest, bool force)
+{
+ struct rp1_dev *rp1 = irqd->domain->host_data;
+ struct irq_data *pcie_irqd = rp1->pcie_irqds[irqd->hwirq];
+
+ return msi_domain_set_affinity(pcie_irqd, dest, force);
+}
+
static struct irq_chip rp1_irq_chip = {
.name = "rp1_irq_chip",
.irq_mask = rp1_mask_irq,
.irq_unmask = rp1_unmask_irq,
.irq_set_type = rp1_irq_set_type,
+ .irq_set_affinity = rp1_irq_set_affinity,
};

static void rp1_chained_handle_irq(struct irq_desc *desc)
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
From d11b1d7f7df4bd1a5ab4df35b2a5c8569f2eacbe Mon Sep 17 00:00:00 2001
From: Phil Elwell <[email protected]>
Date: Thu, 4 Apr 2024 10:47:46 +0100
Subject: [PATCH 2/5] pinctrl: rp1: Use the correct per-bank GPIO base

The GPIO start for each bank - min_gpio - must be used in the IRQ
handler.

Signed-off-by: Phil Elwell <[email protected]>
---
drivers/pinctrl/pinctrl-rp1.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

--- a/drivers/pinctrl/pinctrl-rp1.c
+++ b/drivers/pinctrl/pinctrl-rp1.c
@@ -781,12 +781,12 @@ static void rp1_gpio_irq_handler(struct

ints = readl(pc->gpio_base + bank->ints_offset);
for_each_set_bit(b, &ints, 32) {
- struct rp1_pin_info *pin = rp1_get_pin(chip, b);
+ struct rp1_pin_info *pin = rp1_get_pin(chip, bank->min_gpio + b);

writel(RP1_GPIO_CTRL_IRQRESET,
pin->gpio + RP1_SET_OFFSET + RP1_GPIO_CTRL);
generic_handle_irq(irq_linear_revmap(pc->gpio_chip.irq.domain,
- bank->gpio_offset + b));
+ bank->min_gpio + b));
}

chained_irq_exit(host_chip, desc);
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
From d81e2fafab376d3975c46c5f477945384a38524d Mon Sep 17 00:00:00 2001
From: Phil Elwell <[email protected]>
Date: Thu, 4 Apr 2024 10:50:32 +0100
Subject: [PATCH 3/5] pinctrl: rp1: Allow legacy brcm,pins on all banks

Support the use of the brcm,pins property for GPIOs in banks 1 and 2,
but only for inputs and outputs - no other legacy mapping.

Signed-off-by: Phil Elwell <[email protected]>
---
drivers/pinctrl/pinctrl-rp1.c | 18 ++++++++++--------
1 file changed, 10 insertions(+), 8 deletions(-)

--- a/drivers/pinctrl/pinctrl-rp1.c
+++ b/drivers/pinctrl/pinctrl-rp1.c
@@ -981,7 +981,16 @@ static int rp1_pctl_legacy_map_func(stru
return -EINVAL;
}

- func = legacy_fsel_map[pin][fnum];
+ if (pin < ARRAY_SIZE(legacy_fsel_map)) {
+ func = legacy_fsel_map[pin][fnum];
+ } else if (fnum < 2) {
+ func = func_gpio;
+ } else {
+ dev_err(pc->dev, "%pOF: invalid brcm,pins value %d\n",
+ np, pin);
+ return -EINVAL;
+ }
+
if (func == func_invalid) {
dev_err(pc->dev, "%pOF: brcm,function %d not supported on pin %d\n",
np, fnum, pin);
@@ -1104,13 +1113,6 @@ static int rp1_pctl_dt_node_to_map(struc
err = of_property_read_u32_index(np, "brcm,pins", i, &pin);
if (err)
goto out;
- if (pin >= ARRAY_SIZE(legacy_fsel_map)) {
- dev_err(pc->dev, "%pOF: invalid brcm,pins value %d\n",
- np, pin);
- err = -EINVAL;
- goto out;
- }
-
if (num_funcs) {
err = of_property_read_u32_index(np, "brcm,function",
(num_funcs > 1) ? i : 0,
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
From 086480cc43b9d967647b237a84623b27b8850a64 Mon Sep 17 00:00:00 2001
From: Phil Elwell <[email protected]>
Date: Wed, 3 Apr 2024 23:16:47 +0100
Subject: [PATCH 4/5] pinctrl: rp1: Support interrupt CPU affinity

See: https://github.com/raspberrypi/linux/issues/6077

Signed-off-by: Phil Elwell <[email protected]>
---
drivers/pinctrl/pinctrl-rp1.c | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)

--- a/drivers/pinctrl/pinctrl-rp1.c
+++ b/drivers/pinctrl/pinctrl-rp1.c
@@ -894,6 +894,29 @@ static void rp1_gpio_irq_ack(struct irq_
writel(RP1_GPIO_CTRL_IRQRESET, pin->gpio + RP1_SET_OFFSET + RP1_GPIO_CTRL);
}

+static int rp1_gpio_irq_set_affinity(struct irq_data *data, const struct cpumask *dest, bool force)
+{
+ struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
+ struct rp1_pinctrl *pc = gpiochip_get_data(chip);
+ const struct rp1_iobank_desc *bank;
+ struct irq_data *parent_data = NULL;
+ int i;
+
+ for (i = 0; i < 3; i++) {
+ bank = &rp1_iobanks[i];
+ if (data->hwirq >= bank->min_gpio &&
+ data->hwirq < bank->min_gpio + bank->num_gpios) {
+ parent_data = irq_get_irq_data(pc->irq[i]);
+ break;
+ }
+ }
+
+ if (parent_data && parent_data->chip->irq_set_affinity)
+ return parent_data->chip->irq_set_affinity(parent_data, dest, force);
+
+ return -EINVAL;
+}
+
static struct irq_chip rp1_gpio_irq_chip = {
.name = MODULE_NAME,
.irq_enable = rp1_gpio_irq_enable,
@@ -902,6 +925,7 @@ static struct irq_chip rp1_gpio_irq_chip
.irq_ack = rp1_gpio_irq_ack,
.irq_mask = rp1_gpio_irq_disable,
.irq_unmask = rp1_gpio_irq_enable,
+ .irq_set_affinity = rp1_gpio_irq_set_affinity,
.flags = IRQCHIP_IMMUTABLE,
};

Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
From ba9f37cecf19e4d2b5cc7186d054735e3cc7a4a2 Mon Sep 17 00:00:00 2001
From: Phil Elwell <[email protected]>
Date: Thu, 4 Apr 2024 11:52:33 +0100
Subject: [PATCH 5/5] pinctrl: rp1: Clear events when setting IRQ type

When setting the interrupt type, it is unlikely that any latched events
are of interest, so clear them.

Signed-off-by: Phil Elwell <[email protected]>
---
drivers/pinctrl/pinctrl-rp1.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)

--- a/drivers/pinctrl/pinctrl-rp1.c
+++ b/drivers/pinctrl/pinctrl-rp1.c
@@ -848,10 +848,13 @@ static int rp1_irq_set_type(struct rp1_p
return -EINVAL;
}

- /* Clear them all */
+ /* Clear the event enables */
writel(RP1_INT_MASK << RP1_GPIO_EVENTS_SHIFT_RAW,
pin->gpio + RP1_CLR_OFFSET + RP1_GPIO_CTRL);
- /* Set those that are needed */
+ /* Clear any latched events */
+ writel(RP1_GPIO_CTRL_IRQRESET,
+ pin->gpio + RP1_SET_OFFSET + RP1_GPIO_CTRL);
+ /* Enable the events that are needed */
writel(irq_flags << RP1_GPIO_EVENTS_SHIFT_RAW,
pin->gpio + RP1_SET_OFFSET + RP1_GPIO_CTRL);
pin->irq_type = type;

0 comments on commit 6512333

Please sign in to comment.