diff --git a/drivers/st/clk/stm32mp1_clkfunc.c b/drivers/st/clk/stm32mp1_clkfunc.c index e176f97d4d08f37b757d28e9eafcc1a530bdabe5..19dfe1b25417df5f9146157851edf2dcbd0d3819 100644 --- a/drivers/st/clk/stm32mp1_clkfunc.c +++ b/drivers/st/clk/stm32mp1_clkfunc.c @@ -31,6 +31,14 @@ const char *stm32mp_osc_node_label[NB_OSC] = { [_USB_PHY_48] = "ck_usbo_48m" }; +/******************************************************************************* + * This function returns the RCC node in the device tree. + ******************************************************************************/ +static int fdt_get_rcc_node(void *fdt) +{ + return fdt_node_offset_by_compatible(fdt, -1, DT_RCC_CLK_COMPAT); +} + /******************************************************************************* * This function reads the frequency of an oscillator from its name. * It reads the value indicated inside the device tree. @@ -240,7 +248,7 @@ int fdt_rcc_read_uint32_array(const char *prop_name, /******************************************************************************* * This function gets the subnode offset in rcc-clk section from its name. * It reads the values indicated inside the device tree. - * Returns offset if success, and a negative value else. + * Returns offset on success, and a negative FDT/ERRNO error code on failure. ******************************************************************************/ int fdt_rcc_subnode_offset(const char *name) { @@ -251,7 +259,7 @@ int fdt_rcc_subnode_offset(const char *name) return -ENOENT; } - node = fdt_node_offset_by_compatible(fdt, -1, DT_RCC_CLK_COMPAT); + node = fdt_get_rcc_node(fdt); if (node < 0) { return -FDT_ERR_NOTFOUND; } @@ -280,7 +288,7 @@ const fdt32_t *fdt_rcc_read_prop(const char *prop_name, int *lenp) return NULL; } - node = fdt_node_offset_by_compatible(fdt, -1, DT_RCC_CLK_COMPAT); + node = fdt_get_rcc_node(fdt); if (node < 0) { return NULL; } @@ -297,7 +305,7 @@ const fdt32_t *fdt_rcc_read_prop(const char *prop_name, int *lenp) /******************************************************************************* * This function gets the secure status for rcc node. * It reads secure-status in device tree. - * Returns 1 if rcc is available from secure world, 0 else. + * Returns true if rcc is available from secure world, false if not. ******************************************************************************/ bool fdt_get_rcc_secure_status(void) { @@ -308,18 +316,18 @@ bool fdt_get_rcc_secure_status(void) return false; } - node = fdt_node_offset_by_compatible(fdt, -1, DT_RCC_COMPAT); + node = fdt_get_rcc_node(fdt); if (node < 0) { return false; } - return fdt_check_secure_status(node); + return (fdt_get_status(node) & DT_SECURE) != 0U; } /******************************************************************************* * This function reads the stgen base address. * It reads the value indicated inside the device tree. - * Returns address if success, and NULL value else. + * Returns address on success, and NULL value on failure. ******************************************************************************/ uintptr_t fdt_get_stgen_base(void) { @@ -347,7 +355,7 @@ uintptr_t fdt_get_stgen_base(void) /******************************************************************************* * This function gets the clock ID of the given node. * It reads the value indicated inside the device tree. - * Returns ID if success, and a negative value else. + * Returns ID on success, and a negative FDT/ERRNO error code on failure. ******************************************************************************/ int fdt_get_clock_id(int node) { diff --git a/drivers/st/gpio/stm32_gpio.c b/drivers/st/gpio/stm32_gpio.c index bbee1387cb379560f6c40bba8c0b2acccfbf1943..d217c4501b6f8ca8d0b041211726440aff959b77 100644 --- a/drivers/st/gpio/stm32_gpio.c +++ b/drivers/st/gpio/stm32_gpio.c @@ -4,44 +4,212 @@ * SPDX-License-Identifier: BSD-3-Clause */ +#include <assert.h> +#include <errno.h> #include <stdbool.h> +#include <libfdt.h> + +#include <platform_def.h> + #include <common/bl_common.h> #include <common/debug.h> #include <drivers/st/stm32_gpio.h> +#include <drivers/st/stm32mp1_clk.h> +#include <drivers/st/stm32mp1_clkfunc.h> #include <lib/mmio.h> +#include <lib/utils_def.h> -static bool check_gpio(uint32_t bank, uint32_t pin) +#define DT_GPIO_BANK_SHIFT 12 +#define DT_GPIO_BANK_MASK GENMASK(16, 12) +#define DT_GPIO_PIN_SHIFT 8 +#define DT_GPIO_PIN_MASK GENMASK(11, 8) +#define DT_GPIO_MODE_MASK GENMASK(7, 0) + +/******************************************************************************* + * This function gets GPIO bank node in DT. + * Returns node offset if status is okay in DT, else return 0 + ******************************************************************************/ +static int ckeck_gpio_bank(void *fdt, uint32_t bank, int pinctrl_node) { - if (pin > GPIO_PIN_MAX) { - ERROR("%s: wrong pin number (%d)\n", __func__, pin); - return false; - } + int pinctrl_subnode; + uint32_t bank_offset = stm32_get_gpio_bank_offset(bank); - if ((bank > GPIO_BANK_K) && (bank != GPIO_BANK_Z)) { - ERROR("%s: wrong GPIO bank number (%d)\n", __func__, bank); - return false; + fdt_for_each_subnode(pinctrl_subnode, fdt, pinctrl_node) { + const fdt32_t *cuint; + + if (fdt_getprop(fdt, pinctrl_subnode, + "gpio-controller", NULL) == NULL) { + continue; + } + + cuint = fdt_getprop(fdt, pinctrl_subnode, "reg", NULL); + if (cuint == NULL) { + continue; + } + + if ((fdt32_to_cpu(*cuint) == bank_offset) && + (fdt_get_status(pinctrl_subnode) != DT_DISABLED)) { + return pinctrl_subnode; + } } - return true; + return 0; } -void set_gpio(uint32_t bank, uint32_t pin, uint32_t mode, uint32_t speed, - uint32_t pull, uint32_t alternate) +/******************************************************************************* + * This function gets the pin settings from DT information. + * When analyze and parsing is done, set the GPIO registers. + * Returns 0 on success and a negative FDT error code on failure. + ******************************************************************************/ +static int dt_set_gpio_config(void *fdt, int node, uint8_t status) { - uintptr_t base; + const fdt32_t *cuint, *slewrate; + int len; + int pinctrl_node; + uint32_t i; + uint32_t speed = GPIO_SPEED_LOW; + uint32_t pull = GPIO_NO_PULL; - if (!check_gpio(bank, pin)) { - return; + cuint = fdt_getprop(fdt, node, "pinmux", &len); + if (cuint == NULL) { + return -FDT_ERR_NOTFOUND; } - if (bank == GPIO_BANK_Z) { - base = STM32_GPIOZ_BANK; + pinctrl_node = fdt_parent_offset(fdt, fdt_parent_offset(fdt, node)); + if (pinctrl_node < 0) { + return -FDT_ERR_NOTFOUND; + } + + slewrate = fdt_getprop(fdt, node, "slew-rate", NULL); + if (slewrate != NULL) { + speed = fdt32_to_cpu(*slewrate); + } + + if (fdt_getprop(fdt, node, "bias-pull-up", NULL) != NULL) { + pull = GPIO_PULL_UP; + } else if (fdt_getprop(fdt, node, "bias-pull-down", NULL) != NULL) { + pull = GPIO_PULL_DOWN; } else { - base = STM32_GPIOA_BANK + - (bank * STM32_GPIO_BANK_OFFSET); + VERBOSE("No bias configured in node %d\n", node); } + for (i = 0U; i < ((uint32_t)len / sizeof(uint32_t)); i++) { + uint32_t pincfg; + uint32_t bank; + uint32_t pin; + uint32_t mode; + uint32_t alternate = GPIO_ALTERNATE_(0); + int bank_node; + int clk; + + pincfg = fdt32_to_cpu(*cuint); + cuint++; + + bank = (pincfg & DT_GPIO_BANK_MASK) >> DT_GPIO_BANK_SHIFT; + + pin = (pincfg & DT_GPIO_PIN_MASK) >> DT_GPIO_PIN_SHIFT; + + mode = pincfg & DT_GPIO_MODE_MASK; + + switch (mode) { + case 0: + mode = GPIO_MODE_INPUT; + break; + case 1 ... 16: + alternate = mode - 1U; + mode = GPIO_MODE_ALTERNATE; + break; + case 17: + mode = GPIO_MODE_ANALOG; + break; + default: + mode = GPIO_MODE_OUTPUT; + break; + } + + if (fdt_getprop(fdt, node, "drive-open-drain", NULL) != NULL) { + mode |= GPIO_OPEN_DRAIN; + } + + bank_node = ckeck_gpio_bank(fdt, bank, pinctrl_node); + if (bank_node == 0) { + ERROR("PINCTRL inconsistent in DT\n"); + panic(); + } + + clk = fdt_get_clock_id(bank_node); + if (clk < 0) { + return -FDT_ERR_NOTFOUND; + } + + /* Platform knows the clock: assert it is okay */ + assert((unsigned long)clk == stm32_get_gpio_bank_clock(bank)); + + set_gpio(bank, pin, mode, speed, pull, alternate, status); + } + + return 0; +} + +/******************************************************************************* + * This function gets the pin settings from DT information. + * When analyze and parsing is done, set the GPIO registers. + * Returns 0 on success and a negative FDT/ERRNO error code on failure. + ******************************************************************************/ +int dt_set_pinctrl_config(int node) +{ + const fdt32_t *cuint; + int lenp = 0; + uint32_t i; + uint8_t status = fdt_get_status(node); + void *fdt; + + if (fdt_get_address(&fdt) == 0) { + return -ENOENT; + } + + if (status == DT_DISABLED) { + return -FDT_ERR_NOTFOUND; + } + + cuint = fdt_getprop(fdt, node, "pinctrl-0", &lenp); + if (cuint == NULL) { + return -FDT_ERR_NOTFOUND; + } + + for (i = 0; i < ((uint32_t)lenp / 4U); i++) { + int p_node, p_subnode; + + p_node = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint)); + if (p_node < 0) { + return -FDT_ERR_NOTFOUND; + } + + fdt_for_each_subnode(p_subnode, fdt, p_node) { + int ret = dt_set_gpio_config(fdt, p_subnode, status); + + if (ret < 0) { + return ret; + } + } + + cuint++; + } + + return 0; +} + +void set_gpio(uint32_t bank, uint32_t pin, uint32_t mode, uint32_t speed, + uint32_t pull, uint32_t alternate, uint8_t status) +{ + uintptr_t base = stm32_get_gpio_bank_base(bank); + unsigned long clock = stm32_get_gpio_bank_clock(bank); + + assert(pin <= GPIO_PIN_MAX); + + stm32mp1_clk_enable(clock); + mmio_clrbits_32(base + GPIO_MODE_OFFSET, ((uint32_t)GPIO_MODE_MASK << (pin << 1))); mmio_setbits_32(base + GPIO_MODE_OFFSET, @@ -85,4 +253,24 @@ void set_gpio(uint32_t bank, uint32_t pin, uint32_t mode, uint32_t speed, mmio_read_32(base + GPIO_AFRL_OFFSET)); VERBOSE("GPIO %u mode alternate high to 0x%x\n", bank, mmio_read_32(base + GPIO_AFRH_OFFSET)); + + stm32mp1_clk_disable((unsigned long)clock); +} + +void set_gpio_secure_cfg(uint32_t bank, uint32_t pin, bool secure) +{ + uintptr_t base = stm32_get_gpio_bank_base(bank); + int clock = stm32_get_gpio_bank_clock(bank); + + assert(pin <= GPIO_PIN_MAX); + + stm32mp1_clk_enable((unsigned long)clock); + + if (secure) { + mmio_setbits_32(base + GPIO_SECR_OFFSET, BIT(pin)); + } else { + mmio_clrbits_32(base + GPIO_SECR_OFFSET, BIT(pin)); + } + + stm32mp1_clk_disable((unsigned long)clock); } diff --git a/drivers/st/mmc/stm32_sdmmc2.c b/drivers/st/mmc/stm32_sdmmc2.c index 453455cd91f2bedc3854fd3ff405ca87ecd7f36f..57812d89930b54e40b7b1f79f636570356bda8a4 100644 --- a/drivers/st/mmc/stm32_sdmmc2.c +++ b/drivers/st/mmc/stm32_sdmmc2.c @@ -17,6 +17,7 @@ #include <common/debug.h> #include <drivers/delay_timer.h> #include <drivers/mmc.h> +#include <drivers/st/stm32_gpio.h> #include <drivers/st/stm32_sdmmc2.h> #include <drivers/st/stm32mp1_clk.h> #include <drivers/st/stm32mp1_rcc.h> @@ -642,7 +643,7 @@ static int stm32_sdmmc2_dt_get_config(void) return -FDT_ERR_NOTFOUND; } - if (fdt_check_status(sdmmc_node) == 0) { + if (fdt_get_status(sdmmc_node) == DT_DISABLED) { return -FDT_ERR_NOTFOUND; } diff --git a/drivers/st/pmic/stm32mp_pmic.c b/drivers/st/pmic/stm32mp_pmic.c index 80b4cab500bee4e3adad62a5f0a855bbc92e984d..6beabc15360f7a1853947af2143f88c36fe66761 100644 --- a/drivers/st/pmic/stm32mp_pmic.c +++ b/drivers/st/pmic/stm32mp_pmic.c @@ -61,7 +61,7 @@ bool dt_check_pmic(void) return false; } - return fdt_check_status(node); + return fdt_get_status(node); } static int dt_pmic_i2c_config(struct dt_node_info *i2c_info) diff --git a/include/drivers/st/stm32_gpio.h b/include/drivers/st/stm32_gpio.h index 4fb27e0552ea9cc75c9b27bc239cff306f8b2423..4320eafcdaf07c8458a00c3928fb5c8fe3f9aaad 100644 --- a/include/drivers/st/stm32_gpio.h +++ b/include/drivers/st/stm32_gpio.h @@ -9,10 +9,6 @@ #include <lib/utils_def.h> -#define STM32_GPIOA_BANK U(0x50002000) -#define STM32_GPIOZ_BANK U(0x54004000) -#define STM32_GPIO_BANK_OFFSET U(0x1000) - #define GPIO_MODE_OFFSET U(0x00) #define GPIO_TYPE_OFFSET U(0x04) #define GPIO_SPEED_OFFSET U(0x08) @@ -20,56 +16,14 @@ #define GPIO_BSRR_OFFSET U(0x18) #define GPIO_AFRL_OFFSET U(0x20) #define GPIO_AFRH_OFFSET U(0x24) +#define GPIO_SECR_OFFSET U(0x30) #define GPIO_ALT_LOWER_LIMIT U(0x08) -#define GPIO_BANK_A U(0x00) -#define GPIO_BANK_B U(0x01) -#define GPIO_BANK_C U(0x02) -#define GPIO_BANK_D U(0x03) -#define GPIO_BANK_E U(0x04) -#define GPIO_BANK_F U(0x05) -#define GPIO_BANK_G U(0x06) -#define GPIO_BANK_H U(0x07) -#define GPIO_BANK_I U(0x08) -#define GPIO_BANK_J U(0x09) -#define GPIO_BANK_K U(0x0A) -#define GPIO_BANK_Z U(0x19) - -#define GPIO_PIN_0 U(0x00) -#define GPIO_PIN_1 U(0x01) -#define GPIO_PIN_2 U(0x02) -#define GPIO_PIN_3 U(0x03) -#define GPIO_PIN_4 U(0x04) -#define GPIO_PIN_5 U(0x05) -#define GPIO_PIN_6 U(0x06) -#define GPIO_PIN_7 U(0x07) -#define GPIO_PIN_8 U(0x08) -#define GPIO_PIN_9 U(0x09) -#define GPIO_PIN_10 U(0x0A) -#define GPIO_PIN_11 U(0x0B) -#define GPIO_PIN_12 U(0x0C) -#define GPIO_PIN_13 U(0x0D) -#define GPIO_PIN_14 U(0x0E) -#define GPIO_PIN_15 U(0x0F) -#define GPIO_PIN_MAX GPIO_PIN_15 +#define GPIO_PIN_(_x) U(_x) +#define GPIO_PIN_MAX GPIO_PIN_(15) -#define GPIO_ALTERNATE_0 0x00 -#define GPIO_ALTERNATE_1 0x01 -#define GPIO_ALTERNATE_2 0x02 -#define GPIO_ALTERNATE_3 0x03 -#define GPIO_ALTERNATE_4 0x04 -#define GPIO_ALTERNATE_5 0x05 -#define GPIO_ALTERNATE_6 0x06 -#define GPIO_ALTERNATE_7 0x07 -#define GPIO_ALTERNATE_8 0x08 -#define GPIO_ALTERNATE_9 0x09 -#define GPIO_ALTERNATE_10 0x0A -#define GPIO_ALTERNATE_11 0x0B -#define GPIO_ALTERNATE_12 0x0C -#define GPIO_ALTERNATE_13 0x0D -#define GPIO_ALTERNATE_14 0x0E -#define GPIO_ALTERNATE_15 0x0F +#define GPIO_ALTERNATE_(_x) U(_x) #define GPIO_ALTERNATE_MASK U(0x0F) #define GPIO_MODE_INPUT 0x00 @@ -94,8 +48,10 @@ #ifndef __ASSEMBLY__ #include <stdint.h> +int dt_set_pinctrl_config(int node); void set_gpio(uint32_t bank, uint32_t pin, uint32_t mode, uint32_t speed, - uint32_t pull, uint32_t alternate); + uint32_t pull, uint32_t alternate, uint8_t status); +void set_gpio_secure_cfg(uint32_t bank, uint32_t pin, bool secure); #endif /*__ASSEMBLY__*/ #endif /* STM32_GPIO_H */ diff --git a/plat/st/stm32mp1/include/stm32mp1_dt.h b/plat/st/stm32mp1/include/stm32mp1_dt.h index 19549ee9767b2b8b3323f81586b660ad8f025123..d5640c1fd5607c229dd397d26882c83d1f9f2bb3 100644 --- a/plat/st/stm32mp1/include/stm32mp1_dt.h +++ b/plat/st/stm32mp1/include/stm32mp1_dt.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -9,12 +9,16 @@ #include <stdbool.h> +#define DT_DISABLED U(0) +#define DT_NON_SECURE U(1) +#define DT_SECURE U(2) +#define DT_SHARED (DT_NON_SECURE | DT_SECURE) + struct dt_node_info { uint32_t base; int32_t clock; int32_t reset; - bool status; - bool sec_status; + uint32_t status; }; /******************************************************************************* @@ -23,13 +27,11 @@ struct dt_node_info { int dt_open_and_check(void); int fdt_get_address(void **fdt_addr); bool fdt_check_node(int node); -bool fdt_check_status(int node); -bool fdt_check_secure_status(int node); +uint32_t fdt_get_status(int node); uint32_t fdt_read_uint32_default(int node, const char *prop_name, uint32_t dflt_value); int fdt_read_uint32_array(int node, const char *prop_name, uint32_t *array, uint32_t count); -int dt_set_pinctrl_config(int node); int dt_set_stdout_pinctrl(void); void dt_fill_device_info(struct dt_node_info *info, int node); int dt_get_node(struct dt_node_info *info, int offset, const char *compat); diff --git a/plat/st/stm32mp1/include/stm32mp1_private.h b/plat/st/stm32mp1/include/stm32mp1_private.h index 3404bc685037fa0826b4daf30bb8207e753bfd6f..04c9a9ad5fb566230eb23d1ca1bf8d97d768b1af 100644 --- a/plat/st/stm32mp1/include/stm32mp1_private.h +++ b/plat/st/stm32mp1/include/stm32mp1_private.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -21,4 +21,8 @@ uintptr_t stm32mp1_get_boot_ctx_address(void); void stm32mp1_gic_pcpu_init(void); void stm32mp1_gic_init(void); +uintptr_t stm32_get_gpio_bank_base(unsigned int bank); +unsigned long stm32_get_gpio_bank_clock(unsigned int bank); +uint32_t stm32_get_gpio_bank_offset(unsigned int bank); + #endif /* STM32MP1_PRIVATE_H */ diff --git a/plat/st/stm32mp1/sp_min/sp_min_setup.c b/plat/st/stm32mp1/sp_min/sp_min_setup.c index bff45f68801722899c0114f1cac24f749ad3b893..a0bdbf681fba05beb2fd79201cb9ca08f366ab82 100644 --- a/plat/st/stm32mp1/sp_min/sp_min_setup.c +++ b/plat/st/stm32mp1/sp_min/sp_min_setup.c @@ -117,7 +117,7 @@ void sp_min_early_platform_setup2(u_register_t arg0, u_register_t arg1, result = dt_get_stdout_uart_info(&dt_uart_info); - if ((result > 0) && dt_uart_info.status) { + if ((result > 0) && (dt_uart_info.status != 0U)) { if (console_stm32_register(dt_uart_info.base, 0, STM32MP1_UART_BAUDRATE, &console) == 0) { diff --git a/plat/st/stm32mp1/stm32mp1_common.c b/plat/st/stm32mp1/stm32mp1_common.c index de8cc78ccbeb297407530f0a54202cbecbb17fb6..cd93d2eef7a3e3ff29652e195be395f0eebeec94 100644 --- a/plat/st/stm32mp1/stm32mp1_common.c +++ b/plat/st/stm32mp1/stm32mp1_common.c @@ -12,6 +12,7 @@ #include <common/bl_common.h> #include <common/debug.h> #include <drivers/arm/gicv2.h> +#include <dt-bindings/clock/stm32mp1-clks.h> #include <lib/mmio.h> #include <lib/xlat_tables/xlat_tables_v2.h> #include <plat/common/platform.h> @@ -86,3 +87,37 @@ uintptr_t stm32mp1_get_boot_ctx_address(void) { return boot_ctx_address; } + +uintptr_t stm32_get_gpio_bank_base(unsigned int bank) +{ + switch (bank) { + case GPIO_BANK_A ... GPIO_BANK_K: + return GPIOA_BASE + (bank * GPIO_BANK_OFFSET); + case GPIO_BANK_Z: + return GPIOZ_BASE; + default: + panic(); + } +} + +/* Return clock ID on success, negative value on error */ +unsigned long stm32_get_gpio_bank_clock(unsigned int bank) +{ + switch (bank) { + case GPIO_BANK_A ... GPIO_BANK_K: + return GPIOA + (bank - GPIO_BANK_A); + case GPIO_BANK_Z: + return GPIOZ; + default: + panic(); + } +} + +uint32_t stm32_get_gpio_bank_offset(unsigned int bank) +{ + if (bank == GPIO_BANK_Z) { + return 0; + } else { + return bank * GPIO_BANK_OFFSET; + } +} diff --git a/plat/st/stm32mp1/stm32mp1_def.h b/plat/st/stm32mp1/stm32mp1_def.h index 25a953da36eb4966361b7911d51a07608f8c0b37..0dd721571153656891e74c9a18b9a1deeafff786 100644 --- a/plat/st/stm32mp1/stm32mp1_def.h +++ b/plat/st/stm32mp1/stm32mp1_def.h @@ -111,6 +111,39 @@ enum ddr_type { ******************************************************************************/ #define PWR_BASE U(0x50001000) +/******************************************************************************* + * STM32MP1 GPIO + ******************************************************************************/ +#define GPIOA_BASE U(0x50002000) +#define GPIOB_BASE U(0x50003000) +#define GPIOC_BASE U(0x50004000) +#define GPIOD_BASE U(0x50005000) +#define GPIOE_BASE U(0x50006000) +#define GPIOF_BASE U(0x50007000) +#define GPIOG_BASE U(0x50008000) +#define GPIOH_BASE U(0x50009000) +#define GPIOI_BASE U(0x5000A000) +#define GPIOJ_BASE U(0x5000B000) +#define GPIOK_BASE U(0x5000C000) +#define GPIOZ_BASE U(0x54004000) +#define GPIO_BANK_OFFSET U(0x1000) + +/* Bank IDs used in GPIO driver API */ +#define GPIO_BANK_A U(0) +#define GPIO_BANK_B U(1) +#define GPIO_BANK_C U(2) +#define GPIO_BANK_D U(3) +#define GPIO_BANK_E U(4) +#define GPIO_BANK_F U(5) +#define GPIO_BANK_G U(6) +#define GPIO_BANK_H U(7) +#define GPIO_BANK_I U(8) +#define GPIO_BANK_J U(9) +#define GPIO_BANK_K U(10) +#define GPIO_BANK_Z U(25) + +#define STM32MP_GPIOZ_PIN_MAX_COUNT 8 + /******************************************************************************* * STM32MP1 UART ******************************************************************************/ @@ -122,8 +155,21 @@ enum ddr_type { #define USART6_BASE U(0x44003000) #define UART7_BASE U(0x40018000) #define UART8_BASE U(0x40019000) +#define STM32MP1_UART_BAUDRATE U(115200) + +/* For UART crash console */ #define STM32MP1_DEBUG_USART_BASE UART4_BASE -#define STM32MP1_UART_BAUDRATE 115200 +/* UART4 on HSI@64MHz, TX on GPIOG11 Alternate 6 */ +#define STM32MP1_DEBUG_USART_CLK_FRQ 64000000 +#define DEBUG_UART_TX_GPIO_BANK_ADDRESS GPIOG_BASE +#define DEBUG_UART_TX_GPIO_BANK_CLK_REG RCC_MP_AHB4ENSETR +#define DEBUG_UART_TX_GPIO_BANK_CLK_EN RCC_MP_AHB4ENSETR_GPIOGEN +#define DEBUG_UART_TX_GPIO_PORT 11 +#define DEBUG_UART_TX_GPIO_ALTERNATE 6 +#define DEBUG_UART_TX_CLKSRC_REG RCC_UART24CKSELR +#define DEBUG_UART_TX_CLKSRC RCC_UART24CKSELR_HSI +#define DEBUG_UART_TX_EN_REG RCC_MP_APB1ENSETR +#define DEBUG_UART_TX_EN RCC_MP_APB1ENSETR_UART4EN /******************************************************************************* * STM32MP1 TZC (TZ400) diff --git a/plat/st/stm32mp1/stm32mp1_dt.c b/plat/st/stm32mp1/stm32mp1_dt.c index 29e936aff8d71cb1f39dbcc0e976e2a0f65d544b..8493b87864c21721a23085313826d2531cb3ba4d 100644 --- a/plat/st/stm32mp1/stm32mp1_dt.c +++ b/plat/st/stm32mp1/stm32mp1_dt.c @@ -1,10 +1,11 @@ /* - * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ #include <assert.h> +#include <errno.h> #include <libfdt.h> @@ -17,135 +18,13 @@ #include <drivers/st/stm32mp1_ddr.h> #include <drivers/st/stm32mp1_ram.h> -#include <stm32mp1_dt.h> - -#define DT_GPIO_BANK_SHIFT 12 -#define DT_GPIO_BANK_MASK 0x1F000U -#define DT_GPIO_PIN_SHIFT 8 -#define DT_GPIO_PIN_MASK 0xF00U -#define DT_GPIO_MODE_MASK 0xFFU - static int fdt_checked; static void *fdt = (void *)(uintptr_t)STM32MP1_DTB_BASE; -/******************************************************************************* - * This function gets the pin settings from DT information. - * When analyze and parsing is done, set the GPIO registers. - * Return 0 on success, else return a negative FDT_ERR_xxx error code. - ******************************************************************************/ -static int dt_set_gpio_config(int node) -{ - const fdt32_t *cuint, *slewrate; - int len, pinctrl_node, pinctrl_subnode; - uint32_t i; - uint32_t speed = GPIO_SPEED_LOW; - uint32_t pull = GPIO_NO_PULL; - - cuint = fdt_getprop(fdt, node, "pinmux", &len); - if (cuint == NULL) { - return -FDT_ERR_NOTFOUND; - } - - pinctrl_node = fdt_parent_offset(fdt, fdt_parent_offset(fdt, node)); - if (pinctrl_node < 0) { - return -FDT_ERR_NOTFOUND; - } - - slewrate = fdt_getprop(fdt, node, "slew-rate", NULL); - if (slewrate != NULL) { - speed = fdt32_to_cpu(*slewrate); - } - - if (fdt_getprop(fdt, node, "bias-pull-up", NULL) != NULL) { - pull = GPIO_PULL_UP; - } else if (fdt_getprop(fdt, node, "bias-pull-down", NULL) != NULL) { - pull = GPIO_PULL_DOWN; - } else { - VERBOSE("No bias configured in node %d\n", node); - } - - for (i = 0; i < ((uint32_t)len / sizeof(uint32_t)); i++) { - uint32_t pincfg; - uint32_t bank; - uint32_t pin; - uint32_t mode; - uint32_t alternate = GPIO_ALTERNATE_0; - - pincfg = fdt32_to_cpu(*cuint); - cuint++; - - bank = (pincfg & DT_GPIO_BANK_MASK) >> DT_GPIO_BANK_SHIFT; - - pin = (pincfg & DT_GPIO_PIN_MASK) >> DT_GPIO_PIN_SHIFT; - - mode = pincfg & DT_GPIO_MODE_MASK; - - switch (mode) { - case 0: - mode = GPIO_MODE_INPUT; - break; - case 1 ... 16: - alternate = mode - 1U; - mode = GPIO_MODE_ALTERNATE; - break; - case 17: - mode = GPIO_MODE_ANALOG; - break; - default: - mode = GPIO_MODE_OUTPUT; - break; - } - - if (fdt_getprop(fdt, node, "drive-open-drain", NULL) != NULL) { - mode |= GPIO_OPEN_DRAIN; - } - - fdt_for_each_subnode(pinctrl_subnode, fdt, pinctrl_node) { - uint32_t bank_offset; - const fdt32_t *cuint2; - - if (fdt_getprop(fdt, pinctrl_subnode, - "gpio-controller", NULL) == NULL) { - continue; - } - - cuint2 = fdt_getprop(fdt, pinctrl_subnode, "reg", NULL); - if (cuint2 == NULL) { - continue; - } - - if (bank == GPIO_BANK_Z) { - bank_offset = 0; - } else { - bank_offset = bank * STM32_GPIO_BANK_OFFSET; - } - - if (fdt32_to_cpu(*cuint2) == bank_offset) { - int clk_id = fdt_get_clock_id(pinctrl_subnode); - - if (clk_id < 0) { - return -FDT_ERR_NOTFOUND; - } - - if (stm32mp1_clk_enable((unsigned long)clk_id) < - 0) { - return -FDT_ERR_BADVALUE; - } - - break; - } - } - - set_gpio(bank, pin, mode, speed, pull, alternate); - } - - return 0; -} - /******************************************************************************* * This function checks device tree file with its header. - * Returns 0 if success, and a negative value else. + * Returns 0 on success and a negative FDT error code on failure. ******************************************************************************/ int dt_open_and_check(void) { @@ -174,7 +53,7 @@ int fdt_get_address(void **fdt_addr) /******************************************************************************* * This function check the presence of a node (generic use of fdt library). - * Returns true if present, false else. + * Returns true if present, else return false. ******************************************************************************/ bool fdt_check_node(int node) { @@ -187,37 +66,30 @@ bool fdt_check_node(int node) } /******************************************************************************* - * This function check the status of a node (generic use of fdt library). - * Returns true if "okay" or missing, false else. + * This function return global node status (generic use of fdt library). ******************************************************************************/ -bool fdt_check_status(int node) +uint32_t fdt_get_status(int node) { + uint32_t status = DT_DISABLED; int len; const char *cchar; cchar = fdt_getprop(fdt, node, "status", &len); - if (cchar == NULL) { - return true; + if ((cchar == NULL) || + (strncmp(cchar, "okay", (size_t)len) == 0)) { + status |= DT_NON_SECURE; } - return strncmp(cchar, "okay", (size_t)len) == 0; -} - -/******************************************************************************* - * This function check the secure-status of a node (generic use of fdt library). - * Returns true if "okay" or missing, false else. - ******************************************************************************/ -bool fdt_check_secure_status(int node) -{ - int len; - const char *cchar; - cchar = fdt_getprop(fdt, node, "secure-status", &len); if (cchar == NULL) { - return true; + if (status == DT_NON_SECURE) { + status |= DT_SECURE; + } + } else if (strncmp(cchar, "okay", (size_t)len) == 0) { + status |= DT_SECURE; } - return strncmp(cchar, "okay", (size_t)len) == 0; + return status; } /******************************************************************************* @@ -245,7 +117,7 @@ uint32_t fdt_read_uint32_default(int node, const char *prop_name, * (generic use of fdt library). * It reads the values inside the device tree, from property name and node. * The number of parameters is also indicated as entry parameter. - * Returns 0 if success, and a negative value else. + * Returns 0 on success and a negative FDT error code on failure. * If success, values are stored at the third parameter address. ******************************************************************************/ int fdt_read_uint32_array(int node, const char *prop_name, uint32_t *array, @@ -273,53 +145,10 @@ int fdt_read_uint32_array(int node, const char *prop_name, uint32_t *array, return 0; } -/******************************************************************************* - * This function gets the pin settings from DT information. - * When analyze and parsing is done, set the GPIO registers. - * Returns 0 if success, and a negative value else. - ******************************************************************************/ -int dt_set_pinctrl_config(int node) -{ - const fdt32_t *cuint; - int lenp = 0; - uint32_t i; - - if (!fdt_check_status(node)) { - return -FDT_ERR_NOTFOUND; - } - - cuint = fdt_getprop(fdt, node, "pinctrl-0", &lenp); - if (cuint == NULL) { - return -FDT_ERR_NOTFOUND; - } - - for (i = 0; i < ((uint32_t)lenp / 4U); i++) { - int phandle_node, phandle_subnode; - - phandle_node = - fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint)); - if (phandle_node < 0) { - return -FDT_ERR_NOTFOUND; - } - - fdt_for_each_subnode(phandle_subnode, fdt, phandle_node) { - int ret = dt_set_gpio_config(phandle_subnode); - - if (ret < 0) { - return ret; - } - } - - cuint++; - } - - return 0; -} - /******************************************************************************* * This function gets the stdout pin configuration information from the DT. * And then calls the sub-function to treat it and set GPIO registers. - * Returns 0 if success, and a negative value else. + * Returns 0 on success and a negative FDT error code on failure. ******************************************************************************/ int dt_set_stdout_pinctrl(void) { @@ -363,13 +192,12 @@ void dt_fill_device_info(struct dt_node_info *info, int node) info->reset = -1; } - info->status = fdt_check_status(node); - info->sec_status = fdt_check_secure_status(node); + info->status = fdt_get_status(node); } /******************************************************************************* * This function retrieve the generic information from DT. - * Returns node if success, and a negative value else. + * Returns node on success and a negative FDT error code on failure. ******************************************************************************/ int dt_get_node(struct dt_node_info *info, int offset, const char *compat) { @@ -387,7 +215,7 @@ int dt_get_node(struct dt_node_info *info, int offset, const char *compat) /******************************************************************************* * This function gets the UART instance info of stdout from the DT. - * Returns node if success, and a negative value else. + * Returns node on success and a negative FDT error code on failure. ******************************************************************************/ int dt_get_stdout_uart_info(struct dt_node_info *info) { @@ -448,7 +276,7 @@ int dt_get_stdout_node_offset(void) /******************************************************************************* * This function gets DDR size information from the DT. - * Returns value in bytes if success, and STM32MP1_DDR_SIZE_DFLT else. + * Returns value in bytes on success, and 0 on failure. ******************************************************************************/ uint32_t dt_get_ddr_size(void) { @@ -457,11 +285,10 @@ uint32_t dt_get_ddr_size(void) node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT); if (node < 0) { INFO("%s: Cannot read DDR node in DT\n", __func__); - return STM32MP1_DDR_SIZE_DFLT; + return 0; } - return fdt_read_uint32_default(node, "st,mem-size", - STM32MP1_DDR_SIZE_DFLT); + return fdt_read_uint32_default(node, "st,mem-size", 0); } /******************************************************************************* diff --git a/plat/st/stm32mp1/stm32mp1_helper.S b/plat/st/stm32mp1/stm32mp1_helper.S index 61c587f4f1d0e899701cbe1d7258c5f22d3bdd21..8c2e1b6ea3ea10cb26b72b20d5195728fd7398f1 100644 --- a/plat/st/stm32mp1/stm32mp1_helper.S +++ b/plat/st/stm32mp1/stm32mp1_helper.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -12,11 +12,8 @@ #include <drivers/st/stm32_gpio.h> #include <drivers/st/stm32mp1_rcc.h> -#define GPIO_BANK_G_ADDRESS 0x50008000 -#define GPIO_TX_PORT 11 -#define GPIO_TX_SHIFT (GPIO_TX_PORT << 1) -#define GPIO_TX_ALT_SHIFT ((GPIO_TX_PORT - GPIO_ALT_LOWER_LIMIT) << 2) -#define STM32MP1_HSI_CLK 64000000 +#define GPIO_TX_SHIFT (DEBUG_UART_TX_GPIO_PORT << 1) +#define GPIO_TX_ALT_SHIFT ((DEBUG_UART_TX_GPIO_PORT - GPIO_ALT_LOWER_LIMIT) << 2) .globl platform_mem_init .globl plat_report_exception @@ -112,13 +109,13 @@ endfunc plat_my_core_pos * --------------------------------------------- */ func plat_crash_console_init - /* Enable GPIOs for UART4 TX */ - ldr r1, =(RCC_BASE + RCC_MP_AHB4ENSETR) + /* Enable GPIOs for UART TX */ + ldr r1, =(RCC_BASE + DEBUG_UART_TX_GPIO_BANK_CLK_REG) ldr r2, [r1] - /* Configure GPIO G11 */ - orr r2, r2, #RCC_MP_AHB4ENSETR_GPIOGEN + /* Configure GPIO */ + orr r2, r2, #DEBUG_UART_TX_GPIO_BANK_CLK_EN str r2, [r1] - ldr r1, =GPIO_BANK_G_ADDRESS + ldr r1, =DEBUG_UART_TX_GPIO_BANK_ADDRESS /* Set GPIO mode alternate */ ldr r2, [r1, #GPIO_MODE_OFFSET] bic r2, r2, #(GPIO_MODE_MASK << GPIO_TX_SHIFT) @@ -132,23 +129,22 @@ func plat_crash_console_init ldr r2, [r1, #GPIO_PUPD_OFFSET] bic r2, r2, #(GPIO_PULL_MASK << GPIO_TX_SHIFT) str r2, [r1, #GPIO_PUPD_OFFSET] - /* Set alternate AF6 */ + /* Set alternate */ ldr r2, [r1, #GPIO_AFRH_OFFSET] bic r2, r2, #(GPIO_ALTERNATE_MASK << GPIO_TX_ALT_SHIFT) - orr r2, r2, #(GPIO_ALTERNATE_6 << GPIO_TX_ALT_SHIFT) + orr r2, r2, #(DEBUG_UART_TX_GPIO_ALTERNATE << GPIO_TX_ALT_SHIFT) str r2, [r1, #GPIO_AFRH_OFFSET] - - /* Enable UART clock, with HSI source */ - ldr r1, =(RCC_BASE + RCC_UART24CKSELR) - mov r2, #RCC_UART24CKSELR_HSI + /* Enable UART clock, with its source */ + ldr r1, =(RCC_BASE + DEBUG_UART_TX_CLKSRC_REG) + mov r2, #DEBUG_UART_TX_CLKSRC str r2, [r1] - ldr r1, =(RCC_BASE + RCC_MP_APB1ENSETR) + ldr r1, =(RCC_BASE + DEBUG_UART_TX_EN_REG) ldr r2, [r1] - orr r2, r2, #RCC_MP_APB1ENSETR_UART4EN + orr r2, r2, #DEBUG_UART_TX_EN str r2, [r1] ldr r0, =STM32MP1_DEBUG_USART_BASE - ldr r1, =STM32MP1_HSI_CLK + ldr r1, =STM32MP1_DEBUG_USART_CLK_FRQ ldr r2, =STM32MP1_UART_BAUDRATE b console_stm32_core_init endfunc plat_crash_console_init