138771996SKever Yang /* 238771996SKever Yang * (C) Copyright 2017 Rockchip Electronics Co., Ltd. 338771996SKever Yang * 438771996SKever Yang * SPDX-License-Identifier: GPL-2.0+ 538771996SKever Yang */ 62208cd92SJoseph Chen 738771996SKever Yang #include <common.h> 850d35c45SJoseph Chen #include <amp.h> 986f870d6SJoseph Chen #include <bidram.h> 100ed06f16SJoseph Chen #include <boot_rkimg.h> 110ed06f16SJoseph Chen #include <cli.h> 122208cd92SJoseph Chen #include <clk.h> 132208cd92SJoseph Chen #include <console.h> 14575777c5SKever Yang #include <debug_uart.h> 152208cd92SJoseph Chen #include <dm.h> 162208cd92SJoseph Chen #include <dvfs.h> 172208cd92SJoseph Chen #include <io-domain.h> 187397b961SJoseph Chen #include <key.h> 1986f870d6SJoseph Chen #include <memblk.h> 202208cd92SJoseph Chen #include <misc.h> 212208cd92SJoseph Chen #include <of_live.h> 2238771996SKever Yang #include <ram.h> 232208cd92SJoseph Chen #include <rockchip_debugger.h> 2438771996SKever Yang #include <syscon.h> 256929f85bSJoseph Chen #include <sysmem.h> 262208cd92SJoseph Chen #include <video_rockchip.h> 2738771996SKever Yang #include <asm/io.h> 2838771996SKever Yang #include <asm/gpio.h> 293e45175eSJoseph Chen #include <dm/uclass-internal.h> 302208cd92SJoseph Chen #include <dm/root.h> 312208cd92SJoseph Chen #include <power/charge_display.h> 322208cd92SJoseph Chen #include <power/regulator.h> 332208cd92SJoseph Chen #include <asm/arch/boot_mode.h> 3438771996SKever Yang #include <asm/arch/clock.h> 3560ea26bdSJoseph Chen #include <asm/arch/cpu.h> 36c664909eSJoseph Chen #include <asm/arch/hotkey.h> 376929f85bSJoseph Chen #include <asm/arch/param.h> 382208cd92SJoseph Chen #include <asm/arch/periph.h> 392208cd92SJoseph Chen #include <asm/arch/resource_img.h> 402208cd92SJoseph Chen #include <asm/arch/rk_atags.h> 412208cd92SJoseph Chen #include <asm/arch/vendor.h> 4238771996SKever Yang 4338771996SKever Yang DECLARE_GLOBAL_DATA_PTR; 4438771996SKever Yang 4538771996SKever Yang __weak int rk_board_late_init(void) 4638771996SKever Yang { 4738771996SKever Yang return 0; 4838771996SKever Yang } 4938771996SKever Yang 5038ce6261SJoseph Chen __weak int rk_board_fdt_fixup(void *blob) 5138ce6261SJoseph Chen { 5238ce6261SJoseph Chen return 0; 5338ce6261SJoseph Chen } 5438ce6261SJoseph Chen 55efdbac34SFinley Xiao __weak int soc_clk_dump(void) 56efdbac34SFinley Xiao { 57efdbac34SFinley Xiao return 0; 58efdbac34SFinley Xiao } 59efdbac34SFinley Xiao 60058e5d94SFinley Xiao __weak int set_armclk_rate(void) 61058e5d94SFinley Xiao { 62058e5d94SFinley Xiao return 0; 63058e5d94SFinley Xiao } 64058e5d94SFinley Xiao 652208cd92SJoseph Chen __weak int rk_board_init(void) 662208cd92SJoseph Chen { 672208cd92SJoseph Chen return 0; 682208cd92SJoseph Chen } 692208cd92SJoseph Chen 702208cd92SJoseph Chen /* 712208cd92SJoseph Chen * define serialno max length, the max length is 512 Bytes 722208cd92SJoseph Chen * The remaining bytes are used to ensure that the first 512 bytes 732208cd92SJoseph Chen * are valid when executing 'env_set("serial#", value)'. 742208cd92SJoseph Chen */ 752208cd92SJoseph Chen #define VENDOR_SN_MAX 513 762208cd92SJoseph Chen #define CPUID_LEN 0x10 772208cd92SJoseph Chen #define CPUID_OFF 0x07 782208cd92SJoseph Chen 792208cd92SJoseph Chen static int rockchip_set_ethaddr(void) 802208cd92SJoseph Chen { 812208cd92SJoseph Chen #ifdef CONFIG_ROCKCHIP_VENDOR_PARTITION 822208cd92SJoseph Chen char buf[ARP_HLEN_ASCII + 1]; 832208cd92SJoseph Chen u8 ethaddr[ARP_HLEN]; 842208cd92SJoseph Chen int ret; 852208cd92SJoseph Chen 862208cd92SJoseph Chen ret = vendor_storage_read(VENDOR_LAN_MAC_ID, ethaddr, sizeof(ethaddr)); 872208cd92SJoseph Chen if (ret > 0 && is_valid_ethaddr(ethaddr)) { 882208cd92SJoseph Chen sprintf(buf, "%pM", ethaddr); 892208cd92SJoseph Chen env_set("ethaddr", buf); 902208cd92SJoseph Chen } 912208cd92SJoseph Chen #endif 922208cd92SJoseph Chen return 0; 932208cd92SJoseph Chen } 942208cd92SJoseph Chen 952208cd92SJoseph Chen static int rockchip_set_serialno(void) 962208cd92SJoseph Chen { 972208cd92SJoseph Chen u8 low[CPUID_LEN / 2], high[CPUID_LEN / 2]; 982208cd92SJoseph Chen u8 cpuid[CPUID_LEN] = {0}; 992208cd92SJoseph Chen char serialno_str[VENDOR_SN_MAX]; 1002208cd92SJoseph Chen int ret = 0, i; 1012208cd92SJoseph Chen u64 serialno; 1022208cd92SJoseph Chen 1032208cd92SJoseph Chen /* Read serial number from vendor storage part */ 1042208cd92SJoseph Chen memset(serialno_str, 0, VENDOR_SN_MAX); 1052208cd92SJoseph Chen 1062208cd92SJoseph Chen #ifdef CONFIG_ROCKCHIP_VENDOR_PARTITION 1072208cd92SJoseph Chen ret = vendor_storage_read(VENDOR_SN_ID, serialno_str, (VENDOR_SN_MAX-1)); 1082208cd92SJoseph Chen if (ret > 0) { 1092208cd92SJoseph Chen env_set("serial#", serialno_str); 1102208cd92SJoseph Chen } else { 1112208cd92SJoseph Chen #endif 1122208cd92SJoseph Chen #ifdef CONFIG_ROCKCHIP_EFUSE 1132208cd92SJoseph Chen struct udevice *dev; 1142208cd92SJoseph Chen 1152208cd92SJoseph Chen /* retrieve the device */ 1162208cd92SJoseph Chen ret = uclass_get_device_by_driver(UCLASS_MISC, 1172208cd92SJoseph Chen DM_GET_DRIVER(rockchip_efuse), 1182208cd92SJoseph Chen &dev); 1192208cd92SJoseph Chen if (ret) { 1202208cd92SJoseph Chen printf("%s: could not find efuse device\n", __func__); 1212208cd92SJoseph Chen return ret; 1222208cd92SJoseph Chen } 1232208cd92SJoseph Chen 1242208cd92SJoseph Chen /* read the cpu_id range from the efuses */ 1252208cd92SJoseph Chen ret = misc_read(dev, CPUID_OFF, &cpuid, sizeof(cpuid)); 1262208cd92SJoseph Chen if (ret) { 1272208cd92SJoseph Chen printf("%s: read cpuid from efuses failed, ret=%d\n", 1282208cd92SJoseph Chen __func__, ret); 1292208cd92SJoseph Chen return ret; 1302208cd92SJoseph Chen } 1312208cd92SJoseph Chen #else 1322208cd92SJoseph Chen /* generate random cpuid */ 1332208cd92SJoseph Chen for (i = 0; i < CPUID_LEN; i++) 1342208cd92SJoseph Chen cpuid[i] = (u8)(rand()); 1352208cd92SJoseph Chen #endif 1362208cd92SJoseph Chen /* Generate the serial number based on CPU ID */ 1372208cd92SJoseph Chen for (i = 0; i < 8; i++) { 1382208cd92SJoseph Chen low[i] = cpuid[1 + (i << 1)]; 1392208cd92SJoseph Chen high[i] = cpuid[i << 1]; 1402208cd92SJoseph Chen } 1412208cd92SJoseph Chen 1422208cd92SJoseph Chen serialno = crc32_no_comp(0, low, 8); 1432208cd92SJoseph Chen serialno |= (u64)crc32_no_comp(serialno, high, 8) << 32; 1442208cd92SJoseph Chen snprintf(serialno_str, sizeof(serialno_str), "%llx", serialno); 1452208cd92SJoseph Chen 1462208cd92SJoseph Chen env_set("serial#", serialno_str); 1472208cd92SJoseph Chen #ifdef CONFIG_ROCKCHIP_VENDOR_PARTITION 1482208cd92SJoseph Chen } 1492208cd92SJoseph Chen #endif 1502208cd92SJoseph Chen 1512208cd92SJoseph Chen return ret; 1522208cd92SJoseph Chen } 1532208cd92SJoseph Chen 1542208cd92SJoseph Chen #if defined(CONFIG_USB_FUNCTION_FASTBOOT) 1552208cd92SJoseph Chen int fb_set_reboot_flag(void) 1562208cd92SJoseph Chen { 1572208cd92SJoseph Chen printf("Setting reboot to fastboot flag ...\n"); 1582208cd92SJoseph Chen writel(BOOT_FASTBOOT, CONFIG_ROCKCHIP_BOOT_MODE_REG); 1592208cd92SJoseph Chen 1602208cd92SJoseph Chen return 0; 1612208cd92SJoseph Chen } 1622208cd92SJoseph Chen #endif 1632208cd92SJoseph Chen 1640ed06f16SJoseph Chen #ifdef CONFIG_ROCKCHIP_USB_BOOT 1650ed06f16SJoseph Chen static int boot_from_udisk(void) 1660ed06f16SJoseph Chen { 1670ed06f16SJoseph Chen struct blk_desc *desc; 1680ed06f16SJoseph Chen char *devtype; 1690ed06f16SJoseph Chen char *devnum; 1700ed06f16SJoseph Chen 1710ed06f16SJoseph Chen devtype = env_get("devtype"); 1720ed06f16SJoseph Chen devnum = env_get("devnum"); 1730ed06f16SJoseph Chen 1740ed06f16SJoseph Chen /* Booting priority: mmc1 > udisk */ 1750ed06f16SJoseph Chen if (!strcmp(devtype, "mmc") && !strcmp(devnum, "1")) 1760ed06f16SJoseph Chen return 0; 1770ed06f16SJoseph Chen 1780ed06f16SJoseph Chen if (!run_command("usb start", -1)) { 1790ed06f16SJoseph Chen desc = blk_get_devnum_by_type(IF_TYPE_USB, 0); 1800ed06f16SJoseph Chen if (!desc) { 1810ed06f16SJoseph Chen printf("No usb device found\n"); 1820ed06f16SJoseph Chen return -ENODEV; 1830ed06f16SJoseph Chen } 1840ed06f16SJoseph Chen 1850ed06f16SJoseph Chen if (!run_command("rkimgtest usb 0", -1)) { 1860ed06f16SJoseph Chen rockchip_set_bootdev(desc); 1870ed06f16SJoseph Chen env_set("devtype", "usb"); 1880ed06f16SJoseph Chen env_set("devnum", "0"); 1890ed06f16SJoseph Chen printf("Boot from usb 0\n"); 1900ed06f16SJoseph Chen } else { 1910ed06f16SJoseph Chen printf("No usb dev 0 found\n"); 1920ed06f16SJoseph Chen return -ENODEV; 1930ed06f16SJoseph Chen } 1940ed06f16SJoseph Chen } 1950ed06f16SJoseph Chen 1960ed06f16SJoseph Chen return 0; 1970ed06f16SJoseph Chen } 1980ed06f16SJoseph Chen #endif 1990ed06f16SJoseph Chen 20083c9bd4bSJoseph Chen static void cmdline_handle(void) 20183c9bd4bSJoseph Chen { 20283c9bd4bSJoseph Chen #ifdef CONFIG_ROCKCHIP_PRELOADER_ATAGS 20383c9bd4bSJoseph Chen struct tag *t; 20483c9bd4bSJoseph Chen 20583c9bd4bSJoseph Chen t = atags_get_tag(ATAG_PUB_KEY); 20683c9bd4bSJoseph Chen if (t) { 20783c9bd4bSJoseph Chen /* Pass if efuse/otp programmed */ 20883c9bd4bSJoseph Chen if (t->u.pub_key.flag == PUBKEY_FUSE_PROGRAMMED) 20983c9bd4bSJoseph Chen env_update("bootargs", "fuse.programmed=1"); 21083c9bd4bSJoseph Chen else 21183c9bd4bSJoseph Chen env_update("bootargs", "fuse.programmed=0"); 21283c9bd4bSJoseph Chen } 21383c9bd4bSJoseph Chen #endif 21483c9bd4bSJoseph Chen } 21583c9bd4bSJoseph Chen 21638771996SKever Yang int board_late_init(void) 21738771996SKever Yang { 2182549364dSlanshh rockchip_set_ethaddr(); 219fc1a5563SJason Zhu rockchip_set_serialno(); 22038771996SKever Yang #if (CONFIG_ROCKCHIP_BOOT_MODE_REG > 0) 22138771996SKever Yang setup_boot_mode(); 22238771996SKever Yang #endif 2230ed06f16SJoseph Chen #ifdef CONFIG_ROCKCHIP_USB_BOOT 2240ed06f16SJoseph Chen boot_from_udisk(); 2250ed06f16SJoseph Chen #endif 22638771996SKever Yang #ifdef CONFIG_DM_CHARGE_DISPLAY 22738771996SKever Yang charge_display(); 22838771996SKever Yang #endif 22938771996SKever Yang #ifdef CONFIG_DRM_ROCKCHIP 23038771996SKever Yang rockchip_show_logo(); 23138771996SKever Yang #endif 232efdbac34SFinley Xiao soc_clk_dump(); 23383c9bd4bSJoseph Chen cmdline_handle(); 234efdbac34SFinley Xiao 23538771996SKever Yang return rk_board_late_init(); 23638771996SKever Yang } 23738771996SKever Yang 238f8aaa2c2SKever Yang #ifdef CONFIG_USING_KERNEL_DTB 2393e45175eSJoseph Chen /* Here, only fixup cru phandle, pmucru is not included */ 2409f8dc175SJoseph Chen static int phandles_fixup_cru(void *fdt) 2413e45175eSJoseph Chen { 2423e45175eSJoseph Chen const char *props[] = { "clocks", "assigned-clocks" }; 2433e45175eSJoseph Chen struct udevice *dev; 2443e45175eSJoseph Chen struct uclass *uc; 2453e45175eSJoseph Chen const char *comp; 2463e45175eSJoseph Chen u32 id, nclocks; 2473e45175eSJoseph Chen u32 *clocks; 2483e45175eSJoseph Chen int phandle, ncells; 2493e45175eSJoseph Chen int off, offset; 2503e45175eSJoseph Chen int ret, length; 2513e45175eSJoseph Chen int i, j; 2523e45175eSJoseph Chen int first_phandle = -1; 2533e45175eSJoseph Chen 2543e45175eSJoseph Chen phandle = -ENODATA; 2553e45175eSJoseph Chen ncells = -ENODATA; 2563e45175eSJoseph Chen 2573e45175eSJoseph Chen /* fdt points to kernel dtb, getting cru phandle and "#clock-cells" */ 2583e45175eSJoseph Chen for (offset = fdt_next_node(fdt, 0, NULL); 2593e45175eSJoseph Chen offset >= 0; 2603e45175eSJoseph Chen offset = fdt_next_node(fdt, offset, NULL)) { 2613e45175eSJoseph Chen comp = fdt_getprop(fdt, offset, "compatible", NULL); 2623e45175eSJoseph Chen if (!comp) 2633e45175eSJoseph Chen continue; 2643e45175eSJoseph Chen 2653e45175eSJoseph Chen /* Actually, this is not a good method to get cru node */ 2663e45175eSJoseph Chen off = strlen(comp) - strlen("-cru"); 2673e45175eSJoseph Chen if (off > 0 && !strncmp(comp + off, "-cru", 4)) { 2683e45175eSJoseph Chen phandle = fdt_get_phandle(fdt, offset); 2693e45175eSJoseph Chen ncells = fdtdec_get_int(fdt, offset, 2703e45175eSJoseph Chen "#clock-cells", -ENODATA); 2713e45175eSJoseph Chen break; 2723e45175eSJoseph Chen } 2733e45175eSJoseph Chen } 2743e45175eSJoseph Chen 2753e45175eSJoseph Chen if (phandle == -ENODATA || ncells == -ENODATA) 2763e45175eSJoseph Chen return 0; 2773e45175eSJoseph Chen 2783e45175eSJoseph Chen debug("%s: target cru: clock-cells:%d, phandle:0x%x\n", 2793e45175eSJoseph Chen __func__, ncells, fdt32_to_cpu(phandle)); 2803e45175eSJoseph Chen 2813e45175eSJoseph Chen /* Try to fixup all cru phandle from U-Boot dtb nodes */ 2823e45175eSJoseph Chen for (id = 0; id < UCLASS_COUNT; id++) { 2833e45175eSJoseph Chen ret = uclass_get(id, &uc); 2843e45175eSJoseph Chen if (ret) 2853e45175eSJoseph Chen continue; 2863e45175eSJoseph Chen 2873e45175eSJoseph Chen if (list_empty(&uc->dev_head)) 2883e45175eSJoseph Chen continue; 2893e45175eSJoseph Chen 2903e45175eSJoseph Chen list_for_each_entry(dev, &uc->dev_head, uclass_node) { 2913e45175eSJoseph Chen /* Only U-Boot node go further */ 292d625acc2SJoseph Chen if (!dev_read_bool(dev, "u-boot,dm-pre-reloc") && 2932a5ad8b3SJoseph Chen !dev_read_bool(dev, "u-boot,dm-spl")) 2943e45175eSJoseph Chen continue; 2953e45175eSJoseph Chen 2963e45175eSJoseph Chen for (i = 0; i < ARRAY_SIZE(props); i++) { 2973e45175eSJoseph Chen if (!dev_read_prop(dev, props[i], &length)) 2983e45175eSJoseph Chen continue; 2993e45175eSJoseph Chen 3003e45175eSJoseph Chen clocks = malloc(length); 3013e45175eSJoseph Chen if (!clocks) 3023e45175eSJoseph Chen return -ENOMEM; 3033e45175eSJoseph Chen 3043e45175eSJoseph Chen /* Read "props[]" which contains cru phandle */ 3053e45175eSJoseph Chen nclocks = length / sizeof(u32); 3063e45175eSJoseph Chen if (dev_read_u32_array(dev, props[i], 3073e45175eSJoseph Chen clocks, nclocks)) { 3083e45175eSJoseph Chen free(clocks); 3093e45175eSJoseph Chen continue; 3103e45175eSJoseph Chen } 3113e45175eSJoseph Chen 3123e45175eSJoseph Chen /* Fixup with kernel cru phandle */ 3133e45175eSJoseph Chen for (j = 0; j < nclocks; j += (ncells + 1)) { 3143e45175eSJoseph Chen /* 3153e45175eSJoseph Chen * Check: update pmucru phandle with cru 3163e45175eSJoseph Chen * phandle by mistake. 3173e45175eSJoseph Chen */ 3183e45175eSJoseph Chen if (first_phandle == -1) 3193e45175eSJoseph Chen first_phandle = clocks[j]; 3203e45175eSJoseph Chen 3218526ae77SJoseph Chen if (clocks[j] != first_phandle) { 3228526ae77SJoseph Chen debug("WARN: %s: first cru phandle=%d, this=%d\n", 3233e45175eSJoseph Chen dev_read_name(dev), 3243e45175eSJoseph Chen first_phandle, clocks[j]); 3258526ae77SJoseph Chen continue; 3268526ae77SJoseph Chen } 3273e45175eSJoseph Chen 3283e45175eSJoseph Chen clocks[j] = phandle; 3293e45175eSJoseph Chen } 3303e45175eSJoseph Chen 3313e45175eSJoseph Chen /* 3323e45175eSJoseph Chen * Override live dt nodes but not fdt nodes, 3333e45175eSJoseph Chen * because all U-Boot nodes has been imported 3343e45175eSJoseph Chen * to live dt nodes, should use "dev_xxx()". 3353e45175eSJoseph Chen */ 3363e45175eSJoseph Chen dev_write_u32_array(dev, props[i], 3373e45175eSJoseph Chen clocks, nclocks); 3383e45175eSJoseph Chen free(clocks); 3393e45175eSJoseph Chen } 3403e45175eSJoseph Chen } 3413e45175eSJoseph Chen } 3423e45175eSJoseph Chen 3433e45175eSJoseph Chen return 0; 3443e45175eSJoseph Chen } 3453e45175eSJoseph Chen 3469f8dc175SJoseph Chen static int phandles_fixup_gpio(void *fdt, void *ufdt) 3479f8dc175SJoseph Chen { 3489f8dc175SJoseph Chen struct udevice *dev; 3499f8dc175SJoseph Chen struct uclass *uc; 3509f8dc175SJoseph Chen const char *prop = "gpios"; 3519f8dc175SJoseph Chen const char *comp; 3529f8dc175SJoseph Chen char *gpio_name[10]; 3539f8dc175SJoseph Chen int gpio_off[10]; 3549f8dc175SJoseph Chen int pinctrl; 3559f8dc175SJoseph Chen int offset; 3569f8dc175SJoseph Chen int i = 0; 3579f8dc175SJoseph Chen int n = 0; 3589f8dc175SJoseph Chen 3599f8dc175SJoseph Chen pinctrl = fdt_path_offset(fdt, "/pinctrl"); 3609f8dc175SJoseph Chen if (pinctrl < 0) 3619f8dc175SJoseph Chen return 0; 3629f8dc175SJoseph Chen 3639f8dc175SJoseph Chen memset(gpio_name, 0, sizeof(gpio_name)); 3649f8dc175SJoseph Chen for (offset = fdt_first_subnode(fdt, pinctrl); 3659f8dc175SJoseph Chen offset >= 0; 3669f8dc175SJoseph Chen offset = fdt_next_subnode(fdt, offset)) { 3679f8dc175SJoseph Chen /* assume the font nodes are gpio node */ 3689f8dc175SJoseph Chen if (++i >= ARRAY_SIZE(gpio_name)) 3699f8dc175SJoseph Chen break; 3709f8dc175SJoseph Chen 3719f8dc175SJoseph Chen comp = fdt_getprop(fdt, offset, "compatible", NULL); 3729f8dc175SJoseph Chen if (!comp) 3739f8dc175SJoseph Chen continue; 3749f8dc175SJoseph Chen 3759f8dc175SJoseph Chen if (!strcmp(comp, "rockchip,gpio-bank")) { 3769f8dc175SJoseph Chen gpio_name[n] = (char *)fdt_get_name(fdt, offset, NULL); 3779f8dc175SJoseph Chen gpio_off[n] = offset; 3789f8dc175SJoseph Chen n++; 3799f8dc175SJoseph Chen } 3809f8dc175SJoseph Chen } 3819f8dc175SJoseph Chen 3829f8dc175SJoseph Chen if (!gpio_name[0]) 3839f8dc175SJoseph Chen return 0; 3849f8dc175SJoseph Chen 3859f8dc175SJoseph Chen if (uclass_get(UCLASS_KEY, &uc) || list_empty(&uc->dev_head)) 3869f8dc175SJoseph Chen return 0; 3879f8dc175SJoseph Chen 3889f8dc175SJoseph Chen list_for_each_entry(dev, &uc->dev_head, uclass_node) { 3899f8dc175SJoseph Chen u32 new_phd, phd_old; 3909f8dc175SJoseph Chen char *name; 3919f8dc175SJoseph Chen ofnode ofn; 3929f8dc175SJoseph Chen 3939f8dc175SJoseph Chen if (!dev_read_bool(dev, "u-boot,dm-pre-reloc") && 3949f8dc175SJoseph Chen !dev_read_bool(dev, "u-boot,dm-spl")) 3959f8dc175SJoseph Chen continue; 3969f8dc175SJoseph Chen 3979f8dc175SJoseph Chen if (dev_read_u32_array(dev, prop, &phd_old, 1)) 3989f8dc175SJoseph Chen continue; 3999f8dc175SJoseph Chen 4009f8dc175SJoseph Chen ofn = ofnode_get_by_phandle(phd_old); 4019f8dc175SJoseph Chen if (!ofnode_valid(ofn)) 4029f8dc175SJoseph Chen continue; 4039f8dc175SJoseph Chen 4049f8dc175SJoseph Chen name = (char *)ofnode_get_name(ofn); 4059f8dc175SJoseph Chen if (!name) 4069f8dc175SJoseph Chen continue; 4079f8dc175SJoseph Chen 4089f8dc175SJoseph Chen for (i = 0; i < ARRAY_SIZE(gpio_name[i]); i++) { 4099f8dc175SJoseph Chen if (gpio_name[i] && !strcmp(name, gpio_name[i])) { 4109f8dc175SJoseph Chen new_phd = fdt_get_phandle(fdt, gpio_off[i]); 4119f8dc175SJoseph Chen dev_write_u32_array(dev, prop, &new_phd, 1); 4129f8dc175SJoseph Chen break; 4139f8dc175SJoseph Chen } 4149f8dc175SJoseph Chen } 4159f8dc175SJoseph Chen } 4169f8dc175SJoseph Chen 4179f8dc175SJoseph Chen return 0; 4189f8dc175SJoseph Chen } 4199f8dc175SJoseph Chen 420f8aaa2c2SKever Yang int init_kernel_dtb(void) 421f8aaa2c2SKever Yang { 4222208cd92SJoseph Chen ulong fdt_addr; 4239f8dc175SJoseph Chen void *ufdt_blob; 4242208cd92SJoseph Chen int ret; 425f8aaa2c2SKever Yang 426f8aaa2c2SKever Yang fdt_addr = env_get_ulong("fdt_addr_r", 16, 0); 427f8aaa2c2SKever Yang if (!fdt_addr) { 428f8aaa2c2SKever Yang printf("No Found FDT Load Address.\n"); 429f8aaa2c2SKever Yang return -1; 430f8aaa2c2SKever Yang } 431f8aaa2c2SKever Yang 432740107bbSJoseph Chen ret = rockchip_read_dtb_file((void *)fdt_addr); 433f8aaa2c2SKever Yang if (ret < 0) { 4340ed06f16SJoseph Chen if (!fdt_check_header(gd->fdt_blob_kern)) { 4350ed06f16SJoseph Chen fdt_addr = (ulong)memalign(ARCH_DMA_MINALIGN, 4360ed06f16SJoseph Chen fdt_totalsize(gd->fdt_blob_kern)); 4370ed06f16SJoseph Chen if (!fdt_addr) 4380ed06f16SJoseph Chen return -ENOMEM; 4390ed06f16SJoseph Chen 4400ed06f16SJoseph Chen memcpy((void *)fdt_addr, gd->fdt_blob_kern, 4410ed06f16SJoseph Chen fdt_totalsize(gd->fdt_blob_kern)); 4420ed06f16SJoseph Chen printf("DTB: embedded kern.dtb\n"); 4430ed06f16SJoseph Chen } else { 4440ed06f16SJoseph Chen printf("Failed to get kernel dtb, ret=%d\n", ret); 4450ed06f16SJoseph Chen return ret; 446f8aaa2c2SKever Yang } 4470ed06f16SJoseph Chen } 4480ed06f16SJoseph Chen 4499f8dc175SJoseph Chen ufdt_blob = (void *)gd->fdt_blob; 4500ed06f16SJoseph Chen gd->fdt_blob = (void *)fdt_addr; 451f8aaa2c2SKever Yang 4523e45175eSJoseph Chen /* 4533e45175eSJoseph Chen * There is a phandle miss match between U-Boot and kernel dtb node, 4549f8dc175SJoseph Chen * we fixup it in U-Boot live dt nodes. 4559f8dc175SJoseph Chen * 4569f8dc175SJoseph Chen * CRU: all nodes. 4579f8dc175SJoseph Chen * GPIO: key nodes. 4583e45175eSJoseph Chen */ 4599f8dc175SJoseph Chen phandles_fixup_cru((void *)gd->fdt_blob); 4609f8dc175SJoseph Chen phandles_fixup_gpio((void *)gd->fdt_blob, (void *)ufdt_blob); 4613e45175eSJoseph Chen 4620ed06f16SJoseph Chen of_live_build((void *)gd->fdt_blob, (struct device_node **)&gd->of_root); 4630ed06f16SJoseph Chen dm_scan_fdt((void *)gd->fdt_blob, false); 464f8aaa2c2SKever Yang 4656929f85bSJoseph Chen /* Reserve 'reserved-memory' */ 4666929f85bSJoseph Chen ret = boot_fdt_add_sysmem_rsv_regions((void *)gd->fdt_blob); 4676929f85bSJoseph Chen if (ret) 4686929f85bSJoseph Chen return ret; 4696929f85bSJoseph Chen 470f8aaa2c2SKever Yang return 0; 471f8aaa2c2SKever Yang } 472f8aaa2c2SKever Yang #endif 473f8aaa2c2SKever Yang 474bc04a3ddSJoseph Chen void board_env_fixup(void) 475bc04a3ddSJoseph Chen { 476124f23c6SJoseph Chen struct memblock mem; 477124f23c6SJoseph Chen ulong u_addr_r; 478124f23c6SJoseph Chen phys_size_t end; 4794dfe920aSJoseph Chen char *addr_r; 480124f23c6SJoseph Chen 4814dfe920aSJoseph Chen #ifdef ENV_MEM_LAYOUT_SETTINGS1 4824dfe920aSJoseph Chen const char *env_addr0[] = { 4834dfe920aSJoseph Chen "scriptaddr", "pxefile_addr_r", 4844dfe920aSJoseph Chen "fdt_addr_r", "kernel_addr_r", "ramdisk_addr_r", 4854dfe920aSJoseph Chen }; 4864dfe920aSJoseph Chen const char *env_addr1[] = { 4874dfe920aSJoseph Chen "scriptaddr1", "pxefile_addr1_r", 4884dfe920aSJoseph Chen "fdt_addr1_r", "kernel_addr1_r", "ramdisk_addr1_r", 4894dfe920aSJoseph Chen }; 4904dfe920aSJoseph Chen int i; 491bc04a3ddSJoseph Chen 4924dfe920aSJoseph Chen /* 128M is a typical ram size for most platform, so as default here */ 4934dfe920aSJoseph Chen if (gd->ram_size <= SZ_128M) { 4944dfe920aSJoseph Chen /* Replace orignal xxx_addr_r */ 4954dfe920aSJoseph Chen for (i = 0; i < ARRAY_SIZE(env_addr1); i++) { 4964dfe920aSJoseph Chen addr_r = env_get(env_addr1[i]); 4974dfe920aSJoseph Chen if (addr_r) 4984dfe920aSJoseph Chen env_set(env_addr0[i], addr_r); 4994dfe920aSJoseph Chen } 5004dfe920aSJoseph Chen } 5014dfe920aSJoseph Chen #endif 502bc04a3ddSJoseph Chen /* If bl32 is disabled, maybe kernel can be load to lower address. */ 5034dfe920aSJoseph Chen if (!(gd->flags & GD_FLG_BL32_ENABLED)) { 5044dfe920aSJoseph Chen addr_r = env_get("kernel_addr_no_bl32_r"); 5054dfe920aSJoseph Chen if (addr_r) 5064dfe920aSJoseph Chen env_set("kernel_addr_r", addr_r); 507124f23c6SJoseph Chen /* If bl32 is enlarged, we move ramdisk addr right behind it */ 508124f23c6SJoseph Chen } else { 509124f23c6SJoseph Chen mem = param_parse_optee_mem(); 510124f23c6SJoseph Chen end = mem.base + mem.size; 511124f23c6SJoseph Chen u_addr_r = env_get_ulong("ramdisk_addr_r", 16, 0); 512124f23c6SJoseph Chen if (u_addr_r >= mem.base && u_addr_r < end) 513124f23c6SJoseph Chen env_set_hex("ramdisk_addr_r", end); 5144dfe920aSJoseph Chen } 515bc04a3ddSJoseph Chen } 516f8aaa2c2SKever Yang 5177397b961SJoseph Chen static void early_download_init(void) 518644804edSJoseph Chen { 5197397b961SJoseph Chen #if defined(CONFIG_PWRKEY_DNL_TRIGGER_NUM) && \ 5207397b961SJoseph Chen (CONFIG_PWRKEY_DNL_TRIGGER_NUM > 0) 5217397b961SJoseph Chen if (pwrkey_download_init()) 5227397b961SJoseph Chen printf("Pwrkey download init failed\n"); 5237397b961SJoseph Chen #endif 5247397b961SJoseph Chen 525644804edSJoseph Chen if (!tstc()) 526644804edSJoseph Chen return; 527644804edSJoseph Chen 528644804edSJoseph Chen gd->console_evt = getc(); 52915c8c8dbSJoseph Chen if (gd->console_evt <= 0x1a) /* 'z' */ 53015c8c8dbSJoseph Chen printf("Hotkey: ctrl+%c\n", (gd->console_evt + 'a' - 1)); 53115c8c8dbSJoseph Chen 532644804edSJoseph Chen #if (CONFIG_ROCKCHIP_BOOT_MODE_REG > 0) 533c664909eSJoseph Chen if (is_hotkey(HK_BROM_DNL)) { 534644804edSJoseph Chen printf("Enter bootrom download..."); 535363411a1SJoseph Chen flushc(); 536644804edSJoseph Chen writel(BOOT_BROM_DOWNLOAD, CONFIG_ROCKCHIP_BOOT_MODE_REG); 537644804edSJoseph Chen do_reset(NULL, 0, 0, NULL); 538644804edSJoseph Chen printf("failed!\n"); 539644804edSJoseph Chen } 540644804edSJoseph Chen #endif 541644804edSJoseph Chen } 542644804edSJoseph Chen 543*5d5f363eSJoseph Chen static void board_debug_init(void) 544*5d5f363eSJoseph Chen { 545*5d5f363eSJoseph Chen if (!gd->serial.using_pre_serial) 546*5d5f363eSJoseph Chen board_debug_uart_init(); 547*5d5f363eSJoseph Chen } 548*5d5f363eSJoseph Chen 54938771996SKever Yang int board_init(void) 55038771996SKever Yang { 551*5d5f363eSJoseph Chen board_debug_init(); 552ebb6c439SYouMin Chen 553f0aa8c5dSJason Zhu #ifdef DEBUG 554f0aa8c5dSJason Zhu soc_clk_dump(); 555f0aa8c5dSJason Zhu #endif 556f0aa8c5dSJason Zhu 557f8aaa2c2SKever Yang #ifdef CONFIG_USING_KERNEL_DTB 558f8aaa2c2SKever Yang init_kernel_dtb(); 559f8aaa2c2SKever Yang #endif 5607397b961SJoseph Chen early_download_init(); 5617397b961SJoseph Chen 5629f8e13d3SFinley Xiao /* 5639f8e13d3SFinley Xiao * pmucru isn't referenced on some platforms, so pmucru driver can't 5649f8e13d3SFinley Xiao * probe that the "assigned-clocks" is unused. 5659f8e13d3SFinley Xiao */ 5669f8e13d3SFinley Xiao clks_probe(); 56738771996SKever Yang #ifdef CONFIG_DM_REGULATOR 568dba9c9e5SJoseph Chen if (regulators_enable_boot_on(is_hotkey(HK_REGULATOR))) 5692208cd92SJoseph Chen debug("%s: Can't enable boot on regulator\n", __func__); 57038771996SKever Yang #endif 571dae20286SJianqun Xu 572dae20286SJianqun Xu #ifdef CONFIG_ROCKCHIP_IO_DOMAIN 573dae20286SJianqun Xu io_domain_init(); 574dae20286SJianqun Xu #endif 575dae20286SJianqun Xu 576058e5d94SFinley Xiao set_armclk_rate(); 57738771996SKever Yang 5783acf4edfSJoseph Chen #ifdef CONFIG_DM_DVFS 5793acf4edfSJoseph Chen dvfs_init(true); 5803acf4edfSJoseph Chen #endif 5813acf4edfSJoseph Chen 58238771996SKever Yang return rk_board_init(); 58338771996SKever Yang } 58438771996SKever Yang 585c563adc7SJoseph Chen int interrupt_debugger_init(void) 586c563adc7SJoseph Chen { 587c563adc7SJoseph Chen #ifdef CONFIG_ROCKCHIP_DEBUGGER 5882208cd92SJoseph Chen return rockchip_debugger_init(); 5892208cd92SJoseph Chen #else 5902208cd92SJoseph Chen return 0; 591c563adc7SJoseph Chen #endif 592c563adc7SJoseph Chen } 593c563adc7SJoseph Chen 594e09b1e4aSJoseph Chen int board_fdt_fixup(void *blob) 595e09b1e4aSJoseph Chen { 5962208cd92SJoseph Chen /* Common fixup for DRM */ 597e09b1e4aSJoseph Chen #ifdef CONFIG_DRM_ROCKCHIP 598e09b1e4aSJoseph Chen rockchip_display_fixup(blob); 599e09b1e4aSJoseph Chen #endif 600e09b1e4aSJoseph Chen 60138ce6261SJoseph Chen return rk_board_fdt_fixup(blob); 602e09b1e4aSJoseph Chen } 603e09b1e4aSJoseph Chen 604e3fbd280SJoseph Chen #ifdef CONFIG_ARM64_BOOT_AARCH32 605e3fbd280SJoseph Chen /* 606e3fbd280SJoseph Chen * Fixup MMU region attr for OP-TEE on ARMv8 CPU: 607e3fbd280SJoseph Chen * 608e3fbd280SJoseph Chen * What ever U-Boot is 64-bit or 32-bit mode, the OP-TEE is always 64-bit mode. 609e3fbd280SJoseph Chen * 610e3fbd280SJoseph Chen * Command for OP-TEE: 611e3fbd280SJoseph Chen * 64-bit mode: dcache is always enabled; 612e3fbd280SJoseph Chen * 32-bit mode: dcache is always disabled(Due to some unknown issue); 613e3fbd280SJoseph Chen * 614e3fbd280SJoseph Chen * Command for U-Boot: 615e3fbd280SJoseph Chen * 64-bit mode: MMU table is static defined in rkxxx.c file, all memory 616e3fbd280SJoseph Chen * regions are mapped. That's good to match OP-TEE MMU policy. 617e3fbd280SJoseph Chen * 618e3fbd280SJoseph Chen * 32-bit mode: MMU table is setup according to gd->bd->bi_dram[..] where 619e3fbd280SJoseph Chen * the OP-TEE region has been reserved, so it can not be 620e3fbd280SJoseph Chen * mapped(i.e. dcache is disabled). That's also good to match 621e3fbd280SJoseph Chen * OP-TEE MMU policy. 622e3fbd280SJoseph Chen * 623e3fbd280SJoseph Chen * For the data coherence when communication between U-Boot and OP-TEE, U-Boot 624e3fbd280SJoseph Chen * should follow OP-TEE MMU policy. 625e3fbd280SJoseph Chen * 626e3fbd280SJoseph Chen * Here is the special: 627e3fbd280SJoseph Chen * When CONFIG_ARM64_BOOT_AARCH32 is enabled, U-Boot is 32-bit mode while 628e3fbd280SJoseph Chen * OP-TEE is still 64-bit mode. U-Boot would not map MMU table for OP-TEE 629e3fbd280SJoseph Chen * region(but OP-TEE requires it cacheable) so we fixup here. 630e3fbd280SJoseph Chen */ 631e3fbd280SJoseph Chen int board_initr_caches_fixup(void) 632e3fbd280SJoseph Chen { 633e3fbd280SJoseph Chen struct memblock mem; 634e3fbd280SJoseph Chen 635e3fbd280SJoseph Chen mem = param_parse_optee_mem(); 636e3fbd280SJoseph Chen if (mem.size) 637e3fbd280SJoseph Chen mmu_set_region_dcache_behaviour(mem.base, mem.size, 638e3fbd280SJoseph Chen DCACHE_WRITEBACK); 639e3fbd280SJoseph Chen return 0; 640e3fbd280SJoseph Chen } 641e3fbd280SJoseph Chen #endif 642e3fbd280SJoseph Chen 643665be4b0SJoseph Chen void arch_preboot_os(uint32_t bootm_state) 644665be4b0SJoseph Chen { 645665be4b0SJoseph Chen if (bootm_state & BOOTM_STATE_OS_PREP) 646665be4b0SJoseph Chen hotkey_run(HK_CLI_OS_PRE); 647665be4b0SJoseph Chen } 648665be4b0SJoseph Chen 6493e6a97f9SJoseph Chen void board_quiesce_devices(void) 6503e6a97f9SJoseph Chen { 65115c8c8dbSJoseph Chen hotkey_run(HK_CMDLINE); 652665be4b0SJoseph Chen hotkey_run(HK_CLI_OS_GO); 65315c8c8dbSJoseph Chen 6544892a977SJoseph Chen #ifdef CONFIG_ROCKCHIP_PRELOADER_ATAGS 6553e6a97f9SJoseph Chen /* Destroy atags makes next warm boot safer */ 6563e6a97f9SJoseph Chen atags_destroy(); 6574892a977SJoseph Chen #endif 6589dfc5f87SJoseph Chen 6599dfc5f87SJoseph Chen #if defined(CONFIG_CONSOLE_RECORD) 6609dfc5f87SJoseph Chen /* Print record console data */ 6619dfc5f87SJoseph Chen console_record_print_purge(); 6629dfc5f87SJoseph Chen #endif 6633e6a97f9SJoseph Chen } 6643e6a97f9SJoseph Chen 66538771996SKever Yang void enable_caches(void) 66638771996SKever Yang { 667567735c8SJoseph Chen icache_enable(); 66838771996SKever Yang dcache_enable(); 66938771996SKever Yang } 67038771996SKever Yang 6712dc2d048SJoseph Chen #ifdef CONFIG_LMB 6722c6a058bSJoseph Chen /* 6732c6a058bSJoseph Chen * Using last bi_dram[...] to initialize "bootm_low" and "bootm_mapsize". 6742c6a058bSJoseph Chen * This makes lmb_alloc_base() always alloc from tail of sdram. 6752c6a058bSJoseph Chen * If we don't assign it, bi_dram[0] is used by default and it may cause 6762c6a058bSJoseph Chen * lmb_alloc_base() fail when bi_dram[0] range is small. 6772c6a058bSJoseph Chen */ 6782c6a058bSJoseph Chen void board_lmb_reserve(struct lmb *lmb) 6792c6a058bSJoseph Chen { 6802c6a058bSJoseph Chen char bootm_mapsize[32]; 6812208cd92SJoseph Chen char bootm_low[32]; 6822208cd92SJoseph Chen u64 start, size; 6832c6a058bSJoseph Chen int i; 6842c6a058bSJoseph Chen 6852c6a058bSJoseph Chen for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { 6862c6a058bSJoseph Chen if (!gd->bd->bi_dram[i].size) 6872c6a058bSJoseph Chen break; 6882c6a058bSJoseph Chen } 6892c6a058bSJoseph Chen 6902c6a058bSJoseph Chen start = gd->bd->bi_dram[i - 1].start; 6912c6a058bSJoseph Chen size = gd->bd->bi_dram[i - 1].size; 6922c6a058bSJoseph Chen 6932c6a058bSJoseph Chen /* 6942dc2d048SJoseph Chen * 32-bit kernel: ramdisk/fdt shouldn't be loaded to highmem area(768MB+), 6952dc2d048SJoseph Chen * otherwise "Unable to handle kernel paging request at virtual address ...". 6962dc2d048SJoseph Chen * 6972dc2d048SJoseph Chen * So that we hope limit highest address at 768M, but there comes the the 6982dc2d048SJoseph Chen * problem: ramdisk is a compressed image and it expands after descompress, 6992dc2d048SJoseph Chen * so it accesses 768MB+ and brings the above "Unable to handle kernel ...". 7002dc2d048SJoseph Chen * 7012dc2d048SJoseph Chen * We make a appointment that the highest memory address is 512MB, it 7022dc2d048SJoseph Chen * makes lmb alloc safer. 7032c6a058bSJoseph Chen */ 7042dc2d048SJoseph Chen #ifndef CONFIG_ARM64 7052dc2d048SJoseph Chen if (start >= ((u64)CONFIG_SYS_SDRAM_BASE + SZ_512M)) { 7062c6a058bSJoseph Chen start = gd->bd->bi_dram[i - 2].start; 7072c6a058bSJoseph Chen size = gd->bd->bi_dram[i - 2].size; 7082c6a058bSJoseph Chen } 7092c6a058bSJoseph Chen 7102dc2d048SJoseph Chen if ((start + size) > ((u64)CONFIG_SYS_SDRAM_BASE + SZ_512M)) 7112dc2d048SJoseph Chen size = (u64)CONFIG_SYS_SDRAM_BASE + SZ_512M - start; 7122c6a058bSJoseph Chen #endif 7132c6a058bSJoseph Chen sprintf(bootm_low, "0x%llx", start); 7142c6a058bSJoseph Chen sprintf(bootm_mapsize, "0x%llx", size); 7152c6a058bSJoseph Chen env_set("bootm_low", bootm_low); 7162c6a058bSJoseph Chen env_set("bootm_mapsize", bootm_mapsize); 7172c6a058bSJoseph Chen } 7182dc2d048SJoseph Chen #endif 7192c6a058bSJoseph Chen 72086f870d6SJoseph Chen #ifdef CONFIG_BIDRAM 72186f870d6SJoseph Chen int board_bidram_reserve(struct bidram *bidram) 72286f870d6SJoseph Chen { 72386f870d6SJoseph Chen struct memblock mem; 72486f870d6SJoseph Chen int ret; 72586f870d6SJoseph Chen 72686f870d6SJoseph Chen /* ATF */ 72786f870d6SJoseph Chen mem = param_parse_atf_mem(); 72886f870d6SJoseph Chen ret = bidram_reserve(MEMBLK_ID_ATF, mem.base, mem.size); 72986f870d6SJoseph Chen if (ret) 73086f870d6SJoseph Chen return ret; 73186f870d6SJoseph Chen 73286f870d6SJoseph Chen /* PSTORE/ATAGS/SHM */ 73386f870d6SJoseph Chen mem = param_parse_common_resv_mem(); 73486f870d6SJoseph Chen ret = bidram_reserve(MEMBLK_ID_SHM, mem.base, mem.size); 73586f870d6SJoseph Chen if (ret) 73686f870d6SJoseph Chen return ret; 73786f870d6SJoseph Chen 73886f870d6SJoseph Chen /* OP-TEE */ 73986f870d6SJoseph Chen mem = param_parse_optee_mem(); 74086f870d6SJoseph Chen ret = bidram_reserve(MEMBLK_ID_OPTEE, mem.base, mem.size); 74186f870d6SJoseph Chen if (ret) 74286f870d6SJoseph Chen return ret; 74386f870d6SJoseph Chen 74486f870d6SJoseph Chen return 0; 74586f870d6SJoseph Chen } 74686f870d6SJoseph Chen 74786f870d6SJoseph Chen parse_fn_t board_bidram_parse_fn(void) 74886f870d6SJoseph Chen { 74986f870d6SJoseph Chen return param_parse_ddr_mem; 75086f870d6SJoseph Chen } 75186f870d6SJoseph Chen #endif 75286f870d6SJoseph Chen 75350d35c45SJoseph Chen #ifdef CONFIG_ROCKCHIP_AMP 75450d35c45SJoseph Chen void cpu_secondary_init_r(void) 75550d35c45SJoseph Chen { 75650d35c45SJoseph Chen amp_cpus_on(); 75750d35c45SJoseph Chen } 75850d35c45SJoseph Chen #endif 75950d35c45SJoseph Chen 7604892a977SJoseph Chen #if defined(CONFIG_ROCKCHIP_PRELOADER_SERIAL) && \ 7614892a977SJoseph Chen defined(CONFIG_ROCKCHIP_PRELOADER_ATAGS) 762064eb493SJoseph Chen int board_init_f_init_serial(void) 763064eb493SJoseph Chen { 764064eb493SJoseph Chen struct tag *t = atags_get_tag(ATAG_SERIAL); 765064eb493SJoseph Chen 766064eb493SJoseph Chen if (t) { 767064eb493SJoseph Chen gd->serial.using_pre_serial = t->u.serial.enable; 768064eb493SJoseph Chen gd->serial.addr = t->u.serial.addr; 769064eb493SJoseph Chen gd->serial.baudrate = t->u.serial.baudrate; 770064eb493SJoseph Chen gd->serial.id = t->u.serial.id; 771064eb493SJoseph Chen 772064eb493SJoseph Chen debug("%s: enable=%d, addr=0x%lx, baudrate=%d, id=%d\n", 773064eb493SJoseph Chen __func__, gd->serial.using_pre_serial, 774064eb493SJoseph Chen gd->serial.addr, gd->serial.baudrate, 775064eb493SJoseph Chen gd->serial.id); 776064eb493SJoseph Chen } 777064eb493SJoseph Chen 778064eb493SJoseph Chen return 0; 779064eb493SJoseph Chen } 780064eb493SJoseph Chen #endif 781064eb493SJoseph Chen 78238771996SKever Yang #if defined(CONFIG_USB_GADGET) && defined(CONFIG_USB_GADGET_DWC2_OTG) 7836f7b6465SFrank Wang #include <fdt_support.h> 78438771996SKever Yang #include <usb.h> 78538771996SKever Yang #include <usb/dwc2_udc.h> 78638771996SKever Yang 78738771996SKever Yang static struct dwc2_plat_otg_data otg_data = { 78838771996SKever Yang .rx_fifo_sz = 512, 78938771996SKever Yang .np_tx_fifo_sz = 16, 79038771996SKever Yang .tx_fifo_sz = 128, 79138771996SKever Yang }; 79238771996SKever Yang 79338771996SKever Yang int board_usb_init(int index, enum usb_init_type init) 79438771996SKever Yang { 79538771996SKever Yang const void *blob = gd->fdt_blob; 7962208cd92SJoseph Chen const fdt32_t *reg; 7972208cd92SJoseph Chen fdt_addr_t addr; 7982208cd92SJoseph Chen int node; 79938771996SKever Yang 80038771996SKever Yang /* find the usb_otg node */ 801294ad617SWilliam Wu node = fdt_node_offset_by_compatible(blob, -1, "snps,dwc2"); 80238771996SKever Yang 803294ad617SWilliam Wu retry: 804294ad617SWilliam Wu if (node > 0) { 805294ad617SWilliam Wu reg = fdt_getprop(blob, node, "reg", NULL); 806294ad617SWilliam Wu if (!reg) 807294ad617SWilliam Wu return -EINVAL; 808294ad617SWilliam Wu 809294ad617SWilliam Wu addr = fdt_translate_address(blob, node, reg); 810294ad617SWilliam Wu if (addr == OF_BAD_ADDR) { 811294ad617SWilliam Wu pr_err("Not found usb_otg address\n"); 812294ad617SWilliam Wu return -EINVAL; 81338771996SKever Yang } 81438771996SKever Yang 815294ad617SWilliam Wu #if defined(CONFIG_ROCKCHIP_RK3288) 816294ad617SWilliam Wu if (addr != 0xff580000) { 81738771996SKever Yang node = fdt_node_offset_by_compatible(blob, node, 81838771996SKever Yang "snps,dwc2"); 819294ad617SWilliam Wu goto retry; 82038771996SKever Yang } 821294ad617SWilliam Wu #endif 822294ad617SWilliam Wu } else { 823e7b5bb3cSWilliam Wu /* 824e7b5bb3cSWilliam Wu * With kernel dtb support, rk3288 dwc2 otg node 825e7b5bb3cSWilliam Wu * use the rockchip legacy dwc2 driver "dwc_otg_310" 826e0b87408SJoseph Chen * with the compatible "rockchip,rk3288_usb20_otg", 827e0b87408SJoseph Chen * and rk3368 also use the "dwc_otg_310" driver with 828e0b87408SJoseph Chen * the compatible "rockchip,rk3368-usb". 829e7b5bb3cSWilliam Wu */ 830e0b87408SJoseph Chen #if defined(CONFIG_ROCKCHIP_RK3288) 831e7b5bb3cSWilliam Wu node = fdt_node_offset_by_compatible(blob, -1, 832e7b5bb3cSWilliam Wu "rockchip,rk3288_usb20_otg"); 833e0b87408SJoseph Chen #elif defined(CONFIG_ROCKCHIP_RK3368) 834e0b87408SJoseph Chen node = fdt_node_offset_by_compatible(blob, -1, 835e0b87408SJoseph Chen "rockchip,rk3368-usb"); 836e0b87408SJoseph Chen #endif 837e7b5bb3cSWilliam Wu if (node > 0) { 838294ad617SWilliam Wu goto retry; 839e7b5bb3cSWilliam Wu } else { 840e7b5bb3cSWilliam Wu pr_err("Not found usb_otg device\n"); 84138771996SKever Yang return -ENODEV; 84238771996SKever Yang } 843e7b5bb3cSWilliam Wu } 8446f7b6465SFrank Wang 8456f7b6465SFrank Wang otg_data.regs_otg = (uintptr_t)addr; 84638771996SKever Yang 84738771996SKever Yang return dwc2_udc_probe(&otg_data); 84838771996SKever Yang } 84938771996SKever Yang 85038771996SKever Yang int board_usb_cleanup(int index, enum usb_init_type init) 85138771996SKever Yang { 85238771996SKever Yang return 0; 85338771996SKever Yang } 85438771996SKever Yang #endif 855