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