blob: b462c0906994fef239fb5322a726ac51b7715814 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Kever Yangaa89b552016-08-12 17:58:12 +08002/*
3 * Copyright (c) 2016 Rockchip Electronics Co., Ltd
Kever Yangaa89b552016-08-12 17:58:12 +08004 */
Kever Yang1e7d2be2019-07-22 20:02:10 +08005#include <common.h>
Kever Yang88a87bc2019-07-22 20:02:13 +08006#include <dm.h>
7#include <clk.h>
Kever Yang25c61732019-07-09 21:58:44 +08008#include <asm/armv7.h>
Kever Yangaa89b552016-08-12 17:58:12 +08009#include <asm/io.h>
Kever Yang8af6caf2019-07-22 19:59:30 +080010#include <asm/arch-rockchip/bootrom.h>
Kever Yang88a87bc2019-07-22 20:02:13 +080011#include <asm/arch-rockchip/clock.h>
12#include <asm/arch-rockchip/cru_rk3288.h>
Kever Yang15f09a12019-03-28 11:01:23 +080013#include <asm/arch-rockchip/hardware.h>
Kever Yang070e48b2019-03-29 09:09:03 +080014#include <asm/arch-rockchip/grf_rk3288.h>
Kever Yangf35c4172019-07-22 19:59:26 +080015#include <asm/arch-rockchip/pmu_rk3288.h>
Kever Yang1e7d2be2019-07-22 20:02:10 +080016#include <asm/arch-rockchip/qos_rk3288.h>
Kever Yangf35c4172019-07-22 19:59:26 +080017#include <asm/arch-rockchip/sdram_common.h>
18
19DECLARE_GLOBAL_DATA_PTR;
Kever Yangaa89b552016-08-12 17:58:12 +080020
Kever Yang070e48b2019-03-29 09:09:03 +080021#define GRF_BASE 0xff770000
Kever Yangaa89b552016-08-12 17:58:12 +080022
Kever Yang8af6caf2019-07-22 19:59:30 +080023const char * const boot_devices[BROM_LAST_BOOTSOURCE + 1] = {
24 [BROM_BOOTSOURCE_EMMC] = "dwmmc@ff0f0000",
25 [BROM_BOOTSOURCE_SD] = "dwmmc@ff0c0000",
26};
27
Kever Yang25c61732019-07-09 21:58:44 +080028#ifdef CONFIG_SPL_BUILD
29static 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
Kever Yang1e7d2be2019-07-22 20:02:10 +080049int 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
Kever Yangaa89b552016-08-12 17:58:12 +080067int arch_cpu_init(void)
68{
Kever Yangccab9e72019-07-09 21:58:43 +080069#ifdef CONFIG_SPL_BUILD
70 configure_l2ctlr();
71#else
Kever Yangaa89b552016-08-12 17:58:12 +080072 /* We do some SoC one time setting here. */
Kever Yang070e48b2019-03-29 09:09:03 +080073 struct rk3288_grf * const grf = (void *)GRF_BASE;
Kever Yangaa89b552016-08-12 17:58:12 +080074
75 /* Use rkpwm by default */
Kever Yang070e48b2019-03-29 09:09:03 +080076 rk_setreg(&grf->soc_con2, 1 << 0);
Kever Yang1e7d2be2019-07-22 20:02:10 +080077
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();
Kever Yangccab9e72019-07-09 21:58:43 +080085#endif
Kever Yangaa89b552016-08-12 17:58:12 +080086
87 return 0;
88}
Kever Yange83e8852019-03-29 09:09:04 +080089
90#ifdef CONFIG_DEBUG_UART_BOARD_INIT
91void 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
Kever Yang88a87bc2019-07-22 20:02:13 +0800102
Kever Yang271318a2019-07-22 20:02:14 +0800103static 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
145int rk_board_late_init(void)
146{
147 rk3288_detect_reset_reason();
148
149 return rk3288_board_late_init();
150}
151
Kever Yang88a87bc2019-07-22 20:02:13 +0800152static 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
197U_BOOT_CMD(
198 clock, 2, 1, do_clock,
199 "display information about clocks",
200 ""
201);