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