pinctrl: stm32: prevent the use of the secure protected pins
authorFabien Dessenne <fabien.dessenne@foss.st.com>
Mon, 2 May 2022 15:31:14 +0000 (17:31 +0200)
committerLinus Walleij <linus.walleij@linaro.org>
Wed, 4 May 2022 22:04:04 +0000 (00:04 +0200)
The hardware denies any access from the Linux non-secure world to the
secure-protected pins. Hence, prevent any driver to request such a pin.

Mark the secure-protected GPIO lines as invalid (.init_valid_mask) and
prevent the pinmux request / pinconf setting operations.
Identify the secure pins with "NO ACCESS" in the pinconf sysfs.

Signed-off-by: Fabien Dessenne <fabien.dessenne@foss.st.com>
Link: https://lore.kernel.org/r/20220502153114.283618-1-fabien.dessenne@foss.st.com
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
drivers/pinctrl/stm32/pinctrl-stm32.c
drivers/pinctrl/stm32/pinctrl-stm32.h
drivers/pinctrl/stm32/pinctrl-stm32mp135.c

index 1e0802923cbda660b5a32784c3e22071da85902c..0f7d608151ff578bc31265fed5d54aa5aaafd8b7 100644 (file)
@@ -44,6 +44,7 @@
 #define STM32_GPIO_LCKR                0x1c
 #define STM32_GPIO_AFRL                0x20
 #define STM32_GPIO_AFRH                0x24
+#define STM32_GPIO_SECCFGR     0x30
 
 /* custom bitfield to backup pin status */
 #define STM32_GPIO_BKP_MODE_SHIFT      0
@@ -95,6 +96,7 @@ struct stm32_gpio_bank {
        u32 bank_ioport_nr;
        u32 pin_backup[STM32_GPIO_PINS_PER_BANK];
        u8 irq_type[STM32_GPIO_PINS_PER_BANK];
+       bool secure_control;
 };
 
 struct stm32_pinctrl {
@@ -284,6 +286,33 @@ static int stm32_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
        return ret;
 }
 
+static int stm32_gpio_init_valid_mask(struct gpio_chip *chip,
+                                     unsigned long *valid_mask,
+                                     unsigned int ngpios)
+{
+       struct stm32_gpio_bank *bank = gpiochip_get_data(chip);
+       struct stm32_pinctrl *pctl = dev_get_drvdata(bank->gpio_chip.parent);
+       unsigned int i;
+       u32 sec;
+
+       /* All gpio are valid per default */
+       bitmap_fill(valid_mask, ngpios);
+
+       if (bank->secure_control) {
+               /* Tag secured pins as invalid */
+               sec = readl_relaxed(bank->base + STM32_GPIO_SECCFGR);
+
+               for (i = 0; i < ngpios; i++) {
+                       if (sec & BIT(i)) {
+                               clear_bit(i, valid_mask);
+                               dev_dbg(pctl->dev, "No access to gpio %d - %d\n", bank->bank_nr, i);
+                       }
+               }
+       }
+
+       return 0;
+}
+
 static const struct gpio_chip stm32_gpio_template = {
        .request                = stm32_gpio_request,
        .free                   = stm32_gpio_free,
@@ -294,6 +323,7 @@ static const struct gpio_chip stm32_gpio_template = {
        .to_irq                 = stm32_gpio_to_irq,
        .get_direction          = stm32_gpio_get_direction,
        .set_config             = gpiochip_generic_config,
+       .init_valid_mask        = stm32_gpio_init_valid_mask,
 };
 
 static void stm32_gpio_irq_trigger(struct irq_data *d)
@@ -838,12 +868,32 @@ static int stm32_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
        return stm32_pmx_set_mode(bank, pin, !input, 0);
 }
 
+static int stm32_pmx_request(struct pinctrl_dev *pctldev, unsigned int gpio)
+{
+       struct stm32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+       struct pinctrl_gpio_range *range;
+
+       range = pinctrl_find_gpio_range_from_pin_nolock(pctldev, gpio);
+       if (!range) {
+               dev_err(pctl->dev, "No gpio range defined.\n");
+               return -EINVAL;
+       }
+
+       if (!gpiochip_line_is_valid(range->gc, stm32_gpio_pin(gpio))) {
+               dev_warn(pctl->dev, "Can't access gpio %d\n", gpio);
+               return -EACCES;
+       }
+
+       return 0;
+}
+
 static const struct pinmux_ops stm32_pmx_ops = {
        .get_functions_count    = stm32_pmx_get_funcs_cnt,
        .get_function_name      = stm32_pmx_get_func_name,
        .get_function_groups    = stm32_pmx_get_func_groups,
        .set_mux                = stm32_pmx_set_mux,
        .gpio_set_direction     = stm32_pmx_gpio_set_direction,
+       .request                = stm32_pmx_request,
        .strict                 = true,
 };
 
@@ -1040,6 +1090,11 @@ static int stm32_pconf_parse_conf(struct pinctrl_dev *pctldev,
        bank = gpiochip_get_data(range->gc);
        offset = stm32_gpio_pin(pin);
 
+       if (!gpiochip_line_is_valid(range->gc, offset)) {
+               dev_warn(pctl->dev, "Can't access gpio %d\n", pin);
+               return -EACCES;
+       }
+
        switch (param) {
        case PIN_CONFIG_DRIVE_PUSH_PULL:
                ret = stm32_pconf_set_driving(bank, offset, 0);
@@ -1159,6 +1214,11 @@ static void stm32_pconf_dbg_show(struct pinctrl_dev *pctldev,
        bank = gpiochip_get_data(range->gc);
        offset = stm32_gpio_pin(pin);
 
+       if (!gpiochip_line_is_valid(range->gc, offset)) {
+               seq_puts(s, "NO ACCESS");
+               return;
+       }
+
        stm32_pmx_get_mode(bank, offset, &mode, &alt);
        bias = stm32_pconf_get_bias(bank, offset);
 
@@ -1275,6 +1335,7 @@ static int stm32_gpiolib_register_bank(struct stm32_pinctrl *pctl, struct fwnode
        bank->gpio_chip.parent = dev;
        bank->bank_nr = bank_nr;
        bank->bank_ioport_nr = bank_ioport_nr;
+       bank->secure_control = pctl->match_data->secure_control;
        spin_lock_init(&bank->lock);
 
        /* create irq hierarchical domain */
@@ -1578,6 +1639,9 @@ static int __maybe_unused stm32_pinctrl_restore_gpio_regs(
        if (!range)
                return 0;
 
+       if (!gpiochip_line_is_valid(range->gc, offset))
+               return 0;
+
        pin_is_irq = gpiochip_line_is_irq(range->gc, offset);
 
        if (!desc || (!pin_is_irq && !desc->gpio_owner))
index 2ac2db41a498b0edc25646647936a65a57d5c553..e0c31c4c8bca8fa4e0e7015838a444b2d19c9887 100644 (file)
@@ -59,6 +59,7 @@ struct stm32_desc_pin {
 struct stm32_pinctrl_match_data {
        const struct stm32_desc_pin *pins;
        const unsigned int npins;
+       bool secure_control;
 };
 
 struct stm32_gpio_bank;
index f98717fe23edabdacf75fa8d1aea3cc1f65031f6..fde1df191c2474906da291a9831febbc1fcbff31 100644 (file)
@@ -1649,6 +1649,7 @@ static const struct stm32_desc_pin stm32mp135_pins[] = {
 static struct stm32_pinctrl_match_data stm32mp135_match_data = {
        .pins = stm32mp135_pins,
        .npins = ARRAY_SIZE(stm32mp135_pins),
+       .secure_control = true,
 };
 
 static const struct of_device_id stm32mp135_pctrl_match[] = {