xref: /optee_os/core/drivers/stm32_gpio.c (revision 430c415af209f537649600c9c75574e19070c9d2)
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>
12a650c9cbSEtienne Carriere #include <drivers/firewall.h>
13420a32c5SEtienne Carriere #include <drivers/gpio.h>
14b38386fbSEtienne Carriere #include <drivers/pinctrl.h>
154b5e93edSEtienne Carriere #include <drivers/stm32_gpio.h>
16bd03c8c3SGatien Chevallier #include <drivers/stm32_rif.h>
17a650c9cbSEtienne Carriere #include <dt-bindings/gpio/stm32mp_gpio.h>
184b5e93edSEtienne Carriere #include <io.h>
194b5e93edSEtienne Carriere #include <kernel/dt.h>
2065401337SJens Wiklander #include <kernel/boot.h>
214b5e93edSEtienne Carriere #include <kernel/panic.h>
22bfc43b68SGatien Chevallier #include <kernel/pm.h>
234b5e93edSEtienne Carriere #include <kernel/spinlock.h>
24a2fc83d1SJerome Forissier #include <libfdt.h>
254b5e93edSEtienne Carriere #include <mm/core_memprot.h>
264b5e93edSEtienne Carriere #include <stdbool.h>
2769715ce9SEtienne Carriere #include <stdint.h>
284b5e93edSEtienne Carriere #include <stm32_util.h>
299818a481SEtienne Carriere #include <sys/queue.h>
304b5e93edSEtienne Carriere #include <trace.h>
314b5e93edSEtienne Carriere #include <util.h>
324b5e93edSEtienne Carriere 
331001585eSEtienne Carriere #ifndef CFG_DRIVERS_GPIO
341001585eSEtienne Carriere #error stm32_gpio driver expects CFG_DRIVERS_GPIO
351001585eSEtienne Carriere #endif
361001585eSEtienne Carriere 
374b5e93edSEtienne Carriere #define GPIO_PIN_MAX		15
384b5e93edSEtienne Carriere 
395eed568cSGatien Chevallier #define GPIO_MODER_OFFSET	U(0x00)
405eed568cSGatien Chevallier #define GPIO_OTYPER_OFFSET	U(0x04)
415eed568cSGatien Chevallier #define GPIO_OSPEEDR_OFFSET	U(0x08)
425eed568cSGatien Chevallier #define GPIO_PUPDR_OFFSET	U(0x0c)
435eed568cSGatien Chevallier #define GPIO_IDR_OFFSET		U(0x10)
445eed568cSGatien Chevallier #define GPIO_ODR_OFFSET		U(0x14)
455eed568cSGatien Chevallier #define GPIO_BSRR_OFFSET	U(0x18)
465eed568cSGatien Chevallier #define GPIO_AFRL_OFFSET	U(0x20)
475eed568cSGatien Chevallier #define GPIO_AFRH_OFFSET	U(0x24)
485eed568cSGatien Chevallier #define GPIO_SECR_OFFSET	U(0x30)
49bd03c8c3SGatien Chevallier #define GPIO_PRIVCFGR_OFFSET	U(0x34)
50bd03c8c3SGatien Chevallier #define GPIO_RCFGLOCKR_OFFSET	U(0x38)
51bd03c8c3SGatien Chevallier #define GPIO_CIDCFGR(x)		(U(0x50) + U(0x8) * (x))
52bd03c8c3SGatien Chevallier #define GPIO_SEMCR(x)		(U(0x54) + U(0x8) * (x))
534b5e93edSEtienne Carriere 
545eed568cSGatien Chevallier #define GPIO_ALT_LOWER_LIMIT	U(0x8)
554b5e93edSEtienne Carriere 
56bd03c8c3SGatien Chevallier /*
57bd03c8c3SGatien Chevallier  * CIDCFGR register bitfields
58bd03c8c3SGatien Chevallier  */
59bd03c8c3SGatien Chevallier #define GPIO_CIDCFGR_SEMWL_MASK	GENMASK_32(23, 16)
60bd03c8c3SGatien Chevallier #define GPIO_CIDCFGR_SCID_MASK	GENMASK_32(6, 4)
61bd03c8c3SGatien Chevallier #define GPIO_CIDCFGR_CONF_MASK	(_CIDCFGR_CFEN | _CIDCFGR_SEMEN |	\
62bd03c8c3SGatien Chevallier 				 GPIO_CIDCFGR_SCID_MASK |		\
63bd03c8c3SGatien Chevallier 				 GPIO_CIDCFGR_SEMWL_MASK)
64bd03c8c3SGatien Chevallier 
65bd03c8c3SGatien Chevallier /*
66bd03c8c3SGatien Chevallier  * PRIVCFGR register bitfields
67bd03c8c3SGatien Chevallier  */
68bd03c8c3SGatien Chevallier #define GPIO_PRIVCFGR_MASK	GENMASK_32(15, 0)
69bd03c8c3SGatien Chevallier 
70bd03c8c3SGatien Chevallier /*
71bd03c8c3SGatien Chevallier  * SECCFGR register bitfields
72bd03c8c3SGatien Chevallier  */
73bd03c8c3SGatien Chevallier #define GPIO_SECCFGR_MASK	GENMASK_32(15, 0)
74bd03c8c3SGatien Chevallier 
75bd03c8c3SGatien Chevallier /*
76bd03c8c3SGatien Chevallier  * RCFGLOCKR register bitfields
77bd03c8c3SGatien Chevallier  */
78bd03c8c3SGatien Chevallier #define GPIO_RCFGLOCKR_MASK	GENMASK_32(15, 0)
79bd03c8c3SGatien Chevallier 
80bd03c8c3SGatien Chevallier /*
81bd03c8c3SGatien Chevallier  * SEMCR register bitfields
82bd03c8c3SGatien Chevallier  */
83bd03c8c3SGatien Chevallier #define GPIO_SEMCR_SCID_M	GENMASK_32(6, 4)
84bd03c8c3SGatien Chevallier 
854b5e93edSEtienne Carriere #define GPIO_MODE_MASK		GENMASK_32(1, 0)
864b5e93edSEtienne Carriere #define GPIO_OSPEED_MASK	GENMASK_32(1, 0)
874b5e93edSEtienne Carriere #define GPIO_PUPD_PULL_MASK	GENMASK_32(1, 0)
88729093d5SLionel Debieve #define GPIO_ALTERNATE_MASK	GENMASK_32(3, 0)
894b5e93edSEtienne Carriere 
905eed568cSGatien Chevallier #define DT_GPIO_BANK_SHIFT	U(12)
914b5e93edSEtienne Carriere #define DT_GPIO_BANK_MASK	GENMASK_32(16, 12)
925eed568cSGatien Chevallier #define DT_GPIO_PIN_SHIFT	U(8)
934b5e93edSEtienne Carriere #define DT_GPIO_PIN_MASK	GENMASK_32(11, 8)
944b5e93edSEtienne Carriere #define DT_GPIO_MODE_MASK	GENMASK_32(7, 0)
954b5e93edSEtienne Carriere 
969818a481SEtienne Carriere #define DT_GPIO_BANK_NAME0	"GPIOA"
979818a481SEtienne Carriere 
9869715ce9SEtienne Carriere #define GPIO_MODE_INPUT		U(0x0)
9969715ce9SEtienne Carriere #define GPIO_MODE_OUTPUT	U(0x1)
10069715ce9SEtienne Carriere #define GPIO_MODE_ALTERNATE	U(0x2)
10169715ce9SEtienne Carriere #define GPIO_MODE_ANALOG	U(0x3)
10269715ce9SEtienne Carriere 
10369715ce9SEtienne Carriere #define GPIO_OTYPE_PUSH_PULL	U(0x0)
10469715ce9SEtienne Carriere #define GPIO_OTYPE_OPEN_DRAIN	U(0x1)
10569715ce9SEtienne Carriere 
10669715ce9SEtienne Carriere #define GPIO_OSPEED_LOW		U(0x0)
10769715ce9SEtienne Carriere #define GPIO_OSPEED_MEDIUM	U(0x1)
10869715ce9SEtienne Carriere #define GPIO_OSPEED_HIGH	U(0x2)
10969715ce9SEtienne Carriere #define GPIO_OSPEED_VERY_HIGH	U(0x3)
11069715ce9SEtienne Carriere 
11169715ce9SEtienne Carriere #define GPIO_PUPD_NO_PULL	U(0x0)
11269715ce9SEtienne Carriere #define GPIO_PUPD_PULL_UP	U(0x1)
11369715ce9SEtienne Carriere #define GPIO_PUPD_PULL_DOWN	U(0x2)
11469715ce9SEtienne Carriere 
11569715ce9SEtienne Carriere #define GPIO_OD_LEVEL_LOW	U(0x0)
11669715ce9SEtienne Carriere #define GPIO_OD_LEVEL_HIGH	U(0x1)
11769715ce9SEtienne Carriere 
118bd03c8c3SGatien Chevallier #define GPIO_MAX_CID_SUPPORTED	U(3)
119bd03c8c3SGatien Chevallier 
12069715ce9SEtienne Carriere /*
12169715ce9SEtienne Carriere  * GPIO configuration description structured as single 16bit word
12269715ce9SEtienne Carriere  * for efficient save/restore when GPIO pin suspends or resumes.
12369715ce9SEtienne Carriere  *
12469715ce9SEtienne Carriere  * @mode: One of GPIO_MODE_*
12569715ce9SEtienne Carriere  * @otype: One of GPIO_OTYPE_*
12669715ce9SEtienne Carriere  * @ospeed: One of GPIO_OSPEED_*
12769715ce9SEtienne Carriere  * @pupd: One of GPIO_PUPD_*
12869715ce9SEtienne Carriere  * @od: One of GPIO_OD_*
12969715ce9SEtienne Carriere  * @af: Alternate function numerical ID between 0 and 15
13069715ce9SEtienne Carriere  */
13169715ce9SEtienne Carriere struct gpio_cfg {
13269715ce9SEtienne Carriere 	uint16_t mode:		2;
13369715ce9SEtienne Carriere 	uint16_t otype:		1;
13469715ce9SEtienne Carriere 	uint16_t ospeed:	2;
13569715ce9SEtienne Carriere 	uint16_t pupd:		2;
13669715ce9SEtienne Carriere 	uint16_t od:		1;
13769715ce9SEtienne Carriere 	uint16_t af:		4;
13869715ce9SEtienne Carriere };
13969715ce9SEtienne Carriere 
14069715ce9SEtienne Carriere /*
14169715ce9SEtienne Carriere  * Description of a pin and its muxing
14269715ce9SEtienne Carriere  *
14369715ce9SEtienne Carriere  * @bank: GPIO bank identifier as assigned by the platform
14469715ce9SEtienne Carriere  * @pin: Pin number in the GPIO bank
14569715ce9SEtienne Carriere  * @cfg: Pin configuration
14669715ce9SEtienne Carriere  */
14769715ce9SEtienne Carriere struct stm32_pinctrl {
14869715ce9SEtienne Carriere 	uint8_t bank;
14969715ce9SEtienne Carriere 	uint8_t pin;
15069715ce9SEtienne Carriere 	struct gpio_cfg cfg;
15169715ce9SEtienne Carriere };
15269715ce9SEtienne Carriere 
153b38386fbSEtienne Carriere /*
154b38386fbSEtienne Carriere  * struct stm32_pinctrl_array - Array of pins in a pin control state
155b38386fbSEtienne Carriere  * @count: Number of cells in @pinctrl
156b38386fbSEtienne Carriere  * @pinctrl: Pin control configuration
157b38386fbSEtienne Carriere  */
158b38386fbSEtienne Carriere struct stm32_pinctrl_array {
159b38386fbSEtienne Carriere 	size_t count;
160b38386fbSEtienne Carriere 	struct stm32_pinctrl pinctrl[];
161b38386fbSEtienne Carriere };
162b38386fbSEtienne Carriere 
1639818a481SEtienne Carriere /**
1649818a481SEtienne Carriere  * struct stm32_gpio_bank - GPIO bank instance
1659818a481SEtienne Carriere  *
1669818a481SEtienne Carriere  * @base: base address of the GPIO controller registers.
1679818a481SEtienne Carriere  * @clock: clock identifier.
168420a32c5SEtienne Carriere  * @gpio_chip: GPIO chip reference for that GPIO bank
1699818a481SEtienne Carriere  * @ngpios: number of GPIOs.
1709818a481SEtienne Carriere  * @bank_id: Id of the bank.
1719818a481SEtienne Carriere  * @lock: lock protecting the GPIO bank access.
172bd03c8c3SGatien Chevallier  * @rif_cfg: RIF configuration data
173bd03c8c3SGatien Chevallier  * @seccfgr: non-RIF bank secure configuration data
174bd03c8c3SGatien Chevallier  * @sec_support: True if bank supports pin security protection, else false
175bd03c8c3SGatien Chevallier  * @ready: True if configuration is applied, else false
176bd03c8c3SGatien Chevallier  * @is_tdcid: True if OP-TEE runs as Trusted Domain CID
1779818a481SEtienne Carriere  * @link: Link in bank list
1789818a481SEtienne Carriere  */
1799818a481SEtienne Carriere struct stm32_gpio_bank {
1809818a481SEtienne Carriere 	vaddr_t base;
1819818a481SEtienne Carriere 	struct clk *clock;
182420a32c5SEtienne Carriere 	struct gpio_chip gpio_chip;
1839818a481SEtienne Carriere 	unsigned int ngpios;
1849818a481SEtienne Carriere 	unsigned int bank_id;
1859818a481SEtienne Carriere 	unsigned int lock;
186bd03c8c3SGatien Chevallier 	struct rif_conf_data *rif_cfg;
187bd03c8c3SGatien Chevallier 	uint32_t seccfgr;
188b4893304SGatien Chevallier 	bool sec_support;
189bd03c8c3SGatien Chevallier 	bool ready;
190bd03c8c3SGatien Chevallier 	bool is_tdcid;
1919818a481SEtienne Carriere 	STAILQ_ENTRY(stm32_gpio_bank) link;
1929818a481SEtienne Carriere };
1939818a481SEtienne Carriere 
194bfc43b68SGatien Chevallier /*
195bfc43b68SGatien Chevallier  * struct stm32_gpio_pm_state - Consumed GPIO for PM purpose
196bfc43b68SGatien Chevallier  * @gpio_pinctrl: Reference and configuration state for a consumed GPIO
197bfc43b68SGatien Chevallier  * @level: GPIO level
198bfc43b68SGatien Chevallier  * @link: Link in consumed GPIO list
199bfc43b68SGatien Chevallier  */
200bfc43b68SGatien Chevallier struct stm32_gpio_pm_state {
201bfc43b68SGatien Chevallier 	struct stm32_pinctrl gpio_pinctrl;
202bfc43b68SGatien Chevallier 	uint8_t level;
203bfc43b68SGatien Chevallier 	SLIST_ENTRY(stm32_gpio_pm_state) link;
204bfc43b68SGatien Chevallier };
205bfc43b68SGatien Chevallier 
206b4893304SGatien Chevallier /**
207e569f6adSEtienne Carriere  * Compatibility information of supported banks
208b4893304SGatien Chevallier  *
209b4893304SGatien Chevallier  * @gpioz: True if bank is a GPIOZ bank
210b4893304SGatien Chevallier  * @secure_control: Identify GPIO security bank capability.
211bd03c8c3SGatien Chevallier  * @secure_extended: Identify RIF presence.
212e569f6adSEtienne Carriere  */
213e569f6adSEtienne Carriere struct bank_compat {
214e569f6adSEtienne Carriere 	bool gpioz;
215b4893304SGatien Chevallier 	bool secure_control;
216bd03c8c3SGatien Chevallier 	bool secure_extended;
217e569f6adSEtienne Carriere };
218e569f6adSEtienne Carriere 
2194b5e93edSEtienne Carriere static unsigned int gpio_lock;
2204b5e93edSEtienne Carriere 
2219818a481SEtienne Carriere static STAILQ_HEAD(, stm32_gpio_bank) bank_list =
2229818a481SEtienne Carriere 		STAILQ_HEAD_INITIALIZER(bank_list);
2239818a481SEtienne Carriere 
224bfc43b68SGatien Chevallier static SLIST_HEAD(, stm32_gpio_pm_state) consumed_gpios_head;
225bfc43b68SGatien Chevallier 
226420a32c5SEtienne Carriere static bool is_stm32_gpio_chip(struct gpio_chip *chip);
227420a32c5SEtienne Carriere 
228420a32c5SEtienne Carriere static struct stm32_gpio_bank *gpio_chip_to_bank(struct gpio_chip *chip)
229420a32c5SEtienne Carriere {
230420a32c5SEtienne Carriere 	return container_of(chip, struct stm32_gpio_bank, gpio_chip);
231420a32c5SEtienne Carriere }
232420a32c5SEtienne Carriere 
233420a32c5SEtienne Carriere static enum gpio_level stm32_gpio_get_level(struct gpio_chip *chip,
234420a32c5SEtienne Carriere 					    unsigned int gpio_pin)
235420a32c5SEtienne Carriere {
236420a32c5SEtienne Carriere 	struct stm32_gpio_bank *bank = gpio_chip_to_bank(chip);
237420a32c5SEtienne Carriere 	enum gpio_level level = GPIO_LEVEL_HIGH;
238420a32c5SEtienne Carriere 	unsigned int reg_offset = 0;
239420a32c5SEtienne Carriere 	unsigned int mode = 0;
240420a32c5SEtienne Carriere 
241420a32c5SEtienne Carriere 	assert(gpio_pin < bank->ngpios);
2422fd102ebSEtienne Carriere 
2432fd102ebSEtienne Carriere 	if (clk_enable(bank->clock))
2442fd102ebSEtienne Carriere 		panic();
245420a32c5SEtienne Carriere 
246420a32c5SEtienne Carriere 	mode = (io_read32(bank->base + GPIO_MODER_OFFSET) >> (gpio_pin << 1)) &
247420a32c5SEtienne Carriere 	       GPIO_MODE_MASK;
248420a32c5SEtienne Carriere 
249420a32c5SEtienne Carriere 	switch (mode) {
250420a32c5SEtienne Carriere 	case GPIO_MODE_INPUT:
251420a32c5SEtienne Carriere 		reg_offset = GPIO_IDR_OFFSET;
252420a32c5SEtienne Carriere 		break;
253420a32c5SEtienne Carriere 	case GPIO_MODE_OUTPUT:
254420a32c5SEtienne Carriere 		reg_offset = GPIO_ODR_OFFSET;
255420a32c5SEtienne Carriere 		break;
256420a32c5SEtienne Carriere 	default:
257420a32c5SEtienne Carriere 		panic();
258420a32c5SEtienne Carriere 	}
259420a32c5SEtienne Carriere 
260420a32c5SEtienne Carriere 	if (io_read32(bank->base + reg_offset) & BIT(gpio_pin))
261420a32c5SEtienne Carriere 		level = GPIO_LEVEL_HIGH;
262420a32c5SEtienne Carriere 	else
263420a32c5SEtienne Carriere 		level = GPIO_LEVEL_LOW;
264420a32c5SEtienne Carriere 
265420a32c5SEtienne Carriere 	clk_disable(bank->clock);
266420a32c5SEtienne Carriere 
267420a32c5SEtienne Carriere 	return level;
268420a32c5SEtienne Carriere }
269420a32c5SEtienne Carriere 
270420a32c5SEtienne Carriere static void stm32_gpio_set_level(struct gpio_chip *chip, unsigned int gpio_pin,
271420a32c5SEtienne Carriere 				 enum gpio_level level)
272420a32c5SEtienne Carriere {
273420a32c5SEtienne Carriere 	struct stm32_gpio_bank *bank = gpio_chip_to_bank(chip);
274420a32c5SEtienne Carriere 
275420a32c5SEtienne Carriere 	assert(gpio_pin < bank->ngpios);
2762fd102ebSEtienne Carriere 
2772fd102ebSEtienne Carriere 	if (clk_enable(bank->clock))
2782fd102ebSEtienne Carriere 		panic();
279420a32c5SEtienne Carriere 
280420a32c5SEtienne Carriere 	assert(((io_read32(bank->base + GPIO_MODER_OFFSET) >>
281420a32c5SEtienne Carriere 		 (gpio_pin << 1)) & GPIO_MODE_MASK) == GPIO_MODE_OUTPUT);
282420a32c5SEtienne Carriere 
283420a32c5SEtienne Carriere 	if (level == GPIO_LEVEL_HIGH)
284420a32c5SEtienne Carriere 		io_write32(bank->base + GPIO_BSRR_OFFSET, BIT(gpio_pin));
285420a32c5SEtienne Carriere 	else
286420a32c5SEtienne Carriere 		io_write32(bank->base + GPIO_BSRR_OFFSET, BIT(gpio_pin + 16));
287420a32c5SEtienne Carriere 
288420a32c5SEtienne Carriere 	clk_disable(bank->clock);
289420a32c5SEtienne Carriere }
290420a32c5SEtienne Carriere 
291420a32c5SEtienne Carriere static enum gpio_dir stm32_gpio_get_direction(struct gpio_chip *chip,
292420a32c5SEtienne Carriere 					      unsigned int gpio_pin)
293420a32c5SEtienne Carriere {
294420a32c5SEtienne Carriere 	struct stm32_gpio_bank *bank = gpio_chip_to_bank(chip);
295420a32c5SEtienne Carriere 	uint32_t mode = 0;
296420a32c5SEtienne Carriere 
297420a32c5SEtienne Carriere 	assert(gpio_pin < bank->ngpios);
2982fd102ebSEtienne Carriere 
2992fd102ebSEtienne Carriere 	if (clk_enable(bank->clock))
3002fd102ebSEtienne Carriere 		panic();
301420a32c5SEtienne Carriere 
302420a32c5SEtienne Carriere 	mode = (io_read32(bank->base + GPIO_MODER_OFFSET) >> (gpio_pin << 1)) &
303420a32c5SEtienne Carriere 	       GPIO_MODE_MASK;
304420a32c5SEtienne Carriere 
305420a32c5SEtienne Carriere 	clk_disable(bank->clock);
306420a32c5SEtienne Carriere 
307420a32c5SEtienne Carriere 	switch (mode) {
308420a32c5SEtienne Carriere 	case GPIO_MODE_INPUT:
309420a32c5SEtienne Carriere 		return GPIO_DIR_IN;
310420a32c5SEtienne Carriere 	case GPIO_MODE_OUTPUT:
311420a32c5SEtienne Carriere 		return GPIO_DIR_OUT;
312420a32c5SEtienne Carriere 	default:
313420a32c5SEtienne Carriere 		panic();
314420a32c5SEtienne Carriere 	}
315420a32c5SEtienne Carriere }
316420a32c5SEtienne Carriere 
317420a32c5SEtienne Carriere static void stm32_gpio_set_direction(struct gpio_chip *chip,
318420a32c5SEtienne Carriere 				     unsigned int gpio_pin,
319420a32c5SEtienne Carriere 				     enum gpio_dir direction)
320420a32c5SEtienne Carriere {
321420a32c5SEtienne Carriere 	struct stm32_gpio_bank *bank = gpio_chip_to_bank(chip);
322420a32c5SEtienne Carriere 	uint32_t exceptions = 0;
323420a32c5SEtienne Carriere 	uint32_t mode = 0;
324420a32c5SEtienne Carriere 
325420a32c5SEtienne Carriere 	assert(gpio_pin < bank->ngpios);
326420a32c5SEtienne Carriere 
327420a32c5SEtienne Carriere 	if (direction == GPIO_DIR_IN)
328420a32c5SEtienne Carriere 		mode = GPIO_MODE_INPUT;
329420a32c5SEtienne Carriere 	else
330420a32c5SEtienne Carriere 		mode = GPIO_MODE_OUTPUT;
331420a32c5SEtienne Carriere 
3322fd102ebSEtienne Carriere 	if (clk_enable(bank->clock))
3332fd102ebSEtienne Carriere 		panic();
334420a32c5SEtienne Carriere 	exceptions = cpu_spin_lock_xsave(&gpio_lock);
335420a32c5SEtienne Carriere 	io_clrsetbits32(bank->base + GPIO_MODER_OFFSET,
336420a32c5SEtienne Carriere 			SHIFT_U32(GPIO_MODE_MASK, gpio_pin << 1),
337420a32c5SEtienne Carriere 			SHIFT_U32(mode, gpio_pin << 1));
338420a32c5SEtienne Carriere 	cpu_spin_unlock_xrestore(&gpio_lock, exceptions);
339420a32c5SEtienne Carriere 	clk_disable(bank->clock);
340420a32c5SEtienne Carriere }
341420a32c5SEtienne Carriere 
342bfc43b68SGatien Chevallier /* Forward reference to the PM callback handler for consumed GPIOs */
343bfc43b68SGatien Chevallier static TEE_Result consumed_gpios_pm(enum pm_op op, unsigned int pm_hint,
344bfc43b68SGatien Chevallier 				    const struct pm_callback_handle *pm_hdl);
345bfc43b68SGatien Chevallier 
346*430c415aSEtienne Carriere /* Forward reference to RIF semaphore release helper function */
347*430c415aSEtienne Carriere static void release_rif_semaphore_if_acquired(struct stm32_gpio_bank *bank,
348*430c415aSEtienne Carriere 					      unsigned int pin);
349*430c415aSEtienne Carriere 
350bfc43b68SGatien Chevallier static void stm32_gpio_put_gpio(struct gpio_chip *chip, struct gpio *gpio)
351420a32c5SEtienne Carriere {
352bfc43b68SGatien Chevallier 	struct stm32_gpio_bank *bank = gpio_chip_to_bank(chip);
353bfc43b68SGatien Chevallier 	struct stm32_gpio_pm_state *tstate = NULL;
354bfc43b68SGatien Chevallier 	struct stm32_gpio_pm_state *state = NULL;
355bfc43b68SGatien Chevallier 	uint32_t exceptions = 0;
356bfc43b68SGatien Chevallier 
357420a32c5SEtienne Carriere 	assert(is_stm32_gpio_chip(chip));
358bfc43b68SGatien Chevallier 
359bfc43b68SGatien Chevallier 	exceptions = cpu_spin_lock_xsave(&gpio_lock);
360bfc43b68SGatien Chevallier 
361bfc43b68SGatien Chevallier 	SLIST_FOREACH_SAFE(state, &consumed_gpios_head, link, tstate) {
362bfc43b68SGatien Chevallier 		if (state->gpio_pinctrl.bank == bank->bank_id &&
363bfc43b68SGatien Chevallier 		    state->gpio_pinctrl.pin == gpio->pin) {
364bfc43b68SGatien Chevallier 			SLIST_REMOVE(&consumed_gpios_head, state,
365bfc43b68SGatien Chevallier 				     stm32_gpio_pm_state, link);
366bfc43b68SGatien Chevallier 			unregister_pm_driver_cb(consumed_gpios_pm, state);
367*430c415aSEtienne Carriere 			release_rif_semaphore_if_acquired(bank, gpio->pin);
368bfc43b68SGatien Chevallier 			free(state);
369420a32c5SEtienne Carriere 			free(gpio);
370bfc43b68SGatien Chevallier 			break;
371bfc43b68SGatien Chevallier 		}
372bfc43b68SGatien Chevallier 	}
373bfc43b68SGatien Chevallier 	assert(state);
374bfc43b68SGatien Chevallier 
375bfc43b68SGatien Chevallier 	cpu_spin_unlock_xrestore(&gpio_lock, exceptions);
376420a32c5SEtienne Carriere }
377420a32c5SEtienne Carriere 
378420a32c5SEtienne Carriere static const struct gpio_ops stm32_gpio_ops = {
379420a32c5SEtienne Carriere 	.get_direction = stm32_gpio_get_direction,
380420a32c5SEtienne Carriere 	.set_direction = stm32_gpio_set_direction,
381420a32c5SEtienne Carriere 	.get_value = stm32_gpio_get_level,
382420a32c5SEtienne Carriere 	.set_value = stm32_gpio_set_level,
383420a32c5SEtienne Carriere 	.put = stm32_gpio_put_gpio,
384420a32c5SEtienne Carriere };
385420a32c5SEtienne Carriere 
386420a32c5SEtienne Carriere static bool __maybe_unused is_stm32_gpio_chip(struct gpio_chip *chip)
387420a32c5SEtienne Carriere {
388420a32c5SEtienne Carriere 	return chip && chip->ops == &stm32_gpio_ops;
389420a32c5SEtienne Carriere }
390420a32c5SEtienne Carriere 
391077d486eSEtienne Carriere static struct stm32_gpio_bank *stm32_gpio_get_bank(unsigned int bank_id)
3924b5e93edSEtienne Carriere {
393077d486eSEtienne Carriere 	struct stm32_gpio_bank *bank = NULL;
3944b5e93edSEtienne Carriere 
395077d486eSEtienne Carriere 	STAILQ_FOREACH(bank, &bank_list, link)
396077d486eSEtienne Carriere 		if (bank_id == bank->bank_id)
397077d486eSEtienne Carriere 			return bank;
398077d486eSEtienne Carriere 
399077d486eSEtienne Carriere 	panic();
400077d486eSEtienne Carriere }
401077d486eSEtienne Carriere 
402*430c415aSEtienne Carriere #if defined(CFG_STM32_RIF)
403*430c415aSEtienne Carriere static TEE_Result acquire_rif_semaphore_if_needed(struct stm32_gpio_bank *bank,
404*430c415aSEtienne Carriere 						  unsigned int pin)
405*430c415aSEtienne Carriere {
406*430c415aSEtienne Carriere 	TEE_Result res = TEE_SUCCESS;
407*430c415aSEtienne Carriere 	uint32_t cidcfgr = 0;
408*430c415aSEtienne Carriere 
409*430c415aSEtienne Carriere 	if (!bank->rif_cfg)
410*430c415aSEtienne Carriere 		return TEE_SUCCESS;
411*430c415aSEtienne Carriere 
412*430c415aSEtienne Carriere 	res = clk_enable(bank->clock);
413*430c415aSEtienne Carriere 	if (res)
414*430c415aSEtienne Carriere 		return res;
415*430c415aSEtienne Carriere 
416*430c415aSEtienne Carriere 	cidcfgr = io_read32(bank->base + GPIO_CIDCFGR(pin));
417*430c415aSEtienne Carriere 
418*430c415aSEtienne Carriere 	if (stm32_rif_semaphore_enabled_and_ok(cidcfgr, RIF_CID1))
419*430c415aSEtienne Carriere 		res = stm32_rif_acquire_semaphore(bank->base + GPIO_SEMCR(pin),
420*430c415aSEtienne Carriere 						  GPIO_MAX_CID_SUPPORTED);
421*430c415aSEtienne Carriere 
422*430c415aSEtienne Carriere 	clk_disable(bank->clock);
423*430c415aSEtienne Carriere 
424*430c415aSEtienne Carriere 	return res;
425*430c415aSEtienne Carriere }
426*430c415aSEtienne Carriere 
427*430c415aSEtienne Carriere static uint32_t semaphore_current_cid(struct stm32_gpio_bank *bank,
428*430c415aSEtienne Carriere 				      unsigned int pin)
429*430c415aSEtienne Carriere {
430*430c415aSEtienne Carriere 	return (io_read32(bank->base + GPIO_SEMCR(pin)) >>
431*430c415aSEtienne Carriere 		_CIDCFGR_SCID_SHIFT) &
432*430c415aSEtienne Carriere 		GENMASK_32(GPIO_MAX_CID_SUPPORTED - 1, 0);
433*430c415aSEtienne Carriere }
434*430c415aSEtienne Carriere 
435*430c415aSEtienne Carriere static void release_rif_semaphore_if_acquired(struct stm32_gpio_bank *bank,
436*430c415aSEtienne Carriere 					      unsigned int pin)
437*430c415aSEtienne Carriere {
438*430c415aSEtienne Carriere 	TEE_Result res = TEE_ERROR_GENERIC;
439*430c415aSEtienne Carriere 	uint32_t cidcfgr = 0;
440*430c415aSEtienne Carriere 
441*430c415aSEtienne Carriere 	if (!bank->rif_cfg)
442*430c415aSEtienne Carriere 		return;
443*430c415aSEtienne Carriere 
444*430c415aSEtienne Carriere 	res = clk_enable(bank->clock);
445*430c415aSEtienne Carriere 	if (res)
446*430c415aSEtienne Carriere 		panic();
447*430c415aSEtienne Carriere 
448*430c415aSEtienne Carriere 	cidcfgr = io_read32(bank->base + GPIO_CIDCFGR(pin));
449*430c415aSEtienne Carriere 
450*430c415aSEtienne Carriere 	if (stm32_rif_semaphore_enabled_and_ok(cidcfgr, RIF_CID1) &&
451*430c415aSEtienne Carriere 	    semaphore_current_cid(bank, pin) == RIF_CID1) {
452*430c415aSEtienne Carriere 		res = stm32_rif_release_semaphore(bank->base + GPIO_SEMCR(pin),
453*430c415aSEtienne Carriere 						  GPIO_MAX_CID_SUPPORTED);
454*430c415aSEtienne Carriere 		if (res) {
455*430c415aSEtienne Carriere 			EMSG("Failed to release GPIO %c%u semaphore",
456*430c415aSEtienne Carriere 			     bank->bank_id + 'A', pin);
457*430c415aSEtienne Carriere 			panic();
458*430c415aSEtienne Carriere 		}
459*430c415aSEtienne Carriere 	}
460*430c415aSEtienne Carriere 
461*430c415aSEtienne Carriere 	clk_disable(bank->clock);
462*430c415aSEtienne Carriere }
463*430c415aSEtienne Carriere #else
464*430c415aSEtienne Carriere static TEE_Result
465*430c415aSEtienne Carriere acquire_rif_semaphore_if_needed(struct stm32_gpio_bank *bank __unused,
466*430c415aSEtienne Carriere 				unsigned int pin __unused)
467*430c415aSEtienne Carriere {
468*430c415aSEtienne Carriere 	return TEE_SUCCESS;
469*430c415aSEtienne Carriere }
470*430c415aSEtienne Carriere 
471*430c415aSEtienne Carriere static void
472*430c415aSEtienne Carriere release_rif_semaphore_if_acquired(struct stm32_gpio_bank *bank __unused,
473*430c415aSEtienne Carriere 				  unsigned int pin __unused)
474*430c415aSEtienne Carriere {
475*430c415aSEtienne Carriere }
476*430c415aSEtienne Carriere #endif /*CFG_STM32_RIF*/
477*430c415aSEtienne Carriere 
478077d486eSEtienne Carriere /* Save to output @cfg the current GPIO (@bank_id/@pin) configuration */
479bfc43b68SGatien Chevallier static void get_gpio_cfg(uint32_t bank_id, uint32_t pin, struct gpio_cfg *cfg)
480077d486eSEtienne Carriere {
481077d486eSEtienne Carriere 	struct stm32_gpio_bank *bank = stm32_gpio_get_bank(bank_id);
482077d486eSEtienne Carriere 
483077d486eSEtienne Carriere 	if (clk_enable(bank->clock))
484077d486eSEtienne Carriere 		panic();
4854b5e93edSEtienne Carriere 
4864b5e93edSEtienne Carriere 	/*
4874b5e93edSEtienne Carriere 	 * Save GPIO configuration bits spread over the few bank registers.
4884b5e93edSEtienne Carriere 	 * 1bit fields are accessed at bit position being the pin index.
4894b5e93edSEtienne Carriere 	 * 2bit fields are accessed at bit position being twice the pin index.
4904b5e93edSEtienne Carriere 	 * 4bit fields are accessed at bit position being fourth the pin index
4914b5e93edSEtienne Carriere 	 * but accessed from 2 32bit registers at incremental addresses.
4924b5e93edSEtienne Carriere 	 */
493077d486eSEtienne Carriere 	cfg->mode = (io_read32(bank->base + GPIO_MODER_OFFSET) >> (pin << 1)) &
4944b5e93edSEtienne Carriere 		    GPIO_MODE_MASK;
4954b5e93edSEtienne Carriere 
496077d486eSEtienne Carriere 	cfg->otype = (io_read32(bank->base + GPIO_OTYPER_OFFSET) >> pin) & 1;
4974b5e93edSEtienne Carriere 
498077d486eSEtienne Carriere 	cfg->ospeed = (io_read32(bank->base +  GPIO_OSPEEDR_OFFSET) >>
499077d486eSEtienne Carriere 		       (pin << 1)) & GPIO_OSPEED_MASK;
5004b5e93edSEtienne Carriere 
501077d486eSEtienne Carriere 	cfg->pupd = (io_read32(bank->base +  GPIO_PUPDR_OFFSET) >> (pin << 1)) &
5024b5e93edSEtienne Carriere 		    GPIO_PUPD_PULL_MASK;
5034b5e93edSEtienne Carriere 
504077d486eSEtienne Carriere 	cfg->od = (io_read32(bank->base + GPIO_ODR_OFFSET) >> (pin << 1)) & 1;
5054b5e93edSEtienne Carriere 
5064b5e93edSEtienne Carriere 	if (pin < GPIO_ALT_LOWER_LIMIT)
507077d486eSEtienne Carriere 		cfg->af = (io_read32(bank->base + GPIO_AFRL_OFFSET) >>
508077d486eSEtienne Carriere 			   (pin << 2)) & GPIO_ALTERNATE_MASK;
5094b5e93edSEtienne Carriere 	else
510077d486eSEtienne Carriere 		cfg->af = (io_read32(bank->base + GPIO_AFRH_OFFSET) >>
5114b5e93edSEtienne Carriere 			   ((pin - GPIO_ALT_LOWER_LIMIT) << 2)) &
5124b5e93edSEtienne Carriere 			  GPIO_ALTERNATE_MASK;
5134b5e93edSEtienne Carriere 
514077d486eSEtienne Carriere 	clk_disable(bank->clock);
5154b5e93edSEtienne Carriere }
5164b5e93edSEtienne Carriere 
5174b5e93edSEtienne Carriere /* Apply GPIO (@bank/@pin) configuration described by @cfg */
518077d486eSEtienne Carriere static void set_gpio_cfg(uint32_t bank_id, uint32_t pin, struct gpio_cfg *cfg)
5194b5e93edSEtienne Carriere {
520077d486eSEtienne Carriere 	struct stm32_gpio_bank *bank = stm32_gpio_get_bank(bank_id);
52198dfcedaSEtienne Carriere 	uint32_t exceptions = 0;
5224b5e93edSEtienne Carriere 
523077d486eSEtienne Carriere 	if (clk_enable(bank->clock))
524077d486eSEtienne Carriere 		panic();
52598dfcedaSEtienne Carriere 	exceptions = cpu_spin_lock_xsave(&gpio_lock);
5264b5e93edSEtienne Carriere 
5274b5e93edSEtienne Carriere 	/* Load GPIO MODE value, 2bit value shifted by twice the pin number */
528077d486eSEtienne Carriere 	io_clrsetbits32(bank->base + GPIO_MODER_OFFSET,
529bed4582fSEtienne Carriere 			SHIFT_U32(GPIO_MODE_MASK, pin << 1),
530bed4582fSEtienne Carriere 			SHIFT_U32(cfg->mode, pin << 1));
5314b5e93edSEtienne Carriere 
5324b5e93edSEtienne Carriere 	/* Load GPIO Output TYPE value, 1bit shifted by pin number value */
533077d486eSEtienne Carriere 	io_clrsetbits32(bank->base + GPIO_OTYPER_OFFSET, BIT(pin),
534bed4582fSEtienne Carriere 			SHIFT_U32(cfg->otype, pin));
5354b5e93edSEtienne Carriere 
5364b5e93edSEtienne Carriere 	/* Load GPIO Output Speed confguration, 2bit value */
537077d486eSEtienne Carriere 	io_clrsetbits32(bank->base + GPIO_OSPEEDR_OFFSET,
538bed4582fSEtienne Carriere 			SHIFT_U32(GPIO_OSPEED_MASK, pin << 1),
539bed4582fSEtienne Carriere 			SHIFT_U32(cfg->ospeed, pin << 1));
5404b5e93edSEtienne Carriere 
5414b5e93edSEtienne Carriere 	/* Load GPIO pull configuration, 2bit value */
542077d486eSEtienne Carriere 	io_clrsetbits32(bank->base + GPIO_PUPDR_OFFSET, BIT(pin),
543bed4582fSEtienne Carriere 			SHIFT_U32(cfg->pupd, pin << 1));
5444b5e93edSEtienne Carriere 
5454b5e93edSEtienne Carriere 	/* Load pin mux Alternate Function configuration, 4bit value */
5464b5e93edSEtienne Carriere 	if (pin < GPIO_ALT_LOWER_LIMIT) {
547077d486eSEtienne Carriere 		io_clrsetbits32(bank->base + GPIO_AFRL_OFFSET,
548bed4582fSEtienne Carriere 				SHIFT_U32(GPIO_ALTERNATE_MASK, pin << 2),
549bed4582fSEtienne Carriere 				SHIFT_U32(cfg->af, pin << 2));
5504b5e93edSEtienne Carriere 	} else {
5514b5e93edSEtienne Carriere 		size_t shift = (pin - GPIO_ALT_LOWER_LIMIT) << 2;
5524b5e93edSEtienne Carriere 
553077d486eSEtienne Carriere 		io_clrsetbits32(bank->base + GPIO_AFRH_OFFSET,
554bed4582fSEtienne Carriere 				SHIFT_U32(GPIO_ALTERNATE_MASK, shift),
555bed4582fSEtienne Carriere 				SHIFT_U32(cfg->af, shift));
5564b5e93edSEtienne Carriere 	}
5574b5e93edSEtienne Carriere 
5584b5e93edSEtienne Carriere 	/* Load GPIO Output direction confuguration, 1bit */
559077d486eSEtienne Carriere 	io_clrsetbits32(bank->base + GPIO_ODR_OFFSET, BIT(pin), cfg->od << pin);
5604b5e93edSEtienne Carriere 
561c4cab2bbSEtienne Carriere 	cpu_spin_unlock_xrestore(&gpio_lock, exceptions);
56298dfcedaSEtienne Carriere 	clk_disable(bank->clock);
5634b5e93edSEtienne Carriere }
5644b5e93edSEtienne Carriere 
5654b5e93edSEtienne Carriere /* Count pins described in the DT node and get related data if possible */
566b38386fbSEtienne Carriere static int get_pinctrl_from_fdt(const void *fdt, int node,
5674b5e93edSEtienne Carriere 				struct stm32_pinctrl *pinctrl, size_t count)
5684b5e93edSEtienne Carriere {
569b38386fbSEtienne Carriere 	const fdt32_t *cuint = NULL;
570b38386fbSEtienne Carriere 	const fdt32_t *slewrate = NULL;
57110bcbd6cSEtienne Carriere 	int len = 0;
57210bcbd6cSEtienne Carriere 	uint32_t i = 0;
5734b5e93edSEtienne Carriere 	uint32_t speed = GPIO_OSPEED_LOW;
5744b5e93edSEtienne Carriere 	uint32_t pull = GPIO_PUPD_NO_PULL;
5754b5e93edSEtienne Carriere 	size_t found = 0;
5764b5e93edSEtienne Carriere 
5774b5e93edSEtienne Carriere 	cuint = fdt_getprop(fdt, node, "pinmux", &len);
5784b5e93edSEtienne Carriere 	if (!cuint)
5794b5e93edSEtienne Carriere 		return -FDT_ERR_NOTFOUND;
5804b5e93edSEtienne Carriere 
5814b5e93edSEtienne Carriere 	slewrate = fdt_getprop(fdt, node, "slew-rate", NULL);
5824b5e93edSEtienne Carriere 	if (slewrate)
5834b5e93edSEtienne Carriere 		speed = fdt32_to_cpu(*slewrate);
5844b5e93edSEtienne Carriere 
5854b5e93edSEtienne Carriere 	if (fdt_getprop(fdt, node, "bias-pull-up", NULL))
5864b5e93edSEtienne Carriere 		pull = GPIO_PUPD_PULL_UP;
5874b5e93edSEtienne Carriere 	if (fdt_getprop(fdt, node, "bias-pull-down", NULL))
5884b5e93edSEtienne Carriere 		pull = GPIO_PUPD_PULL_DOWN;
5894b5e93edSEtienne Carriere 
5904b5e93edSEtienne Carriere 	for (i = 0; i < ((uint32_t)len / sizeof(uint32_t)); i++) {
59110bcbd6cSEtienne Carriere 		uint32_t pincfg = 0;
59210bcbd6cSEtienne Carriere 		uint32_t bank = 0;
59310bcbd6cSEtienne Carriere 		uint32_t pin = 0;
59410bcbd6cSEtienne Carriere 		uint32_t mode = 0;
5954b5e93edSEtienne Carriere 		uint32_t alternate = 0;
596322cf9e3SEtienne Carriere 		uint32_t odata = 0;
5974b5e93edSEtienne Carriere 		bool opendrain = false;
5984b5e93edSEtienne Carriere 
5994b5e93edSEtienne Carriere 		pincfg = fdt32_to_cpu(*cuint);
6004b5e93edSEtienne Carriere 		cuint++;
6014b5e93edSEtienne Carriere 
6024b5e93edSEtienne Carriere 		bank = (pincfg & DT_GPIO_BANK_MASK) >> DT_GPIO_BANK_SHIFT;
6034b5e93edSEtienne Carriere 
6044b5e93edSEtienne Carriere 		pin = (pincfg & DT_GPIO_PIN_MASK) >> DT_GPIO_PIN_SHIFT;
6054b5e93edSEtienne Carriere 
6064b5e93edSEtienne Carriere 		mode = pincfg & DT_GPIO_MODE_MASK;
6074b5e93edSEtienne Carriere 
6084b5e93edSEtienne Carriere 		switch (mode) {
6094b5e93edSEtienne Carriere 		case 0:
6104b5e93edSEtienne Carriere 			mode = GPIO_MODE_INPUT;
6114b5e93edSEtienne Carriere 			break;
6124b5e93edSEtienne Carriere 		case 1:
6134b5e93edSEtienne Carriere 		case 2:
6144b5e93edSEtienne Carriere 		case 3:
6154b5e93edSEtienne Carriere 		case 4:
6164b5e93edSEtienne Carriere 		case 5:
6174b5e93edSEtienne Carriere 		case 6:
6184b5e93edSEtienne Carriere 		case 7:
6194b5e93edSEtienne Carriere 		case 8:
6204b5e93edSEtienne Carriere 		case 9:
6214b5e93edSEtienne Carriere 		case 10:
6224b5e93edSEtienne Carriere 		case 11:
6234b5e93edSEtienne Carriere 		case 12:
6244b5e93edSEtienne Carriere 		case 13:
6254b5e93edSEtienne Carriere 		case 14:
6264b5e93edSEtienne Carriere 		case 15:
6274b5e93edSEtienne Carriere 		case 16:
6284b5e93edSEtienne Carriere 			alternate = mode - 1U;
6294b5e93edSEtienne Carriere 			mode = GPIO_MODE_ALTERNATE;
6304b5e93edSEtienne Carriere 			break;
6314b5e93edSEtienne Carriere 		case 17:
6324b5e93edSEtienne Carriere 			mode = GPIO_MODE_ANALOG;
6334b5e93edSEtienne Carriere 			break;
6344b5e93edSEtienne Carriere 		default:
6354b5e93edSEtienne Carriere 			mode = GPIO_MODE_OUTPUT;
6364b5e93edSEtienne Carriere 			break;
6374b5e93edSEtienne Carriere 		}
6384b5e93edSEtienne Carriere 
6394b5e93edSEtienne Carriere 		if (fdt_getprop(fdt, node, "drive-open-drain", NULL))
6404b5e93edSEtienne Carriere 			opendrain = true;
6414b5e93edSEtienne Carriere 
642322cf9e3SEtienne Carriere 		if (fdt_getprop(fdt, node, "output-high", NULL) &&
643322cf9e3SEtienne Carriere 		    mode == GPIO_MODE_INPUT) {
644322cf9e3SEtienne Carriere 			mode = GPIO_MODE_OUTPUT;
645322cf9e3SEtienne Carriere 			odata = 1;
646322cf9e3SEtienne Carriere 		}
647322cf9e3SEtienne Carriere 
648322cf9e3SEtienne Carriere 		if (fdt_getprop(fdt, node, "output-low", NULL) &&
649322cf9e3SEtienne Carriere 		    mode == GPIO_MODE_INPUT) {
650322cf9e3SEtienne Carriere 			mode = GPIO_MODE_OUTPUT;
651322cf9e3SEtienne Carriere 			odata = 0;
652322cf9e3SEtienne Carriere 		}
653322cf9e3SEtienne Carriere 
6544b5e93edSEtienne Carriere 		if (found < count) {
6554b5e93edSEtienne Carriere 			struct stm32_pinctrl *ref = &pinctrl[found];
6564b5e93edSEtienne Carriere 
6574b5e93edSEtienne Carriere 			ref->bank = (uint8_t)bank;
6584b5e93edSEtienne Carriere 			ref->pin = (uint8_t)pin;
659b38386fbSEtienne Carriere 			ref->cfg.mode = mode;
660b38386fbSEtienne Carriere 			if (opendrain)
661b38386fbSEtienne Carriere 				ref->cfg.otype = GPIO_OTYPE_OPEN_DRAIN;
662b38386fbSEtienne Carriere 			else
663b38386fbSEtienne Carriere 				ref->cfg.otype = GPIO_OTYPE_PUSH_PULL;
664b38386fbSEtienne Carriere 			ref->cfg.ospeed = speed;
665b38386fbSEtienne Carriere 			ref->cfg.pupd = pull;
666b38386fbSEtienne Carriere 			ref->cfg.od = odata;
667b38386fbSEtienne Carriere 			ref->cfg.af = alternate;
6684b5e93edSEtienne Carriere 		}
6694b5e93edSEtienne Carriere 
6704b5e93edSEtienne Carriere 		found++;
6714b5e93edSEtienne Carriere 	}
6724b5e93edSEtienne Carriere 
6734b5e93edSEtienne Carriere 	return (int)found;
6744b5e93edSEtienne Carriere }
6754b5e93edSEtienne Carriere 
676bfc43b68SGatien Chevallier static TEE_Result consumed_gpios_pm(enum pm_op op,
677bfc43b68SGatien Chevallier 				    unsigned int pm_hint __unused,
678bfc43b68SGatien Chevallier 				    const struct pm_callback_handle *pm_hdl)
679bfc43b68SGatien Chevallier {
680bfc43b68SGatien Chevallier 	struct stm32_gpio_pm_state *handle = pm_hdl->handle;
681bfc43b68SGatien Chevallier 	unsigned int bank_id = handle->gpio_pinctrl.bank;
682bfc43b68SGatien Chevallier 	unsigned int pin = handle->gpio_pinctrl.pin;
683bfc43b68SGatien Chevallier 	struct gpio_chip *chip = &stm32_gpio_get_bank(bank_id)->gpio_chip;
684bfc43b68SGatien Chevallier 
685bfc43b68SGatien Chevallier 	if (op == PM_OP_RESUME) {
686bfc43b68SGatien Chevallier 		set_gpio_cfg(bank_id, pin, &handle->gpio_pinctrl.cfg);
687bfc43b68SGatien Chevallier 		if (handle->gpio_pinctrl.cfg.mode == GPIO_MODE_OUTPUT)
688bfc43b68SGatien Chevallier 			stm32_gpio_set_level(chip, pin, handle->level);
689bfc43b68SGatien Chevallier 	} else {
690bfc43b68SGatien Chevallier 		get_gpio_cfg(bank_id, pin, &handle->gpio_pinctrl.cfg);
691bfc43b68SGatien Chevallier 		if (handle->gpio_pinctrl.cfg.mode == GPIO_MODE_OUTPUT)
692bfc43b68SGatien Chevallier 			handle->level = stm32_gpio_get_level(chip, pin);
693bfc43b68SGatien Chevallier 	}
694bfc43b68SGatien Chevallier 
695bfc43b68SGatien Chevallier 	return TEE_SUCCESS;
696bfc43b68SGatien Chevallier }
697bfc43b68SGatien Chevallier DECLARE_KEEP_PAGER(consumed_gpios_pm);
698bfc43b68SGatien Chevallier 
699b357d34fSEtienne Carriere static TEE_Result stm32_gpio_get_dt(struct dt_pargs *pargs, void *data,
700b357d34fSEtienne Carriere 				    struct gpio **out_gpio)
701420a32c5SEtienne Carriere {
702b357d34fSEtienne Carriere 	TEE_Result res = TEE_ERROR_GENERIC;
703*430c415aSEtienne Carriere 	const char *consumer_name __maybe_unused = NULL;
7047761b658SEtienne Carriere 	struct stm32_gpio_pm_state *reg_state = NULL;
705bfc43b68SGatien Chevallier 	struct stm32_gpio_pm_state *state = NULL;
706420a32c5SEtienne Carriere 	struct stm32_gpio_bank *bank = data;
707420a32c5SEtienne Carriere 	struct gpio *gpio = NULL;
708420a32c5SEtienne Carriere 	unsigned int shift_1b = 0;
709420a32c5SEtienne Carriere 	unsigned int shift_2b = 0;
710420a32c5SEtienne Carriere 	uint32_t exceptions = 0;
711420a32c5SEtienne Carriere 	uint32_t otype = 0;
712420a32c5SEtienne Carriere 	uint32_t pupd = 0;
713420a32c5SEtienne Carriere 	uint32_t mode = 0;
714420a32c5SEtienne Carriere 
715*430c415aSEtienne Carriere 	consumer_name = fdt_get_name(pargs->fdt, pargs->consumer_node,
716*430c415aSEtienne Carriere 				     NULL);
717*430c415aSEtienne Carriere 
718b357d34fSEtienne Carriere 	res = gpio_dt_alloc_pin(pargs, &gpio);
719b357d34fSEtienne Carriere 	if (res)
720b357d34fSEtienne Carriere 		return res;
721420a32c5SEtienne Carriere 
722420a32c5SEtienne Carriere 	if (gpio->pin >= bank->ngpios) {
723420a32c5SEtienne Carriere 		DMSG("Invalid GPIO reference");
724420a32c5SEtienne Carriere 		free(gpio);
725b357d34fSEtienne Carriere 		return TEE_ERROR_GENERIC;
726420a32c5SEtienne Carriere 	}
727420a32c5SEtienne Carriere 
728bfc43b68SGatien Chevallier 	state = calloc(1, sizeof(*state));
729bfc43b68SGatien Chevallier 	if (!state) {
730bfc43b68SGatien Chevallier 		free(gpio);
731bfc43b68SGatien Chevallier 		return TEE_ERROR_OUT_OF_MEMORY;
732bfc43b68SGatien Chevallier 	}
733bfc43b68SGatien Chevallier 
7347761b658SEtienne Carriere 	SLIST_FOREACH(reg_state, &consumed_gpios_head, link) {
7357761b658SEtienne Carriere 		if (reg_state->gpio_pinctrl.bank == bank->bank_id &&
7367761b658SEtienne Carriere 		    reg_state->gpio_pinctrl.pin == gpio->pin) {
7377761b658SEtienne Carriere 			EMSG("node %s: GPIO %c%u is used by another device",
7387761b658SEtienne Carriere 			     fdt_get_name(pargs->fdt, pargs->consumer_node,
7397761b658SEtienne Carriere 					  NULL),
7407761b658SEtienne Carriere 			     bank->bank_id + 'A', gpio->pin);
7417761b658SEtienne Carriere 			free(state);
7427761b658SEtienne Carriere 			free(gpio);
7437761b658SEtienne Carriere 			return TEE_ERROR_GENERIC;
7447761b658SEtienne Carriere 		}
7457761b658SEtienne Carriere 	}
7467761b658SEtienne Carriere 
747*430c415aSEtienne Carriere 	res = acquire_rif_semaphore_if_needed(bank, gpio->pin);
748*430c415aSEtienne Carriere 	if (res) {
749*430c415aSEtienne Carriere 		EMSG("Failed to acquire GPIO %c%u semaphore for node %s",
750*430c415aSEtienne Carriere 		     bank->bank_id + 'A', gpio->pin, consumer_name);
751*430c415aSEtienne Carriere 		return res;
752*430c415aSEtienne Carriere 	}
753*430c415aSEtienne Carriere 
754bfc43b68SGatien Chevallier 	state->gpio_pinctrl.pin = gpio->pin;
755bfc43b68SGatien Chevallier 	state->gpio_pinctrl.bank = bank->bank_id;
756bfc43b68SGatien Chevallier 	SLIST_INSERT_HEAD(&consumed_gpios_head, state, link);
757bfc43b68SGatien Chevallier 
758bfc43b68SGatien Chevallier 	register_pm_driver_cb(consumed_gpios_pm, state, "stm32-gpio-state");
759bfc43b68SGatien Chevallier 
760420a32c5SEtienne Carriere 	shift_1b = gpio->pin;
761420a32c5SEtienne Carriere 	shift_2b = SHIFT_U32(gpio->pin, 1);
762420a32c5SEtienne Carriere 
763420a32c5SEtienne Carriere 	if (gpio->dt_flags & GPIO_PULL_UP)
764420a32c5SEtienne Carriere 		pupd = GPIO_PUPD_PULL_UP;
765420a32c5SEtienne Carriere 	else if (gpio->dt_flags & GPIO_PULL_DOWN)
766420a32c5SEtienne Carriere 		pupd = GPIO_PUPD_PULL_DOWN;
767420a32c5SEtienne Carriere 	else
768420a32c5SEtienne Carriere 		pupd = GPIO_PUPD_NO_PULL;
769420a32c5SEtienne Carriere 
770420a32c5SEtienne Carriere 	if (gpio->dt_flags & GPIO_LINE_OPEN_DRAIN)
771420a32c5SEtienne Carriere 		otype = GPIO_OTYPE_OPEN_DRAIN;
772420a32c5SEtienne Carriere 	else
773420a32c5SEtienne Carriere 		otype = GPIO_OTYPE_PUSH_PULL;
774420a32c5SEtienne Carriere 
775420a32c5SEtienne Carriere 	if (clk_enable(bank->clock))
776420a32c5SEtienne Carriere 		panic();
777420a32c5SEtienne Carriere 	exceptions = cpu_spin_lock_xsave(&gpio_lock);
778420a32c5SEtienne Carriere 
779420a32c5SEtienne Carriere 	io_clrsetbits32(bank->base + GPIO_MODER_OFFSET,
780420a32c5SEtienne Carriere 			SHIFT_U32(GPIO_MODE_MASK, shift_2b),
781420a32c5SEtienne Carriere 			SHIFT_U32(mode, shift_2b));
782420a32c5SEtienne Carriere 
783420a32c5SEtienne Carriere 	io_clrsetbits32(bank->base + GPIO_OTYPER_OFFSET,
784420a32c5SEtienne Carriere 			SHIFT_U32(GPIO_OTYPE_OPEN_DRAIN, shift_1b),
785420a32c5SEtienne Carriere 			SHIFT_U32(otype, shift_1b));
786420a32c5SEtienne Carriere 
787420a32c5SEtienne Carriere 	io_clrsetbits32(bank->base + GPIO_PUPDR_OFFSET,
788420a32c5SEtienne Carriere 			SHIFT_U32(GPIO_PUPD_PULL_MASK, shift_2b),
789420a32c5SEtienne Carriere 			SHIFT_U32(pupd, shift_2b));
790420a32c5SEtienne Carriere 
791420a32c5SEtienne Carriere 	cpu_spin_unlock_xrestore(&gpio_lock, exceptions);
792420a32c5SEtienne Carriere 	clk_disable(bank->clock);
793420a32c5SEtienne Carriere 
794420a32c5SEtienne Carriere 	gpio->chip = &bank->gpio_chip;
795420a32c5SEtienne Carriere 
796b357d34fSEtienne Carriere 	*out_gpio = gpio;
797420a32c5SEtienne Carriere 
798b357d34fSEtienne Carriere 	return TEE_SUCCESS;
799420a32c5SEtienne Carriere }
800420a32c5SEtienne Carriere 
8019818a481SEtienne Carriere /* Get bank ID from bank node property st,bank-name or panic on failure */
8029818a481SEtienne Carriere static unsigned int dt_get_bank_id(const void *fdt, int node)
8039818a481SEtienne Carriere {
8049818a481SEtienne Carriere 	const int dt_name_len = strlen(DT_GPIO_BANK_NAME0);
8059818a481SEtienne Carriere 	const fdt32_t *cuint = NULL;
8069818a481SEtienne Carriere 	int len = 0;
8079818a481SEtienne Carriere 
8089818a481SEtienne Carriere 	/* Parse "st,bank-name" to get its id (eg: GPIOA -> 0) */
8099818a481SEtienne Carriere 	cuint = fdt_getprop(fdt, node, "st,bank-name", &len);
8109818a481SEtienne Carriere 	if (!cuint || (len != dt_name_len + 1))
8119818a481SEtienne Carriere 		panic("Missing/wrong st,bank-name property");
8129818a481SEtienne Carriere 
8139818a481SEtienne Carriere 	if (strncmp((const char *)cuint, DT_GPIO_BANK_NAME0, dt_name_len - 1) ||
8149818a481SEtienne Carriere 	    strcmp((const char *)cuint, DT_GPIO_BANK_NAME0) < 0)
8159818a481SEtienne Carriere 		panic("Wrong st,bank-name property");
8169818a481SEtienne Carriere 
8179818a481SEtienne Carriere 	return (unsigned int)strcmp((const char *)cuint, DT_GPIO_BANK_NAME0);
8189818a481SEtienne Carriere }
8199818a481SEtienne Carriere 
8209818a481SEtienne Carriere /*
8219818a481SEtienne Carriere  * Return whether or not the GPIO bank related to a DT node is already
8229818a481SEtienne Carriere  * registered in the GPIO bank link.
8239818a481SEtienne Carriere  */
8249818a481SEtienne Carriere static bool bank_is_registered(const void *fdt, int node)
8259818a481SEtienne Carriere {
8269818a481SEtienne Carriere 	unsigned int bank_id = dt_get_bank_id(fdt, node);
8279818a481SEtienne Carriere 	struct stm32_gpio_bank *bank = NULL;
8289818a481SEtienne Carriere 
8299818a481SEtienne Carriere 	STAILQ_FOREACH(bank, &bank_list, link)
8309818a481SEtienne Carriere 		if (bank->bank_id == bank_id)
8319818a481SEtienne Carriere 			return true;
8329818a481SEtienne Carriere 
8339818a481SEtienne Carriere 	return false;
8349818a481SEtienne Carriere }
8359818a481SEtienne Carriere 
8369def1fb7SGatien Chevallier #ifdef CFG_STM32_RIF
837a72f07daSEtienne Carriere static TEE_Result handle_available_semaphores(struct stm32_gpio_bank *bank,
838a72f07daSEtienne Carriere 					      uint32_t gpios_mask)
839bd03c8c3SGatien Chevallier {
840bd03c8c3SGatien Chevallier 	TEE_Result res = TEE_ERROR_GENERIC;
841bd03c8c3SGatien Chevallier 	uint32_t cidcfgr = 0;
842bd03c8c3SGatien Chevallier 	unsigned int i = 0;
843bd03c8c3SGatien Chevallier 
8449def1fb7SGatien Chevallier 	for (i = 0 ; i < bank->ngpios; i++) {
845a72f07daSEtienne Carriere 		if (!(BIT(i) & gpios_mask))
8469def1fb7SGatien Chevallier 			continue;
8479def1fb7SGatien Chevallier 
8489def1fb7SGatien Chevallier 		cidcfgr = io_read32(bank->base + GPIO_CIDCFGR(i));
8499def1fb7SGatien Chevallier 
8509def1fb7SGatien Chevallier 		if (!stm32_rif_semaphore_enabled_and_ok(cidcfgr, RIF_CID1))
8519def1fb7SGatien Chevallier 			continue;
8529def1fb7SGatien Chevallier 
8539def1fb7SGatien Chevallier 		if (!(io_read32(bank->base + GPIO_SECR_OFFSET) & BIT(i))) {
8549def1fb7SGatien Chevallier 			res = stm32_rif_release_semaphore(bank->base +
8559def1fb7SGatien Chevallier 							  GPIO_SEMCR(i),
8569def1fb7SGatien Chevallier 							  MAX_CID_SUPPORTED);
8579def1fb7SGatien Chevallier 			if (res) {
8589def1fb7SGatien Chevallier 				EMSG("Cannot release semaphore for resource %u",
8599def1fb7SGatien Chevallier 				     i);
8609def1fb7SGatien Chevallier 				return res;
8619def1fb7SGatien Chevallier 			}
8629def1fb7SGatien Chevallier 		} else {
8639def1fb7SGatien Chevallier 			res = stm32_rif_acquire_semaphore(bank->base +
8649def1fb7SGatien Chevallier 							  GPIO_SEMCR(i),
8659def1fb7SGatien Chevallier 							  MAX_CID_SUPPORTED);
8669def1fb7SGatien Chevallier 			if (res) {
8679def1fb7SGatien Chevallier 				EMSG("Cannot acquire semaphore for resource %u",
8689def1fb7SGatien Chevallier 				     i);
8699def1fb7SGatien Chevallier 				return res;
8709def1fb7SGatien Chevallier 			}
8719def1fb7SGatien Chevallier 		}
8729def1fb7SGatien Chevallier 	}
8739def1fb7SGatien Chevallier 
8749def1fb7SGatien Chevallier 	return TEE_SUCCESS;
8759def1fb7SGatien Chevallier }
8769def1fb7SGatien Chevallier 
877a72f07daSEtienne Carriere static TEE_Result apply_rif_config(struct stm32_gpio_bank *bank,
878a72f07daSEtienne Carriere 				   uint32_t gpios_mask)
8799def1fb7SGatien Chevallier {
8809def1fb7SGatien Chevallier 	TEE_Result res = TEE_ERROR_GENERIC;
8819def1fb7SGatien Chevallier 	unsigned int i = 0;
8829def1fb7SGatien Chevallier 
883bd03c8c3SGatien Chevallier 	if (!bank->rif_cfg)
884bd03c8c3SGatien Chevallier 		return TEE_SUCCESS;
885bd03c8c3SGatien Chevallier 
886bd03c8c3SGatien Chevallier 	if (clk_enable(bank->clock))
887bd03c8c3SGatien Chevallier 		panic();
888bd03c8c3SGatien Chevallier 
8899def1fb7SGatien Chevallier 	if (bank->is_tdcid) {
890bd03c8c3SGatien Chevallier 		for (i = 0; i < bank->ngpios; i++) {
891a72f07daSEtienne Carriere 			if (!(BIT(i) & gpios_mask))
892bd03c8c3SGatien Chevallier 				continue;
893bd03c8c3SGatien Chevallier 
894bd03c8c3SGatien Chevallier 			/*
8959def1fb7SGatien Chevallier 			 * When TDCID, OP-TEE should be the one to set the CID
8969def1fb7SGatien Chevallier 			 * filtering configuration. Clearing previous
8979def1fb7SGatien Chevallier 			 * configuration prevents undesired events during the
8989def1fb7SGatien Chevallier 			 * only legitimate configuration.
899bd03c8c3SGatien Chevallier 			 */
900bd03c8c3SGatien Chevallier 			io_clrbits32(bank->base + GPIO_CIDCFGR(i),
901bd03c8c3SGatien Chevallier 				     GPIO_CIDCFGR_CONF_MASK);
902bd03c8c3SGatien Chevallier 		}
9039def1fb7SGatien Chevallier 	} else {
904a72f07daSEtienne Carriere 		res = handle_available_semaphores(bank, gpios_mask);
9059def1fb7SGatien Chevallier 		if (res)
9069def1fb7SGatien Chevallier 			panic();
907bd03c8c3SGatien Chevallier 	}
908bd03c8c3SGatien Chevallier 
909bd03c8c3SGatien Chevallier 	/* Security and privilege RIF configuration */
910a72f07daSEtienne Carriere 	io_mask32(bank->base + GPIO_PRIVCFGR_OFFSET,
911a72f07daSEtienne Carriere 		  bank->rif_cfg->priv_conf[0], gpios_mask);
912a72f07daSEtienne Carriere 	io_mask32(bank->base + GPIO_SECR_OFFSET,
913a72f07daSEtienne Carriere 		  bank->rif_cfg->sec_conf[0], gpios_mask);
914bd03c8c3SGatien Chevallier 
915bd03c8c3SGatien Chevallier 	if (!bank->is_tdcid) {
916bd03c8c3SGatien Chevallier 		res = TEE_SUCCESS;
917bd03c8c3SGatien Chevallier 		goto out;
918bd03c8c3SGatien Chevallier 	}
919bd03c8c3SGatien Chevallier 
920bd03c8c3SGatien Chevallier 	for (i = 0; i < bank->ngpios; i++) {
921a72f07daSEtienne Carriere 		if (!(BIT(i) & gpios_mask))
922bd03c8c3SGatien Chevallier 			continue;
923bd03c8c3SGatien Chevallier 
924bd03c8c3SGatien Chevallier 		io_clrsetbits32(bank->base + GPIO_CIDCFGR(i),
925bd03c8c3SGatien Chevallier 				GPIO_CIDCFGR_CONF_MASK,
926bd03c8c3SGatien Chevallier 				bank->rif_cfg->cid_confs[i]);
927bd03c8c3SGatien Chevallier 	}
928bd03c8c3SGatien Chevallier 
929bd03c8c3SGatien Chevallier 	/*
930bd03c8c3SGatien Chevallier 	 * Lock RIF configuration if configured. This cannot be undone until
931bd03c8c3SGatien Chevallier 	 * next reset.
932bd03c8c3SGatien Chevallier 	 */
933bd03c8c3SGatien Chevallier 	io_setbits32(bank->base + GPIO_RCFGLOCKR_OFFSET,
934bd03c8c3SGatien Chevallier 		     bank->rif_cfg->lock_conf[0]);
935bd03c8c3SGatien Chevallier 
936a72f07daSEtienne Carriere 	res = handle_available_semaphores(bank, gpios_mask);
9379def1fb7SGatien Chevallier 	if (res)
9389def1fb7SGatien Chevallier 		panic();
9399def1fb7SGatien Chevallier 
9409def1fb7SGatien Chevallier out:
941bd03c8c3SGatien Chevallier 	if (IS_ENABLED(CFG_TEE_CORE_DEBUG)) {
942bd03c8c3SGatien Chevallier 		/* Check that RIF config are applied, panic otherwise */
943bd03c8c3SGatien Chevallier 		if ((io_read32(bank->base + GPIO_PRIVCFGR_OFFSET) &
944a72f07daSEtienne Carriere 		     gpios_mask) !=
945a72f07daSEtienne Carriere 		    (bank->rif_cfg->priv_conf[0] & gpios_mask)) {
946bd03c8c3SGatien Chevallier 			EMSG("GPIO bank%c priv conf is incorrect",
947bd03c8c3SGatien Chevallier 			     'A' + bank->bank_id);
948bd03c8c3SGatien Chevallier 			panic();
949bd03c8c3SGatien Chevallier 		}
950bd03c8c3SGatien Chevallier 
951a72f07daSEtienne Carriere 		if ((io_read32(bank->base + GPIO_SECR_OFFSET) & gpios_mask) !=
952a72f07daSEtienne Carriere 		    (bank->rif_cfg->sec_conf[0] & gpios_mask)) {
953bd03c8c3SGatien Chevallier 			EMSG("GPIO bank %c sec conf is incorrect",
954bd03c8c3SGatien Chevallier 			     'A' + bank->bank_id);
955bd03c8c3SGatien Chevallier 			panic();
956bd03c8c3SGatien Chevallier 		}
957bd03c8c3SGatien Chevallier 	}
958bd03c8c3SGatien Chevallier 
959bd03c8c3SGatien Chevallier 	clk_disable(bank->clock);
960bd03c8c3SGatien Chevallier 
961bd03c8c3SGatien Chevallier 	return res;
962bd03c8c3SGatien Chevallier }
9639def1fb7SGatien Chevallier #else /* CFG_STM32_RIF */
964a72f07daSEtienne Carriere static TEE_Result apply_rif_config(struct stm32_gpio_bank *bank __unused,
965a72f07daSEtienne Carriere 				   uint32_t gpios_mask __unused)
9669def1fb7SGatien Chevallier {
9679def1fb7SGatien Chevallier 	return TEE_SUCCESS;
9689def1fb7SGatien Chevallier }
9699def1fb7SGatien Chevallier #endif /* CFG_STM32_RIF */
970bd03c8c3SGatien Chevallier 
971a650c9cbSEtienne Carriere /* Forward reference to stm32_gpio_set_conf_sec() defined below */
972a650c9cbSEtienne Carriere static void stm32_gpio_set_conf_sec(struct stm32_gpio_bank *bank);
973a650c9cbSEtienne Carriere 
974a650c9cbSEtienne Carriere static TEE_Result stm32_gpio_fw_configure(struct firewall_query *firewall)
975a650c9cbSEtienne Carriere {
976a650c9cbSEtienne Carriere 	struct stm32_gpio_bank *bank = firewall->ctrl->priv;
977a650c9cbSEtienne Carriere 	uint32_t firewall_arg = 0;
978a650c9cbSEtienne Carriere 	uint32_t gpios_mask = 0;
979a650c9cbSEtienne Carriere 	bool secure = true;
980a650c9cbSEtienne Carriere 
981a650c9cbSEtienne Carriere 	assert(bank->sec_support);
982a650c9cbSEtienne Carriere 
983a650c9cbSEtienne Carriere 	if (firewall->arg_count != 1)
984a650c9cbSEtienne Carriere 		return TEE_ERROR_BAD_PARAMETERS;
985a650c9cbSEtienne Carriere 
986a650c9cbSEtienne Carriere 	firewall_arg = firewall->args[0];
987a650c9cbSEtienne Carriere 
988a650c9cbSEtienne Carriere 	if (bank->rif_cfg) {
989a650c9cbSEtienne Carriere 		gpios_mask = BIT(RIF_CHANNEL_ID(firewall_arg));
990a650c9cbSEtienne Carriere 
991a650c9cbSEtienne Carriere 		/* We're about to change a specific GPIO config */
992a650c9cbSEtienne Carriere 		bank->rif_cfg->access_mask[0] |= gpios_mask;
993a650c9cbSEtienne Carriere 
994a650c9cbSEtienne Carriere 		/*
995a650c9cbSEtienne Carriere 		 * Update bank RIF config with firewall configuration data
996a650c9cbSEtienne Carriere 		 * and apply it.
997a650c9cbSEtienne Carriere 		 */
998a650c9cbSEtienne Carriere 		stm32_rif_parse_cfg(firewall_arg, bank->rif_cfg,
999a650c9cbSEtienne Carriere 				    bank->ngpios);
1000a650c9cbSEtienne Carriere 		return apply_rif_config(bank, gpios_mask);
1001a650c9cbSEtienne Carriere 	}
1002a650c9cbSEtienne Carriere 
1003a650c9cbSEtienne Carriere 	/*
1004a650c9cbSEtienne Carriere 	 * Non RIF GPIO banks use a single cell as a bit mask (bits 0 to 15)
1005a650c9cbSEtienne Carriere 	 * to define the a group of GPIO pins (one or several) to configure
1006a650c9cbSEtienne Carriere 	 * for that bank, and GPIO_STM32_NSEC bit flag to set if these pins
1007a650c9cbSEtienne Carriere 	 * are non-secure (flag set) or non-secure (flag cleared).
1008a650c9cbSEtienne Carriere 	 */
1009a650c9cbSEtienne Carriere 	gpios_mask = firewall_arg & GENMASK_32(15, 0);
1010a650c9cbSEtienne Carriere 
1011a650c9cbSEtienne Carriere 	secure = !(firewall_arg & GPIO_STM32_NSEC);
1012a650c9cbSEtienne Carriere 
1013a650c9cbSEtienne Carriere 	if (gpios_mask & ~GENMASK_32(bank->ngpios, 0)) {
1014a650c9cbSEtienne Carriere 		EMSG("Invalid bitmask %#"PRIx32" for GPIO bank %c",
1015a650c9cbSEtienne Carriere 		     gpios_mask, 'A' + bank->bank_id);
1016a650c9cbSEtienne Carriere 		return TEE_ERROR_GENERIC;
1017a650c9cbSEtienne Carriere 	}
1018a650c9cbSEtienne Carriere 
1019a650c9cbSEtienne Carriere 	/* Update bank secure register configuration data and apply it */
1020a650c9cbSEtienne Carriere 	if (secure)
1021a650c9cbSEtienne Carriere 		bank->seccfgr |= gpios_mask;
1022a650c9cbSEtienne Carriere 	else
1023a650c9cbSEtienne Carriere 		bank->seccfgr &= ~gpios_mask;
1024a650c9cbSEtienne Carriere 
1025a650c9cbSEtienne Carriere 	stm32_gpio_set_conf_sec(bank);
1026a650c9cbSEtienne Carriere 
1027a650c9cbSEtienne Carriere 	return TEE_SUCCESS;
1028a650c9cbSEtienne Carriere }
1029a650c9cbSEtienne Carriere 
1030a650c9cbSEtienne Carriere static const struct firewall_controller_ops stm32_gpio_firewall_ops = {
1031a650c9cbSEtienne Carriere 	.set_conf = stm32_gpio_fw_configure,
1032a650c9cbSEtienne Carriere };
1033a650c9cbSEtienne Carriere 
1034bfc43b68SGatien Chevallier static void stm32_gpio_save_rif_config(struct stm32_gpio_bank *bank)
1035bfc43b68SGatien Chevallier {
1036bfc43b68SGatien Chevallier 	size_t i = 0;
1037bfc43b68SGatien Chevallier 
1038bfc43b68SGatien Chevallier 	for (i = 0; i < bank->ngpios; i++)
1039bfc43b68SGatien Chevallier 		bank->rif_cfg->cid_confs[i] = io_read32(bank->base +
1040bfc43b68SGatien Chevallier 							 GPIO_CIDCFGR(i));
1041bfc43b68SGatien Chevallier 
1042bfc43b68SGatien Chevallier 	bank->rif_cfg->priv_conf[0] = io_read32(bank->base +
1043bfc43b68SGatien Chevallier 						GPIO_PRIVCFGR_OFFSET);
1044bfc43b68SGatien Chevallier 	bank->rif_cfg->sec_conf[0] = io_read32(bank->base +
1045bfc43b68SGatien Chevallier 					       GPIO_SECR_OFFSET);
1046bfc43b68SGatien Chevallier 	bank->rif_cfg->lock_conf[0] = io_read32(bank->base +
1047bfc43b68SGatien Chevallier 						GPIO_RCFGLOCKR_OFFSET);
1048bfc43b68SGatien Chevallier }
1049bfc43b68SGatien Chevallier 
1050bd03c8c3SGatien Chevallier static void stm32_parse_gpio_rif_conf(struct stm32_gpio_bank *bank,
1051bd03c8c3SGatien Chevallier 				      const void *fdt, int node)
1052bd03c8c3SGatien Chevallier {
1053bd03c8c3SGatien Chevallier 	unsigned int i = 0;
1054bd03c8c3SGatien Chevallier 	unsigned int nb_rif_conf = 0;
1055bd03c8c3SGatien Chevallier 	int lenp = 0;
1056bd03c8c3SGatien Chevallier 	const fdt32_t *cuint = NULL;
1057bd03c8c3SGatien Chevallier 
1058bd03c8c3SGatien Chevallier 	cuint = fdt_getprop(fdt, node, "st,protreg", &lenp);
1059bd03c8c3SGatien Chevallier 	if (!cuint) {
1060bd03c8c3SGatien Chevallier 		DMSG("No RIF configuration available");
1061bd03c8c3SGatien Chevallier 		return;
1062bd03c8c3SGatien Chevallier 	}
1063bd03c8c3SGatien Chevallier 
1064bd03c8c3SGatien Chevallier 	bank->rif_cfg = calloc(1, sizeof(*bank->rif_cfg));
1065bd03c8c3SGatien Chevallier 	if (!bank->rif_cfg)
1066bd03c8c3SGatien Chevallier 		panic();
1067bd03c8c3SGatien Chevallier 
1068bd03c8c3SGatien Chevallier 	bank->rif_cfg->sec_conf = calloc(1, sizeof(uint32_t));
1069bd03c8c3SGatien Chevallier 	if (!bank->rif_cfg->sec_conf)
1070bd03c8c3SGatien Chevallier 		panic();
1071bd03c8c3SGatien Chevallier 
1072bd03c8c3SGatien Chevallier 	nb_rif_conf = (unsigned int)(lenp / sizeof(uint32_t));
1073bd03c8c3SGatien Chevallier 	assert(nb_rif_conf <= bank->ngpios);
1074bd03c8c3SGatien Chevallier 
1075bd03c8c3SGatien Chevallier 	bank->rif_cfg->cid_confs = calloc(bank->ngpios, sizeof(uint32_t));
1076bd03c8c3SGatien Chevallier 	bank->rif_cfg->priv_conf = calloc(1, sizeof(uint32_t));
1077bd03c8c3SGatien Chevallier 	bank->rif_cfg->lock_conf = calloc(1, sizeof(uint32_t));
1078bd03c8c3SGatien Chevallier 	bank->rif_cfg->access_mask = calloc(1, sizeof(uint32_t));
1079bd03c8c3SGatien Chevallier 	if (!bank->rif_cfg->cid_confs || !bank->rif_cfg->access_mask ||
1080bd03c8c3SGatien Chevallier 	    !bank->rif_cfg->priv_conf || !bank->rif_cfg->lock_conf)
1081bd03c8c3SGatien Chevallier 		panic("Missing memory capacity for GPIOS RIF configuration");
1082bd03c8c3SGatien Chevallier 
1083bd03c8c3SGatien Chevallier 	for (i = 0; i < nb_rif_conf; i++)
1084bd03c8c3SGatien Chevallier 		stm32_rif_parse_cfg(fdt32_to_cpu(cuint[i]), bank->rif_cfg,
1085646ad62bSGatien Chevallier 				    bank->ngpios);
1086bd03c8c3SGatien Chevallier }
1087bd03c8c3SGatien Chevallier 
10889818a481SEtienne Carriere /* Get GPIO bank information from the DT */
10899818a481SEtienne Carriere static TEE_Result dt_stm32_gpio_bank(const void *fdt, int node,
1090e569f6adSEtienne Carriere 				     const void *compat_data,
10919818a481SEtienne Carriere 				     int range_offset,
10929818a481SEtienne Carriere 				     struct stm32_gpio_bank **out_bank)
10939818a481SEtienne Carriere {
1094e569f6adSEtienne Carriere 	const struct bank_compat *compat = compat_data;
10959818a481SEtienne Carriere 	TEE_Result res = TEE_ERROR_GENERIC;
10969818a481SEtienne Carriere 	struct stm32_gpio_bank *bank = NULL;
10979818a481SEtienne Carriere 	const fdt32_t *cuint = NULL;
10989818a481SEtienne Carriere 	struct io_pa_va pa_va = { };
10999818a481SEtienne Carriere 	struct clk *clk = NULL;
11009818a481SEtienne Carriere 	size_t blen = 0;
11019818a481SEtienne Carriere 	paddr_t pa = 0;
11029818a481SEtienne Carriere 	int len = 0;
11039818a481SEtienne Carriere 	int i = 0;
11049818a481SEtienne Carriere 
11059818a481SEtienne Carriere 	assert(out_bank);
11069818a481SEtienne Carriere 
11079818a481SEtienne Carriere 	/* Probe deferrable devices first */
11089818a481SEtienne Carriere 	res = clk_dt_get_by_index(fdt, node, 0, &clk);
11099818a481SEtienne Carriere 	if (res)
11109818a481SEtienne Carriere 		return res;
11119818a481SEtienne Carriere 
11129818a481SEtienne Carriere 	bank = calloc(1, sizeof(*bank));
11139818a481SEtienne Carriere 	if (!bank)
11149818a481SEtienne Carriere 		return TEE_ERROR_OUT_OF_MEMORY;
11159818a481SEtienne Carriere 
1116bd03c8c3SGatien Chevallier 	if (compat->secure_extended) {
1117bd03c8c3SGatien Chevallier 		res = stm32_rifsc_check_tdcid(&bank->is_tdcid);
1118bd03c8c3SGatien Chevallier 		if (res) {
1119bd03c8c3SGatien Chevallier 			free(bank);
1120bd03c8c3SGatien Chevallier 			return res;
1121bd03c8c3SGatien Chevallier 		}
1122bd03c8c3SGatien Chevallier 	}
1123bd03c8c3SGatien Chevallier 
11249818a481SEtienne Carriere 	/*
11259818a481SEtienne Carriere 	 * Do not rely *only* on the "reg" property to get the address,
11269818a481SEtienne Carriere 	 * but consider also the "ranges" translation property
11279818a481SEtienne Carriere 	 */
11286a0116edSEtienne Carriere 	if (fdt_reg_info(fdt, node, &pa, &blen))
11296a0116edSEtienne Carriere 		panic("missing reg or reg size property");
11309818a481SEtienne Carriere 
11319818a481SEtienne Carriere 	pa_va.pa = pa + range_offset;
11329818a481SEtienne Carriere 
11339818a481SEtienne Carriere 	DMSG("Bank name %s", fdt_get_name(fdt, node, NULL));
11349818a481SEtienne Carriere 	bank->bank_id = dt_get_bank_id(fdt, node);
11359818a481SEtienne Carriere 	bank->clock = clk;
1136420a32c5SEtienne Carriere 	bank->gpio_chip.ops = &stm32_gpio_ops;
1137b4893304SGatien Chevallier 	bank->sec_support = compat->secure_control;
11389818a481SEtienne Carriere 
11399818a481SEtienne Carriere 	/* Parse gpio-ranges with its 4 parameters */
11409818a481SEtienne Carriere 	cuint = fdt_getprop(fdt, node, "gpio-ranges", &len);
11419818a481SEtienne Carriere 	len /= sizeof(*cuint);
11429818a481SEtienne Carriere 	if (len % 4)
11439818a481SEtienne Carriere 		panic("wrong gpio-ranges syntax");
11449818a481SEtienne Carriere 
11459818a481SEtienne Carriere 	/* Get the last defined gpio line (offset + nb of pins) */
11469818a481SEtienne Carriere 	for (i = 0; i < len / 4; i++) {
11479818a481SEtienne Carriere 		bank->ngpios = MAX(bank->ngpios,
11489818a481SEtienne Carriere 				   (unsigned int)(fdt32_to_cpu(*(cuint + 1)) +
11499818a481SEtienne Carriere 						  fdt32_to_cpu(*(cuint + 3))));
11509818a481SEtienne Carriere 		cuint += 4;
11519818a481SEtienne Carriere 	}
11529818a481SEtienne Carriere 
1153bd03c8c3SGatien Chevallier 	if (compat->secure_extended) {
1154bd03c8c3SGatien Chevallier 		/* RIF configuration */
1155bd03c8c3SGatien Chevallier 		bank->base = io_pa_or_va_secure(&pa_va, blen);
1156bd03c8c3SGatien Chevallier 
1157bd03c8c3SGatien Chevallier 		stm32_parse_gpio_rif_conf(bank, fdt, node);
1158bd03c8c3SGatien Chevallier 	} else if (bank->sec_support) {
1159bd03c8c3SGatien Chevallier 		/* Secure configuration */
1160bd03c8c3SGatien Chevallier 		bank->base = io_pa_or_va_secure(&pa_va, blen);
1161bd03c8c3SGatien Chevallier 		cuint = fdt_getprop(fdt, node, "st,protreg", NULL);
1162bd03c8c3SGatien Chevallier 		if (cuint)
1163bd03c8c3SGatien Chevallier 			bank->seccfgr = fdt32_to_cpu(*cuint);
1164bd03c8c3SGatien Chevallier 		else
1165bd03c8c3SGatien Chevallier 			DMSG("GPIO bank %c assigned to non-secure",
1166bd03c8c3SGatien Chevallier 			     bank->bank_id + 'A');
1167bd03c8c3SGatien Chevallier 	} else {
1168bd03c8c3SGatien Chevallier 		bank->base = io_pa_or_va_nsec(&pa_va, blen);
1169bd03c8c3SGatien Chevallier 	}
1170bd03c8c3SGatien Chevallier 
1171e569f6adSEtienne Carriere 	if (compat->gpioz)
1172e569f6adSEtienne Carriere 		stm32mp_register_gpioz_pin_count(bank->ngpios);
1173e569f6adSEtienne Carriere 
11749818a481SEtienne Carriere 	*out_bank = bank;
1175bd03c8c3SGatien Chevallier 
11769818a481SEtienne Carriere 	return TEE_SUCCESS;
11779818a481SEtienne Carriere }
11789818a481SEtienne Carriere 
1179a650c9cbSEtienne Carriere static TEE_Result stm32_gpio_firewall_register(const void *fdt, int node,
1180a650c9cbSEtienne Carriere 					       struct stm32_gpio_bank *bank)
1181a650c9cbSEtienne Carriere {
1182a650c9cbSEtienne Carriere 	struct firewall_controller *controller = NULL;
1183a650c9cbSEtienne Carriere 	TEE_Result res = TEE_ERROR_GENERIC;
1184a650c9cbSEtienne Carriere 	char bank_name[] = "gpio-bank-X";
1185a650c9cbSEtienne Carriere 	char *name = NULL;
1186a650c9cbSEtienne Carriere 
1187a650c9cbSEtienne Carriere 	if (!IS_ENABLED(CFG_DRIVERS_FIREWALL) ||
1188a650c9cbSEtienne Carriere 	    !bank->sec_support)
1189a650c9cbSEtienne Carriere 		return TEE_SUCCESS;
1190a650c9cbSEtienne Carriere 
1191a650c9cbSEtienne Carriere 	controller = calloc(1, sizeof(*controller));
1192a650c9cbSEtienne Carriere 	if (!controller)
1193a650c9cbSEtienne Carriere 		return TEE_ERROR_OUT_OF_MEMORY;
1194a650c9cbSEtienne Carriere 
1195a650c9cbSEtienne Carriere 	bank_name[sizeof(bank_name) - 2] = 'A' + bank->bank_id;
1196a650c9cbSEtienne Carriere 	name = strdup(bank_name);
1197a650c9cbSEtienne Carriere 
1198a650c9cbSEtienne Carriere 	controller->name = name;
1199a650c9cbSEtienne Carriere 	controller->priv = bank;
1200a650c9cbSEtienne Carriere 	controller->ops = &stm32_gpio_firewall_ops;
1201a650c9cbSEtienne Carriere 
1202a650c9cbSEtienne Carriere 	if (!controller->name)
1203a650c9cbSEtienne Carriere 		EMSG("Warning: out of memory to store bank name");
1204a650c9cbSEtienne Carriere 
1205a650c9cbSEtienne Carriere 	res = firewall_dt_controller_register(fdt, node, controller);
1206a650c9cbSEtienne Carriere 	if (res) {
1207a650c9cbSEtienne Carriere 		free(name);
1208a650c9cbSEtienne Carriere 		free(controller);
1209a650c9cbSEtienne Carriere 	}
1210a650c9cbSEtienne Carriere 
1211a650c9cbSEtienne Carriere 	return res;
1212a650c9cbSEtienne Carriere }
1213a650c9cbSEtienne Carriere 
1214bd03c8c3SGatien Chevallier /* Parse a pinctrl node to register the GPIO banks it describes */
12150e0435e2SEtienne Carriere static TEE_Result dt_stm32_gpio_pinctrl(const void *fdt, int node,
12169818a481SEtienne Carriere 					const void *compat_data)
12179818a481SEtienne Carriere {
12189818a481SEtienne Carriere 	TEE_Result res = TEE_SUCCESS;
12199818a481SEtienne Carriere 	const fdt32_t *cuint = NULL;
12209818a481SEtienne Carriere 	int range_offs = 0;
12219818a481SEtienne Carriere 	int b_node = 0;
12229818a481SEtienne Carriere 	int len = 0;
12239818a481SEtienne Carriere 
12249818a481SEtienne Carriere 	/* Read the ranges property (for regs memory translation) */
12259818a481SEtienne Carriere 	cuint = fdt_getprop(fdt, node, "ranges", &len);
12269818a481SEtienne Carriere 	if (!cuint)
12279818a481SEtienne Carriere 		panic("missing ranges property");
12289818a481SEtienne Carriere 
12299818a481SEtienne Carriere 	len /= sizeof(*cuint);
12309818a481SEtienne Carriere 	if (len == 3)
12319818a481SEtienne Carriere 		range_offs = fdt32_to_cpu(*(cuint + 1)) - fdt32_to_cpu(*cuint);
12329818a481SEtienne Carriere 
12339818a481SEtienne Carriere 	fdt_for_each_subnode(b_node, fdt, node) {
12349818a481SEtienne Carriere 		cuint = fdt_getprop(fdt, b_node, "gpio-controller", &len);
12359818a481SEtienne Carriere 		if (cuint) {
12369818a481SEtienne Carriere 			/*
12379818a481SEtienne Carriere 			 * We found a property "gpio-controller" in the node:
12389818a481SEtienne Carriere 			 * the node is a GPIO bank description, add it to the
12399818a481SEtienne Carriere 			 * bank list.
12409818a481SEtienne Carriere 			 */
12419818a481SEtienne Carriere 			struct stm32_gpio_bank *bank = NULL;
12429818a481SEtienne Carriere 
12439818a481SEtienne Carriere 			if (fdt_get_status(fdt, b_node) == DT_STATUS_DISABLED ||
12449818a481SEtienne Carriere 			    bank_is_registered(fdt, b_node))
12459818a481SEtienne Carriere 				continue;
12469818a481SEtienne Carriere 
12479818a481SEtienne Carriere 			res = dt_stm32_gpio_bank(fdt, b_node, compat_data,
12489818a481SEtienne Carriere 						 range_offs, &bank);
12499818a481SEtienne Carriere 			if (res)
12509818a481SEtienne Carriere 				return res;
12519818a481SEtienne Carriere 
1252420a32c5SEtienne Carriere 			/* Registering a provider should not defer probe */
1253420a32c5SEtienne Carriere 			res = gpio_register_provider(fdt, b_node,
1254420a32c5SEtienne Carriere 						     stm32_gpio_get_dt, bank);
1255420a32c5SEtienne Carriere 			if (res)
1256420a32c5SEtienne Carriere 				panic();
1257420a32c5SEtienne Carriere 
1258a650c9cbSEtienne Carriere 			res = stm32_gpio_firewall_register(fdt, b_node, bank);
1259a650c9cbSEtienne Carriere 			if (res)
1260a650c9cbSEtienne Carriere 				panic();
1261a650c9cbSEtienne Carriere 
12629818a481SEtienne Carriere 			STAILQ_INSERT_TAIL(&bank_list, bank, link);
12639818a481SEtienne Carriere 		} else {
12649818a481SEtienne Carriere 			if (len != -FDT_ERR_NOTFOUND)
12659818a481SEtienne Carriere 				panic();
12669818a481SEtienne Carriere 		}
12679818a481SEtienne Carriere 	}
12689818a481SEtienne Carriere 
12699818a481SEtienne Carriere 	return TEE_SUCCESS;
12709818a481SEtienne Carriere }
12719818a481SEtienne Carriere 
1272077d486eSEtienne Carriere void stm32_gpio_set_secure_cfg(unsigned int bank_id, unsigned int pin,
1273077d486eSEtienne Carriere 			       bool secure)
12744b5e93edSEtienne Carriere {
1275077d486eSEtienne Carriere 	struct stm32_gpio_bank *bank = stm32_gpio_get_bank(bank_id);
127698dfcedaSEtienne Carriere 	uint32_t exceptions = 0;
12774b5e93edSEtienne Carriere 
1278077d486eSEtienne Carriere 	if (clk_enable(bank->clock))
1279077d486eSEtienne Carriere 		panic();
128098dfcedaSEtienne Carriere 	exceptions = cpu_spin_lock_xsave(&gpio_lock);
12814b5e93edSEtienne Carriere 
12824b5e93edSEtienne Carriere 	if (secure)
1283077d486eSEtienne Carriere 		io_setbits32(bank->base + GPIO_SECR_OFFSET, BIT(pin));
12844b5e93edSEtienne Carriere 	else
1285077d486eSEtienne Carriere 		io_clrbits32(bank->base + GPIO_SECR_OFFSET, BIT(pin));
12864b5e93edSEtienne Carriere 
1287c4cab2bbSEtienne Carriere 	cpu_spin_unlock_xrestore(&gpio_lock, exceptions);
128898dfcedaSEtienne Carriere 	clk_disable(bank->clock);
12894b5e93edSEtienne Carriere }
12900e0435e2SEtienne Carriere 
1291b38386fbSEtienne Carriere #ifdef CFG_DRIVERS_PINCTRL
1292b38386fbSEtienne Carriere static TEE_Result stm32_pinctrl_conf_apply(struct pinconf *conf)
1293b38386fbSEtienne Carriere {
1294b38386fbSEtienne Carriere 	struct stm32_pinctrl_array *ref = conf->priv;
1295b38386fbSEtienne Carriere 	struct stm32_pinctrl *p = ref->pinctrl;
1296*430c415aSEtienne Carriere 	struct stm32_gpio_bank *bank = NULL;
1297*430c415aSEtienne Carriere 	TEE_Result res = TEE_ERROR_GENERIC;
1298b38386fbSEtienne Carriere 	size_t pin_count = ref->count;
1299b38386fbSEtienne Carriere 	size_t n = 0;
1300*430c415aSEtienne Carriere 	bool error = false;
1301*430c415aSEtienne Carriere 
1302*430c415aSEtienne Carriere 	for (n = 0; n < pin_count; n++) {
1303*430c415aSEtienne Carriere 		bank = stm32_gpio_get_bank(p[n].bank);
1304*430c415aSEtienne Carriere 		res = acquire_rif_semaphore_if_needed(bank, p[n].pin);
1305*430c415aSEtienne Carriere 		if (res) {
1306*430c415aSEtienne Carriere 			EMSG("Failed to acquire GPIO %c%u semaphore",
1307*430c415aSEtienne Carriere 			     bank->bank_id + 'A', p[n].pin);
1308*430c415aSEtienne Carriere 			error = true;
1309*430c415aSEtienne Carriere 		}
1310*430c415aSEtienne Carriere 	}
1311*430c415aSEtienne Carriere 
1312*430c415aSEtienne Carriere 	if (error) {
1313*430c415aSEtienne Carriere 		for (n = 0; n < pin_count; n++) {
1314*430c415aSEtienne Carriere 			bank = stm32_gpio_get_bank(p[n].bank);
1315*430c415aSEtienne Carriere 			release_rif_semaphore_if_acquired(bank, p[n].pin);
1316*430c415aSEtienne Carriere 		}
1317*430c415aSEtienne Carriere 
1318*430c415aSEtienne Carriere 		return TEE_ERROR_SECURITY;
1319*430c415aSEtienne Carriere 	}
1320b38386fbSEtienne Carriere 
1321b38386fbSEtienne Carriere 	for (n = 0; n < pin_count; n++)
1322b38386fbSEtienne Carriere 		set_gpio_cfg(p[n].bank, p[n].pin, &p[n].cfg);
1323b38386fbSEtienne Carriere 
1324b38386fbSEtienne Carriere 	return TEE_SUCCESS;
1325b38386fbSEtienne Carriere }
1326b38386fbSEtienne Carriere 
1327b38386fbSEtienne Carriere static void stm32_pinctrl_conf_free(struct pinconf *conf)
1328b38386fbSEtienne Carriere {
1329b38386fbSEtienne Carriere 	free(conf);
1330b38386fbSEtienne Carriere }
1331b38386fbSEtienne Carriere 
1332b38386fbSEtienne Carriere static const struct pinctrl_ops stm32_pinctrl_ops = {
1333b38386fbSEtienne Carriere 	.conf_apply = stm32_pinctrl_conf_apply,
1334b38386fbSEtienne Carriere 	.conf_free = stm32_pinctrl_conf_free,
1335b38386fbSEtienne Carriere };
1336b38386fbSEtienne Carriere 
1337b38386fbSEtienne Carriere DECLARE_KEEP_PAGER(stm32_pinctrl_ops);
1338b38386fbSEtienne Carriere 
133970ac0db5SEtienne Carriere void stm32_gpio_pinctrl_bank_pin(struct pinctrl_state *pinctrl,
134070ac0db5SEtienne Carriere 				 unsigned int *bank, unsigned int *pin,
134170ac0db5SEtienne Carriere 				 unsigned int *count)
134270ac0db5SEtienne Carriere {
134370ac0db5SEtienne Carriere 	size_t conf_index = 0;
134470ac0db5SEtienne Carriere 	size_t pin_count = 0;
134570ac0db5SEtienne Carriere 	size_t n = 0;
134670ac0db5SEtienne Carriere 
134770ac0db5SEtienne Carriere 	assert(count);
134870ac0db5SEtienne Carriere 	if (!pinctrl)
134970ac0db5SEtienne Carriere 		goto out;
135070ac0db5SEtienne Carriere 
135170ac0db5SEtienne Carriere 	for (conf_index = 0; conf_index < pinctrl->conf_count; conf_index++) {
135270ac0db5SEtienne Carriere 		struct pinconf *pinconf = pinctrl->confs[conf_index];
135370ac0db5SEtienne Carriere 		struct stm32_pinctrl_array *ref = pinconf->priv;
135470ac0db5SEtienne Carriere 
135570ac0db5SEtienne Carriere 		/* Consider only the stm32_gpio pins */
135670ac0db5SEtienne Carriere 		if (pinconf->ops != &stm32_pinctrl_ops)
135770ac0db5SEtienne Carriere 			continue;
135870ac0db5SEtienne Carriere 
135970ac0db5SEtienne Carriere 		if (bank || pin) {
136070ac0db5SEtienne Carriere 			for (n = 0; n < ref->count; n++) {
136170ac0db5SEtienne Carriere 				if (bank && pin_count < *count)
136270ac0db5SEtienne Carriere 					bank[pin_count] = ref->pinctrl[n].bank;
136370ac0db5SEtienne Carriere 				if (pin && pin_count < *count)
136470ac0db5SEtienne Carriere 					pin[pin_count] = ref->pinctrl[n].pin;
136570ac0db5SEtienne Carriere 				pin_count++;
136670ac0db5SEtienne Carriere 			}
136770ac0db5SEtienne Carriere 		} else {
136870ac0db5SEtienne Carriere 			pin_count += ref->count;
136970ac0db5SEtienne Carriere 		}
137070ac0db5SEtienne Carriere 	}
137170ac0db5SEtienne Carriere 
137270ac0db5SEtienne Carriere out:
137370ac0db5SEtienne Carriere 	*count = pin_count;
137470ac0db5SEtienne Carriere }
137570ac0db5SEtienne Carriere 
13767f823a77SEtienne Carriere void stm32_pinctrl_set_secure_cfg(struct pinctrl_state *pinctrl, bool secure)
13777f823a77SEtienne Carriere {
13787f823a77SEtienne Carriere 	size_t conf_index = 0;
13797f823a77SEtienne Carriere 
13807f823a77SEtienne Carriere 	if (!pinctrl)
13817f823a77SEtienne Carriere 		return;
13827f823a77SEtienne Carriere 
13837f823a77SEtienne Carriere 	for (conf_index = 0; conf_index < pinctrl->conf_count; conf_index++) {
13847f823a77SEtienne Carriere 		struct pinconf *pinconf = pinctrl->confs[conf_index];
13857f823a77SEtienne Carriere 		struct stm32_pinctrl_array *ref = pinconf->priv;
13867f823a77SEtienne Carriere 		struct stm32_pinctrl *pc = NULL;
13877f823a77SEtienne Carriere 		size_t n = 0;
13887f823a77SEtienne Carriere 
13897f823a77SEtienne Carriere 		for (n = 0; n < ref->count; n++) {
13907f823a77SEtienne Carriere 			if (pinconf->ops != &stm32_pinctrl_ops)
13917f823a77SEtienne Carriere 				continue;
13927f823a77SEtienne Carriere 
13937f823a77SEtienne Carriere 			pc = ref->pinctrl + n;
13947f823a77SEtienne Carriere 			stm32_gpio_set_secure_cfg(pc->bank, pc->pin, secure);
13957f823a77SEtienne Carriere 		}
13967f823a77SEtienne Carriere 	}
13977f823a77SEtienne Carriere }
13987f823a77SEtienne Carriere 
1399b38386fbSEtienne Carriere /* Allocate and return a pinctrl configuration from a DT reference */
1400b38386fbSEtienne Carriere static TEE_Result stm32_pinctrl_dt_get(struct dt_pargs *pargs,
1401b38386fbSEtienne Carriere 				       void *data __unused,
1402b38386fbSEtienne Carriere 				       struct pinconf **out_pinconf)
1403b38386fbSEtienne Carriere {
1404b38386fbSEtienne Carriere 	struct conf {
1405b38386fbSEtienne Carriere 		struct pinconf pinconf;
1406b38386fbSEtienne Carriere 		struct stm32_pinctrl_array array_ref;
1407b38386fbSEtienne Carriere 	} *loc_conf = NULL;
1408b38386fbSEtienne Carriere 	struct stm32_pinctrl *pinctrl = NULL;
1409b38386fbSEtienne Carriere 	struct pinconf *pinconf = NULL;
1410b38386fbSEtienne Carriere 	const void *fdt = NULL;
1411b38386fbSEtienne Carriere 	size_t pin_count = 0;
1412b38386fbSEtienne Carriere 	int pinctrl_node = 0;
1413b38386fbSEtienne Carriere 	int pinmux_node = 0;
1414b38386fbSEtienne Carriere 	int count = 0;
1415b38386fbSEtienne Carriere 
1416b38386fbSEtienne Carriere 	pinctrl_node = pargs->phandle_node;
1417b38386fbSEtienne Carriere 	fdt = pargs->fdt;
1418b38386fbSEtienne Carriere 	assert(fdt && pinctrl_node);
1419b38386fbSEtienne Carriere 
1420b38386fbSEtienne Carriere 	fdt_for_each_subnode(pinmux_node, fdt, pinctrl_node) {
1421b38386fbSEtienne Carriere 		if (fdt_getprop(fdt, pinmux_node, "pinmux", &count))
1422b38386fbSEtienne Carriere 			pin_count += (size_t)count / sizeof(uint32_t);
1423b38386fbSEtienne Carriere 		else if (count != -FDT_ERR_NOTFOUND)
1424b38386fbSEtienne Carriere 			panic();
1425b38386fbSEtienne Carriere 	}
1426b38386fbSEtienne Carriere 
1427b38386fbSEtienne Carriere 	loc_conf = calloc(1, sizeof(*loc_conf) + sizeof(*pinctrl) * pin_count);
1428b38386fbSEtienne Carriere 	if (!loc_conf)
1429b38386fbSEtienne Carriere 		return TEE_ERROR_OUT_OF_MEMORY;
1430b38386fbSEtienne Carriere 
1431b38386fbSEtienne Carriere 	pinconf = &loc_conf->pinconf;
1432b38386fbSEtienne Carriere 	pinconf->ops = &stm32_pinctrl_ops;
1433b38386fbSEtienne Carriere 	pinconf->priv = &loc_conf->array_ref;
1434b38386fbSEtienne Carriere 
1435b38386fbSEtienne Carriere 	loc_conf->array_ref.count = pin_count;
1436b38386fbSEtienne Carriere 	pinctrl = loc_conf->array_ref.pinctrl;
1437b38386fbSEtienne Carriere 
1438b38386fbSEtienne Carriere 	count = 0;
1439b38386fbSEtienne Carriere 	fdt_for_each_subnode(pinmux_node, fdt, pinctrl_node) {
1440b38386fbSEtienne Carriere 		int found = 0;
1441b38386fbSEtienne Carriere 
1442b38386fbSEtienne Carriere 		found = get_pinctrl_from_fdt(fdt, pinmux_node, pinctrl + count,
1443b38386fbSEtienne Carriere 					     pin_count - count);
1444b38386fbSEtienne Carriere 		if (found <= 0 && found > ((int)pin_count - count)) {
1445b38386fbSEtienne Carriere 			/* We can't recover from an error here so let's panic */
1446b38386fbSEtienne Carriere 			panic();
1447b38386fbSEtienne Carriere 		}
1448b38386fbSEtienne Carriere 
1449b38386fbSEtienne Carriere 		count += found;
1450b38386fbSEtienne Carriere 	}
1451b38386fbSEtienne Carriere 
1452b38386fbSEtienne Carriere 	*out_pinconf = pinconf;
1453b38386fbSEtienne Carriere 
1454b38386fbSEtienne Carriere 	return TEE_SUCCESS;
1455b38386fbSEtienne Carriere }
1456b38386fbSEtienne Carriere #endif /*CFG_DRIVERS_PINCTRL*/
1457b38386fbSEtienne Carriere 
1458bfc43b68SGatien Chevallier static void stm32_gpio_get_conf_sec(struct stm32_gpio_bank *bank)
1459bfc43b68SGatien Chevallier {
1460bfc43b68SGatien Chevallier 	if (bank->sec_support) {
1461bfc43b68SGatien Chevallier 		clk_enable(bank->clock);
1462bfc43b68SGatien Chevallier 		bank->seccfgr = io_read32(bank->base + GPIO_SECR_OFFSET);
1463bfc43b68SGatien Chevallier 		clk_disable(bank->clock);
1464bfc43b68SGatien Chevallier 	}
1465bfc43b68SGatien Chevallier }
1466bfc43b68SGatien Chevallier 
1467bd03c8c3SGatien Chevallier static void stm32_gpio_set_conf_sec(struct stm32_gpio_bank *bank)
1468bd03c8c3SGatien Chevallier {
1469bd03c8c3SGatien Chevallier 	if (bank->sec_support) {
1470bd03c8c3SGatien Chevallier 		clk_enable(bank->clock);
1471bd03c8c3SGatien Chevallier 		io_write32(bank->base + GPIO_SECR_OFFSET, bank->seccfgr);
1472bd03c8c3SGatien Chevallier 		clk_disable(bank->clock);
1473bd03c8c3SGatien Chevallier 	}
1474bd03c8c3SGatien Chevallier }
1475bd03c8c3SGatien Chevallier 
1476bfc43b68SGatien Chevallier static TEE_Result stm32_gpio_sec_config_resume(void)
1477bfc43b68SGatien Chevallier {
1478bfc43b68SGatien Chevallier 	TEE_Result res = TEE_ERROR_GENERIC;
1479bfc43b68SGatien Chevallier 	struct stm32_gpio_bank *bank = NULL;
1480bfc43b68SGatien Chevallier 
1481bfc43b68SGatien Chevallier 	STAILQ_FOREACH(bank, &bank_list, link) {
1482bfc43b68SGatien Chevallier 		if (bank->rif_cfg) {
1483bfc43b68SGatien Chevallier 			if (!bank->is_tdcid)
1484bfc43b68SGatien Chevallier 				continue;
1485bfc43b68SGatien Chevallier 
1486bfc43b68SGatien Chevallier 			bank->rif_cfg->access_mask[0] = GENMASK_32(bank->ngpios,
1487bfc43b68SGatien Chevallier 								   0);
1488bfc43b68SGatien Chevallier 
1489a72f07daSEtienne Carriere 			res = apply_rif_config(bank,
1490a72f07daSEtienne Carriere 					       bank->rif_cfg->access_mask[0]);
1491bfc43b68SGatien Chevallier 			if (res) {
1492bfc43b68SGatien Chevallier 				EMSG("Failed to set GPIO bank %c RIF config",
1493bfc43b68SGatien Chevallier 				     'A' + bank->bank_id);
1494bfc43b68SGatien Chevallier 				return res;
1495bfc43b68SGatien Chevallier 			}
1496bfc43b68SGatien Chevallier 		} else {
1497bfc43b68SGatien Chevallier 			stm32_gpio_set_conf_sec(bank);
1498bfc43b68SGatien Chevallier 		}
1499bfc43b68SGatien Chevallier 	}
1500bfc43b68SGatien Chevallier 
1501bfc43b68SGatien Chevallier 	return TEE_SUCCESS;
1502bfc43b68SGatien Chevallier }
1503bfc43b68SGatien Chevallier 
1504bfc43b68SGatien Chevallier static TEE_Result stm32_gpio_sec_config_suspend(void)
1505bfc43b68SGatien Chevallier {
1506bfc43b68SGatien Chevallier 	struct stm32_gpio_bank *bank = NULL;
1507bfc43b68SGatien Chevallier 
1508bfc43b68SGatien Chevallier 	STAILQ_FOREACH(bank, &bank_list, link) {
1509bfc43b68SGatien Chevallier 		if (bank->rif_cfg) {
1510bfc43b68SGatien Chevallier 			if (bank->is_tdcid)
1511bfc43b68SGatien Chevallier 				stm32_gpio_save_rif_config(bank);
1512bfc43b68SGatien Chevallier 		} else {
1513bfc43b68SGatien Chevallier 			stm32_gpio_get_conf_sec(bank);
1514bfc43b68SGatien Chevallier 		}
1515bfc43b68SGatien Chevallier 	}
1516bfc43b68SGatien Chevallier 
1517bfc43b68SGatien Chevallier 	return TEE_SUCCESS;
1518bfc43b68SGatien Chevallier }
1519bfc43b68SGatien Chevallier 
1520bfc43b68SGatien Chevallier static TEE_Result
1521bfc43b68SGatien Chevallier stm32_gpio_sec_config_pm(enum pm_op op, unsigned int pm_hint,
1522bfc43b68SGatien Chevallier 			 const struct pm_callback_handle *hdl __unused)
1523bfc43b68SGatien Chevallier {
1524bfc43b68SGatien Chevallier 	TEE_Result ret = TEE_ERROR_GENERIC;
1525bfc43b68SGatien Chevallier 
1526bfc43b68SGatien Chevallier 	if (!PM_HINT_IS_STATE(pm_hint, CONTEXT))
1527bfc43b68SGatien Chevallier 		return TEE_SUCCESS;
1528bfc43b68SGatien Chevallier 
1529bfc43b68SGatien Chevallier 	if (op == PM_OP_RESUME)
1530bfc43b68SGatien Chevallier 		ret = stm32_gpio_sec_config_resume();
1531bfc43b68SGatien Chevallier 	else
1532bfc43b68SGatien Chevallier 		ret = stm32_gpio_sec_config_suspend();
1533bfc43b68SGatien Chevallier 
1534bfc43b68SGatien Chevallier 	return ret;
1535bfc43b68SGatien Chevallier }
1536bfc43b68SGatien Chevallier DECLARE_KEEP_PAGER(stm32_gpio_sec_config_pm);
1537bfc43b68SGatien Chevallier 
1538bd03c8c3SGatien Chevallier /*
1539bd03c8c3SGatien Chevallier  * Several pinctrl nodes can be probed. Their bank will be put in the unique
1540bd03c8c3SGatien Chevallier  * bank_list. To avoid multiple configuration set for a bank when looping
1541bd03c8c3SGatien Chevallier  * over each bank in the bank list, ready is set to true when a bank is
1542bd03c8c3SGatien Chevallier  * configured. Therefore, during other bank probes, the configuration won't
1543bd03c8c3SGatien Chevallier  * be set again.
1544bd03c8c3SGatien Chevallier  */
1545bd03c8c3SGatien Chevallier static TEE_Result apply_sec_cfg(void)
1546bd03c8c3SGatien Chevallier {
1547bd03c8c3SGatien Chevallier 	TEE_Result res = TEE_ERROR_GENERIC;
1548bd03c8c3SGatien Chevallier 	struct stm32_gpio_bank *bank = NULL;
1549*430c415aSEtienne Carriere 	unsigned int pin = 0;
1550bd03c8c3SGatien Chevallier 
1551bd03c8c3SGatien Chevallier 	STAILQ_FOREACH(bank, &bank_list, link) {
1552bd03c8c3SGatien Chevallier 		if (bank->ready)
1553bd03c8c3SGatien Chevallier 			continue;
1554bd03c8c3SGatien Chevallier 
1555bd03c8c3SGatien Chevallier 		if (bank->rif_cfg) {
1556a72f07daSEtienne Carriere 			res = apply_rif_config(bank,
1557a72f07daSEtienne Carriere 					       bank->rif_cfg->access_mask[0]);
1558bd03c8c3SGatien Chevallier 			if (res) {
1559bd03c8c3SGatien Chevallier 				EMSG("Failed to set GPIO bank %c RIF config",
1560bd03c8c3SGatien Chevallier 				     'A' + bank->bank_id);
1561bd03c8c3SGatien Chevallier 				STAILQ_REMOVE(&bank_list, bank, stm32_gpio_bank,
1562bd03c8c3SGatien Chevallier 					      link);
15639def1fb7SGatien Chevallier 				free(bank);
1564bd03c8c3SGatien Chevallier 				return res;
1565bd03c8c3SGatien Chevallier 			}
1566*430c415aSEtienne Carriere 
1567*430c415aSEtienne Carriere 			/*
1568*430c415aSEtienne Carriere 			 * Semaphores for pinctrl and GPIO are taken when
1569*430c415aSEtienne Carriere 			 * these are used (pinctrl state applied, GPIO
1570*430c415aSEtienne Carriere 			 * consumed) or when an explicit firewall configuration
1571*430c415aSEtienne Carriere 			 * is requested through the firewall framework.
1572*430c415aSEtienne Carriere 			 * Therefore release here the taken semaphores.
1573*430c415aSEtienne Carriere 			 */
1574*430c415aSEtienne Carriere 			for (pin = 0; pin < bank->ngpios; pin++)
1575*430c415aSEtienne Carriere 				release_rif_semaphore_if_acquired(bank, pin);
1576*430c415aSEtienne Carriere 
1577bd03c8c3SGatien Chevallier 		} else {
1578bd03c8c3SGatien Chevallier 			stm32_gpio_set_conf_sec(bank);
1579bd03c8c3SGatien Chevallier 		}
1580bd03c8c3SGatien Chevallier 
1581bd03c8c3SGatien Chevallier 		bank->ready = true;
1582bd03c8c3SGatien Chevallier 	}
1583bd03c8c3SGatien Chevallier 
1584bd03c8c3SGatien Chevallier 	return TEE_SUCCESS;
1585bd03c8c3SGatien Chevallier }
1586bd03c8c3SGatien Chevallier 
15870e0435e2SEtienne Carriere static TEE_Result stm32_pinctrl_probe(const void *fdt, int node,
15880e0435e2SEtienne Carriere 				      const void *compat_data)
15890e0435e2SEtienne Carriere {
1590bfc43b68SGatien Chevallier 	static bool pm_register;
1591b38386fbSEtienne Carriere 	TEE_Result res = TEE_ERROR_GENERIC;
1592b38386fbSEtienne Carriere 
15930e0435e2SEtienne Carriere 	/* Register GPIO banks described in this pin control node */
1594b38386fbSEtienne Carriere 	res = dt_stm32_gpio_pinctrl(fdt, node, compat_data);
1595b38386fbSEtienne Carriere 	if (res)
1596b38386fbSEtienne Carriere 		return res;
1597b38386fbSEtienne Carriere 
1598bd03c8c3SGatien Chevallier 	if (STAILQ_EMPTY(&bank_list))
1599bd03c8c3SGatien Chevallier 		DMSG("no gpio bank for that driver");
1600bd03c8c3SGatien Chevallier 	else if (apply_sec_cfg())
1601bd03c8c3SGatien Chevallier 		panic();
1602bd03c8c3SGatien Chevallier 
1603bfc43b68SGatien Chevallier 	if (!pm_register) {
1604bfc43b68SGatien Chevallier 		/*
1605bfc43b68SGatien Chevallier 		 * Register to PM once for all probed banks to restore
1606bfc43b68SGatien Chevallier 		 * their secure configuration.
1607bfc43b68SGatien Chevallier 		 */
1608bfc43b68SGatien Chevallier 		register_pm_driver_cb(stm32_gpio_sec_config_pm, NULL,
1609bfc43b68SGatien Chevallier 				      "stm32-gpio-secure-config");
1610bfc43b68SGatien Chevallier 		pm_register = true;
1611bfc43b68SGatien Chevallier 	}
1612bfc43b68SGatien Chevallier 
1613b38386fbSEtienne Carriere #ifdef CFG_DRIVERS_PINCTRL
1614b38386fbSEtienne Carriere 	res = pinctrl_register_provider(fdt, node, stm32_pinctrl_dt_get,
1615b38386fbSEtienne Carriere 					(void *)compat_data);
1616b38386fbSEtienne Carriere 	if (res)
1617bd03c8c3SGatien Chevallier 		panic();
1618b38386fbSEtienne Carriere #endif
1619b38386fbSEtienne Carriere 
1620b38386fbSEtienne Carriere 	return TEE_SUCCESS;
16210e0435e2SEtienne Carriere }
16220e0435e2SEtienne Carriere 
16230e0435e2SEtienne Carriere static const struct dt_device_match stm32_pinctrl_match_table[] = {
1624e569f6adSEtienne Carriere 	{
1625e569f6adSEtienne Carriere 		.compatible = "st,stm32mp135-pinctrl",
1626b4893304SGatien Chevallier 		.compat_data = &(struct bank_compat){
1627b4893304SGatien Chevallier 			.secure_control = true,
1628bd03c8c3SGatien Chevallier 			.secure_extended = false,
1629b4893304SGatien Chevallier 		},
1630e569f6adSEtienne Carriere 	},
1631e569f6adSEtienne Carriere 	{
1632e569f6adSEtienne Carriere 		.compatible = "st,stm32mp157-pinctrl",
1633b4893304SGatien Chevallier 		.compat_data = &(struct bank_compat){
1634b4893304SGatien Chevallier 			.secure_control = false,
1635bd03c8c3SGatien Chevallier 			.secure_extended = false,
1636b4893304SGatien Chevallier 		},
1637e569f6adSEtienne Carriere 	},
1638e569f6adSEtienne Carriere 	{
1639e569f6adSEtienne Carriere 		.compatible = "st,stm32mp157-z-pinctrl",
1640b4893304SGatien Chevallier 		.compat_data = &(struct bank_compat){
1641b4893304SGatien Chevallier 			.gpioz = true,
1642b4893304SGatien Chevallier 			.secure_control = true,
1643bd03c8c3SGatien Chevallier 			.secure_extended = false,
1644bd03c8c3SGatien Chevallier 		},
1645bd03c8c3SGatien Chevallier 	},
1646bd03c8c3SGatien Chevallier 	{
1647bd03c8c3SGatien Chevallier 		.compatible = "st,stm32mp257-pinctrl",
1648bd03c8c3SGatien Chevallier 		.compat_data = &(struct bank_compat){
1649bd03c8c3SGatien Chevallier 			.secure_control = true,
1650bd03c8c3SGatien Chevallier 			.secure_extended = true,
1651bd03c8c3SGatien Chevallier 		},
1652bd03c8c3SGatien Chevallier 	},
1653bd03c8c3SGatien Chevallier 	{
1654bd03c8c3SGatien Chevallier 		.compatible = "st,stm32mp257-z-pinctrl",
1655bd03c8c3SGatien Chevallier 		.compat_data = &(struct bank_compat){
1656bd03c8c3SGatien Chevallier 			.gpioz = true,
1657bd03c8c3SGatien Chevallier 			.secure_control = true,
1658bd03c8c3SGatien Chevallier 			.secure_extended = true,
1659b4893304SGatien Chevallier 		},
1660e569f6adSEtienne Carriere 	},
16610e0435e2SEtienne Carriere 	{ }
16620e0435e2SEtienne Carriere };
16630e0435e2SEtienne Carriere 
16640e0435e2SEtienne Carriere DEFINE_DT_DRIVER(stm32_pinctrl_dt_driver) = {
16650e0435e2SEtienne Carriere 	.name = "stm32_gpio-pinctrl",
16660e0435e2SEtienne Carriere 	.type = DT_DRIVER_PINCTRL,
16670e0435e2SEtienne Carriere 	.match_table = stm32_pinctrl_match_table,
16680e0435e2SEtienne Carriere 	.probe = stm32_pinctrl_probe,
16690e0435e2SEtienne Carriere };
1670