diff --git a/core/arch/arm/plat-stm32mp1/conf.mk b/core/arch/arm/plat-stm32mp1/conf.mk index a72431c4caa..9236bf8a646 100644 --- a/core/arch/arm/plat-stm32mp1/conf.mk +++ b/core/arch/arm/plat-stm32mp1/conf.mk @@ -93,6 +93,7 @@ include core/arch/arm/cpu/cortex-a7.mk $(call force,CFG_DRIVERS_CLK,y) $(call force,CFG_DRIVERS_CLK_DT,y) $(call force,CFG_DRIVERS_GPIO,y) +$(call force,CFG_DRIVERS_PINCTRL,y) $(call force,CFG_GIC,y) $(call force,CFG_INIT_CNTVOFF,y) $(call force,CFG_PSCI_ARM32,y) diff --git a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.c b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.c index 8584f4a3739..2c9f816d622 100644 --- a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.c +++ b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.c @@ -460,8 +460,8 @@ static void parse_regulator_fdt_nodes(void) * Return 0 on success, 1 if no PMIC node found and a negative value otherwise */ static int dt_pmic_i2c_config(struct dt_node_info *i2c_info, - struct stm32_pinctrl **pinctrl, - size_t *pinctrl_count, + struct pinctrl_state **pinctrl_active, + struct pinctrl_state **pinctrl_sleep, struct stm32_i2c_init_s *init) { int pmic_node = 0; @@ -493,8 +493,8 @@ static int dt_pmic_i2c_config(struct dt_node_info *i2c_info, if (!i2c_info->reg) return -FDT_ERR_NOTFOUND; - if (stm32_i2c_get_setup_from_fdt(fdt, i2c_node, init, - pinctrl, pinctrl_count)) + if (stm32_i2c_get_setup_from_fdt(fdt, i2c_node, init, pinctrl_active, + pinctrl_sleep)) panic(); return 0; @@ -510,17 +510,11 @@ static bool initialize_pmic_i2c(void) int ret = 0; struct dt_node_info i2c_info = { }; struct i2c_handle_s *i2c = &i2c_handle; - struct stm32_pinctrl *pinctrl = NULL; - size_t pin_count = 0; struct stm32_i2c_init_s i2c_init = { }; - ret = dt_pmic_i2c_config(&i2c_info, &pinctrl, &pin_count, &i2c_init); - if (ret < 0) { - EMSG("I2C configuration failed %d", ret); + if (dt_pmic_i2c_config(&i2c_info, &i2c->pinctrl, &i2c->pinctrl_sleep, + &i2c_init)) panic(); - } - if (ret) - return false; /* Initialize PMIC I2C */ i2c->base.pa = i2c_info.reg; @@ -533,9 +527,6 @@ static bool initialize_pmic_i2c(void) i2c_init.analog_filter = true; i2c_init.digital_filter_coef = 0; - i2c->pinctrl = pinctrl; - i2c->pinctrl_count = pin_count; - stm32mp_get_pmic(); ret = stm32_i2c_init(i2c, &i2c_init); @@ -586,26 +577,26 @@ void stm32mp_put_pmic(void) static void register_non_secure_pmic(void) { - size_t n = 0; + size_t __maybe_unused n = 0; /* Allow this function to be called when STPMIC1 not used */ if (!i2c_handle.base.pa) return; - for (n = 0; n < i2c_handle.pinctrl_count; n++) - stm32mp_register_non_secure_gpio(i2c_handle.pinctrl[n].bank, - i2c_handle.pinctrl[n].pin); + stm32mp_register_non_secure_pinctrl(i2c_handle.pinctrl); + if (i2c_handle.pinctrl_sleep) + stm32mp_register_non_secure_pinctrl(i2c_handle.pinctrl_sleep); stm32mp_register_non_secure_periph_iomem(i2c_handle.base.pa); } static void register_secure_pmic(void) { - size_t n = 0; + size_t __maybe_unused n = 0; - for (n = 0; n < i2c_handle.pinctrl_count; n++) - stm32mp_register_secure_gpio(i2c_handle.pinctrl[n].bank, - i2c_handle.pinctrl[n].pin); + stm32mp_register_secure_pinctrl(i2c_handle.pinctrl); + if (i2c_handle.pinctrl_sleep) + stm32mp_register_secure_pinctrl(i2c_handle.pinctrl_sleep); stm32mp_register_secure_periph_iomem(i2c_handle.base.pa); register_pm_driver_cb(pmic_pm, NULL, "stm32mp1-pmic"); diff --git a/core/arch/arm/plat-stm32mp1/main.c b/core/arch/arm/plat-stm32mp1/main.c index 9cdc27a4cab..6d37fa61089 100644 --- a/core/arch/arm/plat-stm32mp1/main.c +++ b/core/arch/arm/plat-stm32mp1/main.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -578,3 +579,6 @@ static TEE_Result init_debug(void) } early_init_late(init_debug); #endif /* CFG_STM32_DEBUG_ACCESS */ + +/* Some generic resources need to be unpaged */ +DECLARE_KEEP_PAGER(pinctrl_apply_state); diff --git a/core/arch/arm/plat-stm32mp1/shared_resources.c b/core/arch/arm/plat-stm32mp1/shared_resources.c index 26cf2b305b9..d943f5406cd 100644 --- a/core/arch/arm/plat-stm32mp1/shared_resources.c +++ b/core/arch/arm/plat-stm32mp1/shared_resources.c @@ -1,9 +1,10 @@ // SPDX-License-Identifier: BSD-3-Clause /* - * Copyright (c) 2017-2022, STMicroelectronics + * Copyright (c) 2017-2023, STMicroelectronics */ #include +#include #include #include #include @@ -386,6 +387,54 @@ void stm32mp_register_non_secure_gpio(unsigned int bank, unsigned int pin) } } +void stm32mp_register_secure_pinctrl(struct pinctrl_state *pinctrl) +{ + unsigned int *bank = NULL; + unsigned int *pin = NULL; + size_t count = 0; + size_t n = 0; + + stm32_gpio_pinctrl_bank_pin(pinctrl, NULL, NULL, &count); + if (!count) + return; + + bank = calloc(count, sizeof(*bank)); + pin = calloc(count, sizeof(*pin)); + if (!bank || !pin) + panic(); + + stm32_gpio_pinctrl_bank_pin(pinctrl, bank, pin, &count); + for (n = 0; n < count; n++) + stm32mp_register_secure_gpio(bank[n], pin[n]); + + free(bank); + free(pin); +} + +void stm32mp_register_non_secure_pinctrl(struct pinctrl_state *pinctrl) +{ + unsigned int *bank = NULL; + unsigned int *pin = NULL; + size_t count = 0; + size_t n = 0; + + stm32_gpio_pinctrl_bank_pin(pinctrl, NULL, NULL, &count); + if (!count) + return; + + bank = calloc(count, sizeof(*bank)); + pin = calloc(count, sizeof(*pin)); + if (!bank || !pin) + panic(); + + stm32_gpio_pinctrl_bank_pin(pinctrl, bank, pin, &count); + for (n = 0; n < count; n++) + stm32mp_register_non_secure_gpio(bank[n], pin[n]); + + free(bank); + free(pin); +} + static void lock_registering(void) { registering_locked = true; diff --git a/core/arch/arm/plat-stm32mp1/stm32_util.h b/core/arch/arm/plat-stm32mp1/stm32_util.h index af3c37d3f9b..9eea0a107a8 100644 --- a/core/arch/arm/plat-stm32mp1/stm32_util.h +++ b/core/arch/arm/plat-stm32mp1/stm32_util.h @@ -8,9 +8,11 @@ #include #include +#include #include #include #include +#include #include /* Backup registers and RAM utils */ @@ -255,6 +257,20 @@ void stm32mp_register_secure_gpio(unsigned int bank, unsigned int pin); */ void stm32mp_register_non_secure_gpio(unsigned int bank, unsigned int pin); +/* + * Register pin resource of a pin control state as a secure peripheral + * @bank: Bank of the target GPIO + * @pin: Bit position of the target GPIO in the bank + */ +void stm32mp_register_secure_pinctrl(struct pinctrl_state *pinctrl); + +/* + * Register pin resource of a pin control state as a non-secure peripheral + * @bank: Bank of the target GPIO + * @pin: Bit position of the target GPIO in the bank + */ +void stm32mp_register_non_secure_pinctrl(struct pinctrl_state *pinctrl); + /* Return true if and only if resource @id is registered as secure */ bool stm32mp_periph_is_secure(enum stm32mp_shres id); @@ -298,6 +314,16 @@ static inline void stm32mp_register_non_secure_gpio(unsigned int bank __unused, { } +static inline void +stm32mp_register_secure_pinctrl(struct pinctrl_state *pinctrl __unused) +{ +} + +static inline void +stm32mp_register_non_secure_pinctrl(struct pinctrl_state *pinctrl __unused) +{ +} + static inline bool stm32mp_periph_is_secure(enum stm32mp_shres id __unused) { return true; diff --git a/core/drivers/crypto/se050/glue/i2c_stm32.c b/core/drivers/crypto/se050/glue/i2c_stm32.c index fb2ad6b8db1..c897d5610a0 100644 --- a/core/drivers/crypto/se050/glue/i2c_stm32.c +++ b/core/drivers/crypto/se050/glue/i2c_stm32.c @@ -5,6 +5,7 @@ */ #include +#include #include #include #include @@ -33,7 +34,8 @@ TEE_Result native_i2c_transfer(struct rpc_i2c_request *req, size_t *bytes) } static int dt_i2c_bus_config(struct stm32_i2c_init_s *init, - struct stm32_pinctrl **pctrl, size_t *pcnt) + struct pinctrl_state **pinctrl_active, + struct pinctrl_state **pinctrl_sleep) { const fdt32_t *cuint = NULL; const char *path = NULL; @@ -61,29 +63,26 @@ static int dt_i2c_bus_config(struct stm32_i2c_init_s *init, else if (I2C_STANDARD_RATE != CFG_CORE_SE05X_BAUDRATE) IMSG("SE05x ignoring CFG_CORE_SE05X_BAUDRATE, use built-in"); - return stm32_i2c_get_setup_from_fdt(fdt, node, init, pctrl, pcnt); + return stm32_i2c_get_setup_from_fdt(fdt, node, init, pinctrl_active, + pinctrl_sleep); } int native_i2c_init(void) { struct stm32_i2c_init_s i2c_init = { }; - struct stm32_pinctrl *pinctrl = NULL; - size_t pin_count = 0; /* No need to re-initialize */ if (i2c.base.pa) return 0; /* Support only one device on the platform */ - if (dt_i2c_bus_config(&i2c_init, &pinctrl, &pin_count)) + if (dt_i2c_bus_config(&i2c_init, &i2c.pinctrl, &i2c.pinctrl_sleep)) return -1; /* Probe the device */ i2c_init.own_address1 = SMCOM_I2C_ADDRESS; i2c_init.digital_filter_coef = 0; i2c_init.analog_filter = true; - i2c.pinctrl_count = pin_count; - i2c.pinctrl = pinctrl; stm32_i2c_resume(&i2c); diff --git a/core/drivers/stm32_gpio.c b/core/drivers/stm32_gpio.c index 6ffab8d8a71..e596b5a5ebe 100644 --- a/core/drivers/stm32_gpio.c +++ b/core/drivers/stm32_gpio.c @@ -6,9 +6,11 @@ */ #include +#include #include #include #include +#include #include #include #include @@ -18,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -55,6 +58,69 @@ #define DT_GPIO_BANK_NAME0 "GPIOA" +#define GPIO_MODE_INPUT U(0x0) +#define GPIO_MODE_OUTPUT U(0x1) +#define GPIO_MODE_ALTERNATE U(0x2) +#define GPIO_MODE_ANALOG U(0x3) + +#define GPIO_OTYPE_PUSH_PULL U(0x0) +#define GPIO_OTYPE_OPEN_DRAIN U(0x1) + +#define GPIO_OSPEED_LOW U(0x0) +#define GPIO_OSPEED_MEDIUM U(0x1) +#define GPIO_OSPEED_HIGH U(0x2) +#define GPIO_OSPEED_VERY_HIGH U(0x3) + +#define GPIO_PUPD_NO_PULL U(0x0) +#define GPIO_PUPD_PULL_UP U(0x1) +#define GPIO_PUPD_PULL_DOWN U(0x2) + +#define GPIO_OD_LEVEL_LOW U(0x0) +#define GPIO_OD_LEVEL_HIGH U(0x1) + +/* + * GPIO configuration description structured as single 16bit word + * for efficient save/restore when GPIO pin suspends or resumes. + * + * @mode: One of GPIO_MODE_* + * @otype: One of GPIO_OTYPE_* + * @ospeed: One of GPIO_OSPEED_* + * @pupd: One of GPIO_PUPD_* + * @od: One of GPIO_OD_* + * @af: Alternate function numerical ID between 0 and 15 + */ +struct gpio_cfg { + uint16_t mode: 2; + uint16_t otype: 1; + uint16_t ospeed: 2; + uint16_t pupd: 2; + uint16_t od: 1; + uint16_t af: 4; +}; + +/* + * Description of a pin and its muxing + * + * @bank: GPIO bank identifier as assigned by the platform + * @pin: Pin number in the GPIO bank + * @cfg: Pin configuration + */ +struct stm32_pinctrl { + uint8_t bank; + uint8_t pin; + struct gpio_cfg cfg; +}; + +/* + * struct stm32_pinctrl_array - Array of pins in a pin control state + * @count: Number of cells in @pinctrl + * @pinctrl: Pin control configuration + */ +struct stm32_pinctrl_array { + size_t count; + struct stm32_pinctrl pinctrl[]; +}; + /** * struct stm32_gpio_bank - GPIO bank instance * @@ -231,7 +297,8 @@ static struct stm32_gpio_bank *stm32_gpio_get_bank(unsigned int bank_id) } /* Save to output @cfg the current GPIO (@bank_id/@pin) configuration */ -static void get_gpio_cfg(uint32_t bank_id, uint32_t pin, struct gpio_cfg *cfg) +static void __maybe_unused get_gpio_cfg(uint32_t bank_id, uint32_t pin, + struct gpio_cfg *cfg) { struct stm32_gpio_bank *bank = stm32_gpio_get_bank(bank_id); @@ -317,67 +384,13 @@ static void set_gpio_cfg(uint32_t bank_id, uint32_t pin, struct gpio_cfg *cfg) clk_disable(bank->clock); } -void stm32_pinctrl_load_active_cfg(struct stm32_pinctrl *pinctrl, size_t cnt) -{ - size_t n = 0; - - for (n = 0; n < cnt; n++) - set_gpio_cfg(pinctrl[n].bank, pinctrl[n].pin, - &pinctrl[n].active_cfg); -} - -void stm32_pinctrl_load_standby_cfg(struct stm32_pinctrl *pinctrl, size_t cnt) -{ - size_t n = 0; - - for (n = 0; n < cnt; n++) - set_gpio_cfg(pinctrl[n].bank, pinctrl[n].pin, - &pinctrl[n].standby_cfg); -} - -void stm32_pinctrl_store_standby_cfg(struct stm32_pinctrl *pinctrl, size_t cnt) -{ - size_t n = 0; - - for (n = 0; n < cnt; n++) - get_gpio_cfg(pinctrl[n].bank, pinctrl[n].pin, - &pinctrl[n].standby_cfg); -} - -/* Panic if GPIO bank information from platform do not match DTB description */ -static void ckeck_gpio_bank(void *fdt, uint32_t bank, int pinctrl_node) -{ - int pinctrl_subnode = 0; - - fdt_for_each_subnode(pinctrl_subnode, fdt, pinctrl_node) { - const fdt32_t *cuint = NULL; - - if (fdt_getprop(fdt, pinctrl_subnode, - "gpio-controller", NULL) == NULL) - continue; - - /* Check bank register offset matches platform assumptions */ - cuint = fdt_getprop(fdt, pinctrl_subnode, "reg", NULL); - if (fdt32_to_cpu(*cuint) != stm32_get_gpio_bank_offset(bank)) - continue; - - /* Check controller is enabled */ - if (fdt_get_status(fdt, pinctrl_subnode) == DT_STATUS_DISABLED) - panic(); - - return; - } - - panic(); -} - /* Count pins described in the DT node and get related data if possible */ -static int get_pinctrl_from_fdt(void *fdt, int node, +static int get_pinctrl_from_fdt(const void *fdt, int node, struct stm32_pinctrl *pinctrl, size_t count) { - const fdt32_t *cuint, *slewrate; + const fdt32_t *cuint = NULL; + const fdt32_t *slewrate = NULL; int len = 0; - int pinctrl_node = 0; uint32_t i = 0; uint32_t speed = GPIO_OSPEED_LOW; uint32_t pull = GPIO_PUPD_NO_PULL; @@ -387,10 +400,6 @@ static int get_pinctrl_from_fdt(void *fdt, int node, if (!cuint) return -FDT_ERR_NOTFOUND; - pinctrl_node = fdt_parent_offset(fdt, fdt_parent_offset(fdt, node)); - if (pinctrl_node < 0) - return -FDT_ERR_NOTFOUND; - slewrate = fdt_getprop(fdt, node, "slew-rate", NULL); if (slewrate) speed = fdt32_to_cpu(*slewrate); @@ -464,23 +473,20 @@ static int get_pinctrl_from_fdt(void *fdt, int node, odata = 0; } - /* Check GPIO bank clock/base address against platform */ - ckeck_gpio_bank(fdt, bank, pinctrl_node); - if (found < count) { struct stm32_pinctrl *ref = &pinctrl[found]; ref->bank = (uint8_t)bank; ref->pin = (uint8_t)pin; - ref->active_cfg.mode = mode; - ref->active_cfg.otype = opendrain ? 1 : 0; - ref->active_cfg.ospeed = speed; - ref->active_cfg.pupd = pull; - ref->active_cfg.od = odata; - ref->active_cfg.af = alternate; - /* Default to analog mode for standby state */ - ref->standby_cfg.mode = GPIO_MODE_ANALOG; - ref->standby_cfg.pupd = GPIO_PUPD_NO_PULL; + ref->cfg.mode = mode; + if (opendrain) + ref->cfg.otype = GPIO_OTYPE_OPEN_DRAIN; + else + ref->cfg.otype = GPIO_OTYPE_PUSH_PULL; + ref->cfg.ospeed = speed; + ref->cfg.pupd = pull; + ref->cfg.od = odata; + ref->cfg.af = alternate; } found++; @@ -718,48 +724,6 @@ static TEE_Result dt_stm32_gpio_pinctrl(const void *fdt, int node, return TEE_SUCCESS; } -int stm32_pinctrl_fdt_get_pinctrl(void *fdt, int device_node, - struct stm32_pinctrl *pinctrl, size_t count) -{ - const fdt32_t *cuint = NULL; - int lenp = 0; - int i = 0; - size_t found = 0; - - cuint = fdt_getprop(fdt, device_node, "pinctrl-0", &lenp); - if (!cuint) - return -FDT_ERR_NOTFOUND; - - for (i = 0; i < (lenp / 4); i++) { - int node = 0; - int subnode = 0; - - node = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint)); - if (node < 0) - return -FDT_ERR_NOTFOUND; - - fdt_for_each_subnode(subnode, fdt, node) { - size_t n = 0; - int rc = 0; - - if (count > found) - n = count - found; - else - n = 0; - - rc = get_pinctrl_from_fdt(fdt, subnode, - &pinctrl[found], n); - if (rc < 0) - return rc; - - found += (size_t)rc; - } - - cuint++; - } - - return (int)found; -} int stm32_get_gpio_count(void *fdt, int pinctrl_node, unsigned int bank) { @@ -806,11 +770,169 @@ void stm32_gpio_set_secure_cfg(unsigned int bank_id, unsigned int pin, clk_disable(bank->clock); } +#ifdef CFG_DRIVERS_PINCTRL +static TEE_Result stm32_pinctrl_conf_apply(struct pinconf *conf) +{ + struct stm32_pinctrl_array *ref = conf->priv; + struct stm32_pinctrl *p = ref->pinctrl; + size_t pin_count = ref->count; + size_t n = 0; + + for (n = 0; n < pin_count; n++) + set_gpio_cfg(p[n].bank, p[n].pin, &p[n].cfg); + + return TEE_SUCCESS; +} + +static void stm32_pinctrl_conf_free(struct pinconf *conf) +{ + free(conf); +} + +static const struct pinctrl_ops stm32_pinctrl_ops = { + .conf_apply = stm32_pinctrl_conf_apply, + .conf_free = stm32_pinctrl_conf_free, +}; + +DECLARE_KEEP_PAGER(stm32_pinctrl_ops); + +void stm32_gpio_pinctrl_bank_pin(struct pinctrl_state *pinctrl, + unsigned int *bank, unsigned int *pin, + unsigned int *count) +{ + size_t conf_index = 0; + size_t pin_count = 0; + size_t n = 0; + + assert(count); + if (!pinctrl) + goto out; + + for (conf_index = 0; conf_index < pinctrl->conf_count; conf_index++) { + struct pinconf *pinconf = pinctrl->confs[conf_index]; + struct stm32_pinctrl_array *ref = pinconf->priv; + + /* Consider only the stm32_gpio pins */ + if (pinconf->ops != &stm32_pinctrl_ops) + continue; + + if (bank || pin) { + for (n = 0; n < ref->count; n++) { + if (bank && pin_count < *count) + bank[pin_count] = ref->pinctrl[n].bank; + if (pin && pin_count < *count) + pin[pin_count] = ref->pinctrl[n].pin; + pin_count++; + } + } else { + pin_count += ref->count; + } + } + +out: + *count = pin_count; +} + +void stm32_pinctrl_set_secure_cfg(struct pinctrl_state *pinctrl, bool secure) +{ + size_t conf_index = 0; + + if (!pinctrl) + return; + + for (conf_index = 0; conf_index < pinctrl->conf_count; conf_index++) { + struct pinconf *pinconf = pinctrl->confs[conf_index]; + struct stm32_pinctrl_array *ref = pinconf->priv; + struct stm32_pinctrl *pc = NULL; + size_t n = 0; + + for (n = 0; n < ref->count; n++) { + if (pinconf->ops != &stm32_pinctrl_ops) + continue; + + pc = ref->pinctrl + n; + stm32_gpio_set_secure_cfg(pc->bank, pc->pin, secure); + } + } +} + +/* Allocate and return a pinctrl configuration from a DT reference */ +static TEE_Result stm32_pinctrl_dt_get(struct dt_pargs *pargs, + void *data __unused, + struct pinconf **out_pinconf) +{ + struct conf { + struct pinconf pinconf; + struct stm32_pinctrl_array array_ref; + } *loc_conf = NULL; + struct stm32_pinctrl *pinctrl = NULL; + struct pinconf *pinconf = NULL; + const void *fdt = NULL; + size_t pin_count = 0; + int pinctrl_node = 0; + int pinmux_node = 0; + int count = 0; + + pinctrl_node = pargs->phandle_node; + fdt = pargs->fdt; + assert(fdt && pinctrl_node); + + fdt_for_each_subnode(pinmux_node, fdt, pinctrl_node) { + if (fdt_getprop(fdt, pinmux_node, "pinmux", &count)) + pin_count += (size_t)count / sizeof(uint32_t); + else if (count != -FDT_ERR_NOTFOUND) + panic(); + } + + loc_conf = calloc(1, sizeof(*loc_conf) + sizeof(*pinctrl) * pin_count); + if (!loc_conf) + return TEE_ERROR_OUT_OF_MEMORY; + + pinconf = &loc_conf->pinconf; + pinconf->ops = &stm32_pinctrl_ops; + pinconf->priv = &loc_conf->array_ref; + + loc_conf->array_ref.count = pin_count; + pinctrl = loc_conf->array_ref.pinctrl; + + count = 0; + fdt_for_each_subnode(pinmux_node, fdt, pinctrl_node) { + int found = 0; + + found = get_pinctrl_from_fdt(fdt, pinmux_node, pinctrl + count, + pin_count - count); + if (found <= 0 && found > ((int)pin_count - count)) { + /* We can't recover from an error here so let's panic */ + panic(); + } + + count += found; + } + + *out_pinconf = pinconf; + + return TEE_SUCCESS; +} +#endif /*CFG_DRIVERS_PINCTRL*/ + static TEE_Result stm32_pinctrl_probe(const void *fdt, int node, const void *compat_data) { + TEE_Result res = TEE_ERROR_GENERIC; + /* Register GPIO banks described in this pin control node */ - return dt_stm32_gpio_pinctrl(fdt, node, compat_data); + res = dt_stm32_gpio_pinctrl(fdt, node, compat_data); + if (res) + return res; + +#ifdef CFG_DRIVERS_PINCTRL + res = pinctrl_register_provider(fdt, node, stm32_pinctrl_dt_get, + (void *)compat_data); + if (res) + return res; +#endif + + return TEE_SUCCESS; } static const struct dt_device_match stm32_pinctrl_match_table[] = { diff --git a/core/drivers/stm32_i2c.c b/core/drivers/stm32_i2c.c index 638208f1c32..024e1be513a 100644 --- a/core/drivers/stm32_i2c.c +++ b/core/drivers/stm32_i2c.c @@ -12,6 +12,8 @@ #include #include #include +#include +#include #include #include #include @@ -684,13 +686,13 @@ static int i2c_config_analog_filter(struct i2c_handle_s *hi2c, TEE_Result stm32_i2c_get_setup_from_fdt(void *fdt, int node, struct stm32_i2c_init_s *init, - struct stm32_pinctrl **pinctrl, - size_t *pinctrl_count) + struct pinctrl_state **pinctrl, + struct pinctrl_state **pinctrl_sleep) { TEE_Result res = TEE_ERROR_GENERIC; const fdt32_t *cuint = NULL; struct dt_node_info info = { .status = 0 }; - int count = 0; + int __maybe_unused count = 0; /* Default STM32 specific configs caller may need to overwrite */ memset(init, 0, sizeof(*init)); @@ -732,27 +734,21 @@ TEE_Result stm32_i2c_get_setup_from_fdt(void *fdt, int node, init->bus_rate = I2C_STANDARD_RATE; } - count = stm32_pinctrl_fdt_get_pinctrl(fdt, node, NULL, 0); - if (count <= 0) { - *pinctrl = NULL; - *pinctrl_count = count; - DMSG("Failed to get pinctrl: FDT errno %d", count); - return TEE_ERROR_GENERIC; + if (pinctrl) { + res = pinctrl_get_state_by_name(fdt, node, "default", pinctrl); + if (res) + return res; } - if (count > 2) { - DMSG("Too many PINCTRLs found: %zd", count); - return TEE_ERROR_GENERIC; + if (pinctrl_sleep) { + res = pinctrl_get_state_by_name(fdt, node, "sleep", + pinctrl_sleep); + if (res == TEE_ERROR_ITEM_NOT_FOUND) + res = TEE_SUCCESS; + if (res) + return res; } - *pinctrl = calloc(count, sizeof(**pinctrl)); - if (!*pinctrl) - return TEE_ERROR_OUT_OF_MEMORY; - - *pinctrl_count = stm32_pinctrl_fdt_get_pinctrl(fdt, node, - *pinctrl, count); - assert(*pinctrl_count == (unsigned int)count); - return TEE_SUCCESS; } @@ -834,13 +830,8 @@ int stm32_i2c_init(struct i2c_handle_s *hi2c, if (rc) DMSG("I2C analog filter error %d", rc); - if (IS_ENABLED(CFG_STM32MP13)) { - size_t n = 0; - - for (n = 0; n < hi2c->pinctrl_count; n++) - stm32_gpio_set_secure_cfg(hi2c->pinctrl[n].bank, - hi2c->pinctrl[n].pin, true); - } + if (IS_ENABLED(CFG_STM32MP13)) + stm32_pinctrl_set_secure_cfg(hi2c->pinctrl, true); clk_disable(hi2c->clock); @@ -1531,7 +1522,8 @@ void stm32_i2c_resume(struct i2c_handle_s *hi2c) (hi2c->i2c_state != I2C_STATE_SUSPENDED)) panic(); - stm32_pinctrl_load_active_cfg(hi2c->pinctrl, hi2c->pinctrl_count); + if (pinctrl_apply_state(hi2c->pinctrl)) + panic(); if (hi2c->i2c_state == I2C_STATE_RESET) { /* There is no valid I2C configuration to be loaded yet */ @@ -1540,13 +1532,8 @@ void stm32_i2c_resume(struct i2c_handle_s *hi2c) restore_cfg(hi2c, &hi2c->sec_cfg); - if (IS_ENABLED(CFG_STM32MP13)) { - size_t n = 0; - - for (n = 0; n < hi2c->pinctrl_count; n++) - stm32_gpio_set_secure_cfg(hi2c->pinctrl[n].bank, - hi2c->pinctrl[n].pin, true); - } + if (IS_ENABLED(CFG_STM32MP13)) + stm32_pinctrl_set_secure_cfg(hi2c->pinctrl, true); hi2c->i2c_state = I2C_STATE_READY; } @@ -1560,7 +1547,9 @@ void stm32_i2c_suspend(struct i2c_handle_s *hi2c) panic(); save_cfg(hi2c, &hi2c->sec_cfg); - stm32_pinctrl_load_standby_cfg(hi2c->pinctrl, hi2c->pinctrl_count); + + if (hi2c->pinctrl_sleep && pinctrl_apply_state(hi2c->pinctrl_sleep)) + panic(); hi2c->i2c_state = I2C_STATE_SUSPENDED; } diff --git a/core/drivers/stm32_uart.c b/core/drivers/stm32_uart.c index 7c1ec52eeb7..3862b607cc1 100644 --- a/core/drivers/stm32_uart.c +++ b/core/drivers/stm32_uart.c @@ -110,22 +110,22 @@ void stm32_uart_init(struct stm32_uart_pdata *pd, vaddr_t base) static void register_secure_uart(struct stm32_uart_pdata *pd) { - size_t n = 0; + size_t __maybe_unused n = 0; stm32mp_register_secure_periph_iomem(pd->base.pa); - for (n = 0; n < pd->pinctrl_count; n++) - stm32mp_register_secure_gpio(pd->pinctrl[n].bank, - pd->pinctrl[n].pin); + stm32mp_register_secure_pinctrl(pd->pinctrl); + if (pd->pinctrl_sleep) + stm32mp_register_secure_pinctrl(pd->pinctrl_sleep); } static void register_non_secure_uart(struct stm32_uart_pdata *pd) { - size_t n = 0; + size_t __maybe_unused n = 0; stm32mp_register_non_secure_periph_iomem(pd->base.pa); - for (n = 0; n < pd->pinctrl_count; n++) - stm32mp_register_non_secure_gpio(pd->pinctrl[n].bank, - pd->pinctrl[n].pin); + stm32mp_register_non_secure_pinctrl(pd->pinctrl); + if (pd->pinctrl_sleep) + stm32mp_register_non_secure_pinctrl(pd->pinctrl_sleep); } struct stm32_uart_pdata *stm32_uart_init_from_dt_node(void *fdt, int node) @@ -133,8 +133,6 @@ struct stm32_uart_pdata *stm32_uart_init_from_dt_node(void *fdt, int node) TEE_Result res = TEE_ERROR_GENERIC; struct stm32_uart_pdata *pd = NULL; struct dt_node_info info = { }; - struct stm32_pinctrl *pinctrl_cfg = NULL; - int count = 0; fdt_fill_device_info(fdt, &info, node); @@ -167,20 +165,17 @@ struct stm32_uart_pdata *stm32_uart_init_from_dt_node(void *fdt, int node) pd->secure ? MEM_AREA_IO_SEC : MEM_AREA_IO_NSEC, info.reg_size); - count = stm32_pinctrl_fdt_get_pinctrl(fdt, node, NULL, 0); - if (count < 0) + res = pinctrl_get_state_by_name(fdt, node, "default", &pd->pinctrl); + if (res) panic(); - if (count) { - pinctrl_cfg = calloc(count, sizeof(*pinctrl_cfg)); - if (!pinctrl_cfg) - panic(); + res = pinctrl_get_state_by_name(fdt, node, "sleep", &pd->pinctrl_sleep); + if (res && res != TEE_ERROR_ITEM_NOT_FOUND) + panic(); - stm32_pinctrl_fdt_get_pinctrl(fdt, node, pinctrl_cfg, count); - stm32_pinctrl_load_active_cfg(pinctrl_cfg, count); - } - pd->pinctrl = pinctrl_cfg; - pd->pinctrl_count = count; + res = pinctrl_apply_state(pd->pinctrl); + if (res) + panic(); if (pd->secure) register_secure_uart(pd); diff --git a/core/include/drivers/stm32_gpio.h b/core/include/drivers/stm32_gpio.h index f3f5c08daf4..adc85358c21 100644 --- a/core/include/drivers/stm32_gpio.h +++ b/core/include/drivers/stm32_gpio.h @@ -1,115 +1,19 @@ /* SPDX-License-Identifier: BSD-3-Clause */ /* - * Copyright (c) 2017-2019, STMicroelectronics - * - * STM32 GPIO driver relies on platform util fiunctions to get base address - * and clock ID of the GPIO banks. The drvier API allows to retrieve pin muxing - * configuration for given nodes and load them at runtime. A pin control - * instance provide an active and a standby configuration. Pin onwer is - * responsible to load to expected configuration during PM state transitions - * as STM32 GPIO driver does no register callbacks to the PM framework. + * Copyright (c) 2017-2023, STMicroelectronics */ #ifndef DRIVERS_STM32_GPIO_H #define DRIVERS_STM32_GPIO_H #include +#include #include #include #include -#define GPIO_MODE_INPUT 0x0 -#define GPIO_MODE_OUTPUT 0x1 -#define GPIO_MODE_ALTERNATE 0x2 -#define GPIO_MODE_ANALOG 0x3 - -#define GPIO_OTYPE_PUSH_PULL 0x0 -#define GPIO_OTYPE_OPEN_DRAIN 0x1 - -#define GPIO_OSPEED_LOW 0x0 -#define GPIO_OSPEED_MEDIUM 0x1 -#define GPIO_OSPEED_HIGH 0x2 -#define GPIO_OSPEED_VERY_HIGH 0x3 - -#define GPIO_PUPD_NO_PULL 0x0 -#define GPIO_PUPD_PULL_UP 0x1 -#define GPIO_PUPD_PULL_DOWN 0x2 - -#define GPIO_OD_LEVEL_LOW 0x0 -#define GPIO_OD_LEVEL_HIGH 0x1 - -/* - * GPIO configuration description structured as single 16bit word - * for efficient save/restore when GPIO pin suspends or resumes. - * - * @mode: One of GPIO_MODE_* - * @otype: One of GPIO_OTYPE_* - * @ospeed: One of GPIO_OSPEED_* - * @pupd: One of GPIO_PUPD_* - * @od: One of GPIO_OD_* - * @af: Alternate function numerical ID between 0 and 15 - */ -struct gpio_cfg { - uint16_t mode: 2; - uint16_t otype: 1; - uint16_t ospeed: 2; - uint16_t pupd: 2; - uint16_t od: 1; - uint16_t af: 4; -}; - -/* - * Descrption of a pin and its 2 states muxing - * - * @bank: GPIO bank identifier as assigned by the platform - * @pin: Pin number in the GPIO bank - * @active_cfg: Configuration in active state - * @standby_cfg: Configuration in standby state - */ -struct stm32_pinctrl { - uint8_t bank; - uint8_t pin; - struct gpio_cfg active_cfg; - struct gpio_cfg standby_cfg; -}; - -/* - * Apply series of pin muxing configuration, active state and standby state - * - * @pinctrl: array of pinctrl references - * @count: Number of entries in @pinctrl - */ -void stm32_pinctrl_load_active_cfg(struct stm32_pinctrl *pinctrl, size_t cnt); -void stm32_pinctrl_load_standby_cfg(struct stm32_pinctrl *pinctrl, size_t cnt); - -/* - * Save the current pin configuration as the standby state for a pin series - * - * @pinctrl: array of pinctrl references - * @count: Number of entries in @pinctrl - */ -void stm32_pinctrl_store_standby_cfg(struct stm32_pinctrl *pinctrl, size_t cnt); - -/* - * Save pinctrl instances defined in DT node: identifiers and power states - * - * @fdt: device tree - * @node: device node in the device tree - * @pinctrl: NULL or pointer to array of struct stm32_pinctrl - * @count: number of elements pointed by argument cfg - * - * Return the number of pinctrl instances found or a negative value on error. - * - * When @count is 0, @pinctrl may be NULL. The function will return only the - * number of pinctrl instances found in the device tree for the target - * device node. - * - * If more instances than @count are found then the function returns the - * effective number of pincltr instance found in the node but fills - * output array @pinctrl only for the input @count first entries. - */ -int stm32_pinctrl_fdt_get_pinctrl(void *fdt, int node, - struct stm32_pinctrl *pinctrl, size_t count); +struct pinctrl_state; +struct stm32_pinctrl; #ifdef CFG_STM32_GPIO /* @@ -121,14 +25,6 @@ int stm32_pinctrl_fdt_get_pinctrl(void *fdt, int node, */ void stm32_gpio_set_secure_cfg(unsigned int bank, unsigned int pin, bool secure); -#else -static inline void stm32_gpio_set_secure_cfg(unsigned int bank __unused, - unsigned int pin __unused, - bool secure __unused) -{ - assert(0); -} -#endif /* * Get the number of GPIO pins supported by a target GPIO bank @@ -140,4 +36,36 @@ static inline void stm32_gpio_set_secure_cfg(unsigned int bank __unused, */ int stm32_get_gpio_count(void *fdt, int pinctrl_node, unsigned int bank); +/* + * Configure pin muxing access permission: can be secure or not + * + * @pinctrl: Pin control state where STM32_GPIO pin are to configure + * @secure: True if pin is secure, false otherwise + */ +void stm32_pinctrl_set_secure_cfg(struct pinctrl_state *pinctrl, bool secure); + +/* + * Get the bank and pin indices related to a pin control state + * @pinctrl: Pinctrl state + * @bank: Output bank indices array or NULL + * @pin: Output pin indices array or NULL + * @count: [in] Number of cells of @bank and @pin, [out] pin count in @pinctrl + */ +void stm32_gpio_pinctrl_bank_pin(struct pinctrl_state *pinctrl, + unsigned int *bank, unsigned int *pin, + unsigned int *count); +#else +static inline void +stm32_pinctrl_set_secure_cfg(struct pinctrl_state *pinctrl __unused, + bool secure __unused) +{ +} + +static inline void stm32_gpio_pinctrl_bank_pin(struct pinctrl_state *p __unused, + unsigned int *bank __unused, + unsigned int *pin __unused, + unsigned int *count __unused) +{ +} +#endif /*CFG_STM32_GPIO*/ #endif /*DRIVERS_STM32_GPIO_H*/ diff --git a/core/include/drivers/stm32_i2c.h b/core/include/drivers/stm32_i2c.h index 39b32446623..7fb5c1aec09 100644 --- a/core/include/drivers/stm32_i2c.h +++ b/core/include/drivers/stm32_i2c.h @@ -1,13 +1,13 @@ /* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ /* - * Copyright (c) 2017-2019, STMicroelectronics + * Copyright (c) 2017-2023, STMicroelectronics */ -#ifndef __STM32_I2C_H -#define __STM32_I2C_H +#ifndef DRIVERS_STM32_I2C_H +#define DRIVERS_STM32_I2C_H #include -#include +#include #include #include #include @@ -111,8 +111,8 @@ struct i2c_cfg { * @saved_timing: Saved timing value if already computed * @saved_frequency: Saved frequency value if already computed * @sec_cfg: I2C registers configuration storage - * @pinctrl: PINCTRLs configuration for the I2C PINs - * @pinctrl_count: Number of PINCTRLs elements + * @pinctrl: Pin control configuration for the I2C bus in active state + * @pinctrl_sleep: Pin control configuration for the I2C bus in standby state */ struct i2c_handle_s { struct io_pa_va base; @@ -124,8 +124,8 @@ struct i2c_handle_s { uint32_t saved_timing; unsigned long saved_frequency; struct i2c_cfg sec_cfg; - struct stm32_pinctrl *pinctrl; - size_t pinctrl_count; + struct pinctrl_state *pinctrl; + struct pinctrl_state *pinctrl_sleep; }; /* STM32 specific defines */ @@ -141,14 +141,14 @@ struct i2c_handle_s { * @fdt: Reference to DT * @node: Target I2C node in the DT * @init: Output stm32_i2c_init_s structure - * @pinctrl: Reference to output pinctrl array - * @pinctrl_count: Input @pinctrl array size, output expected size upon success + * @pinctrl_active: Output active I2C pinctrl state + * @pinctrl_sleep: Output suspended I2C pinctrl state * Return a TEE_Result compliant value */ TEE_Result stm32_i2c_get_setup_from_fdt(void *fdt, int node, struct stm32_i2c_init_s *init, - struct stm32_pinctrl **pinctrl, - size_t *pinctrl_count); + struct pinctrl_state **pinctrl_active, + struct pinctrl_state **pinctrl_sleep); /* * Initialize I2C bus handle from input configuration directives @@ -265,4 +265,4 @@ static inline bool i2c_is_secure(struct i2c_handle_s *hi2c) return hi2c->dt_status == DT_STATUS_OK_SEC; } -#endif /* __STM32_I2C_H */ +#endif /* DRIVERS_STM32_I2C_H*/ diff --git a/core/include/drivers/stm32_uart.h b/core/include/drivers/stm32_uart.h index 021b2b9d892..250737f339f 100644 --- a/core/include/drivers/stm32_uart.h +++ b/core/include/drivers/stm32_uart.h @@ -1,22 +1,25 @@ /* SPDX-License-Identifier: BSD-2-Clause */ /* - * Copyright (c) 2017-2018, STMicroelectronics + * Copyright (c) 2017-2023, STMicroelectronics */ -#ifndef __STM32_UART_H__ -#define __STM32_UART_H__ +#ifndef DRIVERS_STM32_UART_H +#define DRIVERS_STM32_UART_H #include +#include #include -#include +#include +#include +#include struct stm32_uart_pdata { struct io_pa_va base; struct serial_chip chip; bool secure; struct clk *clock; - struct stm32_pinctrl *pinctrl; - size_t pinctrl_count; + struct pinctrl_state *pinctrl; + struct pinctrl_state *pinctrl_sleep; }; /* @@ -39,4 +42,4 @@ void stm32_uart_init(struct stm32_uart_pdata *pd, vaddr_t base); */ struct stm32_uart_pdata *stm32_uart_init_from_dt_node(void *fdt, int node); -#endif /*__STM32_UART_H__*/ +#endif /*DRIVERS_STM32_UART_H*/