1 /* 2 * (C) Copyright 2015 Google, Inc 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include <common.h> 8 #include <clk.h> 9 #include <dm.h> 10 #include <ram.h> 11 #include <syscon.h> 12 #include <asm/io.h> 13 #include <asm/arch/clock.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 #define PMU_BASE 0xff730000 26 27 static void setup_boot_mode(void) 28 { 29 struct rk3288_pmu *const pmu = (void *)PMU_BASE; 30 int boot_mode = readl(&pmu->sys_reg[0]); 31 32 debug("boot mode %x.\n", boot_mode); 33 34 /* Clear boot mode */ 35 writel(BOOT_NORMAL, &pmu->sys_reg[0]); 36 37 switch (boot_mode) { 38 case BOOT_FASTBOOT: 39 printf("enter fastboot!\n"); 40 setenv("preboot", "setenv preboot; fastboot usb0"); 41 break; 42 case BOOT_UMS: 43 printf("enter UMS!\n"); 44 setenv("preboot", "setenv preboot; if mmc dev 0;" 45 "then ums mmc 0; else ums mmc 1;fi"); 46 break; 47 } 48 } 49 50 __weak int rk_board_late_init(void) 51 { 52 return 0; 53 } 54 55 int rk3288_qos_init(void) 56 { 57 int val = 2 << PRIORITY_HIGH_SHIFT | 2 << PRIORITY_LOW_SHIFT; 58 /* set vop qos to higher priority */ 59 writel(val, CPU_AXI_QOS_PRIORITY + VIO0_VOP_QOS); 60 writel(val, CPU_AXI_QOS_PRIORITY + VIO1_VOP_QOS); 61 62 if (!fdt_node_check_compatible(gd->fdt_blob, 0, 63 "rockchip,rk3288-miniarm")) 64 { 65 /* set isp qos to higher priority */ 66 writel(val, CPU_AXI_QOS_PRIORITY + VIO1_ISP_R_QOS); 67 writel(val, CPU_AXI_QOS_PRIORITY + VIO1_ISP_W0_QOS); 68 writel(val, CPU_AXI_QOS_PRIORITY + VIO1_ISP_W1_QOS); 69 } 70 return 0; 71 } 72 73 int board_late_init(void) 74 { 75 setup_boot_mode(); 76 rk3288_qos_init(); 77 78 return rk_board_late_init(); 79 } 80 81 #ifndef CONFIG_ROCKCHIP_SPL_BACK_TO_BROM 82 static int veyron_init(void) 83 { 84 struct udevice *dev; 85 struct clk clk; 86 int ret; 87 88 ret = regulator_get_by_platname("vdd_arm", &dev); 89 if (ret) 90 return ret; 91 92 /* Slowly raise to max CPU voltage to prevent overshoot */ 93 ret = regulator_set_value(dev, 1200000); 94 if (ret) 95 return ret; 96 udelay(175); /* Must wait for voltage to stabilize, 2mV/us */ 97 ret = regulator_set_value(dev, 1400000); 98 if (ret) 99 return ret; 100 udelay(100); /* Must wait for voltage to stabilize, 2mV/us */ 101 102 ret = rockchip_get_clk(&clk.dev); 103 if (ret) 104 return ret; 105 clk.id = PLL_APLL; 106 ret = clk_set_rate(&clk, 1800000000); 107 if (IS_ERR_VALUE(ret)) 108 return ret; 109 110 return 0; 111 } 112 #endif 113 114 int board_init(void) 115 { 116 #ifdef CONFIG_ROCKCHIP_SPL_BACK_TO_BROM 117 struct udevice *pinctrl; 118 int ret; 119 120 /* 121 * We need to implement sdcard iomux here for the further 122 * initlization, otherwise, it'll hit sdcard command sending 123 * timeout exception. 124 */ 125 ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl); 126 if (ret) { 127 debug("%s: Cannot find pinctrl device\n", __func__); 128 goto err; 129 } 130 ret = pinctrl_request_noflags(pinctrl, PERIPH_ID_SDCARD); 131 if (ret) { 132 debug("%s: Failed to set up SD card\n", __func__); 133 goto err; 134 } 135 136 return 0; 137 err: 138 printf("board_init: Error %d\n", ret); 139 140 /* No way to report error here */ 141 hang(); 142 143 return -1; 144 #else 145 int ret; 146 147 /* We do some SoC one time setting here */ 148 if (!fdt_node_check_compatible(gd->fdt_blob, 0, "google,veyron")) { 149 ret = veyron_init(); 150 if (ret) 151 return ret; 152 } 153 154 return 0; 155 #endif 156 } 157 158 int dram_init(void) 159 { 160 struct ram_info ram; 161 struct udevice *dev; 162 int ret; 163 164 ret = uclass_get_device(UCLASS_RAM, 0, &dev); 165 if (ret) { 166 debug("DRAM init failed: %d\n", ret); 167 return ret; 168 } 169 ret = ram_get_info(dev, &ram); 170 if (ret) { 171 debug("Cannot get DRAM size: %d\n", ret); 172 return ret; 173 } 174 debug("SDRAM base=%lx, size=%x\n", ram.base, ram.size); 175 gd->ram_size = ram.size; 176 177 return 0; 178 } 179 180 #ifndef CONFIG_SYS_DCACHE_OFF 181 void enable_caches(void) 182 { 183 /* Enable D-cache. I-cache is already enabled in start.S */ 184 dcache_enable(); 185 } 186 #endif 187 188 #if defined(CONFIG_USB_GADGET) && defined(CONFIG_USB_GADGET_DWC2_OTG) 189 #include <usb.h> 190 #include <usb/dwc2_udc.h> 191 192 static struct dwc2_plat_otg_data rk3288_otg_data = { 193 .rx_fifo_sz = 512, 194 .np_tx_fifo_sz = 16, 195 .tx_fifo_sz = 128, 196 }; 197 198 int board_usb_init(int index, enum usb_init_type init) 199 { 200 int node, phy_node; 201 const char *mode; 202 bool matched = false; 203 const void *blob = gd->fdt_blob; 204 u32 grf_phy_offset; 205 206 /* find the usb_otg node */ 207 node = fdt_node_offset_by_compatible(blob, -1, 208 "rockchip,rk3288-usb"); 209 210 while (node > 0) { 211 mode = fdt_getprop(blob, node, "dr_mode", NULL); 212 if (mode && strcmp(mode, "otg") == 0) { 213 matched = true; 214 break; 215 } 216 217 node = fdt_node_offset_by_compatible(blob, node, 218 "rockchip,rk3288-usb"); 219 } 220 if (!matched) { 221 debug("Not found usb_otg device\n"); 222 return -ENODEV; 223 } 224 rk3288_otg_data.regs_otg = fdtdec_get_addr(blob, node, "reg"); 225 226 node = fdtdec_lookup_phandle(blob, node, "phys"); 227 if (node <= 0) { 228 debug("Not found usb phy device\n"); 229 return -ENODEV; 230 } 231 232 phy_node = fdt_parent_offset(blob, node); 233 if (phy_node <= 0) { 234 debug("Not found usb phy device\n"); 235 return -ENODEV; 236 } 237 238 rk3288_otg_data.phy_of_node = phy_node; 239 grf_phy_offset = fdtdec_get_addr(blob, node, "reg"); 240 241 /* find the grf node */ 242 node = fdt_node_offset_by_compatible(blob, -1, 243 "rockchip,rk3288-grf"); 244 if (node <= 0) { 245 debug("Not found grf device\n"); 246 return -ENODEV; 247 } 248 rk3288_otg_data.regs_phy = grf_phy_offset + 249 fdtdec_get_addr(blob, node, "reg"); 250 251 return dwc2_udc_probe(&rk3288_otg_data); 252 } 253 254 int board_usb_cleanup(int index, enum usb_init_type init) 255 { 256 return 0; 257 } 258 #endif 259 260 static int do_clock(cmd_tbl_t *cmdtp, int flag, int argc, 261 char * const argv[]) 262 { 263 static const struct { 264 char *name; 265 int id; 266 } clks[] = { 267 { "osc", CLK_OSC }, 268 { "apll", CLK_ARM }, 269 { "dpll", CLK_DDR }, 270 { "cpll", CLK_CODEC }, 271 { "gpll", CLK_GENERAL }, 272 #ifdef CONFIG_ROCKCHIP_RK3036 273 { "mpll", CLK_NEW }, 274 #else 275 { "npll", CLK_NEW }, 276 #endif 277 }; 278 int ret, i; 279 struct udevice *dev; 280 281 ret = rockchip_get_clk(&dev); 282 if (ret) { 283 printf("clk-uclass not found\n"); 284 return 0; 285 } 286 287 for (i = 0; i < ARRAY_SIZE(clks); i++) { 288 struct clk clk; 289 ulong rate; 290 291 clk.id = clks[i].id; 292 ret = clk_request(dev, &clk); 293 if (ret < 0) 294 continue; 295 296 rate = clk_get_rate(&clk); 297 printf("%s: %lu\n", clks[i].name, rate); 298 299 clk_free(&clk); 300 } 301 302 return 0; 303 } 304 305 U_BOOT_CMD( 306 clock, 2, 1, do_clock, 307 "display information about clocks", 308 "" 309 ); 310