1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2016-2022, STMicroelectronics - All Rights Reserved 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu #include <assert.h> 8*91f16700Schasinglulu #include <errno.h> 9*91f16700Schasinglulu #include <stdbool.h> 10*91f16700Schasinglulu 11*91f16700Schasinglulu #include <common/bl_common.h> 12*91f16700Schasinglulu #include <common/debug.h> 13*91f16700Schasinglulu #include <drivers/clk.h> 14*91f16700Schasinglulu #include <drivers/st/stm32_gpio.h> 15*91f16700Schasinglulu #include <drivers/st/stm32mp_clkfunc.h> 16*91f16700Schasinglulu #include <lib/mmio.h> 17*91f16700Schasinglulu #include <lib/utils_def.h> 18*91f16700Schasinglulu #include <libfdt.h> 19*91f16700Schasinglulu 20*91f16700Schasinglulu #include <platform_def.h> 21*91f16700Schasinglulu 22*91f16700Schasinglulu #define DT_GPIO_BANK_SHIFT 12 23*91f16700Schasinglulu #define DT_GPIO_BANK_MASK GENMASK(16, 12) 24*91f16700Schasinglulu #define DT_GPIO_PIN_SHIFT 8 25*91f16700Schasinglulu #define DT_GPIO_PIN_MASK GENMASK(11, 8) 26*91f16700Schasinglulu #define DT_GPIO_MODE_MASK GENMASK(7, 0) 27*91f16700Schasinglulu 28*91f16700Schasinglulu static void set_gpio(uint32_t bank, uint32_t pin, uint32_t mode, uint32_t type, 29*91f16700Schasinglulu uint32_t speed, uint32_t pull, uint32_t od, 30*91f16700Schasinglulu uint32_t alternate, uint8_t status); 31*91f16700Schasinglulu 32*91f16700Schasinglulu /******************************************************************************* 33*91f16700Schasinglulu * This function gets GPIO bank node in DT. 34*91f16700Schasinglulu * Returns node offset if status is okay in DT, else return 0 35*91f16700Schasinglulu ******************************************************************************/ 36*91f16700Schasinglulu static int ckeck_gpio_bank(void *fdt, uint32_t bank, int pinctrl_node) 37*91f16700Schasinglulu { 38*91f16700Schasinglulu int pinctrl_subnode; 39*91f16700Schasinglulu uint32_t bank_offset = stm32_get_gpio_bank_offset(bank); 40*91f16700Schasinglulu 41*91f16700Schasinglulu fdt_for_each_subnode(pinctrl_subnode, fdt, pinctrl_node) { 42*91f16700Schasinglulu const fdt32_t *cuint; 43*91f16700Schasinglulu 44*91f16700Schasinglulu if (fdt_getprop(fdt, pinctrl_subnode, 45*91f16700Schasinglulu "gpio-controller", NULL) == NULL) { 46*91f16700Schasinglulu continue; 47*91f16700Schasinglulu } 48*91f16700Schasinglulu 49*91f16700Schasinglulu cuint = fdt_getprop(fdt, pinctrl_subnode, "reg", NULL); 50*91f16700Schasinglulu if (cuint == NULL) { 51*91f16700Schasinglulu continue; 52*91f16700Schasinglulu } 53*91f16700Schasinglulu 54*91f16700Schasinglulu if ((fdt32_to_cpu(*cuint) == bank_offset) && 55*91f16700Schasinglulu (fdt_get_status(pinctrl_subnode) != DT_DISABLED)) { 56*91f16700Schasinglulu return pinctrl_subnode; 57*91f16700Schasinglulu } 58*91f16700Schasinglulu } 59*91f16700Schasinglulu 60*91f16700Schasinglulu return 0; 61*91f16700Schasinglulu } 62*91f16700Schasinglulu 63*91f16700Schasinglulu /******************************************************************************* 64*91f16700Schasinglulu * This function gets the pin settings from DT information. 65*91f16700Schasinglulu * When analyze and parsing is done, set the GPIO registers. 66*91f16700Schasinglulu * Returns 0 on success and a negative FDT error code on failure. 67*91f16700Schasinglulu ******************************************************************************/ 68*91f16700Schasinglulu static int dt_set_gpio_config(void *fdt, int node, uint8_t status) 69*91f16700Schasinglulu { 70*91f16700Schasinglulu const fdt32_t *cuint, *slewrate; 71*91f16700Schasinglulu int len; 72*91f16700Schasinglulu int pinctrl_node; 73*91f16700Schasinglulu uint32_t i; 74*91f16700Schasinglulu uint32_t speed = GPIO_SPEED_LOW; 75*91f16700Schasinglulu uint32_t pull = GPIO_NO_PULL; 76*91f16700Schasinglulu 77*91f16700Schasinglulu cuint = fdt_getprop(fdt, node, "pinmux", &len); 78*91f16700Schasinglulu if (cuint == NULL) { 79*91f16700Schasinglulu return -FDT_ERR_NOTFOUND; 80*91f16700Schasinglulu } 81*91f16700Schasinglulu 82*91f16700Schasinglulu pinctrl_node = fdt_parent_offset(fdt, fdt_parent_offset(fdt, node)); 83*91f16700Schasinglulu if (pinctrl_node < 0) { 84*91f16700Schasinglulu return -FDT_ERR_NOTFOUND; 85*91f16700Schasinglulu } 86*91f16700Schasinglulu 87*91f16700Schasinglulu slewrate = fdt_getprop(fdt, node, "slew-rate", NULL); 88*91f16700Schasinglulu if (slewrate != NULL) { 89*91f16700Schasinglulu speed = fdt32_to_cpu(*slewrate); 90*91f16700Schasinglulu } 91*91f16700Schasinglulu 92*91f16700Schasinglulu if (fdt_getprop(fdt, node, "bias-pull-up", NULL) != NULL) { 93*91f16700Schasinglulu pull = GPIO_PULL_UP; 94*91f16700Schasinglulu } else if (fdt_getprop(fdt, node, "bias-pull-down", NULL) != NULL) { 95*91f16700Schasinglulu pull = GPIO_PULL_DOWN; 96*91f16700Schasinglulu } else { 97*91f16700Schasinglulu VERBOSE("No bias configured in node %d\n", node); 98*91f16700Schasinglulu } 99*91f16700Schasinglulu 100*91f16700Schasinglulu for (i = 0U; i < ((uint32_t)len / sizeof(uint32_t)); i++) { 101*91f16700Schasinglulu uint32_t pincfg; 102*91f16700Schasinglulu uint32_t bank; 103*91f16700Schasinglulu uint32_t pin; 104*91f16700Schasinglulu uint32_t mode; 105*91f16700Schasinglulu uint32_t alternate = GPIO_ALTERNATE_(0); 106*91f16700Schasinglulu uint32_t type; 107*91f16700Schasinglulu uint32_t od = GPIO_OD_OUTPUT_LOW; 108*91f16700Schasinglulu int bank_node; 109*91f16700Schasinglulu int clk; 110*91f16700Schasinglulu 111*91f16700Schasinglulu pincfg = fdt32_to_cpu(*cuint); 112*91f16700Schasinglulu cuint++; 113*91f16700Schasinglulu 114*91f16700Schasinglulu bank = (pincfg & DT_GPIO_BANK_MASK) >> DT_GPIO_BANK_SHIFT; 115*91f16700Schasinglulu 116*91f16700Schasinglulu pin = (pincfg & DT_GPIO_PIN_MASK) >> DT_GPIO_PIN_SHIFT; 117*91f16700Schasinglulu 118*91f16700Schasinglulu mode = pincfg & DT_GPIO_MODE_MASK; 119*91f16700Schasinglulu 120*91f16700Schasinglulu switch (mode) { 121*91f16700Schasinglulu case 0: 122*91f16700Schasinglulu mode = GPIO_MODE_INPUT; 123*91f16700Schasinglulu break; 124*91f16700Schasinglulu case 1 ... 16: 125*91f16700Schasinglulu alternate = mode - 1U; 126*91f16700Schasinglulu mode = GPIO_MODE_ALTERNATE; 127*91f16700Schasinglulu break; 128*91f16700Schasinglulu case 17: 129*91f16700Schasinglulu mode = GPIO_MODE_ANALOG; 130*91f16700Schasinglulu break; 131*91f16700Schasinglulu default: 132*91f16700Schasinglulu mode = GPIO_MODE_OUTPUT; 133*91f16700Schasinglulu break; 134*91f16700Schasinglulu } 135*91f16700Schasinglulu 136*91f16700Schasinglulu if (fdt_getprop(fdt, node, "drive-open-drain", NULL) != NULL) { 137*91f16700Schasinglulu type = GPIO_TYPE_OPEN_DRAIN; 138*91f16700Schasinglulu } else { 139*91f16700Schasinglulu type = GPIO_TYPE_PUSH_PULL; 140*91f16700Schasinglulu } 141*91f16700Schasinglulu 142*91f16700Schasinglulu if (fdt_getprop(fdt, node, "output-high", NULL) != NULL) { 143*91f16700Schasinglulu if (mode == GPIO_MODE_INPUT) { 144*91f16700Schasinglulu mode = GPIO_MODE_OUTPUT; 145*91f16700Schasinglulu od = GPIO_OD_OUTPUT_HIGH; 146*91f16700Schasinglulu } 147*91f16700Schasinglulu } 148*91f16700Schasinglulu 149*91f16700Schasinglulu if (fdt_getprop(fdt, node, "output-low", NULL) != NULL) { 150*91f16700Schasinglulu if (mode == GPIO_MODE_INPUT) { 151*91f16700Schasinglulu mode = GPIO_MODE_OUTPUT; 152*91f16700Schasinglulu od = GPIO_OD_OUTPUT_LOW; 153*91f16700Schasinglulu } 154*91f16700Schasinglulu } 155*91f16700Schasinglulu 156*91f16700Schasinglulu bank_node = ckeck_gpio_bank(fdt, bank, pinctrl_node); 157*91f16700Schasinglulu if (bank_node == 0) { 158*91f16700Schasinglulu ERROR("PINCTRL inconsistent in DT\n"); 159*91f16700Schasinglulu panic(); 160*91f16700Schasinglulu } 161*91f16700Schasinglulu 162*91f16700Schasinglulu clk = fdt_get_clock_id(bank_node); 163*91f16700Schasinglulu if (clk < 0) { 164*91f16700Schasinglulu return -FDT_ERR_NOTFOUND; 165*91f16700Schasinglulu } 166*91f16700Schasinglulu 167*91f16700Schasinglulu /* Platform knows the clock: assert it is okay */ 168*91f16700Schasinglulu assert((unsigned long)clk == stm32_get_gpio_bank_clock(bank)); 169*91f16700Schasinglulu 170*91f16700Schasinglulu set_gpio(bank, pin, mode, type, speed, pull, od, alternate, status); 171*91f16700Schasinglulu } 172*91f16700Schasinglulu 173*91f16700Schasinglulu return 0; 174*91f16700Schasinglulu } 175*91f16700Schasinglulu 176*91f16700Schasinglulu /******************************************************************************* 177*91f16700Schasinglulu * This function gets the pin settings from DT information. 178*91f16700Schasinglulu * When analyze and parsing is done, set the GPIO registers. 179*91f16700Schasinglulu * Returns 0 on success and a negative FDT/ERRNO error code on failure. 180*91f16700Schasinglulu ******************************************************************************/ 181*91f16700Schasinglulu int dt_set_pinctrl_config(int node) 182*91f16700Schasinglulu { 183*91f16700Schasinglulu const fdt32_t *cuint; 184*91f16700Schasinglulu int lenp; 185*91f16700Schasinglulu uint32_t i; 186*91f16700Schasinglulu uint8_t status; 187*91f16700Schasinglulu void *fdt; 188*91f16700Schasinglulu 189*91f16700Schasinglulu if (fdt_get_address(&fdt) == 0) { 190*91f16700Schasinglulu return -FDT_ERR_NOTFOUND; 191*91f16700Schasinglulu } 192*91f16700Schasinglulu 193*91f16700Schasinglulu status = fdt_get_status(node); 194*91f16700Schasinglulu if (status == DT_DISABLED) { 195*91f16700Schasinglulu return -FDT_ERR_NOTFOUND; 196*91f16700Schasinglulu } 197*91f16700Schasinglulu 198*91f16700Schasinglulu cuint = fdt_getprop(fdt, node, "pinctrl-0", &lenp); 199*91f16700Schasinglulu if (cuint == NULL) { 200*91f16700Schasinglulu return -FDT_ERR_NOTFOUND; 201*91f16700Schasinglulu } 202*91f16700Schasinglulu 203*91f16700Schasinglulu for (i = 0; i < ((uint32_t)lenp / 4U); i++) { 204*91f16700Schasinglulu int p_node, p_subnode; 205*91f16700Schasinglulu 206*91f16700Schasinglulu p_node = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint)); 207*91f16700Schasinglulu if (p_node < 0) { 208*91f16700Schasinglulu return -FDT_ERR_NOTFOUND; 209*91f16700Schasinglulu } 210*91f16700Schasinglulu 211*91f16700Schasinglulu fdt_for_each_subnode(p_subnode, fdt, p_node) { 212*91f16700Schasinglulu int ret = dt_set_gpio_config(fdt, p_subnode, status); 213*91f16700Schasinglulu 214*91f16700Schasinglulu if (ret < 0) { 215*91f16700Schasinglulu return ret; 216*91f16700Schasinglulu } 217*91f16700Schasinglulu } 218*91f16700Schasinglulu 219*91f16700Schasinglulu cuint++; 220*91f16700Schasinglulu } 221*91f16700Schasinglulu 222*91f16700Schasinglulu return 0; 223*91f16700Schasinglulu } 224*91f16700Schasinglulu 225*91f16700Schasinglulu static void set_gpio(uint32_t bank, uint32_t pin, uint32_t mode, uint32_t type, 226*91f16700Schasinglulu uint32_t speed, uint32_t pull, uint32_t od, 227*91f16700Schasinglulu uint32_t alternate, uint8_t status) 228*91f16700Schasinglulu { 229*91f16700Schasinglulu uintptr_t base = stm32_get_gpio_bank_base(bank); 230*91f16700Schasinglulu unsigned long clock = stm32_get_gpio_bank_clock(bank); 231*91f16700Schasinglulu 232*91f16700Schasinglulu assert(pin <= GPIO_PIN_MAX); 233*91f16700Schasinglulu 234*91f16700Schasinglulu clk_enable(clock); 235*91f16700Schasinglulu 236*91f16700Schasinglulu mmio_clrsetbits_32(base + GPIO_MODE_OFFSET, 237*91f16700Schasinglulu (uint32_t)GPIO_MODE_MASK << (pin << 1U), 238*91f16700Schasinglulu mode << (pin << 1U)); 239*91f16700Schasinglulu 240*91f16700Schasinglulu mmio_clrsetbits_32(base + GPIO_TYPE_OFFSET, 241*91f16700Schasinglulu (uint32_t)GPIO_TYPE_MASK << pin, 242*91f16700Schasinglulu type << pin); 243*91f16700Schasinglulu 244*91f16700Schasinglulu mmio_clrsetbits_32(base + GPIO_SPEED_OFFSET, 245*91f16700Schasinglulu (uint32_t)GPIO_SPEED_MASK << (pin << 1U), 246*91f16700Schasinglulu speed << (pin << 1U)); 247*91f16700Schasinglulu 248*91f16700Schasinglulu mmio_clrsetbits_32(base + GPIO_PUPD_OFFSET, 249*91f16700Schasinglulu (uint32_t)GPIO_PULL_MASK << (pin << 1U), 250*91f16700Schasinglulu pull << (pin << 1U)); 251*91f16700Schasinglulu 252*91f16700Schasinglulu if (pin < GPIO_ALT_LOWER_LIMIT) { 253*91f16700Schasinglulu mmio_clrsetbits_32(base + GPIO_AFRL_OFFSET, 254*91f16700Schasinglulu (uint32_t)GPIO_ALTERNATE_MASK << (pin << 2U), 255*91f16700Schasinglulu alternate << (pin << 2U)); 256*91f16700Schasinglulu } else { 257*91f16700Schasinglulu uint32_t shift = (pin - GPIO_ALT_LOWER_LIMIT) << 2U; 258*91f16700Schasinglulu 259*91f16700Schasinglulu mmio_clrsetbits_32(base + GPIO_AFRH_OFFSET, 260*91f16700Schasinglulu (uint32_t)GPIO_ALTERNATE_MASK << shift, 261*91f16700Schasinglulu alternate << shift); 262*91f16700Schasinglulu } 263*91f16700Schasinglulu 264*91f16700Schasinglulu mmio_clrsetbits_32(base + GPIO_OD_OFFSET, 265*91f16700Schasinglulu (uint32_t)GPIO_OD_MASK << pin, 266*91f16700Schasinglulu od << pin); 267*91f16700Schasinglulu 268*91f16700Schasinglulu VERBOSE("GPIO %u mode set to 0x%x\n", bank, 269*91f16700Schasinglulu mmio_read_32(base + GPIO_MODE_OFFSET)); 270*91f16700Schasinglulu VERBOSE("GPIO %u type set to 0x%x\n", bank, 271*91f16700Schasinglulu mmio_read_32(base + GPIO_TYPE_OFFSET)); 272*91f16700Schasinglulu VERBOSE("GPIO %u speed set to 0x%x\n", bank, 273*91f16700Schasinglulu mmio_read_32(base + GPIO_SPEED_OFFSET)); 274*91f16700Schasinglulu VERBOSE("GPIO %u mode pull to 0x%x\n", bank, 275*91f16700Schasinglulu mmio_read_32(base + GPIO_PUPD_OFFSET)); 276*91f16700Schasinglulu VERBOSE("GPIO %u mode alternate low to 0x%x\n", bank, 277*91f16700Schasinglulu mmio_read_32(base + GPIO_AFRL_OFFSET)); 278*91f16700Schasinglulu VERBOSE("GPIO %u mode alternate high to 0x%x\n", bank, 279*91f16700Schasinglulu mmio_read_32(base + GPIO_AFRH_OFFSET)); 280*91f16700Schasinglulu VERBOSE("GPIO %u output data set to 0x%x\n", bank, 281*91f16700Schasinglulu mmio_read_32(base + GPIO_OD_OFFSET)); 282*91f16700Schasinglulu 283*91f16700Schasinglulu clk_disable(clock); 284*91f16700Schasinglulu 285*91f16700Schasinglulu if (status == DT_SECURE) { 286*91f16700Schasinglulu stm32mp_register_secure_gpio(bank, pin); 287*91f16700Schasinglulu #if !IMAGE_BL2 288*91f16700Schasinglulu set_gpio_secure_cfg(bank, pin, true); 289*91f16700Schasinglulu #endif 290*91f16700Schasinglulu 291*91f16700Schasinglulu } else { 292*91f16700Schasinglulu stm32mp_register_non_secure_gpio(bank, pin); 293*91f16700Schasinglulu #if !IMAGE_BL2 294*91f16700Schasinglulu set_gpio_secure_cfg(bank, pin, false); 295*91f16700Schasinglulu #endif 296*91f16700Schasinglulu } 297*91f16700Schasinglulu } 298*91f16700Schasinglulu 299*91f16700Schasinglulu void set_gpio_secure_cfg(uint32_t bank, uint32_t pin, bool secure) 300*91f16700Schasinglulu { 301*91f16700Schasinglulu uintptr_t base = stm32_get_gpio_bank_base(bank); 302*91f16700Schasinglulu unsigned long clock = stm32_get_gpio_bank_clock(bank); 303*91f16700Schasinglulu 304*91f16700Schasinglulu assert(pin <= GPIO_PIN_MAX); 305*91f16700Schasinglulu 306*91f16700Schasinglulu clk_enable(clock); 307*91f16700Schasinglulu 308*91f16700Schasinglulu if (secure) { 309*91f16700Schasinglulu mmio_setbits_32(base + GPIO_SECR_OFFSET, BIT(pin)); 310*91f16700Schasinglulu } else { 311*91f16700Schasinglulu mmio_clrbits_32(base + GPIO_SECR_OFFSET, BIT(pin)); 312*91f16700Schasinglulu } 313*91f16700Schasinglulu 314*91f16700Schasinglulu clk_disable(clock); 315*91f16700Schasinglulu } 316*91f16700Schasinglulu 317*91f16700Schasinglulu void set_gpio_reset_cfg(uint32_t bank, uint32_t pin) 318*91f16700Schasinglulu { 319*91f16700Schasinglulu set_gpio(bank, pin, GPIO_MODE_ANALOG, GPIO_TYPE_PUSH_PULL, 320*91f16700Schasinglulu GPIO_SPEED_LOW, GPIO_NO_PULL, GPIO_OD_OUTPUT_LOW, 321*91f16700Schasinglulu GPIO_ALTERNATE_(0), DT_DISABLED); 322*91f16700Schasinglulu set_gpio_secure_cfg(bank, pin, stm32_gpio_is_secure_at_reset(bank)); 323*91f16700Schasinglulu } 324