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_REGULATOR 24 #include <power/regulator.h> 25 #endif 26 #ifdef CONFIG_DRM_ROCKCHIP 27 #include <video_rockchip.h> 28 #endif 29 #ifdef CONFIG_ROCKCHIP_DEBUGGER 30 #include <rockchip_debugger.h> 31 #endif 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 debug("Get UCLASS CHARGE DISPLAY failed: %d\n", ret); 119 return ret; 120 } else { 121 debug("Can't find charge display driver\n"); 122 } 123 return 0; 124 } 125 126 return charge_display_show(dev); 127 } 128 #endif 129 130 __weak int rk_board_init(void) 131 { 132 return 0; 133 } 134 135 __weak int rk_board_late_init(void) 136 { 137 return 0; 138 } 139 140 __weak int soc_clk_dump(void) 141 { 142 return 0; 143 } 144 145 __weak int set_armclk_rate(void) 146 { 147 return 0; 148 } 149 150 int board_late_init(void) 151 { 152 rockchip_set_serialno(); 153 #if (CONFIG_ROCKCHIP_BOOT_MODE_REG > 0) 154 setup_boot_mode(); 155 #endif 156 157 #ifdef CONFIG_DM_CHARGE_DISPLAY 158 charge_display(); 159 #endif 160 161 #ifdef CONFIG_DRM_ROCKCHIP 162 rockchip_show_logo(); 163 #endif 164 165 soc_clk_dump(); 166 167 return rk_board_late_init(); 168 } 169 170 #ifdef CONFIG_USING_KERNEL_DTB 171 #include <asm/arch/resource_img.h> 172 173 int init_kernel_dtb(void) 174 { 175 int ret = 0; 176 ulong fdt_addr = 0; 177 178 fdt_addr = env_get_ulong("fdt_addr_r", 16, 0); 179 if (!fdt_addr) { 180 printf("No Found FDT Load Address.\n"); 181 return -1; 182 } 183 184 ret = rockchip_read_dtb_file((void *)fdt_addr); 185 if (ret < 0) { 186 printf("%s dtb in resource read fail\n", __func__); 187 return 0; 188 } 189 190 of_live_build((void *)fdt_addr, (struct device_node **)&gd->of_root); 191 192 dm_scan_fdt((void *)fdt_addr, false); 193 194 gd->fdt_blob = (void *)fdt_addr; 195 196 return 0; 197 } 198 #endif 199 200 201 int board_init(void) 202 { 203 int ret; 204 205 board_debug_uart_init(); 206 207 #ifdef CONFIG_USING_KERNEL_DTB 208 init_kernel_dtb(); 209 #endif 210 /* 211 * pmucru isn't referenced on some platforms, so pmucru driver can't 212 * probe that the "assigned-clocks" is unused. 213 */ 214 clks_probe(); 215 #ifdef CONFIG_DM_REGULATOR 216 ret = regulators_enable_boot_on(false); 217 if (ret) 218 debug("%s: Cannot enable boot on regulator\n", __func__); 219 #endif 220 set_armclk_rate(); 221 222 return rk_board_init(); 223 } 224 225 int interrupt_debugger_init(void) 226 { 227 int ret = 0; 228 229 #ifdef CONFIG_ROCKCHIP_DEBUGGER 230 ret = rockchip_debugger_init(); 231 #endif 232 return ret; 233 } 234 235 int board_fdt_fixup(void *blob) 236 { 237 __maybe_unused int ret = 0; 238 239 #ifdef CONFIG_DRM_ROCKCHIP 240 rockchip_display_fixup(blob); 241 #endif 242 243 #ifdef CONFIG_ROCKCHIP_RK3288 244 /* RK3288W HDMI Revision ID is 0x1A */ 245 if (readl(0xff980004) == 0x1A) { 246 ret = fdt_setprop_string(blob, 0, 247 "compatible", "rockchip,rk3288w"); 248 if (ret) 249 printf("fdt set compatible failed: %d\n", ret); 250 } 251 #endif 252 253 return ret; 254 } 255 256 void enable_caches(void) 257 { 258 icache_enable(); 259 dcache_enable(); 260 } 261 262 #ifdef CONFIG_LMB 263 /* 264 * Using last bi_dram[...] to initialize "bootm_low" and "bootm_mapsize". 265 * This makes lmb_alloc_base() always alloc from tail of sdram. 266 * If we don't assign it, bi_dram[0] is used by default and it may cause 267 * lmb_alloc_base() fail when bi_dram[0] range is small. 268 */ 269 void board_lmb_reserve(struct lmb *lmb) 270 { 271 u64 start, size; 272 char bootm_low[32]; 273 char bootm_mapsize[32]; 274 int i; 275 276 for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { 277 if (!gd->bd->bi_dram[i].size) 278 break; 279 } 280 281 start = gd->bd->bi_dram[i - 1].start; 282 size = gd->bd->bi_dram[i - 1].size; 283 284 /* 285 * 32-bit kernel: ramdisk/fdt shouldn't be loaded to highmem area(768MB+), 286 * otherwise "Unable to handle kernel paging request at virtual address ...". 287 * 288 * So that we hope limit highest address at 768M, but there comes the the 289 * problem: ramdisk is a compressed image and it expands after descompress, 290 * so it accesses 768MB+ and brings the above "Unable to handle kernel ...". 291 * 292 * We make a appointment that the highest memory address is 512MB, it 293 * makes lmb alloc safer. 294 */ 295 #ifndef CONFIG_ARM64 296 if (start >= ((u64)CONFIG_SYS_SDRAM_BASE + SZ_512M)) { 297 start = gd->bd->bi_dram[i - 2].start; 298 size = gd->bd->bi_dram[i - 2].size; 299 } 300 301 if ((start + size) > ((u64)CONFIG_SYS_SDRAM_BASE + SZ_512M)) 302 size = (u64)CONFIG_SYS_SDRAM_BASE + SZ_512M - start; 303 #endif 304 sprintf(bootm_low, "0x%llx", start); 305 sprintf(bootm_mapsize, "0x%llx", size); 306 env_set("bootm_low", bootm_low); 307 env_set("bootm_mapsize", bootm_mapsize); 308 } 309 #endif 310 311 #ifdef CONFIG_ROCKCHIP_PRELOADER_SERIAL 312 int board_init_f_init_serial(void) 313 { 314 struct tag *t = atags_get_tag(ATAG_SERIAL); 315 316 if (t) { 317 gd->serial.using_pre_serial = t->u.serial.enable; 318 gd->serial.addr = t->u.serial.addr; 319 gd->serial.baudrate = t->u.serial.baudrate; 320 gd->serial.id = t->u.serial.id; 321 322 debug("%s: enable=%d, addr=0x%lx, baudrate=%d, id=%d\n", 323 __func__, gd->serial.using_pre_serial, 324 gd->serial.addr, gd->serial.baudrate, 325 gd->serial.id); 326 } 327 328 return 0; 329 } 330 #endif 331 332 #if defined(CONFIG_USB_GADGET) && defined(CONFIG_USB_GADGET_DWC2_OTG) 333 #include <fdt_support.h> 334 #include <usb.h> 335 #include <usb/dwc2_udc.h> 336 337 static struct dwc2_plat_otg_data otg_data = { 338 .rx_fifo_sz = 512, 339 .np_tx_fifo_sz = 16, 340 .tx_fifo_sz = 128, 341 }; 342 343 int board_usb_init(int index, enum usb_init_type init) 344 { 345 int node; 346 const char *mode; 347 fdt_addr_t addr; 348 const fdt32_t *reg; 349 bool matched = false; 350 const void *blob = gd->fdt_blob; 351 352 /* find the usb_otg node */ 353 node = fdt_node_offset_by_compatible(blob, -1, 354 "snps,dwc2"); 355 356 while (node > 0) { 357 mode = fdt_getprop(blob, node, "dr_mode", NULL); 358 if (mode && strcmp(mode, "otg") == 0) { 359 matched = true; 360 break; 361 } 362 363 node = fdt_node_offset_by_compatible(blob, node, 364 "snps,dwc2"); 365 } 366 367 if (!matched) { 368 /* 369 * With kernel dtb support, rk3288 dwc2 otg node 370 * use the rockchip legacy dwc2 driver "dwc_otg_310" 371 * with the compatible "rockchip,rk3288_usb20_otg", 372 * and rk3368 also use the "dwc_otg_310" driver with 373 * the compatible "rockchip,rk3368-usb". 374 */ 375 #if defined(CONFIG_ROCKCHIP_RK3288) 376 node = fdt_node_offset_by_compatible(blob, -1, 377 "rockchip,rk3288_usb20_otg"); 378 #elif defined(CONFIG_ROCKCHIP_RK3368) 379 node = fdt_node_offset_by_compatible(blob, -1, 380 "rockchip,rk3368-usb"); 381 #endif 382 383 if (node > 0) { 384 matched = true; 385 } else { 386 pr_err("Not found usb_otg device\n"); 387 return -ENODEV; 388 } 389 } 390 391 reg = fdt_getprop(blob, node, "reg", NULL); 392 if (!reg) 393 return -EINVAL; 394 395 addr = fdt_translate_address(blob, node, reg); 396 if (addr == OF_BAD_ADDR) { 397 pr_err("Not found usb_otg address\n"); 398 return -EINVAL; 399 } 400 401 otg_data.regs_otg = (uintptr_t)addr; 402 403 return dwc2_udc_probe(&otg_data); 404 } 405 406 int board_usb_cleanup(int index, enum usb_init_type init) 407 { 408 return 0; 409 } 410 #endif 411