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 #include <asm/arch/rk_atags.h> 20 #ifdef CONFIG_DM_CHARGE_DISPLAY 21 #include <power/charge_display.h> 22 #endif 23 #ifdef CONFIG_DM_DVFS 24 #include <dvfs.h> 25 #endif 26 #ifdef CONFIG_DM_REGULATOR 27 #include <power/regulator.h> 28 #endif 29 #ifdef CONFIG_DRM_ROCKCHIP 30 #include <video_rockchip.h> 31 #endif 32 #ifdef CONFIG_ROCKCHIP_DEBUGGER 33 #include <rockchip_debugger.h> 34 #endif 35 #include <of_live.h> 36 #include <dm/root.h> 37 38 DECLARE_GLOBAL_DATA_PTR; 39 /* define serialno max length, the max length is 512 Bytes 40 * The remaining bytes are used to ensure that the first 512 bytes 41 * are valid when executing 'env_set("serial#", value)'. 42 */ 43 #define VENDOR_SN_MAX 513 44 #define CPUID_LEN 0x10 45 #define CPUID_OFF 0x7 46 47 static int rockchip_set_serialno(void) 48 { 49 char serialno_str[VENDOR_SN_MAX]; 50 int ret = 0, i; 51 u8 cpuid[CPUID_LEN] = {0}; 52 u8 low[CPUID_LEN / 2], high[CPUID_LEN / 2]; 53 u64 serialno; 54 55 /* Read serial number from vendor storage part */ 56 memset(serialno_str, 0, VENDOR_SN_MAX); 57 #ifdef CONFIG_ROCKCHIP_VENDOR_PARTITION 58 ret = vendor_storage_read(VENDOR_SN_ID, serialno_str, (VENDOR_SN_MAX-1)); 59 if (ret > 0) { 60 env_set("serial#", serialno_str); 61 } else { 62 #endif 63 #ifdef CONFIG_ROCKCHIP_EFUSE 64 struct udevice *dev; 65 66 /* retrieve the device */ 67 ret = uclass_get_device_by_driver(UCLASS_MISC, 68 DM_GET_DRIVER(rockchip_efuse), &dev); 69 if (ret) { 70 printf("%s: could not find efuse device\n", __func__); 71 return ret; 72 } 73 /* read the cpu_id range from the efuses */ 74 ret = misc_read(dev, CPUID_OFF, &cpuid, sizeof(cpuid)); 75 if (ret) { 76 printf("%s: reading cpuid from the efuses failed\n", __func__); 77 return ret; 78 } 79 #else 80 /* generate random cpuid */ 81 for (i = 0; i < CPUID_LEN; i++) { 82 cpuid[i] = (u8)(rand()); 83 } 84 #endif 85 /* Generate the serial number based on CPU ID */ 86 for (i = 0; i < 8; i++) { 87 low[i] = cpuid[1 + (i << 1)]; 88 high[i] = cpuid[i << 1]; 89 } 90 serialno = crc32_no_comp(0, low, 8); 91 serialno |= (u64)crc32_no_comp(serialno, high, 8) << 32; 92 snprintf(serialno_str, sizeof(serialno_str), "%llx", serialno); 93 94 env_set("serial#", serialno_str); 95 #ifdef CONFIG_ROCKCHIP_VENDOR_PARTITION 96 } 97 #endif 98 return ret; 99 } 100 101 #if defined(CONFIG_USB_FUNCTION_FASTBOOT) 102 int fb_set_reboot_flag(void) 103 { 104 printf("Setting reboot to fastboot flag ...\n"); 105 /* Set boot mode to fastboot */ 106 writel(BOOT_FASTBOOT, CONFIG_ROCKCHIP_BOOT_MODE_REG); 107 108 return 0; 109 } 110 #endif 111 112 #ifdef CONFIG_DM_CHARGE_DISPLAY 113 static int charge_display(void) 114 { 115 int ret; 116 struct udevice *dev; 117 118 ret = uclass_get_device(UCLASS_CHARGE_DISPLAY, 0, &dev); 119 if (ret) { 120 if (ret != -ENODEV) { 121 debug("Get UCLASS CHARGE DISPLAY failed: %d\n", ret); 122 return ret; 123 } else { 124 debug("Can't find charge display driver\n"); 125 } 126 return 0; 127 } 128 129 return charge_display_show(dev); 130 } 131 #endif 132 133 __weak int rk_board_init(void) 134 { 135 return 0; 136 } 137 138 __weak int rk_board_late_init(void) 139 { 140 return 0; 141 } 142 143 __weak int soc_clk_dump(void) 144 { 145 return 0; 146 } 147 148 __weak int set_armclk_rate(void) 149 { 150 return 0; 151 } 152 153 int board_late_init(void) 154 { 155 rockchip_set_serialno(); 156 #if (CONFIG_ROCKCHIP_BOOT_MODE_REG > 0) 157 setup_boot_mode(); 158 #endif 159 160 #ifdef CONFIG_DM_CHARGE_DISPLAY 161 charge_display(); 162 #endif 163 164 #ifdef CONFIG_DRM_ROCKCHIP 165 rockchip_show_logo(); 166 #endif 167 168 soc_clk_dump(); 169 170 return rk_board_late_init(); 171 } 172 173 #ifdef CONFIG_USING_KERNEL_DTB 174 #include <asm/arch/resource_img.h> 175 176 int init_kernel_dtb(void) 177 { 178 int ret = 0; 179 ulong fdt_addr = 0; 180 181 fdt_addr = env_get_ulong("fdt_addr_r", 16, 0); 182 if (!fdt_addr) { 183 printf("No Found FDT Load Address.\n"); 184 return -1; 185 } 186 187 ret = rockchip_read_dtb_file((void *)fdt_addr); 188 if (ret < 0) { 189 printf("%s dtb in resource read fail\n", __func__); 190 return 0; 191 } 192 193 of_live_build((void *)fdt_addr, (struct device_node **)&gd->of_root); 194 195 dm_scan_fdt((void *)fdt_addr, false); 196 197 gd->fdt_blob = (void *)fdt_addr; 198 199 return 0; 200 } 201 #endif 202 203 void board_env_fixup(void) 204 { 205 ulong kernel_addr_r; 206 207 if (gd->flags & GD_FLG_BL32_ENABLED) 208 return; 209 210 /* If bl32 is disabled, maybe kernel can be load to lower address. */ 211 kernel_addr_r = env_get_ulong("kernel_addr_no_bl32_r", 16, -1); 212 if (kernel_addr_r != -1) 213 env_set_hex("kernel_addr_r", kernel_addr_r); 214 } 215 216 int board_init(void) 217 { 218 int ret; 219 220 board_debug_uart_init(); 221 222 #ifdef CONFIG_USING_KERNEL_DTB 223 init_kernel_dtb(); 224 #endif 225 /* 226 * pmucru isn't referenced on some platforms, so pmucru driver can't 227 * probe that the "assigned-clocks" is unused. 228 */ 229 clks_probe(); 230 #ifdef CONFIG_DM_REGULATOR 231 ret = regulators_enable_boot_on(false); 232 if (ret) 233 debug("%s: Cannot enable boot on regulator\n", __func__); 234 #endif 235 set_armclk_rate(); 236 237 #ifdef CONFIG_DM_DVFS 238 dvfs_init(true); 239 #endif 240 241 return rk_board_init(); 242 } 243 244 int interrupt_debugger_init(void) 245 { 246 int ret = 0; 247 248 #ifdef CONFIG_ROCKCHIP_DEBUGGER 249 ret = rockchip_debugger_init(); 250 #endif 251 return ret; 252 } 253 254 int board_fdt_fixup(void *blob) 255 { 256 __maybe_unused int ret = 0; 257 258 #ifdef CONFIG_DRM_ROCKCHIP 259 rockchip_display_fixup(blob); 260 #endif 261 262 #ifdef CONFIG_ROCKCHIP_RK3288 263 /* RK3288W HDMI Revision ID is 0x1A */ 264 if (readl(0xff980004) == 0x1A) { 265 ret = fdt_setprop_string(blob, 0, 266 "compatible", "rockchip,rk3288w"); 267 if (ret) 268 printf("fdt set compatible failed: %d\n", ret); 269 } 270 #endif 271 272 return ret; 273 } 274 275 void board_quiesce_devices(void) 276 { 277 /* Destroy atags makes next warm boot safer */ 278 atags_destroy(); 279 } 280 281 void enable_caches(void) 282 { 283 icache_enable(); 284 dcache_enable(); 285 } 286 287 #ifdef CONFIG_LMB 288 /* 289 * Using last bi_dram[...] to initialize "bootm_low" and "bootm_mapsize". 290 * This makes lmb_alloc_base() always alloc from tail of sdram. 291 * If we don't assign it, bi_dram[0] is used by default and it may cause 292 * lmb_alloc_base() fail when bi_dram[0] range is small. 293 */ 294 void board_lmb_reserve(struct lmb *lmb) 295 { 296 u64 start, size; 297 char bootm_low[32]; 298 char bootm_mapsize[32]; 299 int i; 300 301 for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { 302 if (!gd->bd->bi_dram[i].size) 303 break; 304 } 305 306 start = gd->bd->bi_dram[i - 1].start; 307 size = gd->bd->bi_dram[i - 1].size; 308 309 /* 310 * 32-bit kernel: ramdisk/fdt shouldn't be loaded to highmem area(768MB+), 311 * otherwise "Unable to handle kernel paging request at virtual address ...". 312 * 313 * So that we hope limit highest address at 768M, but there comes the the 314 * problem: ramdisk is a compressed image and it expands after descompress, 315 * so it accesses 768MB+ and brings the above "Unable to handle kernel ...". 316 * 317 * We make a appointment that the highest memory address is 512MB, it 318 * makes lmb alloc safer. 319 */ 320 #ifndef CONFIG_ARM64 321 if (start >= ((u64)CONFIG_SYS_SDRAM_BASE + SZ_512M)) { 322 start = gd->bd->bi_dram[i - 2].start; 323 size = gd->bd->bi_dram[i - 2].size; 324 } 325 326 if ((start + size) > ((u64)CONFIG_SYS_SDRAM_BASE + SZ_512M)) 327 size = (u64)CONFIG_SYS_SDRAM_BASE + SZ_512M - start; 328 #endif 329 sprintf(bootm_low, "0x%llx", start); 330 sprintf(bootm_mapsize, "0x%llx", size); 331 env_set("bootm_low", bootm_low); 332 env_set("bootm_mapsize", bootm_mapsize); 333 } 334 #endif 335 336 #ifdef CONFIG_ROCKCHIP_PRELOADER_SERIAL 337 int board_init_f_init_serial(void) 338 { 339 struct tag *t = atags_get_tag(ATAG_SERIAL); 340 341 if (t) { 342 gd->serial.using_pre_serial = t->u.serial.enable; 343 gd->serial.addr = t->u.serial.addr; 344 gd->serial.baudrate = t->u.serial.baudrate; 345 gd->serial.id = t->u.serial.id; 346 347 debug("%s: enable=%d, addr=0x%lx, baudrate=%d, id=%d\n", 348 __func__, gd->serial.using_pre_serial, 349 gd->serial.addr, gd->serial.baudrate, 350 gd->serial.id); 351 } 352 353 return 0; 354 } 355 #endif 356 357 #if defined(CONFIG_USB_GADGET) && defined(CONFIG_USB_GADGET_DWC2_OTG) 358 #include <fdt_support.h> 359 #include <usb.h> 360 #include <usb/dwc2_udc.h> 361 362 static struct dwc2_plat_otg_data otg_data = { 363 .rx_fifo_sz = 512, 364 .np_tx_fifo_sz = 16, 365 .tx_fifo_sz = 128, 366 }; 367 368 int board_usb_init(int index, enum usb_init_type init) 369 { 370 int node; 371 const char *mode; 372 fdt_addr_t addr; 373 const fdt32_t *reg; 374 bool matched = false; 375 const void *blob = gd->fdt_blob; 376 377 /* find the usb_otg node */ 378 node = fdt_node_offset_by_compatible(blob, -1, 379 "snps,dwc2"); 380 381 while (node > 0) { 382 mode = fdt_getprop(blob, node, "dr_mode", NULL); 383 if (mode && strcmp(mode, "otg") == 0) { 384 matched = true; 385 break; 386 } 387 388 node = fdt_node_offset_by_compatible(blob, node, 389 "snps,dwc2"); 390 } 391 392 if (!matched) { 393 /* 394 * With kernel dtb support, rk3288 dwc2 otg node 395 * use the rockchip legacy dwc2 driver "dwc_otg_310" 396 * with the compatible "rockchip,rk3288_usb20_otg", 397 * and rk3368 also use the "dwc_otg_310" driver with 398 * the compatible "rockchip,rk3368-usb". 399 */ 400 #if defined(CONFIG_ROCKCHIP_RK3288) 401 node = fdt_node_offset_by_compatible(blob, -1, 402 "rockchip,rk3288_usb20_otg"); 403 #elif defined(CONFIG_ROCKCHIP_RK3368) 404 node = fdt_node_offset_by_compatible(blob, -1, 405 "rockchip,rk3368-usb"); 406 #endif 407 408 if (node > 0) { 409 matched = true; 410 } else { 411 pr_err("Not found usb_otg device\n"); 412 return -ENODEV; 413 } 414 } 415 416 reg = fdt_getprop(blob, node, "reg", NULL); 417 if (!reg) 418 return -EINVAL; 419 420 addr = fdt_translate_address(blob, node, reg); 421 if (addr == OF_BAD_ADDR) { 422 pr_err("Not found usb_otg address\n"); 423 return -EINVAL; 424 } 425 426 otg_data.regs_otg = (uintptr_t)addr; 427 428 return dwc2_udc_probe(&otg_data); 429 } 430 431 int board_usb_cleanup(int index, enum usb_init_type init) 432 { 433 return 0; 434 } 435 #endif 436