blob: 9894a25e080f34daa5b574982a6dc6909068ca53 [file] [log] [blame]
Simon Glass2444dae2015-08-30 16:55:38 -06001/*
2 * (C) Copyright 2015 Google, Inc
3 *
4 * SPDX-License-Identifier: GPL-2.0+
5 */
6
7#include <common.h>
Simon Glass74e53e02016-01-21 19:45:07 -07008#include <clk.h>
Simon Glass2444dae2015-08-30 16:55:38 -06009#include <dm.h>
10#include <ram.h>
Jacob Chen67171e12016-09-19 18:46:28 +080011#include <syscon.h>
huang linbe1d5e02015-11-17 14:20:27 +080012#include <asm/io.h>
Stephen Warren135aa952016-06-17 09:44:00 -060013#include <asm/arch/clock.h>
Xu Ziyuanb47ea792016-07-12 19:09:49 +080014#include <asm/arch/periph.h>
Jacob Chen67171e12016-09-19 18:46:28 +080015#include <asm/arch/pmu_rk3288.h>
Nickey Yang Nickey Yang9b832012016-12-29 10:47:30 +080016#include <asm/arch/qos_rk3288.h>
Jacob Chen67171e12016-09-19 18:46:28 +080017#include <asm/arch/boot_mode.h>
Xu Ziyuanb47ea792016-07-12 19:09:49 +080018#include <asm/gpio.h>
19#include <dm/pinctrl.h>
Simon Glass20b13e82016-11-13 14:22:14 -070020#include <dt-bindings/clock/rk3288-cru.h>
21#include <power/regulator.h>
Simon Glass2444dae2015-08-30 16:55:38 -060022
23DECLARE_GLOBAL_DATA_PTR;
24
Jacob Chen67171e12016-09-19 18:46:28 +080025#define PMU_BASE 0xff730000
26
27static 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
Nickey Yang Nickey Yang9b832012016-12-29 10:47:30 +080055int 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,
Eddie Cai6f279762017-01-18 11:03:54 +080063 "rockchip,rk3288-tinker"))
Nickey Yang Nickey Yang9b832012016-12-29 10:47:30 +080064 {
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
Jacob Chen67171e12016-09-19 18:46:28 +080073int board_late_init(void)
74{
75 setup_boot_mode();
Nickey Yang Nickey Yang9b832012016-12-29 10:47:30 +080076 rk3288_qos_init();
Jacob Chen67171e12016-09-19 18:46:28 +080077
78 return rk_board_late_init();
79}
80
Simon Glass20b13e82016-11-13 14:22:14 -070081#ifndef CONFIG_ROCKCHIP_SPL_BACK_TO_BROM
82static 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
Simon Glass2444dae2015-08-30 16:55:38 -0600114int board_init(void)
115{
Xu Ziyuanb47ea792016-07-12 19:09:49 +0800116#ifdef CONFIG_ROCKCHIP_SPL_BACK_TO_BROM
117 struct udevice *pinctrl;
118 int ret;
119
Jacob Chen67171e12016-09-19 18:46:28 +0800120 /*
121 * We need to implement sdcard iomux here for the further
122 * initlization, otherwise, it'll hit sdcard command sending
123 * timeout exception.
124 */
Xu Ziyuanb47ea792016-07-12 19:09:49 +0800125 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
Simon Glass2444dae2015-08-30 16:55:38 -0600136 return 0;
Xu Ziyuanb47ea792016-07-12 19:09:49 +0800137err:
138 printf("board_init: Error %d\n", ret);
139
140 /* No way to report error here */
141 hang();
142
143 return -1;
144#else
Simon Glass20b13e82016-11-13 14:22:14 -0700145 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
Xu Ziyuanb47ea792016-07-12 19:09:49 +0800154 return 0;
155#endif
Simon Glass2444dae2015-08-30 16:55:38 -0600156}
157
158int 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
181void enable_caches(void)
182{
183 /* Enable D-cache. I-cache is already enabled in start.S */
184 dcache_enable();
185}
186#endif
Simon Glassad443b72016-01-21 19:45:06 -0700187
Xu Ziyuan266c8fa2016-07-15 00:26:59 +0800188#if defined(CONFIG_USB_GADGET) && defined(CONFIG_USB_GADGET_DWC2_OTG)
189#include <usb.h>
190#include <usb/dwc2_udc.h>
191
192static 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
198int 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
254int board_usb_cleanup(int index, enum usb_init_type init)
255{
256 return 0;
257}
258#endif
259
Simon Glass74e53e02016-01-21 19:45:07 -0700260static int do_clock(cmd_tbl_t *cmdtp, int flag, int argc,
261 char * const argv[])
262{
Stephen Warren135aa952016-06-17 09:44:00 -0600263 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;
Simon Glass74e53e02016-01-21 19:45:07 -0700279 struct udevice *dev;
280
Simon Glassc3aad6f2016-07-17 15:23:17 -0600281 ret = rockchip_get_clk(&dev);
Stephen Warren135aa952016-06-17 09:44:00 -0600282 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;
Simon Glass74e53e02016-01-21 19:45:07 -0700289 ulong rate;
290
Stephen Warren135aa952016-06-17 09:44:00 -0600291 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);
Simon Glass74e53e02016-01-21 19:45:07 -0700300 }
301
302 return 0;
303}
304
305U_BOOT_CMD(
306 clock, 2, 1, do_clock,
307 "display information about clocks",
308 ""
309);