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> 195b5ca4c0SHeiko 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 965b5ca4c0SHeiko Stuebner #define GRF_BASE 0x20008000 975b5ca4c0SHeiko Stuebner 98df9041ecSHeiko Stübner void board_init_f(ulong dummy) 99df9041ecSHeiko Stübner { 1005b5ca4c0SHeiko 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 106*6c69ed19SHeiko Stuebner enum { 107*6c69ed19SHeiko Stuebner GPIO1B1_SHIFT = 2, 108*6c69ed19SHeiko Stuebner GPIO1B1_MASK = 3, 109*6c69ed19SHeiko Stuebner GPIO1B1_UART2_SOUT = 1, 110*6c69ed19SHeiko Stuebner 111*6c69ed19SHeiko Stuebner GPIO1B0_SHIFT = 0, 112*6c69ed19SHeiko Stuebner GPIO1B0_MASK = 3, 113*6c69ed19SHeiko Stuebner GPIO1B0_UART2_SIN = 1, 114*6c69ed19SHeiko Stuebner }; 115*6c69ed19SHeiko Stuebner 116df9041ecSHeiko Stübner /* Enable early UART on the RK3188 */ 117df9041ecSHeiko Stübner rk_clrsetreg(&grf->gpio1b_iomux, 118df9041ecSHeiko Stübner GPIO1B1_MASK << GPIO1B1_SHIFT | 119df9041ecSHeiko Stübner GPIO1B0_MASK << GPIO1B0_SHIFT, 120df9041ecSHeiko Stübner GPIO1B1_UART2_SOUT << GPIO1B1_SHIFT | 121df9041ecSHeiko Stübner GPIO1B0_UART2_SIN << GPIO1B0_SHIFT); 122df9041ecSHeiko Stübner /* 123df9041ecSHeiko Stübner * Debug UART can be used from here if required: 124df9041ecSHeiko Stübner * 125df9041ecSHeiko Stübner * debug_uart_init(); 126df9041ecSHeiko Stübner * printch('a'); 127df9041ecSHeiko Stübner * printhex8(0x1234); 128df9041ecSHeiko Stübner * printascii("string"); 129df9041ecSHeiko Stübner */ 130df9041ecSHeiko Stübner debug_uart_init(); 131df9041ecSHeiko Stübner printch('s'); 132df9041ecSHeiko Stübner printch('p'); 133df9041ecSHeiko Stübner printch('l'); 134df9041ecSHeiko Stübner printch('\n'); 135df9041ecSHeiko Stübner #endif 136df9041ecSHeiko Stübner 1375b5ca4c0SHeiko Stuebner #ifdef CONFIG_ROCKCHIP_USB_UART 1385b5ca4c0SHeiko Stuebner rk_clrsetreg(&grf->uoc0_con[0], 1395b5ca4c0SHeiko Stuebner SIDDQ_MASK | UOC_DISABLE_MASK | COMMON_ON_N_MASK, 1405b5ca4c0SHeiko Stuebner 1 << SIDDQ_SHIFT | 1 << UOC_DISABLE_SHIFT | 1415b5ca4c0SHeiko Stuebner 1 << COMMON_ON_N_SHIFT); 1425b5ca4c0SHeiko Stuebner rk_clrsetreg(&grf->uoc0_con[2], 1435b5ca4c0SHeiko Stuebner SOFT_CON_SEL_MASK, 1 << SOFT_CON_SEL_SHIFT); 1445b5ca4c0SHeiko Stuebner rk_clrsetreg(&grf->uoc0_con[3], 1455b5ca4c0SHeiko Stuebner OPMODE_MASK | XCVRSELECT_MASK | 1465b5ca4c0SHeiko Stuebner TERMSEL_FULLSPEED_MASK | SUSPENDN_MASK, 1475b5ca4c0SHeiko Stuebner OPMODE_NODRIVING << OPMODE_SHIFT | 1485b5ca4c0SHeiko Stuebner XCVRSELECT_FSTRANSC << XCVRSELECT_SHIFT | 1495b5ca4c0SHeiko Stuebner 1 << TERMSEL_FULLSPEED_SHIFT | 1505b5ca4c0SHeiko Stuebner 1 << SUSPENDN_SHIFT); 1515b5ca4c0SHeiko Stuebner rk_clrsetreg(&grf->uoc0_con[0], 1525b5ca4c0SHeiko Stuebner BYPASSSEL_MASK | BYPASSDMEN_MASK, 1535b5ca4c0SHeiko Stuebner 1 << BYPASSSEL_SHIFT | 1 << BYPASSDMEN_SHIFT); 1545b5ca4c0SHeiko Stuebner #endif 1555b5ca4c0SHeiko Stuebner 156232cf962SKever Yang ret = spl_early_init(); 157df9041ecSHeiko Stübner if (ret) { 158232cf962SKever Yang debug("spl_early_init() failed: %d\n", ret); 159df9041ecSHeiko Stübner hang(); 160df9041ecSHeiko Stübner } 161df9041ecSHeiko Stübner 162df9041ecSHeiko Stübner ret = rockchip_get_clk(&dev); 163df9041ecSHeiko Stübner if (ret) { 164df9041ecSHeiko Stübner debug("CLK init failed: %d\n", ret); 165df9041ecSHeiko Stübner return; 166df9041ecSHeiko Stübner } 167df9041ecSHeiko Stübner 168df9041ecSHeiko Stübner ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl); 169df9041ecSHeiko Stübner if (ret) { 170df9041ecSHeiko Stübner debug("Pinctrl init failed: %d\n", ret); 171df9041ecSHeiko Stübner return; 172df9041ecSHeiko Stübner } 173df9041ecSHeiko Stübner 174df9041ecSHeiko Stübner ret = uclass_get_device(UCLASS_RAM, 0, &dev); 175df9041ecSHeiko Stübner if (ret) { 176df9041ecSHeiko Stübner debug("DRAM init failed: %d\n", ret); 177df9041ecSHeiko Stübner return; 178df9041ecSHeiko Stübner } 179df9041ecSHeiko Stübner 180f4f57c58SHeiko Stübner setup_arm_clock(); 181ee14d29dSPhilipp Tomsich #if CONFIG_IS_ENABLED(ROCKCHIP_BACK_TO_BROM) && !defined(CONFIG_SPL_BOARD_INIT) 182b82bd1f8SPhilipp Tomsich back_to_bootrom(BROM_BOOT_NEXTSTAGE); 183df9041ecSHeiko Stübner #endif 184df9041ecSHeiko Stübner } 185df9041ecSHeiko Stübner 186df9041ecSHeiko Stübner static int setup_led(void) 187df9041ecSHeiko Stübner { 188df9041ecSHeiko Stübner #ifdef CONFIG_SPL_LED 189df9041ecSHeiko Stübner struct udevice *dev; 190df9041ecSHeiko Stübner char *led_name; 191df9041ecSHeiko Stübner int ret; 192df9041ecSHeiko Stübner 193df9041ecSHeiko Stübner led_name = fdtdec_get_config_string(gd->fdt_blob, "u-boot,boot-led"); 194df9041ecSHeiko Stübner if (!led_name) 195df9041ecSHeiko Stübner return 0; 196df9041ecSHeiko Stübner ret = led_get_by_label(led_name, &dev); 197df9041ecSHeiko Stübner if (ret) { 198df9041ecSHeiko Stübner debug("%s: get=%d\n", __func__, ret); 199df9041ecSHeiko Stübner return ret; 200df9041ecSHeiko Stübner } 201df9041ecSHeiko Stübner ret = led_set_on(dev, 1); 202df9041ecSHeiko Stübner if (ret) 203df9041ecSHeiko Stübner return ret; 204df9041ecSHeiko Stübner #endif 205df9041ecSHeiko Stübner 206df9041ecSHeiko Stübner return 0; 207df9041ecSHeiko Stübner } 208df9041ecSHeiko Stübner 209df9041ecSHeiko Stübner void spl_board_init(void) 210df9041ecSHeiko Stübner { 211df9041ecSHeiko Stübner struct udevice *pinctrl; 212df9041ecSHeiko Stübner int ret; 213df9041ecSHeiko Stübner 214df9041ecSHeiko Stübner ret = setup_led(); 215df9041ecSHeiko Stübner if (ret) { 216df9041ecSHeiko Stübner debug("LED ret=%d\n", ret); 217df9041ecSHeiko Stübner hang(); 218df9041ecSHeiko Stübner } 219df9041ecSHeiko Stübner 220df9041ecSHeiko Stübner ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl); 221df9041ecSHeiko Stübner if (ret) { 222df9041ecSHeiko Stübner debug("%s: Cannot find pinctrl device\n", __func__); 223df9041ecSHeiko Stübner goto err; 224df9041ecSHeiko Stübner } 225df9041ecSHeiko Stübner 226df9041ecSHeiko Stübner #ifdef CONFIG_SPL_MMC_SUPPORT 227df9041ecSHeiko Stübner ret = pinctrl_request_noflags(pinctrl, PERIPH_ID_SDCARD); 228df9041ecSHeiko Stübner if (ret) { 229df9041ecSHeiko Stübner debug("%s: Failed to set up SD card\n", __func__); 230df9041ecSHeiko Stübner goto err; 231df9041ecSHeiko Stübner } 232df9041ecSHeiko Stübner #endif 233df9041ecSHeiko Stübner 234df9041ecSHeiko Stübner /* Enable debug UART */ 235df9041ecSHeiko Stübner ret = pinctrl_request_noflags(pinctrl, PERIPH_ID_UART_DBG); 236df9041ecSHeiko Stübner if (ret) { 237df9041ecSHeiko Stübner debug("%s: Failed to set up console UART\n", __func__); 238df9041ecSHeiko Stübner goto err; 239df9041ecSHeiko Stübner } 240df9041ecSHeiko Stübner 241df9041ecSHeiko Stübner preloader_console_init(); 242ee14d29dSPhilipp Tomsich #if CONFIG_IS_ENABLED(ROCKCHIP_BACK_TO_BROM) 243b82bd1f8SPhilipp Tomsich back_to_bootrom(BROM_BOOT_NEXTSTAGE); 244df9041ecSHeiko Stübner #endif 245df9041ecSHeiko Stübner return; 246df9041ecSHeiko Stübner 247df9041ecSHeiko Stübner err: 248df9041ecSHeiko Stübner printf("spl_board_init: Error %d\n", ret); 249df9041ecSHeiko Stübner 250df9041ecSHeiko Stübner /* No way to report error here */ 251df9041ecSHeiko Stübner hang(); 252df9041ecSHeiko Stübner } 253