1 /* 2 * (C) Copyright 2017 Rockchip Electronics Co., Ltd. 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 #include <common.h> 7 #include <clk.h> 8 #include <dm.h> 9 #include <debug_uart.h> 10 #include <ram.h> 11 #include <syscon.h> 12 #include <asm/io.h> 13 #include <asm/arch/vendor.h> 14 #include <misc.h> 15 #include <asm/gpio.h> 16 #include <asm/arch/clock.h> 17 #include <asm/arch/periph.h> 18 #include <asm/arch/boot_mode.h> 19 #ifdef CONFIG_DM_CHARGE_DISPLAY 20 #include <power/charge_display.h> 21 #endif 22 #ifdef CONFIG_DM_REGULATOR 23 #include <power/regulator.h> 24 #endif 25 #ifdef CONFIG_DRM_ROCKCHIP 26 #include <video_rockchip.h> 27 #endif 28 #ifdef CONFIG_ROCKCHIP_DEBUGGER 29 #include <rockchip_debugger.h> 30 #endif 31 #include <mmc.h> 32 #include <of_live.h> 33 #include <dm/root.h> 34 35 DECLARE_GLOBAL_DATA_PTR; 36 /* define serialno max length, the max length is 512 Bytes 37 * The remaining bytes are used to ensure that the first 512 bytes 38 * are valid when executing 'env_set("serial#", value)'. 39 */ 40 #define VENDOR_SN_MAX 513 41 #define CPUID_LEN 0x10 42 #define CPUID_OFF 0x7 43 44 static int rockchip_set_serialno(void) 45 { 46 char serialno_str[VENDOR_SN_MAX]; 47 int ret = 0, i; 48 u8 cpuid[CPUID_LEN] = {0}; 49 u8 low[CPUID_LEN / 2], high[CPUID_LEN / 2]; 50 u64 serialno; 51 52 /* Read serial number from vendor storage part */ 53 memset(serialno_str, 0, VENDOR_SN_MAX); 54 #ifdef CONFIG_ROCKCHIP_VENDOR_PARTITION 55 ret = vendor_storage_read(VENDOR_SN_ID, serialno_str, (VENDOR_SN_MAX-1)); 56 if (ret > 0) { 57 env_set("serial#", serialno_str); 58 } else { 59 #endif 60 #ifdef CONFIG_ROCKCHIP_EFUSE 61 struct udevice *dev; 62 63 /* retrieve the device */ 64 ret = uclass_get_device_by_driver(UCLASS_MISC, 65 DM_GET_DRIVER(rockchip_efuse), &dev); 66 if (ret) { 67 printf("%s: could not find efuse device\n", __func__); 68 return ret; 69 } 70 /* read the cpu_id range from the efuses */ 71 ret = misc_read(dev, CPUID_OFF, &cpuid, sizeof(cpuid)); 72 if (ret) { 73 printf("%s: reading cpuid from the efuses failed\n", __func__); 74 return ret; 75 } 76 #else 77 /* generate random cpuid */ 78 for (i = 0; i < CPUID_LEN; i++) { 79 cpuid[i] = (u8)(rand()); 80 } 81 #endif 82 /* Generate the serial number based on CPU ID */ 83 for (i = 0; i < 8; i++) { 84 low[i] = cpuid[1 + (i << 1)]; 85 high[i] = cpuid[i << 1]; 86 } 87 serialno = crc32_no_comp(0, low, 8); 88 serialno |= (u64)crc32_no_comp(serialno, high, 8) << 32; 89 snprintf(serialno_str, sizeof(serialno_str), "%llx", serialno); 90 91 env_set("serial#", serialno_str); 92 #ifdef CONFIG_ROCKCHIP_VENDOR_PARTITION 93 } 94 #endif 95 return ret; 96 } 97 98 #if defined(CONFIG_USB_FUNCTION_FASTBOOT) 99 int fb_set_reboot_flag(void) 100 { 101 printf("Setting reboot to fastboot flag ...\n"); 102 /* Set boot mode to fastboot */ 103 writel(BOOT_FASTBOOT, CONFIG_ROCKCHIP_BOOT_MODE_REG); 104 105 return 0; 106 } 107 #endif 108 109 #ifdef CONFIG_DM_CHARGE_DISPLAY 110 static int charge_display(void) 111 { 112 int ret; 113 struct udevice *dev; 114 115 ret = uclass_get_device(UCLASS_CHARGE_DISPLAY, 0, &dev); 116 if (ret) { 117 if (ret != -ENODEV) { 118 printf("Get UCLASS CHARGE DISPLAY failed: %d\n", ret); 119 return ret; 120 } 121 return 0; 122 } 123 124 return charge_display_show(dev); 125 } 126 #endif 127 128 __weak int rk_board_init(void) 129 { 130 return 0; 131 } 132 133 __weak int rk_board_late_init(void) 134 { 135 return 0; 136 } 137 138 __weak int soc_clk_dump(void) 139 { 140 return 0; 141 } 142 143 __weak int set_armclk_rate(void) 144 { 145 return 0; 146 } 147 148 int board_late_init(void) 149 { 150 #if (CONFIG_ROCKCHIP_BOOT_MODE_REG > 0) 151 setup_boot_mode(); 152 #endif 153 154 #ifdef CONFIG_DM_CHARGE_DISPLAY 155 charge_display(); 156 #endif 157 158 #ifdef CONFIG_DRM_ROCKCHIP 159 rockchip_show_logo(); 160 #endif 161 rockchip_set_serialno(); 162 163 soc_clk_dump(); 164 165 return rk_board_late_init(); 166 } 167 168 #ifdef CONFIG_USING_KERNEL_DTB 169 #include <asm/arch/resource_img.h> 170 171 int init_kernel_dtb(void) 172 { 173 int ret = 0; 174 struct mmc *mmc; 175 struct udevice *dev; 176 ulong fdt_addr = 0; 177 178 ret = mmc_initialize(gd->bd); 179 if (ret) 180 goto scan_nand; 181 mmc = find_mmc_device(0); 182 if (!mmc) { 183 printf("no mmc device at slot 0\n"); 184 goto scan_nand; 185 } 186 ret = mmc_init(mmc); 187 if (!ret) 188 goto init_dtb; 189 printf("%s mmc init fail %d\n", __func__, ret); 190 scan_nand: 191 ret = uclass_get_device(UCLASS_RKNAND, 0, &dev); 192 if (ret) { 193 printf("%s: Cannot find rknand device\n", __func__); 194 return -1; 195 } 196 197 init_dtb: 198 fdt_addr = env_get_ulong("fdt_addr_r", 16, 0); 199 if (!fdt_addr) { 200 printf("No Found FDT Load Address.\n"); 201 return -1; 202 } 203 204 ret = rockchip_read_dtb_file((void *)fdt_addr); 205 if (ret < 0) { 206 printf("%s dtb in resource read fail\n", __func__); 207 return 0; 208 } 209 210 of_live_build((void *)fdt_addr, (struct device_node **)&gd->of_root); 211 212 dm_scan_fdt((void *)fdt_addr, false); 213 214 gd->fdt_blob = (void *)fdt_addr; 215 216 return 0; 217 } 218 #endif 219 220 221 int board_init(void) 222 { 223 int ret; 224 225 #if !defined(CONFIG_SUPPORT_SPL) 226 board_debug_uart_init(); 227 #endif 228 #ifdef CONFIG_USING_KERNEL_DTB 229 init_kernel_dtb(); 230 #endif 231 /* 232 * pmucru isn't referenced on some platforms, so pmucru driver can't 233 * probe that the "assigned-clocks" is unused. 234 */ 235 clks_probe(); 236 #ifdef CONFIG_DM_REGULATOR 237 ret = regulators_enable_boot_on(false); 238 if (ret) 239 debug("%s: Cannot enable boot on regulator\n", __func__); 240 #endif 241 set_armclk_rate(); 242 243 return rk_board_init(); 244 } 245 246 int interrupt_debugger_init(void) 247 { 248 int ret = 0; 249 250 #ifdef CONFIG_ROCKCHIP_DEBUGGER 251 ret = rockchip_debugger_init(); 252 #endif 253 return ret; 254 } 255 256 int board_fdt_fixup(void *blob) 257 { 258 __maybe_unused int ret = 0; 259 260 #ifdef CONFIG_DRM_ROCKCHIP 261 rockchip_display_fixup(blob); 262 #endif 263 264 #ifdef CONFIG_ROCKCHIP_RK3288 265 /* RK3288W HDMI Revision ID is 0x1A */ 266 if (readl(0xff980004) == 0x1A) { 267 ret = fdt_setprop_string(blob, 0, 268 "compatible", "rockchip,rk3288w"); 269 if (ret) 270 printf("fdt set compatible failed: %d\n", ret); 271 } 272 #endif 273 274 return ret; 275 } 276 277 #if !defined(CONFIG_SYS_DCACHE_OFF) && !defined(CONFIG_ARM64) 278 void enable_caches(void) 279 { 280 /* Enable D-cache. I-cache is already enabled in start.S */ 281 dcache_enable(); 282 } 283 #endif 284 285 #if defined(CONFIG_USB_GADGET) && defined(CONFIG_USB_GADGET_DWC2_OTG) 286 #include <fdt_support.h> 287 #include <usb.h> 288 #include <usb/dwc2_udc.h> 289 290 static struct dwc2_plat_otg_data otg_data = { 291 .rx_fifo_sz = 512, 292 .np_tx_fifo_sz = 16, 293 .tx_fifo_sz = 128, 294 }; 295 296 int board_usb_init(int index, enum usb_init_type init) 297 { 298 int node; 299 const char *mode; 300 fdt_addr_t addr; 301 const fdt32_t *reg; 302 bool matched = false; 303 const void *blob = gd->fdt_blob; 304 305 /* find the usb_otg node */ 306 node = fdt_node_offset_by_compatible(blob, -1, 307 "snps,dwc2"); 308 309 while (node > 0) { 310 mode = fdt_getprop(blob, node, "dr_mode", NULL); 311 if (mode && strcmp(mode, "otg") == 0) { 312 matched = true; 313 break; 314 } 315 316 node = fdt_node_offset_by_compatible(blob, node, 317 "snps,dwc2"); 318 } 319 if (!matched) { 320 debug("Not found usb_otg device\n"); 321 return -ENODEV; 322 } 323 324 reg = fdt_getprop(blob, node, "reg", NULL); 325 if (!reg) 326 return -EINVAL; 327 328 addr = fdt_translate_address(blob, node, reg); 329 if (addr == OF_BAD_ADDR) { 330 pr_err("Not found usb_otg address\n"); 331 return -EINVAL; 332 } 333 334 otg_data.regs_otg = (uintptr_t)addr; 335 336 return dwc2_udc_probe(&otg_data); 337 } 338 339 int board_usb_cleanup(int index, enum usb_init_type init) 340 { 341 return 0; 342 } 343 #endif 344