X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=arch%2Farm%2Fmach-rockchip%2Frk3399-board-spl.c;h=2333694caa0b7a5a3800b2dcc763044cffeb1be7;hb=1e72a757bb32e3ccc4fe5d23baaa6d19b3760a1e;hp=34061564478d165742f3f1abc719f017e77e7014;hpb=975f97b43181694041f77ecd8118364afe588144;p=oweals%2Fu-boot.git diff --git a/arch/arm/mach-rockchip/rk3399-board-spl.c b/arch/arm/mach-rockchip/rk3399-board-spl.c index 3406156447..2333694caa 100644 --- a/arch/arm/mach-rockchip/rk3399-board-spl.c +++ b/arch/arm/mach-rockchip/rk3399-board-spl.c @@ -1,32 +1,112 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * (C) Copyright 2016 Rockchip Electronics Co., Ltd - * - * SPDX-License-Identifier: GPL-2.0+ + * (C) Copyright 2017 Theobroma Systems Design und Consulting GmbH */ #include -#include -#include -#include -#include -#include #include #include -#include #include #include +#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void board_return_to_bootrom(void) +{ + back_to_bootrom(BROM_BOOT_NEXTSTAGE); +} + +static const char * const boot_devices[BROM_LAST_BOOTSOURCE + 1] = { + [BROM_BOOTSOURCE_EMMC] = "/sdhci@fe330000", + [BROM_BOOTSOURCE_SPINOR] = "/spi@ff1d0000", + [BROM_BOOTSOURCE_SD] = "/dwmmc@fe320000", +}; + +const char *board_spl_was_booted_from(void) +{ + u32 bootdevice_brom_id = readl(RK3399_BROM_BOOTSOURCE_ID_ADDR); + const char *bootdevice_ofpath = NULL; -DECLARE_GLOBAL_DATA_PTR; + if (bootdevice_brom_id < ARRAY_SIZE(boot_devices)) + bootdevice_ofpath = boot_devices[bootdevice_brom_id]; + + if (bootdevice_ofpath) + debug("%s: brom_bootdevice_id %x maps to '%s'\n", + __func__, bootdevice_brom_id, bootdevice_ofpath); + else + debug("%s: failed to resolve brom_bootdevice_id %x\n", + __func__, bootdevice_brom_id); + + return bootdevice_ofpath; +} u32 spl_boot_device(void) { - return BOOT_DEVICE_MMC1; + u32 boot_device = BOOT_DEVICE_MMC1; + + if (CONFIG_IS_ENABLED(ROCKCHIP_BACK_TO_BROM)) + return BOOT_DEVICE_BOOTROM; + + return boot_device; +} + +const char *spl_decode_boot_device(u32 boot_device) +{ + int i; + static const struct { + u32 boot_device; + const char *ofpath; + } spl_boot_devices_tbl[] = { + { BOOT_DEVICE_MMC1, "/dwmmc@fe320000" }, + { BOOT_DEVICE_MMC2, "/sdhci@fe330000" }, + { BOOT_DEVICE_SPI, "/spi@ff1d0000" }, + }; + + for (i = 0; i < ARRAY_SIZE(spl_boot_devices_tbl); ++i) + if (spl_boot_devices_tbl[i].boot_device == boot_device) + return spl_boot_devices_tbl[i].ofpath; + + return NULL; } -u32 spl_boot_mode(const u32 boot_device) +void spl_perform_fixups(struct spl_image_info *spl_image) { - return MMCSD_MODE_RAW; + void *blob = spl_image->fdt_addr; + const char *boot_ofpath; + int chosen; + + /* + * Inject the ofpath of the device the full U-Boot (or Linux in + * Falcon-mode) was booted from into the FDT, if a FDT has been + * loaded at the same time. + */ + if (!blob) + return; + + boot_ofpath = spl_decode_boot_device(spl_image->boot_device); + if (!boot_ofpath) { + pr_err("%s: could not map boot_device to ofpath\n", __func__); + return; + } + + chosen = fdt_find_or_add_subnode(blob, 0, "chosen"); + if (chosen < 0) { + pr_err("%s: could not find/create '/chosen'\n", __func__); + return; + } + fdt_setprop_string(blob, chosen, + "u-boot,spl-boot-device", boot_ofpath); } #define TIMER_CHN10_BASE 0xff8680a0 @@ -49,44 +129,31 @@ void secure_timer_init(void) writel(TIMER_EN | TIMER_FMODE, TIMER_CHN10_BASE + TIMER_CONTROL_REG); } -void board_debug_uart_init(void) -{ -#define GRF_BASE 0xff770000 - struct rk3399_grf_regs * const grf = (void *)GRF_BASE; - -#if defined(CONFIG_DEBUG_UART_BASE) && (CONFIG_DEBUG_UART_BASE == 0xff180000) - /* Enable early UART0 on the RK3399 */ - rk_clrsetreg(&grf->gpio2c_iomux, - GRF_GPIO2C0_SEL_MASK, - GRF_UART0BT_SIN << GRF_GPIO2C0_SEL_SHIFT); - rk_clrsetreg(&grf->gpio2c_iomux, - GRF_GPIO2C1_SEL_MASK, - GRF_UART0BT_SOUT << GRF_GPIO2C1_SEL_SHIFT); -#else - /* Enable early UART2 channel C on the RK3399 */ - rk_clrsetreg(&grf->gpio4c_iomux, - GRF_GPIO4C3_SEL_MASK, - GRF_UART2DGBC_SIN << GRF_GPIO4C3_SEL_SHIFT); - rk_clrsetreg(&grf->gpio4c_iomux, - GRF_GPIO4C4_SEL_MASK, - GRF_UART2DBGC_SOUT << GRF_GPIO4C4_SEL_SHIFT); - /* Set channel C as UART2 input */ - rk_clrsetreg(&grf->soc_con7, - GRF_UART_DBG_SEL_MASK, - GRF_UART_DBG_SEL_C << GRF_UART_DBG_SEL_SHIFT); -#endif -} void board_init_f(ulong dummy) { - struct udevice *pinctrl; struct udevice *dev; struct rk3399_pmusgrf_regs *sgrf; struct rk3399_grf_regs *grf; int ret; -#define EARLY_UART -#ifdef EARLY_UART +#ifdef CONFIG_DEBUG_UART + debug_uart_init(); + +# ifdef CONFIG_TARGET_CHROMEBOOK_BOB + int sum, i; + + /* + * Add a delay and ensure that the compiler does not optimise this out. + * This is needed since the power rails tail a while to turn on, and + * we get garbage serial output otherwise. + */ + sum = 0; + for (i = 0; i < 150000; i++) + sum += i; + gru_dummy_function(sum); +#endif /* CONFIG_TARGET_CHROMEBOOK_BOB */ + /* * Debug UART can be used from here if required: * @@ -95,8 +162,7 @@ void board_init_f(ulong dummy) * printhex8(0x1234); * printascii("string"); */ - debug_uart_init(); - printascii("U-Boot SPL board init"); + debug("U-Boot SPL board init\n"); #endif ret = spl_early_init(); @@ -124,48 +190,71 @@ void board_init_f(ulong dummy) secure_timer_init(); - ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl); - if (ret) { - debug("Pinctrl init failed: %d\n", ret); - return; - } - ret = uclass_get_device(UCLASS_RAM, 0, &dev); if (ret) { - debug("DRAM init failed: %d\n", ret); + pr_err("DRAM init failed: %d\n", ret); return; } } -void spl_board_init(void) +#if defined(SPL_GPIO_SUPPORT) +static void rk3399_force_power_on_reset(void) { - struct udevice *pinctrl; - int ret; + ofnode node; + struct gpio_desc sysreset_gpio; - ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl); - if (ret) { - debug("%s: Cannot find pinctrl device\n", __func__); - goto err; + debug("%s: trying to force a power-on reset\n", __func__); + + node = ofnode_path("/config"); + if (!ofnode_valid(node)) { + debug("%s: no /config node?\n", __func__); + return; } - /* Enable debug UART */ - ret = pinctrl_request_noflags(pinctrl, PERIPH_ID_UART_DBG); - if (ret) { - debug("%s: Failed to set up console UART\n", __func__); - goto err; + if (gpio_request_by_name_nodev(node, "sysreset-gpio", 0, + &sysreset_gpio, GPIOD_IS_OUT)) { + debug("%s: could not find a /config/sysreset-gpio\n", __func__); + return; } - preloader_console_init(); -#if CONFIG_IS_ENABLED(ROCKCHIP_BACK_TO_BROM) - back_to_bootrom(); + dm_gpio_set_value(&sysreset_gpio, 1); +} +#endif + +void spl_board_init(void) +{ +#if defined(SPL_GPIO_SUPPORT) + struct rk3399_cru *cru = rockchip_get_cru(); + + /* + * The RK3399 resets only 'almost all logic' (see also in the TRM + * "3.9.4 Global software reset"), when issuing a software reset. + * This may cause issues during boot-up for some configurations of + * the application software stack. + * + * To work around this, we test whether the last reset reason was + * a power-on reset and (if not) issue an overtemp-reset to reset + * the entire module. + * + * While this was previously fixed by modifying the various places + * that could generate a software reset (e.g. U-Boot's sysreset + * driver, the ATF or Linux), we now have it here to ensure that + * we no longer have to track this through the various components. + */ + if (cru->glb_rst_st != 0) + rk3399_force_power_on_reset(); #endif - return; -err: - printf("spl_board_init: Error %d\n", ret); +#if defined(SPL_DM_REGULATOR) + /* + * Turning the eMMC and SPI back on (if disabled via the Qseven + * BIOS_ENABLE) signal is done through a always-on regulator). + */ + if (regulators_enable_boot_on(false)) + debug("%s: Cannot enable boot on regulator\n", __func__); +#endif - /* No way to report error here */ - hang(); + preloader_console_init(); } #ifdef CONFIG_SPL_LOAD_FIT