1df9041ecSHeiko Stübner /* 2df9041ecSHeiko Stübner * (C) Copyright 2015 Google, Inc 3df9041ecSHeiko Stübner * 4df9041ecSHeiko Stübner * SPDX-License-Identifier: GPL-2.0+ 5df9041ecSHeiko Stübner */ 6df9041ecSHeiko Stübner 7f4f57c58SHeiko Stübner #include <clk.h> 8df9041ecSHeiko Stübner #include <common.h> 9df9041ecSHeiko Stübner #include <debug_uart.h> 10df9041ecSHeiko Stübner #include <dm.h> 11df9041ecSHeiko Stübner #include <fdtdec.h> 12df9041ecSHeiko Stübner #include <led.h> 13df9041ecSHeiko Stübner #include <malloc.h> 14df9041ecSHeiko Stübner #include <ram.h> 15df9041ecSHeiko Stübner #include <spl.h> 16df9041ecSHeiko Stübner #include <asm/gpio.h> 17df9041ecSHeiko Stübner #include <asm/io.h> 18df9041ecSHeiko Stübner #include <asm/arch/bootrom.h> 19df9041ecSHeiko Stübner #include <asm/arch/clock.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 } 53df9041ecSHeiko Stübner ret = device_get_global_by_of_offset(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 75df9041ecSHeiko Stübner u32 spl_boot_mode(const u32 boot_device) 76df9041ecSHeiko Stübner { 77df9041ecSHeiko Stübner return MMCSD_MODE_RAW; 78df9041ecSHeiko Stübner } 79df9041ecSHeiko Stübner 80f4f57c58SHeiko Stübner static int setup_arm_clock(void) 81f4f57c58SHeiko Stübner { 82f4f57c58SHeiko Stübner struct udevice *dev; 83f4f57c58SHeiko Stübner struct clk clk; 84f4f57c58SHeiko Stübner int ret; 85f4f57c58SHeiko Stübner 86f4f57c58SHeiko Stübner ret = rockchip_get_clk(&dev); 87f4f57c58SHeiko Stübner if (ret) 88f4f57c58SHeiko Stübner return ret; 89f4f57c58SHeiko Stübner 90f4f57c58SHeiko Stübner clk.id = CLK_ARM; 91f4f57c58SHeiko Stübner ret = clk_request(dev, &clk); 92f4f57c58SHeiko Stübner if (ret < 0) 93f4f57c58SHeiko Stübner return ret; 94f4f57c58SHeiko Stübner 95f4f57c58SHeiko Stübner ret = clk_set_rate(&clk, 600000000); 96f4f57c58SHeiko Stübner 97f4f57c58SHeiko Stübner clk_free(&clk); 98f4f57c58SHeiko Stübner return ret; 99f4f57c58SHeiko Stübner } 100f4f57c58SHeiko Stübner 101df9041ecSHeiko Stübner void board_init_f(ulong dummy) 102df9041ecSHeiko Stübner { 103df9041ecSHeiko Stübner struct udevice *pinctrl, *dev; 104df9041ecSHeiko Stübner struct rk3188_pmu *pmu; 105df9041ecSHeiko Stübner int ret; 106df9041ecSHeiko Stübner 107df9041ecSHeiko Stübner /* Example code showing how to enable the debug UART on RK3188 */ 108df9041ecSHeiko Stübner #ifdef EARLY_UART 109df9041ecSHeiko Stübner #include <asm/arch/grf_rk3188.h> 110df9041ecSHeiko Stübner /* Enable early UART on the RK3188 */ 111df9041ecSHeiko Stübner #define GRF_BASE 0x20008000 112df9041ecSHeiko Stübner struct rk3188_grf * const grf = (void *)GRF_BASE; 113df9041ecSHeiko Stübner 114df9041ecSHeiko Stübner rk_clrsetreg(&grf->gpio1b_iomux, 115df9041ecSHeiko Stübner GPIO1B1_MASK << GPIO1B1_SHIFT | 116df9041ecSHeiko Stübner GPIO1B0_MASK << GPIO1B0_SHIFT, 117df9041ecSHeiko Stübner GPIO1B1_UART2_SOUT << GPIO1B1_SHIFT | 118df9041ecSHeiko Stübner GPIO1B0_UART2_SIN << GPIO1B0_SHIFT); 119df9041ecSHeiko Stübner /* 120df9041ecSHeiko Stübner * Debug UART can be used from here if required: 121df9041ecSHeiko Stübner * 122df9041ecSHeiko Stübner * debug_uart_init(); 123df9041ecSHeiko Stübner * printch('a'); 124df9041ecSHeiko Stübner * printhex8(0x1234); 125df9041ecSHeiko Stübner * printascii("string"); 126df9041ecSHeiko Stübner */ 127df9041ecSHeiko Stübner debug_uart_init(); 128df9041ecSHeiko Stübner printch('s'); 129df9041ecSHeiko Stübner printch('p'); 130df9041ecSHeiko Stübner printch('l'); 131df9041ecSHeiko Stübner printch('\n'); 132df9041ecSHeiko Stübner #endif 133df9041ecSHeiko Stübner 134232cf962SKever Yang ret = spl_early_init(); 135df9041ecSHeiko Stübner if (ret) { 136232cf962SKever Yang debug("spl_early_init() failed: %d\n", ret); 137df9041ecSHeiko Stübner hang(); 138df9041ecSHeiko Stübner } 139df9041ecSHeiko Stübner 140df9041ecSHeiko Stübner rockchip_timer_init(); 141df9041ecSHeiko Stübner 142df9041ecSHeiko Stübner ret = rockchip_get_clk(&dev); 143df9041ecSHeiko Stübner if (ret) { 144df9041ecSHeiko Stübner debug("CLK init failed: %d\n", ret); 145df9041ecSHeiko Stübner return; 146df9041ecSHeiko Stübner } 147df9041ecSHeiko Stübner 148df9041ecSHeiko Stübner /* 149df9041ecSHeiko Stübner * Recover the bootrom's stackpointer. 150df9041ecSHeiko Stübner * For whatever reason needs to run after rockchip_get_clk. 151df9041ecSHeiko Stübner */ 152df9041ecSHeiko Stübner pmu = syscon_get_first_range(ROCKCHIP_SYSCON_PMU); 153df9041ecSHeiko Stübner if (IS_ERR(pmu)) 154df9041ecSHeiko Stübner error("pmu syscon returned %ld\n", PTR_ERR(pmu)); 155df9041ecSHeiko Stübner SAVE_SP_ADDR = readl(&pmu->sys_reg[2]); 156df9041ecSHeiko Stübner 157df9041ecSHeiko Stübner ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl); 158df9041ecSHeiko Stübner if (ret) { 159df9041ecSHeiko Stübner debug("Pinctrl init failed: %d\n", ret); 160df9041ecSHeiko Stübner return; 161df9041ecSHeiko Stübner } 162df9041ecSHeiko Stübner 163df9041ecSHeiko Stübner ret = uclass_get_device(UCLASS_RAM, 0, &dev); 164df9041ecSHeiko Stübner if (ret) { 165df9041ecSHeiko Stübner debug("DRAM init failed: %d\n", ret); 166df9041ecSHeiko Stübner return; 167df9041ecSHeiko Stübner } 168df9041ecSHeiko Stübner 169f4f57c58SHeiko Stübner setup_arm_clock(); 170*ee14d29dSPhilipp Tomsich #if CONFIG_IS_ENABLED(ROCKCHIP_BACK_TO_BROM) && !defined(CONFIG_SPL_BOARD_INIT) 171df9041ecSHeiko Stübner back_to_bootrom(); 172df9041ecSHeiko Stübner #endif 173df9041ecSHeiko Stübner } 174df9041ecSHeiko Stübner 175df9041ecSHeiko Stübner static int setup_led(void) 176df9041ecSHeiko Stübner { 177df9041ecSHeiko Stübner #ifdef CONFIG_SPL_LED 178df9041ecSHeiko Stübner struct udevice *dev; 179df9041ecSHeiko Stübner char *led_name; 180df9041ecSHeiko Stübner int ret; 181df9041ecSHeiko Stübner 182df9041ecSHeiko Stübner led_name = fdtdec_get_config_string(gd->fdt_blob, "u-boot,boot-led"); 183df9041ecSHeiko Stübner if (!led_name) 184df9041ecSHeiko Stübner return 0; 185df9041ecSHeiko Stübner ret = led_get_by_label(led_name, &dev); 186df9041ecSHeiko Stübner if (ret) { 187df9041ecSHeiko Stübner debug("%s: get=%d\n", __func__, ret); 188df9041ecSHeiko Stübner return ret; 189df9041ecSHeiko Stübner } 190df9041ecSHeiko Stübner ret = led_set_on(dev, 1); 191df9041ecSHeiko Stübner if (ret) 192df9041ecSHeiko Stübner return ret; 193df9041ecSHeiko Stübner #endif 194df9041ecSHeiko Stübner 195df9041ecSHeiko Stübner return 0; 196df9041ecSHeiko Stübner } 197df9041ecSHeiko Stübner 198df9041ecSHeiko Stübner void spl_board_init(void) 199df9041ecSHeiko Stübner { 200df9041ecSHeiko Stübner struct udevice *pinctrl; 201df9041ecSHeiko Stübner int ret; 202df9041ecSHeiko Stübner 203df9041ecSHeiko Stübner ret = setup_led(); 204df9041ecSHeiko Stübner if (ret) { 205df9041ecSHeiko Stübner debug("LED ret=%d\n", ret); 206df9041ecSHeiko Stübner hang(); 207df9041ecSHeiko Stübner } 208df9041ecSHeiko Stübner 209df9041ecSHeiko Stübner ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl); 210df9041ecSHeiko Stübner if (ret) { 211df9041ecSHeiko Stübner debug("%s: Cannot find pinctrl device\n", __func__); 212df9041ecSHeiko Stübner goto err; 213df9041ecSHeiko Stübner } 214df9041ecSHeiko Stübner 215df9041ecSHeiko Stübner #ifdef CONFIG_SPL_MMC_SUPPORT 216df9041ecSHeiko Stübner ret = pinctrl_request_noflags(pinctrl, PERIPH_ID_SDCARD); 217df9041ecSHeiko Stübner if (ret) { 218df9041ecSHeiko Stübner debug("%s: Failed to set up SD card\n", __func__); 219df9041ecSHeiko Stübner goto err; 220df9041ecSHeiko Stübner } 221df9041ecSHeiko Stübner #endif 222df9041ecSHeiko Stübner 223df9041ecSHeiko Stübner /* Enable debug UART */ 224df9041ecSHeiko Stübner ret = pinctrl_request_noflags(pinctrl, PERIPH_ID_UART_DBG); 225df9041ecSHeiko Stübner if (ret) { 226df9041ecSHeiko Stübner debug("%s: Failed to set up console UART\n", __func__); 227df9041ecSHeiko Stübner goto err; 228df9041ecSHeiko Stübner } 229df9041ecSHeiko Stübner 230df9041ecSHeiko Stübner preloader_console_init(); 231*ee14d29dSPhilipp Tomsich #if CONFIG_IS_ENABLED(ROCKCHIP_BACK_TO_BROM) 232df9041ecSHeiko Stübner back_to_bootrom(); 233df9041ecSHeiko Stübner #endif 234df9041ecSHeiko Stübner return; 235df9041ecSHeiko Stübner 236df9041ecSHeiko Stübner err: 237df9041ecSHeiko Stübner printf("spl_board_init: Error %d\n", ret); 238df9041ecSHeiko Stübner 239df9041ecSHeiko Stübner /* No way to report error here */ 240df9041ecSHeiko Stübner hang(); 241df9041ecSHeiko Stübner } 242