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