diff options
Diffstat (limited to 'board/st/stm32mp2/stm32mp2.c')
-rw-r--r-- | board/st/stm32mp2/stm32mp2.c | 140 |
1 files changed, 139 insertions, 1 deletions
diff --git a/board/st/stm32mp2/stm32mp2.c b/board/st/stm32mp2/stm32mp2.c index aa7dd31996e..2547f2e4bb7 100644 --- a/board/st/stm32mp2/stm32mp2.c +++ b/board/st/stm32mp2/stm32mp2.c @@ -5,16 +5,21 @@ #define LOG_CATEGORY LOGC_BOARD +#include <button.h> #include <config.h> -#include <env.h> +#include <env_internal.h> #include <fdt_support.h> +#include <led.h> #include <log.h> #include <misc.h> +#include <mmc.h> #include <asm/global_data.h> +#include <asm/io.h> #include <asm/arch/sys_proto.h> #include <dm/device.h> #include <dm/ofnode.h> #include <dm/uclass.h> +#include <linux/delay.h> /* * Get a global data pointer @@ -53,12 +58,140 @@ int checkboard(void) return 0; } +static int get_led(struct udevice **dev, char *led_string) +{ + const char *led_name; + int ret; + + led_name = ofnode_conf_read_str(led_string); + if (!led_name) { + log_debug("could not find %s config string\n", led_string); + return -ENOENT; + } + ret = led_get_by_label(led_name, dev); + if (ret) { + log_debug("get=%d\n", ret); + return ret; + } + + return 0; +} + +static int setup_led(enum led_state_t cmd) +{ + struct udevice *dev; + int ret; + + if (!CONFIG_IS_ENABLED(LED)) + return 0; + + ret = get_led(&dev, "u-boot,boot-led"); + if (ret) + return ret; + + ret = led_set_state(dev, cmd); + return ret; +} + +static void check_user_button(void) +{ + struct udevice *button; + int i; + + if (!IS_ENABLED(CONFIG_CMD_STM32PROG) || !IS_ENABLED(CONFIG_BUTTON)) + return; + + if (button_get_by_label("User-2", &button)) + return; + + for (i = 0; i < 21; ++i) { + if (button_get_state(button) != BUTTON_ON) + return; + if (i < 20) + mdelay(50); + } + + log_notice("entering download mode...\n"); + clrsetbits_le32(TAMP_BOOT_CONTEXT, TAMP_BOOT_FORCED_MASK, BOOT_STM32PROG); +} + /* board dependent setup after realloc */ int board_init(void) { + setup_led(LEDST_ON); + check_user_button(); + return 0; } +enum env_location env_get_location(enum env_operation op, int prio) +{ + u32 bootmode = get_bootmode(); + + if (prio) + return ENVL_UNKNOWN; + + switch (bootmode & TAMP_BOOT_DEVICE_MASK) { + case BOOT_FLASH_SD: + case BOOT_FLASH_EMMC: + if (CONFIG_IS_ENABLED(ENV_IS_IN_MMC)) + return ENVL_MMC; + else + return ENVL_NOWHERE; + + case BOOT_FLASH_NAND: + case BOOT_FLASH_SPINAND: + if (CONFIG_IS_ENABLED(ENV_IS_IN_UBI)) + return ENVL_UBI; + else + return ENVL_NOWHERE; + + case BOOT_FLASH_NOR: + if (CONFIG_IS_ENABLED(ENV_IS_IN_SPI_FLASH)) + return ENVL_SPI_FLASH; + else + return ENVL_NOWHERE; + default: + return ENVL_NOWHERE; + } +} + +int mmc_get_boot(void) +{ + struct udevice *dev; + u32 boot_mode = get_bootmode(); + unsigned int instance = (boot_mode & TAMP_BOOT_INSTANCE_MASK) - 1; + char cmd[20]; + const u32 sdmmc_addr[] = { + STM32_SDMMC1_BASE, + STM32_SDMMC2_BASE, + STM32_SDMMC3_BASE + }; + + if (instance > ARRAY_SIZE(sdmmc_addr)) + return 0; + + /* search associated sdmmc node in devicetree */ + snprintf(cmd, sizeof(cmd), "mmc@%x", sdmmc_addr[instance]); + if (uclass_get_device_by_name(UCLASS_MMC, cmd, &dev)) { + log_err("mmc%d = %s not found in device tree!\n", instance, cmd); + return 0; + } + + return dev_seq(dev); +}; + +int mmc_get_env_dev(void) +{ + const int mmc_env_dev = CONFIG_IS_ENABLED(ENV_IS_IN_MMC, (CONFIG_SYS_MMC_ENV_DEV), (-1)); + + if (mmc_env_dev >= 0) + return mmc_env_dev; + + /* use boot instance to select the correct mmc device identifier */ + return mmc_get_boot(); +} + int board_late_init(void) { const void *fdt_compat; @@ -86,3 +219,8 @@ int board_late_init(void) return 0; } + +void board_quiesce_devices(void) +{ + setup_led(LEDST_OFF); +} |