env: Move env_set() to env.h
[oweals/u-boot.git] / arch / arm / mach-rockchip / rk3288 / rk3288.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2016 Rockchip Electronics Co., Ltd
4  */
5 #include <common.h>
6 #include <dm.h>
7 #include <env.h>
8 #include <clk.h>
9 #include <asm/armv7.h>
10 #include <asm/io.h>
11 #include <asm/arch-rockchip/bootrom.h>
12 #include <asm/arch-rockchip/clock.h>
13 #include <asm/arch-rockchip/cru_rk3288.h>
14 #include <asm/arch-rockchip/hardware.h>
15 #include <asm/arch-rockchip/grf_rk3288.h>
16 #include <asm/arch-rockchip/pmu_rk3288.h>
17 #include <asm/arch-rockchip/qos_rk3288.h>
18 #include <asm/arch-rockchip/sdram_common.h>
19
20 DECLARE_GLOBAL_DATA_PTR;
21
22 #define GRF_BASE        0xff770000
23
24 const char * const boot_devices[BROM_LAST_BOOTSOURCE + 1] = {
25         [BROM_BOOTSOURCE_EMMC] = "dwmmc@ff0f0000",
26         [BROM_BOOTSOURCE_SD] = "dwmmc@ff0c0000",
27 };
28
29 #ifdef CONFIG_SPL_BUILD
30 static void configure_l2ctlr(void)
31 {
32         u32 l2ctlr;
33
34         l2ctlr = read_l2ctlr();
35         l2ctlr &= 0xfffc0000; /* clear bit0~bit17 */
36
37         /*
38          * Data RAM write latency: 2 cycles
39          * Data RAM read latency: 2 cycles
40          * Data RAM setup latency: 1 cycle
41          * Tag RAM write latency: 1 cycle
42          * Tag RAM read latency: 1 cycle
43          * Tag RAM setup latency: 1 cycle
44          */
45         l2ctlr |= (1 << 3 | 1 << 0);
46         write_l2ctlr(l2ctlr);
47 }
48 #endif
49
50 int rk3288_qos_init(void)
51 {
52         int val = 2 << PRIORITY_HIGH_SHIFT | 2 << PRIORITY_LOW_SHIFT;
53         /* set vop qos to higher priority */
54         writel(val, CPU_AXI_QOS_PRIORITY + VIO0_VOP_QOS);
55         writel(val, CPU_AXI_QOS_PRIORITY + VIO1_VOP_QOS);
56
57         if (!fdt_node_check_compatible(gd->fdt_blob, 0,
58                                        "rockchip,rk3288-tinker")) {
59                 /* set isp qos to higher priority */
60                 writel(val, CPU_AXI_QOS_PRIORITY + VIO1_ISP_R_QOS);
61                 writel(val, CPU_AXI_QOS_PRIORITY + VIO1_ISP_W0_QOS);
62                 writel(val, CPU_AXI_QOS_PRIORITY + VIO1_ISP_W1_QOS);
63         }
64
65         return 0;
66 }
67
68 int arch_cpu_init(void)
69 {
70 #ifdef CONFIG_SPL_BUILD
71         configure_l2ctlr();
72 #else
73         /* We do some SoC one time setting here. */
74         struct rk3288_grf * const grf = (void *)GRF_BASE;
75
76         /* Use rkpwm by default */
77         rk_setreg(&grf->soc_con2, 1 << 0);
78
79         /*
80          * Disable JTAG on sdmmc0 IO. The SDMMC won't work until this bit is
81          * cleared
82          */
83         rk_clrreg(&grf->soc_con0, 1 << 12);
84
85         rk3288_qos_init();
86 #endif
87
88         return 0;
89 }
90
91 #ifdef CONFIG_DEBUG_UART_BOARD_INIT
92 void board_debug_uart_init(void)
93 {
94         /* Enable early UART on the RK3288 */
95         struct rk3288_grf * const grf = (void *)GRF_BASE;
96
97         rk_clrsetreg(&grf->gpio7ch_iomux, GPIO7C7_MASK << GPIO7C7_SHIFT |
98                      GPIO7C6_MASK << GPIO7C6_SHIFT,
99                      GPIO7C7_UART2DBG_SOUT << GPIO7C7_SHIFT |
100                      GPIO7C6_UART2DBG_SIN << GPIO7C6_SHIFT);
101 }
102 #endif
103
104 static void rk3288_detect_reset_reason(void)
105 {
106         struct rk3288_cru *cru = rockchip_get_cru();
107         const char *reason;
108
109         if (IS_ERR(cru))
110                 return;
111
112         switch (cru->cru_glb_rst_st) {
113         case GLB_POR_RST:
114                 reason = "POR";
115                 break;
116         case FST_GLB_RST_ST:
117         case SND_GLB_RST_ST:
118                 reason = "RST";
119                 break;
120         case FST_GLB_TSADC_RST_ST:
121         case SND_GLB_TSADC_RST_ST:
122                 reason = "THERMAL";
123                 break;
124         case FST_GLB_WDT_RST_ST:
125         case SND_GLB_WDT_RST_ST:
126                 reason = "WDOG";
127                 break;
128         default:
129                 reason = "unknown reset";
130         }
131
132         env_set("reset_reason", reason);
133
134         /*
135          * Clear cru_glb_rst_st, so we can determine the last reset cause
136          * for following resets.
137          */
138         rk_clrreg(&cru->cru_glb_rst_st, GLB_RST_ST_MASK);
139 }
140
141 __weak int rk3288_board_late_init(void)
142 {
143         return 0;
144 }
145
146 int rk_board_late_init(void)
147 {
148         rk3288_detect_reset_reason();
149
150         return rk3288_board_late_init();
151 }
152
153 static int do_clock(cmd_tbl_t *cmdtp, int flag, int argc,
154                        char * const argv[])
155 {
156         static const struct {
157                 char *name;
158                 int id;
159         } clks[] = {
160                 { "osc", CLK_OSC },
161                 { "apll", CLK_ARM },
162                 { "dpll", CLK_DDR },
163                 { "cpll", CLK_CODEC },
164                 { "gpll", CLK_GENERAL },
165 #ifdef CONFIG_ROCKCHIP_RK3036
166                 { "mpll", CLK_NEW },
167 #else
168                 { "npll", CLK_NEW },
169 #endif
170         };
171         int ret, i;
172         struct udevice *dev;
173
174         ret = rockchip_get_clk(&dev);
175         if (ret) {
176                 printf("clk-uclass not found\n");
177                 return 0;
178         }
179
180         for (i = 0; i < ARRAY_SIZE(clks); i++) {
181                 struct clk clk;
182                 ulong rate;
183
184                 clk.id = clks[i].id;
185                 ret = clk_request(dev, &clk);
186                 if (ret < 0)
187                         continue;
188
189                 rate = clk_get_rate(&clk);
190                 printf("%s: %lu\n", clks[i].name, rate);
191
192                 clk_free(&clk);
193         }
194
195         return 0;
196 }
197
198 U_BOOT_CMD(
199         clock, 2, 1, do_clock,
200         "display information about clocks",
201         ""
202 );