183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+ 2df9041ecSHeiko Stübner /* 3df9041ecSHeiko Stübner * (C) Copyright 2015 Google, Inc 4df9041ecSHeiko Stübner */ 5df9041ecSHeiko Stübner 6f4f57c58SHeiko Stübner #include <clk.h> 7df9041ecSHeiko Stübner #include <common.h> 8df9041ecSHeiko Stübner #include <debug_uart.h> 9df9041ecSHeiko Stübner #include <dm.h> 10df9041ecSHeiko Stübner #include <fdtdec.h> 11df9041ecSHeiko Stübner #include <led.h> 12df9041ecSHeiko Stübner #include <malloc.h> 13df9041ecSHeiko Stübner #include <ram.h> 14df9041ecSHeiko Stübner #include <spl.h> 15df9041ecSHeiko Stübner #include <asm/gpio.h> 16df9041ecSHeiko Stübner #include <asm/io.h> 17df9041ecSHeiko Stübner #include <asm/arch/bootrom.h> 18df9041ecSHeiko Stübner #include <asm/arch/clock.h> 19*5b5ca4c0SHeiko Stuebner #include <asm/arch/grf_rk3188.h> 20df9041ecSHeiko Stübner #include <asm/arch/hardware.h> 21df9041ecSHeiko Stübner #include <asm/arch/periph.h> 22df9041ecSHeiko Stübner #include <asm/arch/pmu_rk3188.h> 23df9041ecSHeiko Stübner #include <asm/arch/sdram.h> 24df9041ecSHeiko Stübner #include <asm/arch/timer.h> 25df9041ecSHeiko Stübner #include <dm/pinctrl.h> 26df9041ecSHeiko Stübner #include <dm/root.h> 27df9041ecSHeiko Stübner #include <dm/test.h> 28df9041ecSHeiko Stübner #include <dm/util.h> 29df9041ecSHeiko Stübner #include <power/regulator.h> 30df9041ecSHeiko Stübner #include <syscon.h> 31df9041ecSHeiko Stübner 32df9041ecSHeiko Stübner DECLARE_GLOBAL_DATA_PTR; 33df9041ecSHeiko Stübner 34df9041ecSHeiko Stübner u32 spl_boot_device(void) 35df9041ecSHeiko Stübner { 36df9041ecSHeiko Stübner #if !CONFIG_IS_ENABLED(OF_PLATDATA) 37df9041ecSHeiko Stübner const void *blob = gd->fdt_blob; 38df9041ecSHeiko Stübner struct udevice *dev; 39df9041ecSHeiko Stübner const char *bootdev; 40df9041ecSHeiko Stübner int node; 41df9041ecSHeiko Stübner int ret; 42df9041ecSHeiko Stübner 43df9041ecSHeiko Stübner bootdev = fdtdec_get_config_string(blob, "u-boot,boot0"); 44df9041ecSHeiko Stübner debug("Boot device %s\n", bootdev); 45df9041ecSHeiko Stübner if (!bootdev) 46df9041ecSHeiko Stübner goto fallback; 47df9041ecSHeiko Stübner 48df9041ecSHeiko Stübner node = fdt_path_offset(blob, bootdev); 49df9041ecSHeiko Stübner if (node < 0) { 50df9041ecSHeiko Stübner debug("node=%d\n", node); 51df9041ecSHeiko Stübner goto fallback; 52df9041ecSHeiko Stübner } 537ec9181dSJean-Jacques Hiblot ret = device_get_global_by_ofnode(offset_to_ofnode(node), &dev); 54df9041ecSHeiko Stübner if (ret) { 55df9041ecSHeiko Stübner debug("device at node %s/%d not found: %d\n", bootdev, node, 56df9041ecSHeiko Stübner ret); 57df9041ecSHeiko Stübner goto fallback; 58df9041ecSHeiko Stübner } 59df9041ecSHeiko Stübner debug("Found device %s\n", dev->name); 60df9041ecSHeiko Stübner switch (device_get_uclass_id(dev)) { 61df9041ecSHeiko Stübner case UCLASS_SPI_FLASH: 62df9041ecSHeiko Stübner return BOOT_DEVICE_SPI; 63df9041ecSHeiko Stübner case UCLASS_MMC: 64df9041ecSHeiko Stübner return BOOT_DEVICE_MMC1; 65df9041ecSHeiko Stübner default: 66df9041ecSHeiko Stübner debug("Booting from device uclass '%s' not supported\n", 67df9041ecSHeiko Stübner dev_get_uclass_name(dev)); 68df9041ecSHeiko Stübner } 69df9041ecSHeiko Stübner 70df9041ecSHeiko Stübner fallback: 71df9041ecSHeiko Stübner #endif 72df9041ecSHeiko Stübner return BOOT_DEVICE_MMC1; 73df9041ecSHeiko Stübner } 74df9041ecSHeiko Stübner 75f4f57c58SHeiko Stübner static int setup_arm_clock(void) 76f4f57c58SHeiko Stübner { 77f4f57c58SHeiko Stübner struct udevice *dev; 78f4f57c58SHeiko Stübner struct clk clk; 79f4f57c58SHeiko Stübner int ret; 80f4f57c58SHeiko Stübner 81f4f57c58SHeiko Stübner ret = rockchip_get_clk(&dev); 82f4f57c58SHeiko Stübner if (ret) 83f4f57c58SHeiko Stübner return ret; 84f4f57c58SHeiko Stübner 85f4f57c58SHeiko Stübner clk.id = CLK_ARM; 86f4f57c58SHeiko Stübner ret = clk_request(dev, &clk); 87f4f57c58SHeiko Stübner if (ret < 0) 88f4f57c58SHeiko Stübner return ret; 89f4f57c58SHeiko Stübner 90f4f57c58SHeiko Stübner ret = clk_set_rate(&clk, 600000000); 91f4f57c58SHeiko Stübner 92f4f57c58SHeiko Stübner clk_free(&clk); 93f4f57c58SHeiko Stübner return ret; 94f4f57c58SHeiko Stübner } 95f4f57c58SHeiko Stübner 96*5b5ca4c0SHeiko Stuebner #define GRF_BASE 0x20008000 97*5b5ca4c0SHeiko Stuebner 98df9041ecSHeiko Stübner void board_init_f(ulong dummy) 99df9041ecSHeiko Stübner { 100*5b5ca4c0SHeiko Stuebner __maybe_unused struct rk3188_grf * const grf = (void *)GRF_BASE; 101df9041ecSHeiko Stübner struct udevice *pinctrl, *dev; 102df9041ecSHeiko Stübner int ret; 103df9041ecSHeiko Stübner 104df9041ecSHeiko Stübner /* Example code showing how to enable the debug UART on RK3188 */ 105df9041ecSHeiko Stübner #ifdef EARLY_UART 106df9041ecSHeiko Stübner /* Enable early UART on the RK3188 */ 107df9041ecSHeiko Stübner rk_clrsetreg(&grf->gpio1b_iomux, 108df9041ecSHeiko Stübner GPIO1B1_MASK << GPIO1B1_SHIFT | 109df9041ecSHeiko Stübner GPIO1B0_MASK << GPIO1B0_SHIFT, 110df9041ecSHeiko Stübner GPIO1B1_UART2_SOUT << GPIO1B1_SHIFT | 111df9041ecSHeiko Stübner GPIO1B0_UART2_SIN << GPIO1B0_SHIFT); 112df9041ecSHeiko Stübner /* 113df9041ecSHeiko Stübner * Debug UART can be used from here if required: 114df9041ecSHeiko Stübner * 115df9041ecSHeiko Stübner * debug_uart_init(); 116df9041ecSHeiko Stübner * printch('a'); 117df9041ecSHeiko Stübner * printhex8(0x1234); 118df9041ecSHeiko Stübner * printascii("string"); 119df9041ecSHeiko Stübner */ 120df9041ecSHeiko Stübner debug_uart_init(); 121df9041ecSHeiko Stübner printch('s'); 122df9041ecSHeiko Stübner printch('p'); 123df9041ecSHeiko Stübner printch('l'); 124df9041ecSHeiko Stübner printch('\n'); 125df9041ecSHeiko Stübner #endif 126df9041ecSHeiko Stübner 127*5b5ca4c0SHeiko Stuebner #ifdef CONFIG_ROCKCHIP_USB_UART 128*5b5ca4c0SHeiko Stuebner rk_clrsetreg(&grf->uoc0_con[0], 129*5b5ca4c0SHeiko Stuebner SIDDQ_MASK | UOC_DISABLE_MASK | COMMON_ON_N_MASK, 130*5b5ca4c0SHeiko Stuebner 1 << SIDDQ_SHIFT | 1 << UOC_DISABLE_SHIFT | 131*5b5ca4c0SHeiko Stuebner 1 << COMMON_ON_N_SHIFT); 132*5b5ca4c0SHeiko Stuebner rk_clrsetreg(&grf->uoc0_con[2], 133*5b5ca4c0SHeiko Stuebner SOFT_CON_SEL_MASK, 1 << SOFT_CON_SEL_SHIFT); 134*5b5ca4c0SHeiko Stuebner rk_clrsetreg(&grf->uoc0_con[3], 135*5b5ca4c0SHeiko Stuebner OPMODE_MASK | XCVRSELECT_MASK | 136*5b5ca4c0SHeiko Stuebner TERMSEL_FULLSPEED_MASK | SUSPENDN_MASK, 137*5b5ca4c0SHeiko Stuebner OPMODE_NODRIVING << OPMODE_SHIFT | 138*5b5ca4c0SHeiko Stuebner XCVRSELECT_FSTRANSC << XCVRSELECT_SHIFT | 139*5b5ca4c0SHeiko Stuebner 1 << TERMSEL_FULLSPEED_SHIFT | 140*5b5ca4c0SHeiko Stuebner 1 << SUSPENDN_SHIFT); 141*5b5ca4c0SHeiko Stuebner rk_clrsetreg(&grf->uoc0_con[0], 142*5b5ca4c0SHeiko Stuebner BYPASSSEL_MASK | BYPASSDMEN_MASK, 143*5b5ca4c0SHeiko Stuebner 1 << BYPASSSEL_SHIFT | 1 << BYPASSDMEN_SHIFT); 144*5b5ca4c0SHeiko Stuebner #endif 145*5b5ca4c0SHeiko Stuebner 146232cf962SKever Yang ret = spl_early_init(); 147df9041ecSHeiko Stübner if (ret) { 148232cf962SKever Yang debug("spl_early_init() failed: %d\n", ret); 149df9041ecSHeiko Stübner hang(); 150df9041ecSHeiko Stübner } 151df9041ecSHeiko Stübner 152df9041ecSHeiko Stübner ret = rockchip_get_clk(&dev); 153df9041ecSHeiko Stübner if (ret) { 154df9041ecSHeiko Stübner debug("CLK init failed: %d\n", ret); 155df9041ecSHeiko Stübner return; 156df9041ecSHeiko Stübner } 157df9041ecSHeiko Stübner 158df9041ecSHeiko Stübner ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl); 159df9041ecSHeiko Stübner if (ret) { 160df9041ecSHeiko Stübner debug("Pinctrl init failed: %d\n", ret); 161df9041ecSHeiko Stübner return; 162df9041ecSHeiko Stübner } 163df9041ecSHeiko Stübner 164df9041ecSHeiko Stübner ret = uclass_get_device(UCLASS_RAM, 0, &dev); 165df9041ecSHeiko Stübner if (ret) { 166df9041ecSHeiko Stübner debug("DRAM init failed: %d\n", ret); 167df9041ecSHeiko Stübner return; 168df9041ecSHeiko Stübner } 169df9041ecSHeiko Stübner 170f4f57c58SHeiko Stübner setup_arm_clock(); 171ee14d29dSPhilipp Tomsich #if CONFIG_IS_ENABLED(ROCKCHIP_BACK_TO_BROM) && !defined(CONFIG_SPL_BOARD_INIT) 172b82bd1f8SPhilipp Tomsich back_to_bootrom(BROM_BOOT_NEXTSTAGE); 173df9041ecSHeiko Stübner #endif 174df9041ecSHeiko Stübner } 175df9041ecSHeiko Stübner 176df9041ecSHeiko Stübner static int setup_led(void) 177df9041ecSHeiko Stübner { 178df9041ecSHeiko Stübner #ifdef CONFIG_SPL_LED 179df9041ecSHeiko Stübner struct udevice *dev; 180df9041ecSHeiko Stübner char *led_name; 181df9041ecSHeiko Stübner int ret; 182df9041ecSHeiko Stübner 183df9041ecSHeiko Stübner led_name = fdtdec_get_config_string(gd->fdt_blob, "u-boot,boot-led"); 184df9041ecSHeiko Stübner if (!led_name) 185df9041ecSHeiko Stübner return 0; 186df9041ecSHeiko Stübner ret = led_get_by_label(led_name, &dev); 187df9041ecSHeiko Stübner if (ret) { 188df9041ecSHeiko Stübner debug("%s: get=%d\n", __func__, ret); 189df9041ecSHeiko Stübner return ret; 190df9041ecSHeiko Stübner } 191df9041ecSHeiko Stübner ret = led_set_on(dev, 1); 192df9041ecSHeiko Stübner if (ret) 193df9041ecSHeiko Stübner return ret; 194df9041ecSHeiko Stübner #endif 195df9041ecSHeiko Stübner 196df9041ecSHeiko Stübner return 0; 197df9041ecSHeiko Stübner } 198df9041ecSHeiko Stübner 199df9041ecSHeiko Stübner void spl_board_init(void) 200df9041ecSHeiko Stübner { 201df9041ecSHeiko Stübner struct udevice *pinctrl; 202df9041ecSHeiko Stübner int ret; 203df9041ecSHeiko Stübner 204df9041ecSHeiko Stübner ret = setup_led(); 205df9041ecSHeiko Stübner if (ret) { 206df9041ecSHeiko Stübner debug("LED ret=%d\n", ret); 207df9041ecSHeiko Stübner hang(); 208df9041ecSHeiko Stübner } 209df9041ecSHeiko Stübner 210df9041ecSHeiko Stübner ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl); 211df9041ecSHeiko Stübner if (ret) { 212df9041ecSHeiko Stübner debug("%s: Cannot find pinctrl device\n", __func__); 213df9041ecSHeiko Stübner goto err; 214df9041ecSHeiko Stübner } 215df9041ecSHeiko Stübner 216df9041ecSHeiko Stübner #ifdef CONFIG_SPL_MMC_SUPPORT 217df9041ecSHeiko Stübner ret = pinctrl_request_noflags(pinctrl, PERIPH_ID_SDCARD); 218df9041ecSHeiko Stübner if (ret) { 219df9041ecSHeiko Stübner debug("%s: Failed to set up SD card\n", __func__); 220df9041ecSHeiko Stübner goto err; 221df9041ecSHeiko Stübner } 222df9041ecSHeiko Stübner #endif 223df9041ecSHeiko Stübner 224df9041ecSHeiko Stübner /* Enable debug UART */ 225df9041ecSHeiko Stübner ret = pinctrl_request_noflags(pinctrl, PERIPH_ID_UART_DBG); 226df9041ecSHeiko Stübner if (ret) { 227df9041ecSHeiko Stübner debug("%s: Failed to set up console UART\n", __func__); 228df9041ecSHeiko Stübner goto err; 229df9041ecSHeiko Stübner } 230df9041ecSHeiko Stübner 231df9041ecSHeiko Stübner preloader_console_init(); 232ee14d29dSPhilipp Tomsich #if CONFIG_IS_ENABLED(ROCKCHIP_BACK_TO_BROM) 233b82bd1f8SPhilipp Tomsich back_to_bootrom(BROM_BOOT_NEXTSTAGE); 234df9041ecSHeiko Stübner #endif 235df9041ecSHeiko Stübner return; 236df9041ecSHeiko Stübner 237df9041ecSHeiko Stübner err: 238df9041ecSHeiko Stübner printf("spl_board_init: Error %d\n", ret); 239df9041ecSHeiko Stübner 240df9041ecSHeiko Stübner /* No way to report error here */ 241df9041ecSHeiko Stübner hang(); 242df9041ecSHeiko Stübner } 243