14b5e93edSEtienne Carriere // SPDX-License-Identifier: BSD-3-Clause 24b5e93edSEtienne Carriere /* 3bd03c8c3SGatien Chevallier * Copyright (c) 2017-2024, STMicroelectronics 44b5e93edSEtienne Carriere * 54b5e93edSEtienne Carriere * STM32 GPIO driver is used as pin controller for stm32mp SoCs. 64b5e93edSEtienne Carriere */ 74b5e93edSEtienne Carriere 84b5e93edSEtienne Carriere #include <assert.h> 969715ce9SEtienne Carriere #include <compiler.h> 1097391ffbSEtienne Carriere #include <drivers/clk.h> 1197391ffbSEtienne Carriere #include <drivers/clk_dt.h> 12420a32c5SEtienne Carriere #include <drivers/gpio.h> 13b38386fbSEtienne Carriere #include <drivers/pinctrl.h> 144b5e93edSEtienne Carriere #include <drivers/stm32_gpio.h> 15bd03c8c3SGatien Chevallier #include <drivers/stm32_rif.h> 16bd03c8c3SGatien Chevallier #include <dt-bindings/gpio/gpio.h> 174b5e93edSEtienne Carriere #include <io.h> 184b5e93edSEtienne Carriere #include <kernel/dt.h> 1965401337SJens Wiklander #include <kernel/boot.h> 204b5e93edSEtienne Carriere #include <kernel/panic.h> 21bfc43b68SGatien Chevallier #include <kernel/pm.h> 224b5e93edSEtienne Carriere #include <kernel/spinlock.h> 23a2fc83d1SJerome Forissier #include <libfdt.h> 244b5e93edSEtienne Carriere #include <mm/core_memprot.h> 254b5e93edSEtienne Carriere #include <stdbool.h> 2669715ce9SEtienne Carriere #include <stdint.h> 274b5e93edSEtienne Carriere #include <stm32_util.h> 289818a481SEtienne Carriere #include <sys/queue.h> 294b5e93edSEtienne Carriere #include <trace.h> 304b5e93edSEtienne Carriere #include <util.h> 314b5e93edSEtienne Carriere 321001585eSEtienne Carriere #ifndef CFG_DRIVERS_GPIO 331001585eSEtienne Carriere #error stm32_gpio driver expects CFG_DRIVERS_GPIO 341001585eSEtienne Carriere #endif 351001585eSEtienne Carriere 364b5e93edSEtienne Carriere #define GPIO_PIN_MAX 15 374b5e93edSEtienne Carriere 385eed568cSGatien Chevallier #define GPIO_MODER_OFFSET U(0x00) 395eed568cSGatien Chevallier #define GPIO_OTYPER_OFFSET U(0x04) 405eed568cSGatien Chevallier #define GPIO_OSPEEDR_OFFSET U(0x08) 415eed568cSGatien Chevallier #define GPIO_PUPDR_OFFSET U(0x0c) 425eed568cSGatien Chevallier #define GPIO_IDR_OFFSET U(0x10) 435eed568cSGatien Chevallier #define GPIO_ODR_OFFSET U(0x14) 445eed568cSGatien Chevallier #define GPIO_BSRR_OFFSET U(0x18) 455eed568cSGatien Chevallier #define GPIO_AFRL_OFFSET U(0x20) 465eed568cSGatien Chevallier #define GPIO_AFRH_OFFSET U(0x24) 475eed568cSGatien Chevallier #define GPIO_SECR_OFFSET U(0x30) 48bd03c8c3SGatien Chevallier #define GPIO_PRIVCFGR_OFFSET U(0x34) 49bd03c8c3SGatien Chevallier #define GPIO_RCFGLOCKR_OFFSET U(0x38) 50bd03c8c3SGatien Chevallier #define GPIO_CIDCFGR(x) (U(0x50) + U(0x8) * (x)) 51bd03c8c3SGatien Chevallier #define GPIO_SEMCR(x) (U(0x54) + U(0x8) * (x)) 524b5e93edSEtienne Carriere 535eed568cSGatien Chevallier #define GPIO_ALT_LOWER_LIMIT U(0x8) 544b5e93edSEtienne Carriere 55bd03c8c3SGatien Chevallier /* 56bd03c8c3SGatien Chevallier * CIDCFGR register bitfields 57bd03c8c3SGatien Chevallier */ 58bd03c8c3SGatien Chevallier #define GPIO_CIDCFGR_SEMWL_MASK GENMASK_32(23, 16) 59bd03c8c3SGatien Chevallier #define GPIO_CIDCFGR_SCID_MASK GENMASK_32(6, 4) 60bd03c8c3SGatien Chevallier #define GPIO_CIDCFGR_CONF_MASK (_CIDCFGR_CFEN | _CIDCFGR_SEMEN | \ 61bd03c8c3SGatien Chevallier GPIO_CIDCFGR_SCID_MASK | \ 62bd03c8c3SGatien Chevallier GPIO_CIDCFGR_SEMWL_MASK) 63bd03c8c3SGatien Chevallier 64bd03c8c3SGatien Chevallier /* 65bd03c8c3SGatien Chevallier * PRIVCFGR register bitfields 66bd03c8c3SGatien Chevallier */ 67bd03c8c3SGatien Chevallier #define GPIO_PRIVCFGR_MASK GENMASK_32(15, 0) 68bd03c8c3SGatien Chevallier 69bd03c8c3SGatien Chevallier /* 70bd03c8c3SGatien Chevallier * SECCFGR register bitfields 71bd03c8c3SGatien Chevallier */ 72bd03c8c3SGatien Chevallier #define GPIO_SECCFGR_MASK GENMASK_32(15, 0) 73bd03c8c3SGatien Chevallier 74bd03c8c3SGatien Chevallier /* 75bd03c8c3SGatien Chevallier * RCFGLOCKR register bitfields 76bd03c8c3SGatien Chevallier */ 77bd03c8c3SGatien Chevallier #define GPIO_RCFGLOCKR_MASK GENMASK_32(15, 0) 78bd03c8c3SGatien Chevallier 79bd03c8c3SGatien Chevallier /* 80bd03c8c3SGatien Chevallier * SEMCR register bitfields 81bd03c8c3SGatien Chevallier */ 82bd03c8c3SGatien Chevallier #define GPIO_SEMCR_SCID_M GENMASK_32(6, 4) 83bd03c8c3SGatien Chevallier 844b5e93edSEtienne Carriere #define GPIO_MODE_MASK GENMASK_32(1, 0) 854b5e93edSEtienne Carriere #define GPIO_OSPEED_MASK GENMASK_32(1, 0) 864b5e93edSEtienne Carriere #define GPIO_PUPD_PULL_MASK GENMASK_32(1, 0) 87729093d5SLionel Debieve #define GPIO_ALTERNATE_MASK GENMASK_32(3, 0) 884b5e93edSEtienne Carriere 895eed568cSGatien Chevallier #define DT_GPIO_BANK_SHIFT U(12) 904b5e93edSEtienne Carriere #define DT_GPIO_BANK_MASK GENMASK_32(16, 12) 915eed568cSGatien Chevallier #define DT_GPIO_PIN_SHIFT U(8) 924b5e93edSEtienne Carriere #define DT_GPIO_PIN_MASK GENMASK_32(11, 8) 934b5e93edSEtienne Carriere #define DT_GPIO_MODE_MASK GENMASK_32(7, 0) 944b5e93edSEtienne Carriere 959818a481SEtienne Carriere #define DT_GPIO_BANK_NAME0 "GPIOA" 969818a481SEtienne Carriere 9769715ce9SEtienne Carriere #define GPIO_MODE_INPUT U(0x0) 9869715ce9SEtienne Carriere #define GPIO_MODE_OUTPUT U(0x1) 9969715ce9SEtienne Carriere #define GPIO_MODE_ALTERNATE U(0x2) 10069715ce9SEtienne Carriere #define GPIO_MODE_ANALOG U(0x3) 10169715ce9SEtienne Carriere 10269715ce9SEtienne Carriere #define GPIO_OTYPE_PUSH_PULL U(0x0) 10369715ce9SEtienne Carriere #define GPIO_OTYPE_OPEN_DRAIN U(0x1) 10469715ce9SEtienne Carriere 10569715ce9SEtienne Carriere #define GPIO_OSPEED_LOW U(0x0) 10669715ce9SEtienne Carriere #define GPIO_OSPEED_MEDIUM U(0x1) 10769715ce9SEtienne Carriere #define GPIO_OSPEED_HIGH U(0x2) 10869715ce9SEtienne Carriere #define GPIO_OSPEED_VERY_HIGH U(0x3) 10969715ce9SEtienne Carriere 11069715ce9SEtienne Carriere #define GPIO_PUPD_NO_PULL U(0x0) 11169715ce9SEtienne Carriere #define GPIO_PUPD_PULL_UP U(0x1) 11269715ce9SEtienne Carriere #define GPIO_PUPD_PULL_DOWN U(0x2) 11369715ce9SEtienne Carriere 11469715ce9SEtienne Carriere #define GPIO_OD_LEVEL_LOW U(0x0) 11569715ce9SEtienne Carriere #define GPIO_OD_LEVEL_HIGH U(0x1) 11669715ce9SEtienne Carriere 117bd03c8c3SGatien Chevallier #define GPIO_MAX_CID_SUPPORTED U(3) 118bd03c8c3SGatien Chevallier 11969715ce9SEtienne Carriere /* 12069715ce9SEtienne Carriere * GPIO configuration description structured as single 16bit word 12169715ce9SEtienne Carriere * for efficient save/restore when GPIO pin suspends or resumes. 12269715ce9SEtienne Carriere * 12369715ce9SEtienne Carriere * @mode: One of GPIO_MODE_* 12469715ce9SEtienne Carriere * @otype: One of GPIO_OTYPE_* 12569715ce9SEtienne Carriere * @ospeed: One of GPIO_OSPEED_* 12669715ce9SEtienne Carriere * @pupd: One of GPIO_PUPD_* 12769715ce9SEtienne Carriere * @od: One of GPIO_OD_* 12869715ce9SEtienne Carriere * @af: Alternate function numerical ID between 0 and 15 12969715ce9SEtienne Carriere */ 13069715ce9SEtienne Carriere struct gpio_cfg { 13169715ce9SEtienne Carriere uint16_t mode: 2; 13269715ce9SEtienne Carriere uint16_t otype: 1; 13369715ce9SEtienne Carriere uint16_t ospeed: 2; 13469715ce9SEtienne Carriere uint16_t pupd: 2; 13569715ce9SEtienne Carriere uint16_t od: 1; 13669715ce9SEtienne Carriere uint16_t af: 4; 13769715ce9SEtienne Carriere }; 13869715ce9SEtienne Carriere 13969715ce9SEtienne Carriere /* 14069715ce9SEtienne Carriere * Description of a pin and its muxing 14169715ce9SEtienne Carriere * 14269715ce9SEtienne Carriere * @bank: GPIO bank identifier as assigned by the platform 14369715ce9SEtienne Carriere * @pin: Pin number in the GPIO bank 14469715ce9SEtienne Carriere * @cfg: Pin configuration 14569715ce9SEtienne Carriere */ 14669715ce9SEtienne Carriere struct stm32_pinctrl { 14769715ce9SEtienne Carriere uint8_t bank; 14869715ce9SEtienne Carriere uint8_t pin; 14969715ce9SEtienne Carriere struct gpio_cfg cfg; 15069715ce9SEtienne Carriere }; 15169715ce9SEtienne Carriere 152b38386fbSEtienne Carriere /* 153b38386fbSEtienne Carriere * struct stm32_pinctrl_array - Array of pins in a pin control state 154b38386fbSEtienne Carriere * @count: Number of cells in @pinctrl 155b38386fbSEtienne Carriere * @pinctrl: Pin control configuration 156b38386fbSEtienne Carriere */ 157b38386fbSEtienne Carriere struct stm32_pinctrl_array { 158b38386fbSEtienne Carriere size_t count; 159b38386fbSEtienne Carriere struct stm32_pinctrl pinctrl[]; 160b38386fbSEtienne Carriere }; 161b38386fbSEtienne Carriere 1629818a481SEtienne Carriere /** 1639818a481SEtienne Carriere * struct stm32_gpio_bank - GPIO bank instance 1649818a481SEtienne Carriere * 1659818a481SEtienne Carriere * @base: base address of the GPIO controller registers. 1669818a481SEtienne Carriere * @clock: clock identifier. 167420a32c5SEtienne Carriere * @gpio_chip: GPIO chip reference for that GPIO bank 1689818a481SEtienne Carriere * @ngpios: number of GPIOs. 1699818a481SEtienne Carriere * @bank_id: Id of the bank. 1709818a481SEtienne Carriere * @lock: lock protecting the GPIO bank access. 171bd03c8c3SGatien Chevallier * @rif_cfg: RIF configuration data 172bd03c8c3SGatien Chevallier * @seccfgr: non-RIF bank secure configuration data 173bd03c8c3SGatien Chevallier * @sec_support: True if bank supports pin security protection, else false 174bd03c8c3SGatien Chevallier * @ready: True if configuration is applied, else false 175bd03c8c3SGatien Chevallier * @is_tdcid: True if OP-TEE runs as Trusted Domain CID 1769818a481SEtienne Carriere * @link: Link in bank list 1779818a481SEtienne Carriere */ 1789818a481SEtienne Carriere struct stm32_gpio_bank { 1799818a481SEtienne Carriere vaddr_t base; 1809818a481SEtienne Carriere struct clk *clock; 181420a32c5SEtienne Carriere struct gpio_chip gpio_chip; 1829818a481SEtienne Carriere unsigned int ngpios; 1839818a481SEtienne Carriere unsigned int bank_id; 1849818a481SEtienne Carriere unsigned int lock; 185bd03c8c3SGatien Chevallier struct rif_conf_data *rif_cfg; 186bd03c8c3SGatien Chevallier uint32_t seccfgr; 187b4893304SGatien Chevallier bool sec_support; 188bd03c8c3SGatien Chevallier bool ready; 189bd03c8c3SGatien Chevallier bool is_tdcid; 1909818a481SEtienne Carriere STAILQ_ENTRY(stm32_gpio_bank) link; 1919818a481SEtienne Carriere }; 1929818a481SEtienne Carriere 193bfc43b68SGatien Chevallier /* 194bfc43b68SGatien Chevallier * struct stm32_gpio_pm_state - Consumed GPIO for PM purpose 195bfc43b68SGatien Chevallier * @gpio_pinctrl: Reference and configuration state for a consumed GPIO 196bfc43b68SGatien Chevallier * @level: GPIO level 197bfc43b68SGatien Chevallier * @link: Link in consumed GPIO list 198bfc43b68SGatien Chevallier */ 199bfc43b68SGatien Chevallier struct stm32_gpio_pm_state { 200bfc43b68SGatien Chevallier struct stm32_pinctrl gpio_pinctrl; 201bfc43b68SGatien Chevallier uint8_t level; 202bfc43b68SGatien Chevallier SLIST_ENTRY(stm32_gpio_pm_state) link; 203bfc43b68SGatien Chevallier }; 204bfc43b68SGatien Chevallier 205b4893304SGatien Chevallier /** 206e569f6adSEtienne Carriere * Compatibility information of supported banks 207b4893304SGatien Chevallier * 208b4893304SGatien Chevallier * @gpioz: True if bank is a GPIOZ bank 209b4893304SGatien Chevallier * @secure_control: Identify GPIO security bank capability. 210bd03c8c3SGatien Chevallier * @secure_extended: Identify RIF presence. 211e569f6adSEtienne Carriere */ 212e569f6adSEtienne Carriere struct bank_compat { 213e569f6adSEtienne Carriere bool gpioz; 214b4893304SGatien Chevallier bool secure_control; 215bd03c8c3SGatien Chevallier bool secure_extended; 216e569f6adSEtienne Carriere }; 217e569f6adSEtienne Carriere 2184b5e93edSEtienne Carriere static unsigned int gpio_lock; 2194b5e93edSEtienne Carriere 2209818a481SEtienne Carriere static STAILQ_HEAD(, stm32_gpio_bank) bank_list = 2219818a481SEtienne Carriere STAILQ_HEAD_INITIALIZER(bank_list); 2229818a481SEtienne Carriere 223bfc43b68SGatien Chevallier static SLIST_HEAD(, stm32_gpio_pm_state) consumed_gpios_head; 224bfc43b68SGatien Chevallier 225420a32c5SEtienne Carriere static bool is_stm32_gpio_chip(struct gpio_chip *chip); 226420a32c5SEtienne Carriere 227420a32c5SEtienne Carriere static struct stm32_gpio_bank *gpio_chip_to_bank(struct gpio_chip *chip) 228420a32c5SEtienne Carriere { 229420a32c5SEtienne Carriere return container_of(chip, struct stm32_gpio_bank, gpio_chip); 230420a32c5SEtienne Carriere } 231420a32c5SEtienne Carriere 232420a32c5SEtienne Carriere static enum gpio_level stm32_gpio_get_level(struct gpio_chip *chip, 233420a32c5SEtienne Carriere unsigned int gpio_pin) 234420a32c5SEtienne Carriere { 235420a32c5SEtienne Carriere struct stm32_gpio_bank *bank = gpio_chip_to_bank(chip); 236420a32c5SEtienne Carriere enum gpio_level level = GPIO_LEVEL_HIGH; 237420a32c5SEtienne Carriere unsigned int reg_offset = 0; 238420a32c5SEtienne Carriere unsigned int mode = 0; 239420a32c5SEtienne Carriere 240420a32c5SEtienne Carriere assert(gpio_pin < bank->ngpios); 2412fd102ebSEtienne Carriere 2422fd102ebSEtienne Carriere if (clk_enable(bank->clock)) 2432fd102ebSEtienne Carriere panic(); 244420a32c5SEtienne Carriere 245420a32c5SEtienne Carriere mode = (io_read32(bank->base + GPIO_MODER_OFFSET) >> (gpio_pin << 1)) & 246420a32c5SEtienne Carriere GPIO_MODE_MASK; 247420a32c5SEtienne Carriere 248420a32c5SEtienne Carriere switch (mode) { 249420a32c5SEtienne Carriere case GPIO_MODE_INPUT: 250420a32c5SEtienne Carriere reg_offset = GPIO_IDR_OFFSET; 251420a32c5SEtienne Carriere break; 252420a32c5SEtienne Carriere case GPIO_MODE_OUTPUT: 253420a32c5SEtienne Carriere reg_offset = GPIO_ODR_OFFSET; 254420a32c5SEtienne Carriere break; 255420a32c5SEtienne Carriere default: 256420a32c5SEtienne Carriere panic(); 257420a32c5SEtienne Carriere } 258420a32c5SEtienne Carriere 259420a32c5SEtienne Carriere if (io_read32(bank->base + reg_offset) & BIT(gpio_pin)) 260420a32c5SEtienne Carriere level = GPIO_LEVEL_HIGH; 261420a32c5SEtienne Carriere else 262420a32c5SEtienne Carriere level = GPIO_LEVEL_LOW; 263420a32c5SEtienne Carriere 264420a32c5SEtienne Carriere clk_disable(bank->clock); 265420a32c5SEtienne Carriere 266420a32c5SEtienne Carriere return level; 267420a32c5SEtienne Carriere } 268420a32c5SEtienne Carriere 269420a32c5SEtienne Carriere static void stm32_gpio_set_level(struct gpio_chip *chip, unsigned int gpio_pin, 270420a32c5SEtienne Carriere enum gpio_level level) 271420a32c5SEtienne Carriere { 272420a32c5SEtienne Carriere struct stm32_gpio_bank *bank = gpio_chip_to_bank(chip); 273420a32c5SEtienne Carriere 274420a32c5SEtienne Carriere assert(gpio_pin < bank->ngpios); 2752fd102ebSEtienne Carriere 2762fd102ebSEtienne Carriere if (clk_enable(bank->clock)) 2772fd102ebSEtienne Carriere panic(); 278420a32c5SEtienne Carriere 279420a32c5SEtienne Carriere assert(((io_read32(bank->base + GPIO_MODER_OFFSET) >> 280420a32c5SEtienne Carriere (gpio_pin << 1)) & GPIO_MODE_MASK) == GPIO_MODE_OUTPUT); 281420a32c5SEtienne Carriere 282420a32c5SEtienne Carriere if (level == GPIO_LEVEL_HIGH) 283420a32c5SEtienne Carriere io_write32(bank->base + GPIO_BSRR_OFFSET, BIT(gpio_pin)); 284420a32c5SEtienne Carriere else 285420a32c5SEtienne Carriere io_write32(bank->base + GPIO_BSRR_OFFSET, BIT(gpio_pin + 16)); 286420a32c5SEtienne Carriere 287420a32c5SEtienne Carriere clk_disable(bank->clock); 288420a32c5SEtienne Carriere } 289420a32c5SEtienne Carriere 290420a32c5SEtienne Carriere static enum gpio_dir stm32_gpio_get_direction(struct gpio_chip *chip, 291420a32c5SEtienne Carriere unsigned int gpio_pin) 292420a32c5SEtienne Carriere { 293420a32c5SEtienne Carriere struct stm32_gpio_bank *bank = gpio_chip_to_bank(chip); 294420a32c5SEtienne Carriere uint32_t mode = 0; 295420a32c5SEtienne Carriere 296420a32c5SEtienne Carriere assert(gpio_pin < bank->ngpios); 2972fd102ebSEtienne Carriere 2982fd102ebSEtienne Carriere if (clk_enable(bank->clock)) 2992fd102ebSEtienne Carriere panic(); 300420a32c5SEtienne Carriere 301420a32c5SEtienne Carriere mode = (io_read32(bank->base + GPIO_MODER_OFFSET) >> (gpio_pin << 1)) & 302420a32c5SEtienne Carriere GPIO_MODE_MASK; 303420a32c5SEtienne Carriere 304420a32c5SEtienne Carriere clk_disable(bank->clock); 305420a32c5SEtienne Carriere 306420a32c5SEtienne Carriere switch (mode) { 307420a32c5SEtienne Carriere case GPIO_MODE_INPUT: 308420a32c5SEtienne Carriere return GPIO_DIR_IN; 309420a32c5SEtienne Carriere case GPIO_MODE_OUTPUT: 310420a32c5SEtienne Carriere return GPIO_DIR_OUT; 311420a32c5SEtienne Carriere default: 312420a32c5SEtienne Carriere panic(); 313420a32c5SEtienne Carriere } 314420a32c5SEtienne Carriere } 315420a32c5SEtienne Carriere 316420a32c5SEtienne Carriere static void stm32_gpio_set_direction(struct gpio_chip *chip, 317420a32c5SEtienne Carriere unsigned int gpio_pin, 318420a32c5SEtienne Carriere enum gpio_dir direction) 319420a32c5SEtienne Carriere { 320420a32c5SEtienne Carriere struct stm32_gpio_bank *bank = gpio_chip_to_bank(chip); 321420a32c5SEtienne Carriere uint32_t exceptions = 0; 322420a32c5SEtienne Carriere uint32_t mode = 0; 323420a32c5SEtienne Carriere 324420a32c5SEtienne Carriere assert(gpio_pin < bank->ngpios); 325420a32c5SEtienne Carriere 326420a32c5SEtienne Carriere if (direction == GPIO_DIR_IN) 327420a32c5SEtienne Carriere mode = GPIO_MODE_INPUT; 328420a32c5SEtienne Carriere else 329420a32c5SEtienne Carriere mode = GPIO_MODE_OUTPUT; 330420a32c5SEtienne Carriere 3312fd102ebSEtienne Carriere if (clk_enable(bank->clock)) 3322fd102ebSEtienne Carriere panic(); 333420a32c5SEtienne Carriere exceptions = cpu_spin_lock_xsave(&gpio_lock); 334420a32c5SEtienne Carriere io_clrsetbits32(bank->base + GPIO_MODER_OFFSET, 335420a32c5SEtienne Carriere SHIFT_U32(GPIO_MODE_MASK, gpio_pin << 1), 336420a32c5SEtienne Carriere SHIFT_U32(mode, gpio_pin << 1)); 337420a32c5SEtienne Carriere cpu_spin_unlock_xrestore(&gpio_lock, exceptions); 338420a32c5SEtienne Carriere clk_disable(bank->clock); 339420a32c5SEtienne Carriere } 340420a32c5SEtienne Carriere 341bfc43b68SGatien Chevallier /* Forward reference to the PM callback handler for consumed GPIOs */ 342bfc43b68SGatien Chevallier static TEE_Result consumed_gpios_pm(enum pm_op op, unsigned int pm_hint, 343bfc43b68SGatien Chevallier const struct pm_callback_handle *pm_hdl); 344bfc43b68SGatien Chevallier 345bfc43b68SGatien Chevallier static void stm32_gpio_put_gpio(struct gpio_chip *chip, struct gpio *gpio) 346420a32c5SEtienne Carriere { 347bfc43b68SGatien Chevallier struct stm32_gpio_bank *bank = gpio_chip_to_bank(chip); 348bfc43b68SGatien Chevallier struct stm32_gpio_pm_state *tstate = NULL; 349bfc43b68SGatien Chevallier struct stm32_gpio_pm_state *state = NULL; 350bfc43b68SGatien Chevallier uint32_t exceptions = 0; 351bfc43b68SGatien Chevallier 352420a32c5SEtienne Carriere assert(is_stm32_gpio_chip(chip)); 353bfc43b68SGatien Chevallier 354bfc43b68SGatien Chevallier exceptions = cpu_spin_lock_xsave(&gpio_lock); 355bfc43b68SGatien Chevallier 356bfc43b68SGatien Chevallier SLIST_FOREACH_SAFE(state, &consumed_gpios_head, link, tstate) { 357bfc43b68SGatien Chevallier if (state->gpio_pinctrl.bank == bank->bank_id && 358bfc43b68SGatien Chevallier state->gpio_pinctrl.pin == gpio->pin) { 359bfc43b68SGatien Chevallier SLIST_REMOVE(&consumed_gpios_head, state, 360bfc43b68SGatien Chevallier stm32_gpio_pm_state, link); 361bfc43b68SGatien Chevallier unregister_pm_driver_cb(consumed_gpios_pm, state); 362bfc43b68SGatien Chevallier free(state); 363420a32c5SEtienne Carriere free(gpio); 364bfc43b68SGatien Chevallier break; 365bfc43b68SGatien Chevallier } 366bfc43b68SGatien Chevallier } 367bfc43b68SGatien Chevallier assert(state); 368bfc43b68SGatien Chevallier 369bfc43b68SGatien Chevallier cpu_spin_unlock_xrestore(&gpio_lock, exceptions); 370420a32c5SEtienne Carriere } 371420a32c5SEtienne Carriere 372420a32c5SEtienne Carriere static const struct gpio_ops stm32_gpio_ops = { 373420a32c5SEtienne Carriere .get_direction = stm32_gpio_get_direction, 374420a32c5SEtienne Carriere .set_direction = stm32_gpio_set_direction, 375420a32c5SEtienne Carriere .get_value = stm32_gpio_get_level, 376420a32c5SEtienne Carriere .set_value = stm32_gpio_set_level, 377420a32c5SEtienne Carriere .put = stm32_gpio_put_gpio, 378420a32c5SEtienne Carriere }; 379420a32c5SEtienne Carriere 380420a32c5SEtienne Carriere static bool __maybe_unused is_stm32_gpio_chip(struct gpio_chip *chip) 381420a32c5SEtienne Carriere { 382420a32c5SEtienne Carriere return chip && chip->ops == &stm32_gpio_ops; 383420a32c5SEtienne Carriere } 384420a32c5SEtienne Carriere 385077d486eSEtienne Carriere static struct stm32_gpio_bank *stm32_gpio_get_bank(unsigned int bank_id) 3864b5e93edSEtienne Carriere { 387077d486eSEtienne Carriere struct stm32_gpio_bank *bank = NULL; 3884b5e93edSEtienne Carriere 389077d486eSEtienne Carriere STAILQ_FOREACH(bank, &bank_list, link) 390077d486eSEtienne Carriere if (bank_id == bank->bank_id) 391077d486eSEtienne Carriere return bank; 392077d486eSEtienne Carriere 393077d486eSEtienne Carriere panic(); 394077d486eSEtienne Carriere } 395077d486eSEtienne Carriere 396077d486eSEtienne Carriere /* Save to output @cfg the current GPIO (@bank_id/@pin) configuration */ 397bfc43b68SGatien Chevallier static void get_gpio_cfg(uint32_t bank_id, uint32_t pin, struct gpio_cfg *cfg) 398077d486eSEtienne Carriere { 399077d486eSEtienne Carriere struct stm32_gpio_bank *bank = stm32_gpio_get_bank(bank_id); 400077d486eSEtienne Carriere 401077d486eSEtienne Carriere if (clk_enable(bank->clock)) 402077d486eSEtienne Carriere panic(); 4034b5e93edSEtienne Carriere 4044b5e93edSEtienne Carriere /* 4054b5e93edSEtienne Carriere * Save GPIO configuration bits spread over the few bank registers. 4064b5e93edSEtienne Carriere * 1bit fields are accessed at bit position being the pin index. 4074b5e93edSEtienne Carriere * 2bit fields are accessed at bit position being twice the pin index. 4084b5e93edSEtienne Carriere * 4bit fields are accessed at bit position being fourth the pin index 4094b5e93edSEtienne Carriere * but accessed from 2 32bit registers at incremental addresses. 4104b5e93edSEtienne Carriere */ 411077d486eSEtienne Carriere cfg->mode = (io_read32(bank->base + GPIO_MODER_OFFSET) >> (pin << 1)) & 4124b5e93edSEtienne Carriere GPIO_MODE_MASK; 4134b5e93edSEtienne Carriere 414077d486eSEtienne Carriere cfg->otype = (io_read32(bank->base + GPIO_OTYPER_OFFSET) >> pin) & 1; 4154b5e93edSEtienne Carriere 416077d486eSEtienne Carriere cfg->ospeed = (io_read32(bank->base + GPIO_OSPEEDR_OFFSET) >> 417077d486eSEtienne Carriere (pin << 1)) & GPIO_OSPEED_MASK; 4184b5e93edSEtienne Carriere 419077d486eSEtienne Carriere cfg->pupd = (io_read32(bank->base + GPIO_PUPDR_OFFSET) >> (pin << 1)) & 4204b5e93edSEtienne Carriere GPIO_PUPD_PULL_MASK; 4214b5e93edSEtienne Carriere 422077d486eSEtienne Carriere cfg->od = (io_read32(bank->base + GPIO_ODR_OFFSET) >> (pin << 1)) & 1; 4234b5e93edSEtienne Carriere 4244b5e93edSEtienne Carriere if (pin < GPIO_ALT_LOWER_LIMIT) 425077d486eSEtienne Carriere cfg->af = (io_read32(bank->base + GPIO_AFRL_OFFSET) >> 426077d486eSEtienne Carriere (pin << 2)) & GPIO_ALTERNATE_MASK; 4274b5e93edSEtienne Carriere else 428077d486eSEtienne Carriere cfg->af = (io_read32(bank->base + GPIO_AFRH_OFFSET) >> 4294b5e93edSEtienne Carriere ((pin - GPIO_ALT_LOWER_LIMIT) << 2)) & 4304b5e93edSEtienne Carriere GPIO_ALTERNATE_MASK; 4314b5e93edSEtienne Carriere 432077d486eSEtienne Carriere clk_disable(bank->clock); 4334b5e93edSEtienne Carriere } 4344b5e93edSEtienne Carriere 4354b5e93edSEtienne Carriere /* Apply GPIO (@bank/@pin) configuration described by @cfg */ 436077d486eSEtienne Carriere static void set_gpio_cfg(uint32_t bank_id, uint32_t pin, struct gpio_cfg *cfg) 4374b5e93edSEtienne Carriere { 438077d486eSEtienne Carriere struct stm32_gpio_bank *bank = stm32_gpio_get_bank(bank_id); 43998dfcedaSEtienne Carriere uint32_t exceptions = 0; 4404b5e93edSEtienne Carriere 441077d486eSEtienne Carriere if (clk_enable(bank->clock)) 442077d486eSEtienne Carriere panic(); 44398dfcedaSEtienne Carriere exceptions = cpu_spin_lock_xsave(&gpio_lock); 4444b5e93edSEtienne Carriere 4454b5e93edSEtienne Carriere /* Load GPIO MODE value, 2bit value shifted by twice the pin number */ 446077d486eSEtienne Carriere io_clrsetbits32(bank->base + GPIO_MODER_OFFSET, 447bed4582fSEtienne Carriere SHIFT_U32(GPIO_MODE_MASK, pin << 1), 448bed4582fSEtienne Carriere SHIFT_U32(cfg->mode, pin << 1)); 4494b5e93edSEtienne Carriere 4504b5e93edSEtienne Carriere /* Load GPIO Output TYPE value, 1bit shifted by pin number value */ 451077d486eSEtienne Carriere io_clrsetbits32(bank->base + GPIO_OTYPER_OFFSET, BIT(pin), 452bed4582fSEtienne Carriere SHIFT_U32(cfg->otype, pin)); 4534b5e93edSEtienne Carriere 4544b5e93edSEtienne Carriere /* Load GPIO Output Speed confguration, 2bit value */ 455077d486eSEtienne Carriere io_clrsetbits32(bank->base + GPIO_OSPEEDR_OFFSET, 456bed4582fSEtienne Carriere SHIFT_U32(GPIO_OSPEED_MASK, pin << 1), 457bed4582fSEtienne Carriere SHIFT_U32(cfg->ospeed, pin << 1)); 4584b5e93edSEtienne Carriere 4594b5e93edSEtienne Carriere /* Load GPIO pull configuration, 2bit value */ 460077d486eSEtienne Carriere io_clrsetbits32(bank->base + GPIO_PUPDR_OFFSET, BIT(pin), 461bed4582fSEtienne Carriere SHIFT_U32(cfg->pupd, pin << 1)); 4624b5e93edSEtienne Carriere 4634b5e93edSEtienne Carriere /* Load pin mux Alternate Function configuration, 4bit value */ 4644b5e93edSEtienne Carriere if (pin < GPIO_ALT_LOWER_LIMIT) { 465077d486eSEtienne Carriere io_clrsetbits32(bank->base + GPIO_AFRL_OFFSET, 466bed4582fSEtienne Carriere SHIFT_U32(GPIO_ALTERNATE_MASK, pin << 2), 467bed4582fSEtienne Carriere SHIFT_U32(cfg->af, pin << 2)); 4684b5e93edSEtienne Carriere } else { 4694b5e93edSEtienne Carriere size_t shift = (pin - GPIO_ALT_LOWER_LIMIT) << 2; 4704b5e93edSEtienne Carriere 471077d486eSEtienne Carriere io_clrsetbits32(bank->base + GPIO_AFRH_OFFSET, 472bed4582fSEtienne Carriere SHIFT_U32(GPIO_ALTERNATE_MASK, shift), 473bed4582fSEtienne Carriere SHIFT_U32(cfg->af, shift)); 4744b5e93edSEtienne Carriere } 4754b5e93edSEtienne Carriere 4764b5e93edSEtienne Carriere /* Load GPIO Output direction confuguration, 1bit */ 477077d486eSEtienne Carriere io_clrsetbits32(bank->base + GPIO_ODR_OFFSET, BIT(pin), cfg->od << pin); 4784b5e93edSEtienne Carriere 479c4cab2bbSEtienne Carriere cpu_spin_unlock_xrestore(&gpio_lock, exceptions); 48098dfcedaSEtienne Carriere clk_disable(bank->clock); 4814b5e93edSEtienne Carriere } 4824b5e93edSEtienne Carriere 4834b5e93edSEtienne Carriere /* Count pins described in the DT node and get related data if possible */ 484b38386fbSEtienne Carriere static int get_pinctrl_from_fdt(const void *fdt, int node, 4854b5e93edSEtienne Carriere struct stm32_pinctrl *pinctrl, size_t count) 4864b5e93edSEtienne Carriere { 487b38386fbSEtienne Carriere const fdt32_t *cuint = NULL; 488b38386fbSEtienne Carriere const fdt32_t *slewrate = NULL; 48910bcbd6cSEtienne Carriere int len = 0; 49010bcbd6cSEtienne Carriere uint32_t i = 0; 4914b5e93edSEtienne Carriere uint32_t speed = GPIO_OSPEED_LOW; 4924b5e93edSEtienne Carriere uint32_t pull = GPIO_PUPD_NO_PULL; 4934b5e93edSEtienne Carriere size_t found = 0; 4944b5e93edSEtienne Carriere 4954b5e93edSEtienne Carriere cuint = fdt_getprop(fdt, node, "pinmux", &len); 4964b5e93edSEtienne Carriere if (!cuint) 4974b5e93edSEtienne Carriere return -FDT_ERR_NOTFOUND; 4984b5e93edSEtienne Carriere 4994b5e93edSEtienne Carriere slewrate = fdt_getprop(fdt, node, "slew-rate", NULL); 5004b5e93edSEtienne Carriere if (slewrate) 5014b5e93edSEtienne Carriere speed = fdt32_to_cpu(*slewrate); 5024b5e93edSEtienne Carriere 5034b5e93edSEtienne Carriere if (fdt_getprop(fdt, node, "bias-pull-up", NULL)) 5044b5e93edSEtienne Carriere pull = GPIO_PUPD_PULL_UP; 5054b5e93edSEtienne Carriere if (fdt_getprop(fdt, node, "bias-pull-down", NULL)) 5064b5e93edSEtienne Carriere pull = GPIO_PUPD_PULL_DOWN; 5074b5e93edSEtienne Carriere 5084b5e93edSEtienne Carriere for (i = 0; i < ((uint32_t)len / sizeof(uint32_t)); i++) { 50910bcbd6cSEtienne Carriere uint32_t pincfg = 0; 51010bcbd6cSEtienne Carriere uint32_t bank = 0; 51110bcbd6cSEtienne Carriere uint32_t pin = 0; 51210bcbd6cSEtienne Carriere uint32_t mode = 0; 5134b5e93edSEtienne Carriere uint32_t alternate = 0; 514322cf9e3SEtienne Carriere uint32_t odata = 0; 5154b5e93edSEtienne Carriere bool opendrain = false; 5164b5e93edSEtienne Carriere 5174b5e93edSEtienne Carriere pincfg = fdt32_to_cpu(*cuint); 5184b5e93edSEtienne Carriere cuint++; 5194b5e93edSEtienne Carriere 5204b5e93edSEtienne Carriere bank = (pincfg & DT_GPIO_BANK_MASK) >> DT_GPIO_BANK_SHIFT; 5214b5e93edSEtienne Carriere 5224b5e93edSEtienne Carriere pin = (pincfg & DT_GPIO_PIN_MASK) >> DT_GPIO_PIN_SHIFT; 5234b5e93edSEtienne Carriere 5244b5e93edSEtienne Carriere mode = pincfg & DT_GPIO_MODE_MASK; 5254b5e93edSEtienne Carriere 5264b5e93edSEtienne Carriere switch (mode) { 5274b5e93edSEtienne Carriere case 0: 5284b5e93edSEtienne Carriere mode = GPIO_MODE_INPUT; 5294b5e93edSEtienne Carriere break; 5304b5e93edSEtienne Carriere case 1: 5314b5e93edSEtienne Carriere case 2: 5324b5e93edSEtienne Carriere case 3: 5334b5e93edSEtienne Carriere case 4: 5344b5e93edSEtienne Carriere case 5: 5354b5e93edSEtienne Carriere case 6: 5364b5e93edSEtienne Carriere case 7: 5374b5e93edSEtienne Carriere case 8: 5384b5e93edSEtienne Carriere case 9: 5394b5e93edSEtienne Carriere case 10: 5404b5e93edSEtienne Carriere case 11: 5414b5e93edSEtienne Carriere case 12: 5424b5e93edSEtienne Carriere case 13: 5434b5e93edSEtienne Carriere case 14: 5444b5e93edSEtienne Carriere case 15: 5454b5e93edSEtienne Carriere case 16: 5464b5e93edSEtienne Carriere alternate = mode - 1U; 5474b5e93edSEtienne Carriere mode = GPIO_MODE_ALTERNATE; 5484b5e93edSEtienne Carriere break; 5494b5e93edSEtienne Carriere case 17: 5504b5e93edSEtienne Carriere mode = GPIO_MODE_ANALOG; 5514b5e93edSEtienne Carriere break; 5524b5e93edSEtienne Carriere default: 5534b5e93edSEtienne Carriere mode = GPIO_MODE_OUTPUT; 5544b5e93edSEtienne Carriere break; 5554b5e93edSEtienne Carriere } 5564b5e93edSEtienne Carriere 5574b5e93edSEtienne Carriere if (fdt_getprop(fdt, node, "drive-open-drain", NULL)) 5584b5e93edSEtienne Carriere opendrain = true; 5594b5e93edSEtienne Carriere 560322cf9e3SEtienne Carriere if (fdt_getprop(fdt, node, "output-high", NULL) && 561322cf9e3SEtienne Carriere mode == GPIO_MODE_INPUT) { 562322cf9e3SEtienne Carriere mode = GPIO_MODE_OUTPUT; 563322cf9e3SEtienne Carriere odata = 1; 564322cf9e3SEtienne Carriere } 565322cf9e3SEtienne Carriere 566322cf9e3SEtienne Carriere if (fdt_getprop(fdt, node, "output-low", NULL) && 567322cf9e3SEtienne Carriere mode == GPIO_MODE_INPUT) { 568322cf9e3SEtienne Carriere mode = GPIO_MODE_OUTPUT; 569322cf9e3SEtienne Carriere odata = 0; 570322cf9e3SEtienne Carriere } 571322cf9e3SEtienne Carriere 5724b5e93edSEtienne Carriere if (found < count) { 5734b5e93edSEtienne Carriere struct stm32_pinctrl *ref = &pinctrl[found]; 5744b5e93edSEtienne Carriere 5754b5e93edSEtienne Carriere ref->bank = (uint8_t)bank; 5764b5e93edSEtienne Carriere ref->pin = (uint8_t)pin; 577b38386fbSEtienne Carriere ref->cfg.mode = mode; 578b38386fbSEtienne Carriere if (opendrain) 579b38386fbSEtienne Carriere ref->cfg.otype = GPIO_OTYPE_OPEN_DRAIN; 580b38386fbSEtienne Carriere else 581b38386fbSEtienne Carriere ref->cfg.otype = GPIO_OTYPE_PUSH_PULL; 582b38386fbSEtienne Carriere ref->cfg.ospeed = speed; 583b38386fbSEtienne Carriere ref->cfg.pupd = pull; 584b38386fbSEtienne Carriere ref->cfg.od = odata; 585b38386fbSEtienne Carriere ref->cfg.af = alternate; 5864b5e93edSEtienne Carriere } 5874b5e93edSEtienne Carriere 5884b5e93edSEtienne Carriere found++; 5894b5e93edSEtienne Carriere } 5904b5e93edSEtienne Carriere 5914b5e93edSEtienne Carriere return (int)found; 5924b5e93edSEtienne Carriere } 5934b5e93edSEtienne Carriere 594bfc43b68SGatien Chevallier static TEE_Result consumed_gpios_pm(enum pm_op op, 595bfc43b68SGatien Chevallier unsigned int pm_hint __unused, 596bfc43b68SGatien Chevallier const struct pm_callback_handle *pm_hdl) 597bfc43b68SGatien Chevallier { 598bfc43b68SGatien Chevallier struct stm32_gpio_pm_state *handle = pm_hdl->handle; 599bfc43b68SGatien Chevallier unsigned int bank_id = handle->gpio_pinctrl.bank; 600bfc43b68SGatien Chevallier unsigned int pin = handle->gpio_pinctrl.pin; 601bfc43b68SGatien Chevallier struct gpio_chip *chip = &stm32_gpio_get_bank(bank_id)->gpio_chip; 602bfc43b68SGatien Chevallier 603bfc43b68SGatien Chevallier if (op == PM_OP_RESUME) { 604bfc43b68SGatien Chevallier set_gpio_cfg(bank_id, pin, &handle->gpio_pinctrl.cfg); 605bfc43b68SGatien Chevallier if (handle->gpio_pinctrl.cfg.mode == GPIO_MODE_OUTPUT) 606bfc43b68SGatien Chevallier stm32_gpio_set_level(chip, pin, handle->level); 607bfc43b68SGatien Chevallier } else { 608bfc43b68SGatien Chevallier get_gpio_cfg(bank_id, pin, &handle->gpio_pinctrl.cfg); 609bfc43b68SGatien Chevallier if (handle->gpio_pinctrl.cfg.mode == GPIO_MODE_OUTPUT) 610bfc43b68SGatien Chevallier handle->level = stm32_gpio_get_level(chip, pin); 611bfc43b68SGatien Chevallier } 612bfc43b68SGatien Chevallier 613bfc43b68SGatien Chevallier return TEE_SUCCESS; 614bfc43b68SGatien Chevallier } 615bfc43b68SGatien Chevallier DECLARE_KEEP_PAGER(consumed_gpios_pm); 616bfc43b68SGatien Chevallier 617b357d34fSEtienne Carriere static TEE_Result stm32_gpio_get_dt(struct dt_pargs *pargs, void *data, 618b357d34fSEtienne Carriere struct gpio **out_gpio) 619420a32c5SEtienne Carriere { 620b357d34fSEtienne Carriere TEE_Result res = TEE_ERROR_GENERIC; 6217761b658SEtienne Carriere struct stm32_gpio_pm_state *reg_state = NULL; 622bfc43b68SGatien Chevallier struct stm32_gpio_pm_state *state = NULL; 623420a32c5SEtienne Carriere struct stm32_gpio_bank *bank = data; 624420a32c5SEtienne Carriere struct gpio *gpio = NULL; 625420a32c5SEtienne Carriere unsigned int shift_1b = 0; 626420a32c5SEtienne Carriere unsigned int shift_2b = 0; 627420a32c5SEtienne Carriere uint32_t exceptions = 0; 628420a32c5SEtienne Carriere uint32_t otype = 0; 629420a32c5SEtienne Carriere uint32_t pupd = 0; 630420a32c5SEtienne Carriere uint32_t mode = 0; 631420a32c5SEtienne Carriere 632b357d34fSEtienne Carriere res = gpio_dt_alloc_pin(pargs, &gpio); 633b357d34fSEtienne Carriere if (res) 634b357d34fSEtienne Carriere return res; 635420a32c5SEtienne Carriere 636420a32c5SEtienne Carriere if (gpio->pin >= bank->ngpios) { 637420a32c5SEtienne Carriere DMSG("Invalid GPIO reference"); 638420a32c5SEtienne Carriere free(gpio); 639b357d34fSEtienne Carriere return TEE_ERROR_GENERIC; 640420a32c5SEtienne Carriere } 641420a32c5SEtienne Carriere 642bfc43b68SGatien Chevallier state = calloc(1, sizeof(*state)); 643bfc43b68SGatien Chevallier if (!state) { 644bfc43b68SGatien Chevallier free(gpio); 645bfc43b68SGatien Chevallier return TEE_ERROR_OUT_OF_MEMORY; 646bfc43b68SGatien Chevallier } 647bfc43b68SGatien Chevallier 6487761b658SEtienne Carriere SLIST_FOREACH(reg_state, &consumed_gpios_head, link) { 6497761b658SEtienne Carriere if (reg_state->gpio_pinctrl.bank == bank->bank_id && 6507761b658SEtienne Carriere reg_state->gpio_pinctrl.pin == gpio->pin) { 6517761b658SEtienne Carriere EMSG("node %s: GPIO %c%u is used by another device", 6527761b658SEtienne Carriere fdt_get_name(pargs->fdt, pargs->consumer_node, 6537761b658SEtienne Carriere NULL), 6547761b658SEtienne Carriere bank->bank_id + 'A', gpio->pin); 6557761b658SEtienne Carriere free(state); 6567761b658SEtienne Carriere free(gpio); 6577761b658SEtienne Carriere return TEE_ERROR_GENERIC; 6587761b658SEtienne Carriere } 6597761b658SEtienne Carriere } 6607761b658SEtienne Carriere 661bfc43b68SGatien Chevallier state->gpio_pinctrl.pin = gpio->pin; 662bfc43b68SGatien Chevallier state->gpio_pinctrl.bank = bank->bank_id; 663bfc43b68SGatien Chevallier SLIST_INSERT_HEAD(&consumed_gpios_head, state, link); 664bfc43b68SGatien Chevallier 665bfc43b68SGatien Chevallier register_pm_driver_cb(consumed_gpios_pm, state, "stm32-gpio-state"); 666bfc43b68SGatien Chevallier 667420a32c5SEtienne Carriere shift_1b = gpio->pin; 668420a32c5SEtienne Carriere shift_2b = SHIFT_U32(gpio->pin, 1); 669420a32c5SEtienne Carriere 670420a32c5SEtienne Carriere if (gpio->dt_flags & GPIO_PULL_UP) 671420a32c5SEtienne Carriere pupd = GPIO_PUPD_PULL_UP; 672420a32c5SEtienne Carriere else if (gpio->dt_flags & GPIO_PULL_DOWN) 673420a32c5SEtienne Carriere pupd = GPIO_PUPD_PULL_DOWN; 674420a32c5SEtienne Carriere else 675420a32c5SEtienne Carriere pupd = GPIO_PUPD_NO_PULL; 676420a32c5SEtienne Carriere 677420a32c5SEtienne Carriere if (gpio->dt_flags & GPIO_LINE_OPEN_DRAIN) 678420a32c5SEtienne Carriere otype = GPIO_OTYPE_OPEN_DRAIN; 679420a32c5SEtienne Carriere else 680420a32c5SEtienne Carriere otype = GPIO_OTYPE_PUSH_PULL; 681420a32c5SEtienne Carriere 682420a32c5SEtienne Carriere if (clk_enable(bank->clock)) 683420a32c5SEtienne Carriere panic(); 684420a32c5SEtienne Carriere exceptions = cpu_spin_lock_xsave(&gpio_lock); 685420a32c5SEtienne Carriere 686420a32c5SEtienne Carriere io_clrsetbits32(bank->base + GPIO_MODER_OFFSET, 687420a32c5SEtienne Carriere SHIFT_U32(GPIO_MODE_MASK, shift_2b), 688420a32c5SEtienne Carriere SHIFT_U32(mode, shift_2b)); 689420a32c5SEtienne Carriere 690420a32c5SEtienne Carriere io_clrsetbits32(bank->base + GPIO_OTYPER_OFFSET, 691420a32c5SEtienne Carriere SHIFT_U32(GPIO_OTYPE_OPEN_DRAIN, shift_1b), 692420a32c5SEtienne Carriere SHIFT_U32(otype, shift_1b)); 693420a32c5SEtienne Carriere 694420a32c5SEtienne Carriere io_clrsetbits32(bank->base + GPIO_PUPDR_OFFSET, 695420a32c5SEtienne Carriere SHIFT_U32(GPIO_PUPD_PULL_MASK, shift_2b), 696420a32c5SEtienne Carriere SHIFT_U32(pupd, shift_2b)); 697420a32c5SEtienne Carriere 698420a32c5SEtienne Carriere cpu_spin_unlock_xrestore(&gpio_lock, exceptions); 699420a32c5SEtienne Carriere clk_disable(bank->clock); 700420a32c5SEtienne Carriere 701420a32c5SEtienne Carriere gpio->chip = &bank->gpio_chip; 702420a32c5SEtienne Carriere 703b357d34fSEtienne Carriere *out_gpio = gpio; 704420a32c5SEtienne Carriere 705b357d34fSEtienne Carriere return TEE_SUCCESS; 706420a32c5SEtienne Carriere } 707420a32c5SEtienne Carriere 7089818a481SEtienne Carriere /* Get bank ID from bank node property st,bank-name or panic on failure */ 7099818a481SEtienne Carriere static unsigned int dt_get_bank_id(const void *fdt, int node) 7109818a481SEtienne Carriere { 7119818a481SEtienne Carriere const int dt_name_len = strlen(DT_GPIO_BANK_NAME0); 7129818a481SEtienne Carriere const fdt32_t *cuint = NULL; 7139818a481SEtienne Carriere int len = 0; 7149818a481SEtienne Carriere 7159818a481SEtienne Carriere /* Parse "st,bank-name" to get its id (eg: GPIOA -> 0) */ 7169818a481SEtienne Carriere cuint = fdt_getprop(fdt, node, "st,bank-name", &len); 7179818a481SEtienne Carriere if (!cuint || (len != dt_name_len + 1)) 7189818a481SEtienne Carriere panic("Missing/wrong st,bank-name property"); 7199818a481SEtienne Carriere 7209818a481SEtienne Carriere if (strncmp((const char *)cuint, DT_GPIO_BANK_NAME0, dt_name_len - 1) || 7219818a481SEtienne Carriere strcmp((const char *)cuint, DT_GPIO_BANK_NAME0) < 0) 7229818a481SEtienne Carriere panic("Wrong st,bank-name property"); 7239818a481SEtienne Carriere 7249818a481SEtienne Carriere return (unsigned int)strcmp((const char *)cuint, DT_GPIO_BANK_NAME0); 7259818a481SEtienne Carriere } 7269818a481SEtienne Carriere 7279818a481SEtienne Carriere /* 7289818a481SEtienne Carriere * Return whether or not the GPIO bank related to a DT node is already 7299818a481SEtienne Carriere * registered in the GPIO bank link. 7309818a481SEtienne Carriere */ 7319818a481SEtienne Carriere static bool bank_is_registered(const void *fdt, int node) 7329818a481SEtienne Carriere { 7339818a481SEtienne Carriere unsigned int bank_id = dt_get_bank_id(fdt, node); 7349818a481SEtienne Carriere struct stm32_gpio_bank *bank = NULL; 7359818a481SEtienne Carriere 7369818a481SEtienne Carriere STAILQ_FOREACH(bank, &bank_list, link) 7379818a481SEtienne Carriere if (bank->bank_id == bank_id) 7389818a481SEtienne Carriere return true; 7399818a481SEtienne Carriere 7409818a481SEtienne Carriere return false; 7419818a481SEtienne Carriere } 7429818a481SEtienne Carriere 7439def1fb7SGatien Chevallier #ifdef CFG_STM32_RIF 744*a72f07daSEtienne Carriere static TEE_Result handle_available_semaphores(struct stm32_gpio_bank *bank, 745*a72f07daSEtienne Carriere uint32_t gpios_mask) 746bd03c8c3SGatien Chevallier { 747bd03c8c3SGatien Chevallier TEE_Result res = TEE_ERROR_GENERIC; 748bd03c8c3SGatien Chevallier uint32_t cidcfgr = 0; 749bd03c8c3SGatien Chevallier unsigned int i = 0; 750bd03c8c3SGatien Chevallier 7519def1fb7SGatien Chevallier for (i = 0 ; i < bank->ngpios; i++) { 752*a72f07daSEtienne Carriere if (!(BIT(i) & gpios_mask)) 7539def1fb7SGatien Chevallier continue; 7549def1fb7SGatien Chevallier 7559def1fb7SGatien Chevallier cidcfgr = io_read32(bank->base + GPIO_CIDCFGR(i)); 7569def1fb7SGatien Chevallier 7579def1fb7SGatien Chevallier if (!stm32_rif_semaphore_enabled_and_ok(cidcfgr, RIF_CID1)) 7589def1fb7SGatien Chevallier continue; 7599def1fb7SGatien Chevallier 7609def1fb7SGatien Chevallier if (!(io_read32(bank->base + GPIO_SECR_OFFSET) & BIT(i))) { 7619def1fb7SGatien Chevallier res = stm32_rif_release_semaphore(bank->base + 7629def1fb7SGatien Chevallier GPIO_SEMCR(i), 7639def1fb7SGatien Chevallier MAX_CID_SUPPORTED); 7649def1fb7SGatien Chevallier if (res) { 7659def1fb7SGatien Chevallier EMSG("Cannot release semaphore for resource %u", 7669def1fb7SGatien Chevallier i); 7679def1fb7SGatien Chevallier return res; 7689def1fb7SGatien Chevallier } 7699def1fb7SGatien Chevallier } else { 7709def1fb7SGatien Chevallier res = stm32_rif_acquire_semaphore(bank->base + 7719def1fb7SGatien Chevallier GPIO_SEMCR(i), 7729def1fb7SGatien Chevallier MAX_CID_SUPPORTED); 7739def1fb7SGatien Chevallier if (res) { 7749def1fb7SGatien Chevallier EMSG("Cannot acquire semaphore for resource %u", 7759def1fb7SGatien Chevallier i); 7769def1fb7SGatien Chevallier return res; 7779def1fb7SGatien Chevallier } 7789def1fb7SGatien Chevallier } 7799def1fb7SGatien Chevallier } 7809def1fb7SGatien Chevallier 7819def1fb7SGatien Chevallier return TEE_SUCCESS; 7829def1fb7SGatien Chevallier } 7839def1fb7SGatien Chevallier 784*a72f07daSEtienne Carriere static TEE_Result apply_rif_config(struct stm32_gpio_bank *bank, 785*a72f07daSEtienne Carriere uint32_t gpios_mask) 7869def1fb7SGatien Chevallier { 7879def1fb7SGatien Chevallier TEE_Result res = TEE_ERROR_GENERIC; 7889def1fb7SGatien Chevallier unsigned int i = 0; 7899def1fb7SGatien Chevallier 790bd03c8c3SGatien Chevallier if (!bank->rif_cfg) 791bd03c8c3SGatien Chevallier return TEE_SUCCESS; 792bd03c8c3SGatien Chevallier 793bd03c8c3SGatien Chevallier if (clk_enable(bank->clock)) 794bd03c8c3SGatien Chevallier panic(); 795bd03c8c3SGatien Chevallier 7969def1fb7SGatien Chevallier if (bank->is_tdcid) { 797bd03c8c3SGatien Chevallier for (i = 0; i < bank->ngpios; i++) { 798*a72f07daSEtienne Carriere if (!(BIT(i) & gpios_mask)) 799bd03c8c3SGatien Chevallier continue; 800bd03c8c3SGatien Chevallier 801bd03c8c3SGatien Chevallier /* 8029def1fb7SGatien Chevallier * When TDCID, OP-TEE should be the one to set the CID 8039def1fb7SGatien Chevallier * filtering configuration. Clearing previous 8049def1fb7SGatien Chevallier * configuration prevents undesired events during the 8059def1fb7SGatien Chevallier * only legitimate configuration. 806bd03c8c3SGatien Chevallier */ 807bd03c8c3SGatien Chevallier io_clrbits32(bank->base + GPIO_CIDCFGR(i), 808bd03c8c3SGatien Chevallier GPIO_CIDCFGR_CONF_MASK); 809bd03c8c3SGatien Chevallier } 8109def1fb7SGatien Chevallier } else { 811*a72f07daSEtienne Carriere res = handle_available_semaphores(bank, gpios_mask); 8129def1fb7SGatien Chevallier if (res) 8139def1fb7SGatien Chevallier panic(); 814bd03c8c3SGatien Chevallier } 815bd03c8c3SGatien Chevallier 816bd03c8c3SGatien Chevallier /* Security and privilege RIF configuration */ 817*a72f07daSEtienne Carriere io_mask32(bank->base + GPIO_PRIVCFGR_OFFSET, 818*a72f07daSEtienne Carriere bank->rif_cfg->priv_conf[0], gpios_mask); 819*a72f07daSEtienne Carriere io_mask32(bank->base + GPIO_SECR_OFFSET, 820*a72f07daSEtienne Carriere bank->rif_cfg->sec_conf[0], gpios_mask); 821bd03c8c3SGatien Chevallier 822bd03c8c3SGatien Chevallier if (!bank->is_tdcid) { 823bd03c8c3SGatien Chevallier res = TEE_SUCCESS; 824bd03c8c3SGatien Chevallier goto out; 825bd03c8c3SGatien Chevallier } 826bd03c8c3SGatien Chevallier 827bd03c8c3SGatien Chevallier for (i = 0; i < bank->ngpios; i++) { 828*a72f07daSEtienne Carriere if (!(BIT(i) & gpios_mask)) 829bd03c8c3SGatien Chevallier continue; 830bd03c8c3SGatien Chevallier 831bd03c8c3SGatien Chevallier io_clrsetbits32(bank->base + GPIO_CIDCFGR(i), 832bd03c8c3SGatien Chevallier GPIO_CIDCFGR_CONF_MASK, 833bd03c8c3SGatien Chevallier bank->rif_cfg->cid_confs[i]); 834bd03c8c3SGatien Chevallier } 835bd03c8c3SGatien Chevallier 836bd03c8c3SGatien Chevallier /* 837bd03c8c3SGatien Chevallier * Lock RIF configuration if configured. This cannot be undone until 838bd03c8c3SGatien Chevallier * next reset. 839bd03c8c3SGatien Chevallier */ 840bd03c8c3SGatien Chevallier io_setbits32(bank->base + GPIO_RCFGLOCKR_OFFSET, 841bd03c8c3SGatien Chevallier bank->rif_cfg->lock_conf[0]); 842bd03c8c3SGatien Chevallier 843*a72f07daSEtienne Carriere res = handle_available_semaphores(bank, gpios_mask); 8449def1fb7SGatien Chevallier if (res) 8459def1fb7SGatien Chevallier panic(); 8469def1fb7SGatien Chevallier 8479def1fb7SGatien Chevallier out: 848bd03c8c3SGatien Chevallier if (IS_ENABLED(CFG_TEE_CORE_DEBUG)) { 849bd03c8c3SGatien Chevallier /* Check that RIF config are applied, panic otherwise */ 850bd03c8c3SGatien Chevallier if ((io_read32(bank->base + GPIO_PRIVCFGR_OFFSET) & 851*a72f07daSEtienne Carriere gpios_mask) != 852*a72f07daSEtienne Carriere (bank->rif_cfg->priv_conf[0] & gpios_mask)) { 853bd03c8c3SGatien Chevallier EMSG("GPIO bank%c priv conf is incorrect", 854bd03c8c3SGatien Chevallier 'A' + bank->bank_id); 855bd03c8c3SGatien Chevallier panic(); 856bd03c8c3SGatien Chevallier } 857bd03c8c3SGatien Chevallier 858*a72f07daSEtienne Carriere if ((io_read32(bank->base + GPIO_SECR_OFFSET) & gpios_mask) != 859*a72f07daSEtienne Carriere (bank->rif_cfg->sec_conf[0] & gpios_mask)) { 860bd03c8c3SGatien Chevallier EMSG("GPIO bank %c sec conf is incorrect", 861bd03c8c3SGatien Chevallier 'A' + bank->bank_id); 862bd03c8c3SGatien Chevallier panic(); 863bd03c8c3SGatien Chevallier } 864bd03c8c3SGatien Chevallier } 865bd03c8c3SGatien Chevallier 866bd03c8c3SGatien Chevallier clk_disable(bank->clock); 867bd03c8c3SGatien Chevallier 868bd03c8c3SGatien Chevallier return res; 869bd03c8c3SGatien Chevallier } 8709def1fb7SGatien Chevallier #else /* CFG_STM32_RIF */ 871*a72f07daSEtienne Carriere static TEE_Result apply_rif_config(struct stm32_gpio_bank *bank __unused, 872*a72f07daSEtienne Carriere uint32_t gpios_mask __unused) 8739def1fb7SGatien Chevallier { 8749def1fb7SGatien Chevallier return TEE_SUCCESS; 8759def1fb7SGatien Chevallier } 8769def1fb7SGatien Chevallier #endif /* CFG_STM32_RIF */ 877bd03c8c3SGatien Chevallier 878bfc43b68SGatien Chevallier static void stm32_gpio_save_rif_config(struct stm32_gpio_bank *bank) 879bfc43b68SGatien Chevallier { 880bfc43b68SGatien Chevallier size_t i = 0; 881bfc43b68SGatien Chevallier 882bfc43b68SGatien Chevallier for (i = 0; i < bank->ngpios; i++) 883bfc43b68SGatien Chevallier bank->rif_cfg->cid_confs[i] = io_read32(bank->base + 884bfc43b68SGatien Chevallier GPIO_CIDCFGR(i)); 885bfc43b68SGatien Chevallier 886bfc43b68SGatien Chevallier bank->rif_cfg->priv_conf[0] = io_read32(bank->base + 887bfc43b68SGatien Chevallier GPIO_PRIVCFGR_OFFSET); 888bfc43b68SGatien Chevallier bank->rif_cfg->sec_conf[0] = io_read32(bank->base + 889bfc43b68SGatien Chevallier GPIO_SECR_OFFSET); 890bfc43b68SGatien Chevallier bank->rif_cfg->lock_conf[0] = io_read32(bank->base + 891bfc43b68SGatien Chevallier GPIO_RCFGLOCKR_OFFSET); 892bfc43b68SGatien Chevallier } 893bfc43b68SGatien Chevallier 894bd03c8c3SGatien Chevallier static void stm32_parse_gpio_rif_conf(struct stm32_gpio_bank *bank, 895bd03c8c3SGatien Chevallier const void *fdt, int node) 896bd03c8c3SGatien Chevallier { 897bd03c8c3SGatien Chevallier unsigned int i = 0; 898bd03c8c3SGatien Chevallier unsigned int nb_rif_conf = 0; 899bd03c8c3SGatien Chevallier int lenp = 0; 900bd03c8c3SGatien Chevallier const fdt32_t *cuint = NULL; 901bd03c8c3SGatien Chevallier 902bd03c8c3SGatien Chevallier cuint = fdt_getprop(fdt, node, "st,protreg", &lenp); 903bd03c8c3SGatien Chevallier if (!cuint) { 904bd03c8c3SGatien Chevallier DMSG("No RIF configuration available"); 905bd03c8c3SGatien Chevallier return; 906bd03c8c3SGatien Chevallier } 907bd03c8c3SGatien Chevallier 908bd03c8c3SGatien Chevallier bank->rif_cfg = calloc(1, sizeof(*bank->rif_cfg)); 909bd03c8c3SGatien Chevallier if (!bank->rif_cfg) 910bd03c8c3SGatien Chevallier panic(); 911bd03c8c3SGatien Chevallier 912bd03c8c3SGatien Chevallier bank->rif_cfg->sec_conf = calloc(1, sizeof(uint32_t)); 913bd03c8c3SGatien Chevallier if (!bank->rif_cfg->sec_conf) 914bd03c8c3SGatien Chevallier panic(); 915bd03c8c3SGatien Chevallier 916bd03c8c3SGatien Chevallier nb_rif_conf = (unsigned int)(lenp / sizeof(uint32_t)); 917bd03c8c3SGatien Chevallier assert(nb_rif_conf <= bank->ngpios); 918bd03c8c3SGatien Chevallier 919bd03c8c3SGatien Chevallier bank->rif_cfg->cid_confs = calloc(bank->ngpios, sizeof(uint32_t)); 920bd03c8c3SGatien Chevallier bank->rif_cfg->priv_conf = calloc(1, sizeof(uint32_t)); 921bd03c8c3SGatien Chevallier bank->rif_cfg->lock_conf = calloc(1, sizeof(uint32_t)); 922bd03c8c3SGatien Chevallier bank->rif_cfg->access_mask = calloc(1, sizeof(uint32_t)); 923bd03c8c3SGatien Chevallier if (!bank->rif_cfg->cid_confs || !bank->rif_cfg->access_mask || 924bd03c8c3SGatien Chevallier !bank->rif_cfg->priv_conf || !bank->rif_cfg->lock_conf) 925bd03c8c3SGatien Chevallier panic("Missing memory capacity for GPIOS RIF configuration"); 926bd03c8c3SGatien Chevallier 927bd03c8c3SGatien Chevallier for (i = 0; i < nb_rif_conf; i++) 928bd03c8c3SGatien Chevallier stm32_rif_parse_cfg(fdt32_to_cpu(cuint[i]), bank->rif_cfg, 929646ad62bSGatien Chevallier bank->ngpios); 930bd03c8c3SGatien Chevallier } 931bd03c8c3SGatien Chevallier 9329818a481SEtienne Carriere /* Get GPIO bank information from the DT */ 9339818a481SEtienne Carriere static TEE_Result dt_stm32_gpio_bank(const void *fdt, int node, 934e569f6adSEtienne Carriere const void *compat_data, 9359818a481SEtienne Carriere int range_offset, 9369818a481SEtienne Carriere struct stm32_gpio_bank **out_bank) 9379818a481SEtienne Carriere { 938e569f6adSEtienne Carriere const struct bank_compat *compat = compat_data; 9399818a481SEtienne Carriere TEE_Result res = TEE_ERROR_GENERIC; 9409818a481SEtienne Carriere struct stm32_gpio_bank *bank = NULL; 9419818a481SEtienne Carriere const fdt32_t *cuint = NULL; 9429818a481SEtienne Carriere struct io_pa_va pa_va = { }; 9439818a481SEtienne Carriere struct clk *clk = NULL; 9449818a481SEtienne Carriere size_t blen = 0; 9459818a481SEtienne Carriere paddr_t pa = 0; 9469818a481SEtienne Carriere int len = 0; 9479818a481SEtienne Carriere int i = 0; 9489818a481SEtienne Carriere 9499818a481SEtienne Carriere assert(out_bank); 9509818a481SEtienne Carriere 9519818a481SEtienne Carriere /* Probe deferrable devices first */ 9529818a481SEtienne Carriere res = clk_dt_get_by_index(fdt, node, 0, &clk); 9539818a481SEtienne Carriere if (res) 9549818a481SEtienne Carriere return res; 9559818a481SEtienne Carriere 9569818a481SEtienne Carriere bank = calloc(1, sizeof(*bank)); 9579818a481SEtienne Carriere if (!bank) 9589818a481SEtienne Carriere return TEE_ERROR_OUT_OF_MEMORY; 9599818a481SEtienne Carriere 960bd03c8c3SGatien Chevallier if (compat->secure_extended) { 961bd03c8c3SGatien Chevallier res = stm32_rifsc_check_tdcid(&bank->is_tdcid); 962bd03c8c3SGatien Chevallier if (res) { 963bd03c8c3SGatien Chevallier free(bank); 964bd03c8c3SGatien Chevallier return res; 965bd03c8c3SGatien Chevallier } 966bd03c8c3SGatien Chevallier } 967bd03c8c3SGatien Chevallier 9689818a481SEtienne Carriere /* 9699818a481SEtienne Carriere * Do not rely *only* on the "reg" property to get the address, 9709818a481SEtienne Carriere * but consider also the "ranges" translation property 9719818a481SEtienne Carriere */ 9726a0116edSEtienne Carriere if (fdt_reg_info(fdt, node, &pa, &blen)) 9736a0116edSEtienne Carriere panic("missing reg or reg size property"); 9749818a481SEtienne Carriere 9759818a481SEtienne Carriere pa_va.pa = pa + range_offset; 9769818a481SEtienne Carriere 9779818a481SEtienne Carriere DMSG("Bank name %s", fdt_get_name(fdt, node, NULL)); 9789818a481SEtienne Carriere bank->bank_id = dt_get_bank_id(fdt, node); 9799818a481SEtienne Carriere bank->clock = clk; 980420a32c5SEtienne Carriere bank->gpio_chip.ops = &stm32_gpio_ops; 981b4893304SGatien Chevallier bank->sec_support = compat->secure_control; 9829818a481SEtienne Carriere 9839818a481SEtienne Carriere /* Parse gpio-ranges with its 4 parameters */ 9849818a481SEtienne Carriere cuint = fdt_getprop(fdt, node, "gpio-ranges", &len); 9859818a481SEtienne Carriere len /= sizeof(*cuint); 9869818a481SEtienne Carriere if (len % 4) 9879818a481SEtienne Carriere panic("wrong gpio-ranges syntax"); 9889818a481SEtienne Carriere 9899818a481SEtienne Carriere /* Get the last defined gpio line (offset + nb of pins) */ 9909818a481SEtienne Carriere for (i = 0; i < len / 4; i++) { 9919818a481SEtienne Carriere bank->ngpios = MAX(bank->ngpios, 9929818a481SEtienne Carriere (unsigned int)(fdt32_to_cpu(*(cuint + 1)) + 9939818a481SEtienne Carriere fdt32_to_cpu(*(cuint + 3)))); 9949818a481SEtienne Carriere cuint += 4; 9959818a481SEtienne Carriere } 9969818a481SEtienne Carriere 997bd03c8c3SGatien Chevallier if (compat->secure_extended) { 998bd03c8c3SGatien Chevallier /* RIF configuration */ 999bd03c8c3SGatien Chevallier bank->base = io_pa_or_va_secure(&pa_va, blen); 1000bd03c8c3SGatien Chevallier 1001bd03c8c3SGatien Chevallier stm32_parse_gpio_rif_conf(bank, fdt, node); 1002bd03c8c3SGatien Chevallier } else if (bank->sec_support) { 1003bd03c8c3SGatien Chevallier /* Secure configuration */ 1004bd03c8c3SGatien Chevallier bank->base = io_pa_or_va_secure(&pa_va, blen); 1005bd03c8c3SGatien Chevallier cuint = fdt_getprop(fdt, node, "st,protreg", NULL); 1006bd03c8c3SGatien Chevallier if (cuint) 1007bd03c8c3SGatien Chevallier bank->seccfgr = fdt32_to_cpu(*cuint); 1008bd03c8c3SGatien Chevallier else 1009bd03c8c3SGatien Chevallier DMSG("GPIO bank %c assigned to non-secure", 1010bd03c8c3SGatien Chevallier bank->bank_id + 'A'); 1011bd03c8c3SGatien Chevallier } else { 1012bd03c8c3SGatien Chevallier bank->base = io_pa_or_va_nsec(&pa_va, blen); 1013bd03c8c3SGatien Chevallier } 1014bd03c8c3SGatien Chevallier 1015e569f6adSEtienne Carriere if (compat->gpioz) 1016e569f6adSEtienne Carriere stm32mp_register_gpioz_pin_count(bank->ngpios); 1017e569f6adSEtienne Carriere 10189818a481SEtienne Carriere *out_bank = bank; 1019bd03c8c3SGatien Chevallier 10209818a481SEtienne Carriere return TEE_SUCCESS; 10219818a481SEtienne Carriere } 10229818a481SEtienne Carriere 1023bd03c8c3SGatien Chevallier /* Parse a pinctrl node to register the GPIO banks it describes */ 10240e0435e2SEtienne Carriere static TEE_Result dt_stm32_gpio_pinctrl(const void *fdt, int node, 10259818a481SEtienne Carriere const void *compat_data) 10269818a481SEtienne Carriere { 10279818a481SEtienne Carriere TEE_Result res = TEE_SUCCESS; 10289818a481SEtienne Carriere const fdt32_t *cuint = NULL; 10299818a481SEtienne Carriere int range_offs = 0; 10309818a481SEtienne Carriere int b_node = 0; 10319818a481SEtienne Carriere int len = 0; 10329818a481SEtienne Carriere 10339818a481SEtienne Carriere /* Read the ranges property (for regs memory translation) */ 10349818a481SEtienne Carriere cuint = fdt_getprop(fdt, node, "ranges", &len); 10359818a481SEtienne Carriere if (!cuint) 10369818a481SEtienne Carriere panic("missing ranges property"); 10379818a481SEtienne Carriere 10389818a481SEtienne Carriere len /= sizeof(*cuint); 10399818a481SEtienne Carriere if (len == 3) 10409818a481SEtienne Carriere range_offs = fdt32_to_cpu(*(cuint + 1)) - fdt32_to_cpu(*cuint); 10419818a481SEtienne Carriere 10429818a481SEtienne Carriere fdt_for_each_subnode(b_node, fdt, node) { 10439818a481SEtienne Carriere cuint = fdt_getprop(fdt, b_node, "gpio-controller", &len); 10449818a481SEtienne Carriere if (cuint) { 10459818a481SEtienne Carriere /* 10469818a481SEtienne Carriere * We found a property "gpio-controller" in the node: 10479818a481SEtienne Carriere * the node is a GPIO bank description, add it to the 10489818a481SEtienne Carriere * bank list. 10499818a481SEtienne Carriere */ 10509818a481SEtienne Carriere struct stm32_gpio_bank *bank = NULL; 10519818a481SEtienne Carriere 10529818a481SEtienne Carriere if (fdt_get_status(fdt, b_node) == DT_STATUS_DISABLED || 10539818a481SEtienne Carriere bank_is_registered(fdt, b_node)) 10549818a481SEtienne Carriere continue; 10559818a481SEtienne Carriere 10569818a481SEtienne Carriere res = dt_stm32_gpio_bank(fdt, b_node, compat_data, 10579818a481SEtienne Carriere range_offs, &bank); 10589818a481SEtienne Carriere if (res) 10599818a481SEtienne Carriere return res; 10609818a481SEtienne Carriere 1061420a32c5SEtienne Carriere /* Registering a provider should not defer probe */ 1062420a32c5SEtienne Carriere res = gpio_register_provider(fdt, b_node, 1063420a32c5SEtienne Carriere stm32_gpio_get_dt, bank); 1064420a32c5SEtienne Carriere if (res) 1065420a32c5SEtienne Carriere panic(); 1066420a32c5SEtienne Carriere 10679818a481SEtienne Carriere STAILQ_INSERT_TAIL(&bank_list, bank, link); 10689818a481SEtienne Carriere } else { 10699818a481SEtienne Carriere if (len != -FDT_ERR_NOTFOUND) 10709818a481SEtienne Carriere panic(); 10719818a481SEtienne Carriere } 10729818a481SEtienne Carriere } 10739818a481SEtienne Carriere 10749818a481SEtienne Carriere return TEE_SUCCESS; 10759818a481SEtienne Carriere } 10769818a481SEtienne Carriere 1077077d486eSEtienne Carriere void stm32_gpio_set_secure_cfg(unsigned int bank_id, unsigned int pin, 1078077d486eSEtienne Carriere bool secure) 10794b5e93edSEtienne Carriere { 1080077d486eSEtienne Carriere struct stm32_gpio_bank *bank = stm32_gpio_get_bank(bank_id); 108198dfcedaSEtienne Carriere uint32_t exceptions = 0; 10824b5e93edSEtienne Carriere 1083077d486eSEtienne Carriere if (clk_enable(bank->clock)) 1084077d486eSEtienne Carriere panic(); 108598dfcedaSEtienne Carriere exceptions = cpu_spin_lock_xsave(&gpio_lock); 10864b5e93edSEtienne Carriere 10874b5e93edSEtienne Carriere if (secure) 1088077d486eSEtienne Carriere io_setbits32(bank->base + GPIO_SECR_OFFSET, BIT(pin)); 10894b5e93edSEtienne Carriere else 1090077d486eSEtienne Carriere io_clrbits32(bank->base + GPIO_SECR_OFFSET, BIT(pin)); 10914b5e93edSEtienne Carriere 1092c4cab2bbSEtienne Carriere cpu_spin_unlock_xrestore(&gpio_lock, exceptions); 109398dfcedaSEtienne Carriere clk_disable(bank->clock); 10944b5e93edSEtienne Carriere } 10950e0435e2SEtienne Carriere 1096b38386fbSEtienne Carriere #ifdef CFG_DRIVERS_PINCTRL 1097b38386fbSEtienne Carriere static TEE_Result stm32_pinctrl_conf_apply(struct pinconf *conf) 1098b38386fbSEtienne Carriere { 1099b38386fbSEtienne Carriere struct stm32_pinctrl_array *ref = conf->priv; 1100b38386fbSEtienne Carriere struct stm32_pinctrl *p = ref->pinctrl; 1101b38386fbSEtienne Carriere size_t pin_count = ref->count; 1102b38386fbSEtienne Carriere size_t n = 0; 1103b38386fbSEtienne Carriere 1104b38386fbSEtienne Carriere for (n = 0; n < pin_count; n++) 1105b38386fbSEtienne Carriere set_gpio_cfg(p[n].bank, p[n].pin, &p[n].cfg); 1106b38386fbSEtienne Carriere 1107b38386fbSEtienne Carriere return TEE_SUCCESS; 1108b38386fbSEtienne Carriere } 1109b38386fbSEtienne Carriere 1110b38386fbSEtienne Carriere static void stm32_pinctrl_conf_free(struct pinconf *conf) 1111b38386fbSEtienne Carriere { 1112b38386fbSEtienne Carriere free(conf); 1113b38386fbSEtienne Carriere } 1114b38386fbSEtienne Carriere 1115b38386fbSEtienne Carriere static const struct pinctrl_ops stm32_pinctrl_ops = { 1116b38386fbSEtienne Carriere .conf_apply = stm32_pinctrl_conf_apply, 1117b38386fbSEtienne Carriere .conf_free = stm32_pinctrl_conf_free, 1118b38386fbSEtienne Carriere }; 1119b38386fbSEtienne Carriere 1120b38386fbSEtienne Carriere DECLARE_KEEP_PAGER(stm32_pinctrl_ops); 1121b38386fbSEtienne Carriere 112270ac0db5SEtienne Carriere void stm32_gpio_pinctrl_bank_pin(struct pinctrl_state *pinctrl, 112370ac0db5SEtienne Carriere unsigned int *bank, unsigned int *pin, 112470ac0db5SEtienne Carriere unsigned int *count) 112570ac0db5SEtienne Carriere { 112670ac0db5SEtienne Carriere size_t conf_index = 0; 112770ac0db5SEtienne Carriere size_t pin_count = 0; 112870ac0db5SEtienne Carriere size_t n = 0; 112970ac0db5SEtienne Carriere 113070ac0db5SEtienne Carriere assert(count); 113170ac0db5SEtienne Carriere if (!pinctrl) 113270ac0db5SEtienne Carriere goto out; 113370ac0db5SEtienne Carriere 113470ac0db5SEtienne Carriere for (conf_index = 0; conf_index < pinctrl->conf_count; conf_index++) { 113570ac0db5SEtienne Carriere struct pinconf *pinconf = pinctrl->confs[conf_index]; 113670ac0db5SEtienne Carriere struct stm32_pinctrl_array *ref = pinconf->priv; 113770ac0db5SEtienne Carriere 113870ac0db5SEtienne Carriere /* Consider only the stm32_gpio pins */ 113970ac0db5SEtienne Carriere if (pinconf->ops != &stm32_pinctrl_ops) 114070ac0db5SEtienne Carriere continue; 114170ac0db5SEtienne Carriere 114270ac0db5SEtienne Carriere if (bank || pin) { 114370ac0db5SEtienne Carriere for (n = 0; n < ref->count; n++) { 114470ac0db5SEtienne Carriere if (bank && pin_count < *count) 114570ac0db5SEtienne Carriere bank[pin_count] = ref->pinctrl[n].bank; 114670ac0db5SEtienne Carriere if (pin && pin_count < *count) 114770ac0db5SEtienne Carriere pin[pin_count] = ref->pinctrl[n].pin; 114870ac0db5SEtienne Carriere pin_count++; 114970ac0db5SEtienne Carriere } 115070ac0db5SEtienne Carriere } else { 115170ac0db5SEtienne Carriere pin_count += ref->count; 115270ac0db5SEtienne Carriere } 115370ac0db5SEtienne Carriere } 115470ac0db5SEtienne Carriere 115570ac0db5SEtienne Carriere out: 115670ac0db5SEtienne Carriere *count = pin_count; 115770ac0db5SEtienne Carriere } 115870ac0db5SEtienne Carriere 11597f823a77SEtienne Carriere void stm32_pinctrl_set_secure_cfg(struct pinctrl_state *pinctrl, bool secure) 11607f823a77SEtienne Carriere { 11617f823a77SEtienne Carriere size_t conf_index = 0; 11627f823a77SEtienne Carriere 11637f823a77SEtienne Carriere if (!pinctrl) 11647f823a77SEtienne Carriere return; 11657f823a77SEtienne Carriere 11667f823a77SEtienne Carriere for (conf_index = 0; conf_index < pinctrl->conf_count; conf_index++) { 11677f823a77SEtienne Carriere struct pinconf *pinconf = pinctrl->confs[conf_index]; 11687f823a77SEtienne Carriere struct stm32_pinctrl_array *ref = pinconf->priv; 11697f823a77SEtienne Carriere struct stm32_pinctrl *pc = NULL; 11707f823a77SEtienne Carriere size_t n = 0; 11717f823a77SEtienne Carriere 11727f823a77SEtienne Carriere for (n = 0; n < ref->count; n++) { 11737f823a77SEtienne Carriere if (pinconf->ops != &stm32_pinctrl_ops) 11747f823a77SEtienne Carriere continue; 11757f823a77SEtienne Carriere 11767f823a77SEtienne Carriere pc = ref->pinctrl + n; 11777f823a77SEtienne Carriere stm32_gpio_set_secure_cfg(pc->bank, pc->pin, secure); 11787f823a77SEtienne Carriere } 11797f823a77SEtienne Carriere } 11807f823a77SEtienne Carriere } 11817f823a77SEtienne Carriere 1182b38386fbSEtienne Carriere /* Allocate and return a pinctrl configuration from a DT reference */ 1183b38386fbSEtienne Carriere static TEE_Result stm32_pinctrl_dt_get(struct dt_pargs *pargs, 1184b38386fbSEtienne Carriere void *data __unused, 1185b38386fbSEtienne Carriere struct pinconf **out_pinconf) 1186b38386fbSEtienne Carriere { 1187b38386fbSEtienne Carriere struct conf { 1188b38386fbSEtienne Carriere struct pinconf pinconf; 1189b38386fbSEtienne Carriere struct stm32_pinctrl_array array_ref; 1190b38386fbSEtienne Carriere } *loc_conf = NULL; 1191b38386fbSEtienne Carriere struct stm32_pinctrl *pinctrl = NULL; 1192b38386fbSEtienne Carriere struct pinconf *pinconf = NULL; 1193b38386fbSEtienne Carriere const void *fdt = NULL; 1194b38386fbSEtienne Carriere size_t pin_count = 0; 1195b38386fbSEtienne Carriere int pinctrl_node = 0; 1196b38386fbSEtienne Carriere int pinmux_node = 0; 1197b38386fbSEtienne Carriere int count = 0; 1198b38386fbSEtienne Carriere 1199b38386fbSEtienne Carriere pinctrl_node = pargs->phandle_node; 1200b38386fbSEtienne Carriere fdt = pargs->fdt; 1201b38386fbSEtienne Carriere assert(fdt && pinctrl_node); 1202b38386fbSEtienne Carriere 1203b38386fbSEtienne Carriere fdt_for_each_subnode(pinmux_node, fdt, pinctrl_node) { 1204b38386fbSEtienne Carriere if (fdt_getprop(fdt, pinmux_node, "pinmux", &count)) 1205b38386fbSEtienne Carriere pin_count += (size_t)count / sizeof(uint32_t); 1206b38386fbSEtienne Carriere else if (count != -FDT_ERR_NOTFOUND) 1207b38386fbSEtienne Carriere panic(); 1208b38386fbSEtienne Carriere } 1209b38386fbSEtienne Carriere 1210b38386fbSEtienne Carriere loc_conf = calloc(1, sizeof(*loc_conf) + sizeof(*pinctrl) * pin_count); 1211b38386fbSEtienne Carriere if (!loc_conf) 1212b38386fbSEtienne Carriere return TEE_ERROR_OUT_OF_MEMORY; 1213b38386fbSEtienne Carriere 1214b38386fbSEtienne Carriere pinconf = &loc_conf->pinconf; 1215b38386fbSEtienne Carriere pinconf->ops = &stm32_pinctrl_ops; 1216b38386fbSEtienne Carriere pinconf->priv = &loc_conf->array_ref; 1217b38386fbSEtienne Carriere 1218b38386fbSEtienne Carriere loc_conf->array_ref.count = pin_count; 1219b38386fbSEtienne Carriere pinctrl = loc_conf->array_ref.pinctrl; 1220b38386fbSEtienne Carriere 1221b38386fbSEtienne Carriere count = 0; 1222b38386fbSEtienne Carriere fdt_for_each_subnode(pinmux_node, fdt, pinctrl_node) { 1223b38386fbSEtienne Carriere int found = 0; 1224b38386fbSEtienne Carriere 1225b38386fbSEtienne Carriere found = get_pinctrl_from_fdt(fdt, pinmux_node, pinctrl + count, 1226b38386fbSEtienne Carriere pin_count - count); 1227b38386fbSEtienne Carriere if (found <= 0 && found > ((int)pin_count - count)) { 1228b38386fbSEtienne Carriere /* We can't recover from an error here so let's panic */ 1229b38386fbSEtienne Carriere panic(); 1230b38386fbSEtienne Carriere } 1231b38386fbSEtienne Carriere 1232b38386fbSEtienne Carriere count += found; 1233b38386fbSEtienne Carriere } 1234b38386fbSEtienne Carriere 1235b38386fbSEtienne Carriere *out_pinconf = pinconf; 1236b38386fbSEtienne Carriere 1237b38386fbSEtienne Carriere return TEE_SUCCESS; 1238b38386fbSEtienne Carriere } 1239b38386fbSEtienne Carriere #endif /*CFG_DRIVERS_PINCTRL*/ 1240b38386fbSEtienne Carriere 1241bfc43b68SGatien Chevallier static void stm32_gpio_get_conf_sec(struct stm32_gpio_bank *bank) 1242bfc43b68SGatien Chevallier { 1243bfc43b68SGatien Chevallier if (bank->sec_support) { 1244bfc43b68SGatien Chevallier clk_enable(bank->clock); 1245bfc43b68SGatien Chevallier bank->seccfgr = io_read32(bank->base + GPIO_SECR_OFFSET); 1246bfc43b68SGatien Chevallier clk_disable(bank->clock); 1247bfc43b68SGatien Chevallier } 1248bfc43b68SGatien Chevallier } 1249bfc43b68SGatien Chevallier 1250bd03c8c3SGatien Chevallier static void stm32_gpio_set_conf_sec(struct stm32_gpio_bank *bank) 1251bd03c8c3SGatien Chevallier { 1252bd03c8c3SGatien Chevallier if (bank->sec_support) { 1253bd03c8c3SGatien Chevallier clk_enable(bank->clock); 1254bd03c8c3SGatien Chevallier io_write32(bank->base + GPIO_SECR_OFFSET, bank->seccfgr); 1255bd03c8c3SGatien Chevallier clk_disable(bank->clock); 1256bd03c8c3SGatien Chevallier } 1257bd03c8c3SGatien Chevallier } 1258bd03c8c3SGatien Chevallier 1259bfc43b68SGatien Chevallier static TEE_Result stm32_gpio_sec_config_resume(void) 1260bfc43b68SGatien Chevallier { 1261bfc43b68SGatien Chevallier TEE_Result res = TEE_ERROR_GENERIC; 1262bfc43b68SGatien Chevallier struct stm32_gpio_bank *bank = NULL; 1263bfc43b68SGatien Chevallier 1264bfc43b68SGatien Chevallier STAILQ_FOREACH(bank, &bank_list, link) { 1265bfc43b68SGatien Chevallier if (bank->rif_cfg) { 1266bfc43b68SGatien Chevallier if (!bank->is_tdcid) 1267bfc43b68SGatien Chevallier continue; 1268bfc43b68SGatien Chevallier 1269bfc43b68SGatien Chevallier bank->rif_cfg->access_mask[0] = GENMASK_32(bank->ngpios, 1270bfc43b68SGatien Chevallier 0); 1271bfc43b68SGatien Chevallier 1272*a72f07daSEtienne Carriere res = apply_rif_config(bank, 1273*a72f07daSEtienne Carriere bank->rif_cfg->access_mask[0]); 1274bfc43b68SGatien Chevallier if (res) { 1275bfc43b68SGatien Chevallier EMSG("Failed to set GPIO bank %c RIF config", 1276bfc43b68SGatien Chevallier 'A' + bank->bank_id); 1277bfc43b68SGatien Chevallier return res; 1278bfc43b68SGatien Chevallier } 1279bfc43b68SGatien Chevallier } else { 1280bfc43b68SGatien Chevallier stm32_gpio_set_conf_sec(bank); 1281bfc43b68SGatien Chevallier } 1282bfc43b68SGatien Chevallier } 1283bfc43b68SGatien Chevallier 1284bfc43b68SGatien Chevallier return TEE_SUCCESS; 1285bfc43b68SGatien Chevallier } 1286bfc43b68SGatien Chevallier 1287bfc43b68SGatien Chevallier static TEE_Result stm32_gpio_sec_config_suspend(void) 1288bfc43b68SGatien Chevallier { 1289bfc43b68SGatien Chevallier struct stm32_gpio_bank *bank = NULL; 1290bfc43b68SGatien Chevallier 1291bfc43b68SGatien Chevallier STAILQ_FOREACH(bank, &bank_list, link) { 1292bfc43b68SGatien Chevallier if (bank->rif_cfg) { 1293bfc43b68SGatien Chevallier if (bank->is_tdcid) 1294bfc43b68SGatien Chevallier stm32_gpio_save_rif_config(bank); 1295bfc43b68SGatien Chevallier } else { 1296bfc43b68SGatien Chevallier stm32_gpio_get_conf_sec(bank); 1297bfc43b68SGatien Chevallier } 1298bfc43b68SGatien Chevallier } 1299bfc43b68SGatien Chevallier 1300bfc43b68SGatien Chevallier return TEE_SUCCESS; 1301bfc43b68SGatien Chevallier } 1302bfc43b68SGatien Chevallier 1303bfc43b68SGatien Chevallier static TEE_Result 1304bfc43b68SGatien Chevallier stm32_gpio_sec_config_pm(enum pm_op op, unsigned int pm_hint, 1305bfc43b68SGatien Chevallier const struct pm_callback_handle *hdl __unused) 1306bfc43b68SGatien Chevallier { 1307bfc43b68SGatien Chevallier TEE_Result ret = TEE_ERROR_GENERIC; 1308bfc43b68SGatien Chevallier 1309bfc43b68SGatien Chevallier if (!PM_HINT_IS_STATE(pm_hint, CONTEXT)) 1310bfc43b68SGatien Chevallier return TEE_SUCCESS; 1311bfc43b68SGatien Chevallier 1312bfc43b68SGatien Chevallier if (op == PM_OP_RESUME) 1313bfc43b68SGatien Chevallier ret = stm32_gpio_sec_config_resume(); 1314bfc43b68SGatien Chevallier else 1315bfc43b68SGatien Chevallier ret = stm32_gpio_sec_config_suspend(); 1316bfc43b68SGatien Chevallier 1317bfc43b68SGatien Chevallier return ret; 1318bfc43b68SGatien Chevallier } 1319bfc43b68SGatien Chevallier DECLARE_KEEP_PAGER(stm32_gpio_sec_config_pm); 1320bfc43b68SGatien Chevallier 1321bd03c8c3SGatien Chevallier /* 1322bd03c8c3SGatien Chevallier * Several pinctrl nodes can be probed. Their bank will be put in the unique 1323bd03c8c3SGatien Chevallier * bank_list. To avoid multiple configuration set for a bank when looping 1324bd03c8c3SGatien Chevallier * over each bank in the bank list, ready is set to true when a bank is 1325bd03c8c3SGatien Chevallier * configured. Therefore, during other bank probes, the configuration won't 1326bd03c8c3SGatien Chevallier * be set again. 1327bd03c8c3SGatien Chevallier */ 1328bd03c8c3SGatien Chevallier static TEE_Result apply_sec_cfg(void) 1329bd03c8c3SGatien Chevallier { 1330bd03c8c3SGatien Chevallier TEE_Result res = TEE_ERROR_GENERIC; 1331bd03c8c3SGatien Chevallier struct stm32_gpio_bank *bank = NULL; 1332bd03c8c3SGatien Chevallier 1333bd03c8c3SGatien Chevallier STAILQ_FOREACH(bank, &bank_list, link) { 1334bd03c8c3SGatien Chevallier if (bank->ready) 1335bd03c8c3SGatien Chevallier continue; 1336bd03c8c3SGatien Chevallier 1337bd03c8c3SGatien Chevallier if (bank->rif_cfg) { 1338*a72f07daSEtienne Carriere res = apply_rif_config(bank, 1339*a72f07daSEtienne Carriere bank->rif_cfg->access_mask[0]); 1340bd03c8c3SGatien Chevallier if (res) { 1341bd03c8c3SGatien Chevallier EMSG("Failed to set GPIO bank %c RIF config", 1342bd03c8c3SGatien Chevallier 'A' + bank->bank_id); 1343bd03c8c3SGatien Chevallier STAILQ_REMOVE(&bank_list, bank, stm32_gpio_bank, 1344bd03c8c3SGatien Chevallier link); 13459def1fb7SGatien Chevallier free(bank); 1346bd03c8c3SGatien Chevallier return res; 1347bd03c8c3SGatien Chevallier } 1348bd03c8c3SGatien Chevallier } else { 1349bd03c8c3SGatien Chevallier stm32_gpio_set_conf_sec(bank); 1350bd03c8c3SGatien Chevallier } 1351bd03c8c3SGatien Chevallier 1352bd03c8c3SGatien Chevallier bank->ready = true; 1353bd03c8c3SGatien Chevallier } 1354bd03c8c3SGatien Chevallier 1355bd03c8c3SGatien Chevallier return TEE_SUCCESS; 1356bd03c8c3SGatien Chevallier } 1357bd03c8c3SGatien Chevallier 13580e0435e2SEtienne Carriere static TEE_Result stm32_pinctrl_probe(const void *fdt, int node, 13590e0435e2SEtienne Carriere const void *compat_data) 13600e0435e2SEtienne Carriere { 1361bfc43b68SGatien Chevallier static bool pm_register; 1362b38386fbSEtienne Carriere TEE_Result res = TEE_ERROR_GENERIC; 1363b38386fbSEtienne Carriere 13640e0435e2SEtienne Carriere /* Register GPIO banks described in this pin control node */ 1365b38386fbSEtienne Carriere res = dt_stm32_gpio_pinctrl(fdt, node, compat_data); 1366b38386fbSEtienne Carriere if (res) 1367b38386fbSEtienne Carriere return res; 1368b38386fbSEtienne Carriere 1369bd03c8c3SGatien Chevallier if (STAILQ_EMPTY(&bank_list)) 1370bd03c8c3SGatien Chevallier DMSG("no gpio bank for that driver"); 1371bd03c8c3SGatien Chevallier else if (apply_sec_cfg()) 1372bd03c8c3SGatien Chevallier panic(); 1373bd03c8c3SGatien Chevallier 1374bfc43b68SGatien Chevallier if (!pm_register) { 1375bfc43b68SGatien Chevallier /* 1376bfc43b68SGatien Chevallier * Register to PM once for all probed banks to restore 1377bfc43b68SGatien Chevallier * their secure configuration. 1378bfc43b68SGatien Chevallier */ 1379bfc43b68SGatien Chevallier register_pm_driver_cb(stm32_gpio_sec_config_pm, NULL, 1380bfc43b68SGatien Chevallier "stm32-gpio-secure-config"); 1381bfc43b68SGatien Chevallier pm_register = true; 1382bfc43b68SGatien Chevallier } 1383bfc43b68SGatien Chevallier 1384b38386fbSEtienne Carriere #ifdef CFG_DRIVERS_PINCTRL 1385b38386fbSEtienne Carriere res = pinctrl_register_provider(fdt, node, stm32_pinctrl_dt_get, 1386b38386fbSEtienne Carriere (void *)compat_data); 1387b38386fbSEtienne Carriere if (res) 1388bd03c8c3SGatien Chevallier panic(); 1389b38386fbSEtienne Carriere #endif 1390b38386fbSEtienne Carriere 1391b38386fbSEtienne Carriere return TEE_SUCCESS; 13920e0435e2SEtienne Carriere } 13930e0435e2SEtienne Carriere 13940e0435e2SEtienne Carriere static const struct dt_device_match stm32_pinctrl_match_table[] = { 1395e569f6adSEtienne Carriere { 1396e569f6adSEtienne Carriere .compatible = "st,stm32mp135-pinctrl", 1397b4893304SGatien Chevallier .compat_data = &(struct bank_compat){ 1398b4893304SGatien Chevallier .secure_control = true, 1399bd03c8c3SGatien Chevallier .secure_extended = false, 1400b4893304SGatien Chevallier }, 1401e569f6adSEtienne Carriere }, 1402e569f6adSEtienne Carriere { 1403e569f6adSEtienne Carriere .compatible = "st,stm32mp157-pinctrl", 1404b4893304SGatien Chevallier .compat_data = &(struct bank_compat){ 1405b4893304SGatien Chevallier .secure_control = false, 1406bd03c8c3SGatien Chevallier .secure_extended = false, 1407b4893304SGatien Chevallier }, 1408e569f6adSEtienne Carriere }, 1409e569f6adSEtienne Carriere { 1410e569f6adSEtienne Carriere .compatible = "st,stm32mp157-z-pinctrl", 1411b4893304SGatien Chevallier .compat_data = &(struct bank_compat){ 1412b4893304SGatien Chevallier .gpioz = true, 1413b4893304SGatien Chevallier .secure_control = true, 1414bd03c8c3SGatien Chevallier .secure_extended = false, 1415bd03c8c3SGatien Chevallier }, 1416bd03c8c3SGatien Chevallier }, 1417bd03c8c3SGatien Chevallier { 1418bd03c8c3SGatien Chevallier .compatible = "st,stm32mp257-pinctrl", 1419bd03c8c3SGatien Chevallier .compat_data = &(struct bank_compat){ 1420bd03c8c3SGatien Chevallier .secure_control = true, 1421bd03c8c3SGatien Chevallier .secure_extended = true, 1422bd03c8c3SGatien Chevallier }, 1423bd03c8c3SGatien Chevallier }, 1424bd03c8c3SGatien Chevallier { 1425bd03c8c3SGatien Chevallier .compatible = "st,stm32mp257-z-pinctrl", 1426bd03c8c3SGatien Chevallier .compat_data = &(struct bank_compat){ 1427bd03c8c3SGatien Chevallier .gpioz = true, 1428bd03c8c3SGatien Chevallier .secure_control = true, 1429bd03c8c3SGatien Chevallier .secure_extended = true, 1430b4893304SGatien Chevallier }, 1431e569f6adSEtienne Carriere }, 14320e0435e2SEtienne Carriere { } 14330e0435e2SEtienne Carriere }; 14340e0435e2SEtienne Carriere 14350e0435e2SEtienne Carriere DEFINE_DT_DRIVER(stm32_pinctrl_dt_driver) = { 14360e0435e2SEtienne Carriere .name = "stm32_gpio-pinctrl", 14370e0435e2SEtienne Carriere .type = DT_DRIVER_PINCTRL, 14380e0435e2SEtienne Carriere .match_table = stm32_pinctrl_match_table, 14390e0435e2SEtienne Carriere .probe = stm32_pinctrl_probe, 14400e0435e2SEtienne Carriere }; 1441