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