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 } 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 #if (CONFIG_ROCKCHIP_BOOT_MODE_REG > 0) 153 setup_boot_mode(); 154 #endif 155 156 #ifdef CONFIG_DM_CHARGE_DISPLAY 157 charge_display(); 158 #endif 159 160 #ifdef CONFIG_DRM_ROCKCHIP 161 rockchip_show_logo(); 162 #endif 163 rockchip_set_serialno(); 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 struct mmc *mmc; 177 struct udevice *dev; 178 ulong fdt_addr = 0; 179 180 ret = mmc_initialize(gd->bd); 181 if (ret) 182 goto scan_nand; 183 mmc = find_mmc_device(0); 184 if (!mmc) { 185 printf("no mmc device at slot 0\n"); 186 goto scan_nand; 187 } 188 ret = mmc_init(mmc); 189 if (!ret) 190 goto init_dtb; 191 printf("%s mmc init fail %d\n", __func__, ret); 192 scan_nand: 193 ret = uclass_get_device(UCLASS_RKNAND, 0, &dev); 194 if (ret) { 195 printf("%s: Cannot find rknand device\n", __func__); 196 return -1; 197 } 198 199 init_dtb: 200 fdt_addr = env_get_ulong("fdt_addr_r", 16, 0); 201 if (!fdt_addr) { 202 printf("No Found FDT Load Address.\n"); 203 return -1; 204 } 205 206 ret = rockchip_read_dtb_file((void *)fdt_addr); 207 if (ret < 0) { 208 printf("%s dtb in resource read fail\n", __func__); 209 return 0; 210 } 211 212 of_live_build((void *)fdt_addr, (struct device_node **)&gd->of_root); 213 214 dm_scan_fdt((void *)fdt_addr, false); 215 216 gd->fdt_blob = (void *)fdt_addr; 217 218 printf("Using kernel dtb\n"); 219 220 return 0; 221 } 222 #endif 223 224 225 int board_init(void) 226 { 227 int ret; 228 229 #if !defined(CONFIG_SUPPORT_SPL) 230 board_debug_uart_init(); 231 #endif 232 #ifdef CONFIG_USING_KERNEL_DTB 233 init_kernel_dtb(); 234 #endif 235 /* 236 * pmucru isn't referenced on some platforms, so pmucru driver can't 237 * probe that the "assigned-clocks" is unused. 238 */ 239 clks_probe(); 240 #ifdef CONFIG_DM_REGULATOR 241 ret = regulators_enable_boot_on(false); 242 if (ret) 243 debug("%s: Cannot enable boot on regulator\n", __func__); 244 #endif 245 set_armclk_rate(); 246 247 return rk_board_init(); 248 } 249 250 int interrupt_debugger_init(void) 251 { 252 int ret = 0; 253 254 #ifdef CONFIG_ROCKCHIP_DEBUGGER 255 ret = rockchip_debugger_init(); 256 #endif 257 return ret; 258 } 259 260 int board_fdt_fixup(void *blob) 261 { 262 __maybe_unused int ret = 0; 263 264 #ifdef CONFIG_DRM_ROCKCHIP 265 rockchip_display_fixup(blob); 266 #endif 267 268 #ifdef CONFIG_ROCKCHIP_RK3288 269 /* RK3288W HDMI Revision ID is 0x1A */ 270 if (readl(0xff980004) == 0x1A) { 271 ret = fdt_setprop_string(blob, 0, 272 "compatible", "rockchip,rk3288w"); 273 if (ret) 274 printf("fdt set compatible failed: %d\n", ret); 275 } 276 #endif 277 278 return ret; 279 } 280 281 #if !defined(CONFIG_SYS_DCACHE_OFF) && !defined(CONFIG_ARM64) 282 void enable_caches(void) 283 { 284 /* Enable D-cache. I-cache is already enabled in start.S */ 285 dcache_enable(); 286 } 287 #endif 288 289 #if defined(CONFIG_USB_GADGET) && defined(CONFIG_USB_GADGET_DWC2_OTG) 290 #include <fdt_support.h> 291 #include <usb.h> 292 #include <usb/dwc2_udc.h> 293 294 static struct dwc2_plat_otg_data otg_data = { 295 .rx_fifo_sz = 512, 296 .np_tx_fifo_sz = 16, 297 .tx_fifo_sz = 128, 298 }; 299 300 int board_usb_init(int index, enum usb_init_type init) 301 { 302 int node; 303 const char *mode; 304 fdt_addr_t addr; 305 const fdt32_t *reg; 306 bool matched = false; 307 const void *blob = gd->fdt_blob; 308 309 /* find the usb_otg node */ 310 node = fdt_node_offset_by_compatible(blob, -1, 311 "snps,dwc2"); 312 313 while (node > 0) { 314 mode = fdt_getprop(blob, node, "dr_mode", NULL); 315 if (mode && strcmp(mode, "otg") == 0) { 316 matched = true; 317 break; 318 } 319 320 node = fdt_node_offset_by_compatible(blob, node, 321 "snps,dwc2"); 322 } 323 324 if (!matched) { 325 /* 326 * With kernel dtb support, rk3288 dwc2 otg node 327 * use the rockchip legacy dwc2 driver "dwc_otg_310" 328 * with the compatible "rockchip,rk3288_usb20_otg". 329 */ 330 node = fdt_node_offset_by_compatible(blob, -1, 331 "rockchip,rk3288_usb20_otg"); 332 if (node > 0) { 333 matched = true; 334 } else { 335 pr_err("Not found usb_otg device\n"); 336 return -ENODEV; 337 } 338 } 339 340 reg = fdt_getprop(blob, node, "reg", NULL); 341 if (!reg) 342 return -EINVAL; 343 344 addr = fdt_translate_address(blob, node, reg); 345 if (addr == OF_BAD_ADDR) { 346 pr_err("Not found usb_otg address\n"); 347 return -EINVAL; 348 } 349 350 otg_data.regs_otg = (uintptr_t)addr; 351 352 return dwc2_udc_probe(&otg_data); 353 } 354 355 int board_usb_cleanup(int index, enum usb_init_type init) 356 { 357 return 0; 358 } 359 #endif 360