[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250610143042.295376-4-antonio.borneo@foss.st.com>
Date: Tue, 10 Jun 2025 16:30:40 +0200
From: Antonio Borneo <antonio.borneo@...s.st.com>
To: Catalin Marinas <catalin.marinas@....com>, Will Deacon <will@...nel.org>,
Linus Walleij <linus.walleij@...aro.org>,
Alexandre Torgue
<alexandre.torgue@...s.st.com>,
<linux-kernel@...r.kernel.org>, <linux-gpio@...r.kernel.org>
CC: Antonio Borneo <antonio.borneo@...s.st.com>,
Maxime Coquelin
<mcoquelin.stm32@...il.com>,
Clément Le Goffic
<clement.legoffic@...s.st.com>,
<linux-arm-kernel@...ts.infradead.org>,
<linux-stm32@...md-mailman.stormreply.com>,
Gatien Chevallier
<gatien.chevallier@...s.st.com>
Subject: [PATCH v2 3/5] pinctrl: stm32: Add RIF support for stm32mp257
On SoC stm32mp257, GPIO supports security and isolation compliant
with the Resource Isolation Framework (RIF). Each GPIO line can be
assigned to different security and compartment domains.
Add the generic code to handle the RIF configuration set by the
secure world and initialize the GPIO valid mask accordingly.
Enable the RIF support for stm32mp257.
Co-developed-by: Gatien Chevallier <gatien.chevallier@...s.st.com>
Signed-off-by: Gatien Chevallier <gatien.chevallier@...s.st.com>
Signed-off-by: Antonio Borneo <antonio.borneo@...s.st.com>
---
drivers/pinctrl/stm32/pinctrl-stm32.c | 121 ++++++++++++++++++++-
drivers/pinctrl/stm32/pinctrl-stm32.h | 1 +
drivers/pinctrl/stm32/pinctrl-stm32mp257.c | 4 +
3 files changed, 125 insertions(+), 1 deletion(-)
diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.c b/drivers/pinctrl/stm32/pinctrl-stm32.c
index e0e3e649976b8..e7621f9b00056 100644
--- a/drivers/pinctrl/stm32/pinctrl-stm32.c
+++ b/drivers/pinctrl/stm32/pinctrl-stm32.c
@@ -6,6 +6,7 @@
*
* Heavily based on Mediatek's pinctrl driver
*/
+#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/gpio/driver.h>
#include <linux/hwspinlock.h>
@@ -36,6 +37,8 @@
#include "../pinctrl-utils.h"
#include "pinctrl-stm32.h"
+#define STM32_GPIO_CID1 1
+
#define STM32_GPIO_MODER 0x00
#define STM32_GPIO_TYPER 0x04
#define STM32_GPIO_SPEEDR 0x08
@@ -47,6 +50,8 @@
#define STM32_GPIO_AFRL 0x20
#define STM32_GPIO_AFRH 0x24
#define STM32_GPIO_SECCFGR 0x30
+#define STM32_GPIO_CIDCFGR(x) (0x50 + (0x8 * (x)))
+#define STM32_GPIO_SEMCR(x) (0x54 + (0x8 * (x)))
/* custom bitfield to backup pin status */
#define STM32_GPIO_BKP_MODE_SHIFT 0
@@ -60,6 +65,14 @@
#define STM32_GPIO_BKP_TYPE 10
#define STM32_GPIO_BKP_VAL 11
+#define STM32_GPIO_CIDCFGR_CFEN BIT(0)
+#define STM32_GPIO_CIDCFGR_SEMEN BIT(1)
+#define STM32_GPIO_CIDCFGR_SCID_MASK GENMASK(5, 4)
+#define STM32_GPIO_CIDCFGR_SEMWL_CID1 BIT(16 + STM32_GPIO_CID1)
+
+#define STM32_GPIO_SEMCR_SEM_MUTEX BIT(0)
+#define STM32_GPIO_SEMCR_SEMCID_MASK GENMASK(5, 4)
+
#define STM32_GPIO_PINS_PER_BANK 16
#define STM32_GPIO_IRQ_LINE 16
@@ -98,6 +111,7 @@ struct stm32_gpio_bank {
u32 pin_backup[STM32_GPIO_PINS_PER_BANK];
u8 irq_type[STM32_GPIO_PINS_PER_BANK];
bool secure_control;
+ bool rif_control;
};
struct stm32_pinctrl {
@@ -194,6 +208,80 @@ static void stm32_gpio_backup_bias(struct stm32_gpio_bank *bank, u32 offset,
bank->pin_backup[offset] |= bias << STM32_GPIO_BKP_PUPD_SHIFT;
}
+/* RIF functions */
+
+static bool stm32_gpio_rif_valid(struct stm32_gpio_bank *bank, unsigned int gpio_nr)
+{
+ u32 cid;
+
+ cid = readl_relaxed(bank->base + STM32_GPIO_CIDCFGR(gpio_nr));
+
+ if (!(cid & STM32_GPIO_CIDCFGR_CFEN))
+ return true;
+
+ if (!(cid & STM32_GPIO_CIDCFGR_SEMEN)) {
+ if (FIELD_GET(STM32_GPIO_CIDCFGR_SCID_MASK, cid) == STM32_GPIO_CID1)
+ return true;
+
+ return false;
+ }
+
+ if (cid & STM32_GPIO_CIDCFGR_SEMWL_CID1)
+ return true;
+
+ return false;
+}
+
+static bool stm32_gpio_rif_acquire_semaphore(struct stm32_gpio_bank *bank, unsigned int gpio_nr)
+{
+ u32 cid, sem;
+
+ cid = readl_relaxed(bank->base + STM32_GPIO_CIDCFGR(gpio_nr));
+
+ if (!(cid & STM32_GPIO_CIDCFGR_CFEN))
+ return true;
+
+ if (!(cid & STM32_GPIO_CIDCFGR_SEMEN)) {
+ if (FIELD_GET(STM32_GPIO_CIDCFGR_SCID_MASK, cid) == STM32_GPIO_CID1)
+ return true;
+
+ return false;
+ }
+
+ if (!(cid & STM32_GPIO_CIDCFGR_SEMWL_CID1))
+ return false;
+
+ sem = readl_relaxed(bank->base + STM32_GPIO_SEMCR(gpio_nr));
+ if (sem & STM32_GPIO_SEMCR_SEM_MUTEX) {
+ if (FIELD_GET(STM32_GPIO_SEMCR_SEMCID_MASK, sem) == STM32_GPIO_CID1)
+ return true;
+
+ return false;
+ }
+
+ writel_relaxed(STM32_GPIO_SEMCR_SEM_MUTEX, bank->base + STM32_GPIO_SEMCR(gpio_nr));
+
+ sem = readl_relaxed(bank->base + STM32_GPIO_SEMCR(gpio_nr));
+ if (sem & STM32_GPIO_SEMCR_SEM_MUTEX &&
+ FIELD_GET(STM32_GPIO_SEMCR_SEMCID_MASK, sem) == STM32_GPIO_CID1)
+ return true;
+
+ return false;
+}
+
+static void stm32_gpio_rif_release_semaphore(struct stm32_gpio_bank *bank, unsigned int gpio_nr)
+{
+ u32 cid;
+
+ cid = readl_relaxed(bank->base + STM32_GPIO_CIDCFGR(gpio_nr));
+
+ if (!(cid & STM32_GPIO_CIDCFGR_CFEN))
+ return;
+
+ if (cid & STM32_GPIO_CIDCFGR_SEMEN)
+ writel_relaxed(0, bank->base + STM32_GPIO_SEMCR(gpio_nr));
+}
+
/* GPIO functions */
static inline void __stm32_gpio_set(struct stm32_gpio_bank *bank,
@@ -220,9 +308,26 @@ static int stm32_gpio_request(struct gpio_chip *chip, unsigned offset)
return -EINVAL;
}
+ if (bank->rif_control) {
+ if (!stm32_gpio_rif_acquire_semaphore(bank, offset)) {
+ dev_err(pctl->dev, "pin %d not available.\n", pin);
+ return -EINVAL;
+ }
+ }
+
return pinctrl_gpio_request(chip, offset);
}
+static void stm32_gpio_free(struct gpio_chip *chip, unsigned int offset)
+{
+ struct stm32_gpio_bank *bank = gpiochip_get_data(chip);
+
+ pinctrl_gpio_free(chip, offset);
+
+ if (bank->rif_control)
+ stm32_gpio_rif_release_semaphore(bank, offset);
+}
+
static int stm32_gpio_get(struct gpio_chip *chip, unsigned offset)
{
struct stm32_gpio_bank *bank = gpiochip_get_data(chip);
@@ -306,12 +411,25 @@ static int stm32_gpio_init_valid_mask(struct gpio_chip *chip,
}
}
+ if (bank->rif_control) {
+ for (i = 0; i < ngpios; i++) {
+ if (!test_bit(i, valid_mask))
+ continue;
+
+ if (stm32_gpio_rif_valid(bank, i))
+ continue;
+
+ dev_dbg(pctl->dev, "RIF semaphore ownership conflict, GPIO %u", i);
+ clear_bit(i, valid_mask);
+ }
+ }
+
return 0;
}
static const struct gpio_chip stm32_gpio_template = {
.request = stm32_gpio_request,
- .free = pinctrl_gpio_free,
+ .free = stm32_gpio_free,
.get = stm32_gpio_get,
.set_rv = stm32_gpio_set,
.direction_input = pinctrl_gpio_direction_input,
@@ -1350,6 +1468,7 @@ static int stm32_gpiolib_register_bank(struct stm32_pinctrl *pctl, struct fwnode
bank->bank_nr = bank_nr;
bank->bank_ioport_nr = bank_ioport_nr;
bank->secure_control = pctl->match_data->secure_control;
+ bank->rif_control = pctl->match_data->rif_control;
spin_lock_init(&bank->lock);
if (pctl->domain) {
diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.h b/drivers/pinctrl/stm32/pinctrl-stm32.h
index 8790fef2d58a2..ed525f5bdd7cd 100644
--- a/drivers/pinctrl/stm32/pinctrl-stm32.h
+++ b/drivers/pinctrl/stm32/pinctrl-stm32.h
@@ -63,6 +63,7 @@ struct stm32_pinctrl_match_data {
const struct stm32_desc_pin *pins;
const unsigned int npins;
bool secure_control;
+ bool rif_control;
};
int stm32_pctl_probe(struct platform_device *pdev);
diff --git a/drivers/pinctrl/stm32/pinctrl-stm32mp257.c b/drivers/pinctrl/stm32/pinctrl-stm32mp257.c
index 23aebd4695e99..984587207956a 100644
--- a/drivers/pinctrl/stm32/pinctrl-stm32mp257.c
+++ b/drivers/pinctrl/stm32/pinctrl-stm32mp257.c
@@ -2542,11 +2542,15 @@ static const struct stm32_desc_pin stm32mp257_z_pins[] = {
static struct stm32_pinctrl_match_data stm32mp257_match_data = {
.pins = stm32mp257_pins,
.npins = ARRAY_SIZE(stm32mp257_pins),
+ .secure_control = true,
+ .rif_control = true,
};
static struct stm32_pinctrl_match_data stm32mp257_z_match_data = {
.pins = stm32mp257_z_pins,
.npins = ARRAY_SIZE(stm32mp257_z_pins),
+ .secure_control = true,
+ .rif_control = true,
};
static const struct of_device_id stm32mp257_pctrl_match[] = {
--
2.34.1
Powered by blists - more mailing lists