2 * Copyright (c) 2016-2019, STMicroelectronics - All Rights Reserved
4 * SPDX-License-Identifier: BSD-3-Clause
13 #include <platform_def.h>
15 #include <common/bl_common.h>
16 #include <common/debug.h>
17 #include <drivers/st/stm32_gpio.h>
18 #include <drivers/st/stm32mp_clkfunc.h>
20 #include <lib/utils_def.h>
22 #define DT_GPIO_BANK_SHIFT 12
23 #define DT_GPIO_BANK_MASK GENMASK(16, 12)
24 #define DT_GPIO_PIN_SHIFT 8
25 #define DT_GPIO_PIN_MASK GENMASK(11, 8)
26 #define DT_GPIO_MODE_MASK GENMASK(7, 0)
28 /*******************************************************************************
29 * This function gets GPIO bank node in DT.
30 * Returns node offset if status is okay in DT, else return 0
31 ******************************************************************************/
32 static int ckeck_gpio_bank(void *fdt
, uint32_t bank
, int pinctrl_node
)
35 uint32_t bank_offset
= stm32_get_gpio_bank_offset(bank
);
37 fdt_for_each_subnode(pinctrl_subnode
, fdt
, pinctrl_node
) {
40 if (fdt_getprop(fdt
, pinctrl_subnode
,
41 "gpio-controller", NULL
) == NULL
) {
45 cuint
= fdt_getprop(fdt
, pinctrl_subnode
, "reg", NULL
);
50 if ((fdt32_to_cpu(*cuint
) == bank_offset
) &&
51 (fdt_get_status(pinctrl_subnode
) != DT_DISABLED
)) {
52 return pinctrl_subnode
;
59 /*******************************************************************************
60 * This function gets the pin settings from DT information.
61 * When analyze and parsing is done, set the GPIO registers.
62 * Returns 0 on success and a negative FDT error code on failure.
63 ******************************************************************************/
64 static int dt_set_gpio_config(void *fdt
, int node
, uint8_t status
)
66 const fdt32_t
*cuint
, *slewrate
;
70 uint32_t speed
= GPIO_SPEED_LOW
;
71 uint32_t pull
= GPIO_NO_PULL
;
73 cuint
= fdt_getprop(fdt
, node
, "pinmux", &len
);
75 return -FDT_ERR_NOTFOUND
;
78 pinctrl_node
= fdt_parent_offset(fdt
, fdt_parent_offset(fdt
, node
));
79 if (pinctrl_node
< 0) {
80 return -FDT_ERR_NOTFOUND
;
83 slewrate
= fdt_getprop(fdt
, node
, "slew-rate", NULL
);
84 if (slewrate
!= NULL
) {
85 speed
= fdt32_to_cpu(*slewrate
);
88 if (fdt_getprop(fdt
, node
, "bias-pull-up", NULL
) != NULL
) {
90 } else if (fdt_getprop(fdt
, node
, "bias-pull-down", NULL
) != NULL
) {
91 pull
= GPIO_PULL_DOWN
;
93 VERBOSE("No bias configured in node %d\n", node
);
96 for (i
= 0U; i
< ((uint32_t)len
/ sizeof(uint32_t)); i
++) {
101 uint32_t alternate
= GPIO_ALTERNATE_(0);
105 pincfg
= fdt32_to_cpu(*cuint
);
108 bank
= (pincfg
& DT_GPIO_BANK_MASK
) >> DT_GPIO_BANK_SHIFT
;
110 pin
= (pincfg
& DT_GPIO_PIN_MASK
) >> DT_GPIO_PIN_SHIFT
;
112 mode
= pincfg
& DT_GPIO_MODE_MASK
;
116 mode
= GPIO_MODE_INPUT
;
119 alternate
= mode
- 1U;
120 mode
= GPIO_MODE_ALTERNATE
;
123 mode
= GPIO_MODE_ANALOG
;
126 mode
= GPIO_MODE_OUTPUT
;
130 if (fdt_getprop(fdt
, node
, "drive-open-drain", NULL
) != NULL
) {
131 mode
|= GPIO_OPEN_DRAIN
;
134 bank_node
= ckeck_gpio_bank(fdt
, bank
, pinctrl_node
);
135 if (bank_node
== 0) {
136 ERROR("PINCTRL inconsistent in DT\n");
140 clk
= fdt_get_clock_id(bank_node
);
142 return -FDT_ERR_NOTFOUND
;
145 /* Platform knows the clock: assert it is okay */
146 assert((unsigned long)clk
== stm32_get_gpio_bank_clock(bank
));
148 set_gpio(bank
, pin
, mode
, speed
, pull
, alternate
, status
);
154 /*******************************************************************************
155 * This function gets the pin settings from DT information.
156 * When analyze and parsing is done, set the GPIO registers.
157 * Returns 0 on success and a negative FDT/ERRNO error code on failure.
158 ******************************************************************************/
159 int dt_set_pinctrl_config(int node
)
161 const fdt32_t
*cuint
;
164 uint8_t status
= fdt_get_status(node
);
167 if (fdt_get_address(&fdt
) == 0) {
168 return -FDT_ERR_NOTFOUND
;
171 if (status
== DT_DISABLED
) {
172 return -FDT_ERR_NOTFOUND
;
175 cuint
= fdt_getprop(fdt
, node
, "pinctrl-0", &lenp
);
177 return -FDT_ERR_NOTFOUND
;
180 for (i
= 0; i
< ((uint32_t)lenp
/ 4U); i
++) {
181 int p_node
, p_subnode
;
183 p_node
= fdt_node_offset_by_phandle(fdt
, fdt32_to_cpu(*cuint
));
185 return -FDT_ERR_NOTFOUND
;
188 fdt_for_each_subnode(p_subnode
, fdt
, p_node
) {
189 int ret
= dt_set_gpio_config(fdt
, p_subnode
, status
);
202 void set_gpio(uint32_t bank
, uint32_t pin
, uint32_t mode
, uint32_t speed
,
203 uint32_t pull
, uint32_t alternate
, uint8_t status
)
205 uintptr_t base
= stm32_get_gpio_bank_base(bank
);
206 unsigned long clock
= stm32_get_gpio_bank_clock(bank
);
208 assert(pin
<= GPIO_PIN_MAX
);
210 stm32mp_clk_enable(clock
);
212 mmio_clrbits_32(base
+ GPIO_MODE_OFFSET
,
213 ((uint32_t)GPIO_MODE_MASK
<< (pin
<< 1)));
214 mmio_setbits_32(base
+ GPIO_MODE_OFFSET
,
215 (mode
& ~GPIO_OPEN_DRAIN
) << (pin
<< 1));
217 if ((mode
& GPIO_OPEN_DRAIN
) != 0U) {
218 mmio_setbits_32(base
+ GPIO_TYPE_OFFSET
, BIT(pin
));
220 mmio_clrbits_32(base
+ GPIO_TYPE_OFFSET
, BIT(pin
));
223 mmio_clrbits_32(base
+ GPIO_SPEED_OFFSET
,
224 ((uint32_t)GPIO_SPEED_MASK
<< (pin
<< 1)));
225 mmio_setbits_32(base
+ GPIO_SPEED_OFFSET
, speed
<< (pin
<< 1));
227 mmio_clrbits_32(base
+ GPIO_PUPD_OFFSET
,
228 ((uint32_t)GPIO_PULL_MASK
<< (pin
<< 1)));
229 mmio_setbits_32(base
+ GPIO_PUPD_OFFSET
, pull
<< (pin
<< 1));
231 if (pin
< GPIO_ALT_LOWER_LIMIT
) {
232 mmio_clrbits_32(base
+ GPIO_AFRL_OFFSET
,
233 ((uint32_t)GPIO_ALTERNATE_MASK
<< (pin
<< 2)));
234 mmio_setbits_32(base
+ GPIO_AFRL_OFFSET
,
235 alternate
<< (pin
<< 2));
237 mmio_clrbits_32(base
+ GPIO_AFRH_OFFSET
,
238 ((uint32_t)GPIO_ALTERNATE_MASK
<<
239 ((pin
- GPIO_ALT_LOWER_LIMIT
) << 2)));
240 mmio_setbits_32(base
+ GPIO_AFRH_OFFSET
,
241 alternate
<< ((pin
- GPIO_ALT_LOWER_LIMIT
) <<
245 VERBOSE("GPIO %u mode set to 0x%x\n", bank
,
246 mmio_read_32(base
+ GPIO_MODE_OFFSET
));
247 VERBOSE("GPIO %u speed set to 0x%x\n", bank
,
248 mmio_read_32(base
+ GPIO_SPEED_OFFSET
));
249 VERBOSE("GPIO %u mode pull to 0x%x\n", bank
,
250 mmio_read_32(base
+ GPIO_PUPD_OFFSET
));
251 VERBOSE("GPIO %u mode alternate low to 0x%x\n", bank
,
252 mmio_read_32(base
+ GPIO_AFRL_OFFSET
));
253 VERBOSE("GPIO %u mode alternate high to 0x%x\n", bank
,
254 mmio_read_32(base
+ GPIO_AFRH_OFFSET
));
256 stm32mp_clk_disable(clock
);
259 void set_gpio_secure_cfg(uint32_t bank
, uint32_t pin
, bool secure
)
261 uintptr_t base
= stm32_get_gpio_bank_base(bank
);
262 unsigned long clock
= stm32_get_gpio_bank_clock(bank
);
264 assert(pin
<= GPIO_PIN_MAX
);
266 stm32mp_clk_enable(clock
);
269 mmio_setbits_32(base
+ GPIO_SECR_OFFSET
, BIT(pin
));
271 mmio_clrbits_32(base
+ GPIO_SECR_OFFSET
, BIT(pin
));
274 stm32mp_clk_disable(clock
);