1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * (C) Copyright 2015 Google, Inc 4 */ 5 6 #include <common.h> 7 #include <clk.h> 8 #include <dm.h> 9 #include <ram.h> 10 #include <syscon.h> 11 #include <asm/io.h> 12 #include <asm/arch/clock.h> 13 #include <asm/arch/cru_rk3288.h> 14 #include <asm/arch/periph.h> 15 #include <asm/arch/pmu_rk3288.h> 16 #include <asm/arch/qos_rk3288.h> 17 #include <asm/arch/boot_mode.h> 18 #include <asm/gpio.h> 19 #include <dm/pinctrl.h> 20 #include <dt-bindings/clock/rk3288-cru.h> 21 #include <power/regulator.h> 22 23 DECLARE_GLOBAL_DATA_PTR; 24 25 __weak int rk_board_late_init(void) 26 { 27 return 0; 28 } 29 30 int rk3288_qos_init(void) 31 { 32 int val = 2 << PRIORITY_HIGH_SHIFT | 2 << PRIORITY_LOW_SHIFT; 33 /* set vop qos to higher priority */ 34 writel(val, CPU_AXI_QOS_PRIORITY + VIO0_VOP_QOS); 35 writel(val, CPU_AXI_QOS_PRIORITY + VIO1_VOP_QOS); 36 37 if (!fdt_node_check_compatible(gd->fdt_blob, 0, 38 "rockchip,rk3288-tinker")) 39 { 40 /* set isp qos to higher priority */ 41 writel(val, CPU_AXI_QOS_PRIORITY + VIO1_ISP_R_QOS); 42 writel(val, CPU_AXI_QOS_PRIORITY + VIO1_ISP_W0_QOS); 43 writel(val, CPU_AXI_QOS_PRIORITY + VIO1_ISP_W1_QOS); 44 } 45 return 0; 46 } 47 48 static void rk3288_detect_reset_reason(void) 49 { 50 struct rk3288_cru *cru = rockchip_get_cru(); 51 const char *reason; 52 53 if (IS_ERR(cru)) 54 return; 55 56 switch (cru->cru_glb_rst_st) { 57 case GLB_POR_RST: 58 reason = "POR"; 59 break; 60 case FST_GLB_RST_ST: 61 case SND_GLB_RST_ST: 62 reason = "RST"; 63 break; 64 case FST_GLB_TSADC_RST_ST: 65 case SND_GLB_TSADC_RST_ST: 66 reason = "THERMAL"; 67 break; 68 case FST_GLB_WDT_RST_ST: 69 case SND_GLB_WDT_RST_ST: 70 reason = "WDOG"; 71 break; 72 default: 73 reason = "unknown reset"; 74 } 75 76 env_set("reset_reason", reason); 77 78 /* 79 * Clear cru_glb_rst_st, so we can determine the last reset cause 80 * for following resets. 81 */ 82 rk_clrreg(&cru->cru_glb_rst_st, GLB_RST_ST_MASK); 83 } 84 85 int board_late_init(void) 86 { 87 setup_boot_mode(); 88 rk3288_qos_init(); 89 rk3288_detect_reset_reason(); 90 91 return rk_board_late_init(); 92 } 93 94 #if !CONFIG_IS_ENABLED(ROCKCHIP_BACK_TO_BROM) 95 static int veyron_init(void) 96 { 97 struct udevice *dev; 98 struct clk clk; 99 int ret; 100 101 ret = regulator_get_by_platname("vdd_arm", &dev); 102 if (ret) { 103 debug("Cannot set regulator name\n"); 104 return ret; 105 } 106 107 /* Slowly raise to max CPU voltage to prevent overshoot */ 108 ret = regulator_set_value(dev, 1200000); 109 if (ret) 110 return ret; 111 udelay(175); /* Must wait for voltage to stabilize, 2mV/us */ 112 ret = regulator_set_value(dev, 1400000); 113 if (ret) 114 return ret; 115 udelay(100); /* Must wait for voltage to stabilize, 2mV/us */ 116 117 ret = rockchip_get_clk(&clk.dev); 118 if (ret) 119 return ret; 120 clk.id = PLL_APLL; 121 ret = clk_set_rate(&clk, 1800000000); 122 if (IS_ERR_VALUE(ret)) 123 return ret; 124 125 return 0; 126 } 127 #endif 128 129 int board_init(void) 130 { 131 #if CONFIG_IS_ENABLED(ROCKCHIP_BACK_TO_BROM) 132 struct udevice *pinctrl; 133 int ret; 134 135 /* 136 * We need to implement sdcard iomux here for the further 137 * initlization, otherwise, it'll hit sdcard command sending 138 * timeout exception. 139 */ 140 ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl); 141 if (ret) { 142 debug("%s: Cannot find pinctrl device\n", __func__); 143 goto err; 144 } 145 ret = pinctrl_request_noflags(pinctrl, PERIPH_ID_SDCARD); 146 if (ret) { 147 debug("%s: Failed to set up SD card\n", __func__); 148 goto err; 149 } 150 151 return 0; 152 err: 153 printf("board_init: Error %d\n", ret); 154 155 /* No way to report error here */ 156 hang(); 157 158 return -1; 159 #else 160 int ret; 161 162 /* We do some SoC one time setting here */ 163 if (!fdt_node_check_compatible(gd->fdt_blob, 0, "google,veyron")) { 164 ret = veyron_init(); 165 if (ret) 166 return ret; 167 } 168 169 return 0; 170 #endif 171 } 172 173 #ifndef CONFIG_SYS_DCACHE_OFF 174 void enable_caches(void) 175 { 176 /* Enable D-cache. I-cache is already enabled in start.S */ 177 dcache_enable(); 178 } 179 #endif 180 181 #if defined(CONFIG_USB_GADGET) && defined(CONFIG_USB_GADGET_DWC2_OTG) 182 #include <usb.h> 183 #include <usb/dwc2_udc.h> 184 185 static struct dwc2_plat_otg_data rk3288_otg_data = { 186 .rx_fifo_sz = 512, 187 .np_tx_fifo_sz = 16, 188 .tx_fifo_sz = 128, 189 }; 190 191 int board_usb_init(int index, enum usb_init_type init) 192 { 193 int node, phy_node; 194 const char *mode; 195 bool matched = false; 196 const void *blob = gd->fdt_blob; 197 u32 grf_phy_offset; 198 199 /* find the usb_otg node */ 200 node = fdt_node_offset_by_compatible(blob, -1, 201 "rockchip,rk3288-usb"); 202 203 while (node > 0) { 204 mode = fdt_getprop(blob, node, "dr_mode", NULL); 205 if (mode && strcmp(mode, "otg") == 0) { 206 matched = true; 207 break; 208 } 209 210 node = fdt_node_offset_by_compatible(blob, node, 211 "rockchip,rk3288-usb"); 212 } 213 if (!matched) { 214 debug("Not found usb_otg device\n"); 215 return -ENODEV; 216 } 217 rk3288_otg_data.regs_otg = fdtdec_get_addr(blob, node, "reg"); 218 219 node = fdtdec_lookup_phandle(blob, node, "phys"); 220 if (node <= 0) { 221 debug("Not found usb phy device\n"); 222 return -ENODEV; 223 } 224 225 phy_node = fdt_parent_offset(blob, node); 226 if (phy_node <= 0) { 227 debug("Not found usb phy device\n"); 228 return -ENODEV; 229 } 230 231 rk3288_otg_data.phy_of_node = phy_node; 232 grf_phy_offset = fdtdec_get_addr(blob, node, "reg"); 233 234 /* find the grf node */ 235 node = fdt_node_offset_by_compatible(blob, -1, 236 "rockchip,rk3288-grf"); 237 if (node <= 0) { 238 debug("Not found grf device\n"); 239 return -ENODEV; 240 } 241 rk3288_otg_data.regs_phy = grf_phy_offset + 242 fdtdec_get_addr(blob, node, "reg"); 243 244 return dwc2_udc_probe(&rk3288_otg_data); 245 } 246 247 int board_usb_cleanup(int index, enum usb_init_type init) 248 { 249 return 0; 250 } 251 #endif 252 253 static int do_clock(cmd_tbl_t *cmdtp, int flag, int argc, 254 char * const argv[]) 255 { 256 static const struct { 257 char *name; 258 int id; 259 } clks[] = { 260 { "osc", CLK_OSC }, 261 { "apll", CLK_ARM }, 262 { "dpll", CLK_DDR }, 263 { "cpll", CLK_CODEC }, 264 { "gpll", CLK_GENERAL }, 265 #ifdef CONFIG_ROCKCHIP_RK3036 266 { "mpll", CLK_NEW }, 267 #else 268 { "npll", CLK_NEW }, 269 #endif 270 }; 271 int ret, i; 272 struct udevice *dev; 273 274 ret = rockchip_get_clk(&dev); 275 if (ret) { 276 printf("clk-uclass not found\n"); 277 return 0; 278 } 279 280 for (i = 0; i < ARRAY_SIZE(clks); i++) { 281 struct clk clk; 282 ulong rate; 283 284 clk.id = clks[i].id; 285 ret = clk_request(dev, &clk); 286 if (ret < 0) 287 continue; 288 289 rate = clk_get_rate(&clk); 290 printf("%s: %lu\n", clks[i].name, rate); 291 292 clk_free(&clk); 293 } 294 295 return 0; 296 } 297 298 U_BOOT_CMD( 299 clock, 2, 1, do_clock, 300 "display information about clocks", 301 "" 302 ); 303 304 #define GRF_SOC_CON2 0xff77024c 305 306 int board_early_init_f(void) 307 { 308 struct udevice *pinctrl; 309 struct udevice *dev; 310 int ret; 311 312 /* 313 * This init is done in SPL, but when chain-loading U-Boot SPL will 314 * have been skipped. Allow the clock driver to check if it needs 315 * setting up. 316 */ 317 ret = rockchip_get_clk(&dev); 318 if (ret) { 319 debug("CLK init failed: %d\n", ret); 320 return ret; 321 } 322 ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl); 323 if (ret) { 324 debug("%s: Cannot find pinctrl device\n", __func__); 325 return ret; 326 } 327 328 /* Enable debug UART */ 329 ret = pinctrl_request_noflags(pinctrl, PERIPH_ID_UART_DBG); 330 if (ret) { 331 debug("%s: Failed to set up console UART\n", __func__); 332 return ret; 333 } 334 rk_setreg(GRF_SOC_CON2, 1 << 0); 335 336 return 0; 337 } 338