blob: 1a4ecdf62546da38c6a08ac1793bba5efaf47a5f [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>
Simon Glass09140112020-05-10 11:40:03 -06006#include <command.h>
Kever Yang88a87bc2019-07-22 20:02:13 +08007#include <dm.h>
Simon Glass9fb625c2019-08-01 09:46:51 -06008#include <env.h>
Kever Yang88a87bc2019-07-22 20:02:13 +08009#include <clk.h>
Simon Glass52559322019-11-14 12:57:46 -070010#include <init.h>
Simon Glass336d4612020-02-03 07:36:16 -070011#include <malloc.h>
Kever Yang25c61732019-07-09 21:58:44 +080012#include <asm/armv7.h>
Kever Yangaa89b552016-08-12 17:58:12 +080013#include <asm/io.h>
Kever Yang8af6caf2019-07-22 19:59:30 +080014#include <asm/arch-rockchip/bootrom.h>
Kever Yang88a87bc2019-07-22 20:02:13 +080015#include <asm/arch-rockchip/clock.h>
Jagan Tekieab5c502020-07-21 12:16:38 +053016#include <asm/arch-rockchip/cpu_rk3288.h>
Jagan Tekib52a1992020-01-09 14:22:17 +053017#include <asm/arch-rockchip/cru.h>
Kever Yang15f09a12019-03-28 11:01:23 +080018#include <asm/arch-rockchip/hardware.h>
Kever Yang070e48b2019-03-29 09:09:03 +080019#include <asm/arch-rockchip/grf_rk3288.h>
Kever Yangf35c4172019-07-22 19:59:26 +080020#include <asm/arch-rockchip/pmu_rk3288.h>
Kever Yang1e7d2be2019-07-22 20:02:10 +080021#include <asm/arch-rockchip/qos_rk3288.h>
Kever Yang5d19ddf2019-11-15 11:04:33 +080022#include <asm/arch-rockchip/sdram.h>
Simon Glass61b29b82020-02-03 07:36:15 -070023#include <linux/err.h>
Kever Yangf35c4172019-07-22 19:59:26 +080024
25DECLARE_GLOBAL_DATA_PTR;
Kever Yangaa89b552016-08-12 17:58:12 +080026
Kever Yang070e48b2019-03-29 09:09:03 +080027#define GRF_BASE 0xff770000
Kever Yangaa89b552016-08-12 17:58:12 +080028
Kever Yang8af6caf2019-07-22 19:59:30 +080029const char * const boot_devices[BROM_LAST_BOOTSOURCE + 1] = {
Levin Du2d86ab52019-10-17 15:22:38 +080030 [BROM_BOOTSOURCE_EMMC] = "/dwmmc@ff0f0000",
31 [BROM_BOOTSOURCE_SD] = "/dwmmc@ff0c0000",
Kever Yang8af6caf2019-07-22 19:59:30 +080032};
33
Kever Yang25c61732019-07-09 21:58:44 +080034#ifdef CONFIG_SPL_BUILD
35static void configure_l2ctlr(void)
36{
37 u32 l2ctlr;
38
39 l2ctlr = read_l2ctlr();
40 l2ctlr &= 0xfffc0000; /* clear bit0~bit17 */
41
42 /*
43 * Data RAM write latency: 2 cycles
44 * Data RAM read latency: 2 cycles
45 * Data RAM setup latency: 1 cycle
46 * Tag RAM write latency: 1 cycle
47 * Tag RAM read latency: 1 cycle
48 * Tag RAM setup latency: 1 cycle
49 */
50 l2ctlr |= (1 << 3 | 1 << 0);
51 write_l2ctlr(l2ctlr);
52}
53#endif
54
Kever Yang1e7d2be2019-07-22 20:02:10 +080055int rk3288_qos_init(void)
56{
57 int val = 2 << PRIORITY_HIGH_SHIFT | 2 << PRIORITY_LOW_SHIFT;
58 /* set vop qos to higher priority */
59 writel(val, CPU_AXI_QOS_PRIORITY + VIO0_VOP_QOS);
60 writel(val, CPU_AXI_QOS_PRIORITY + VIO1_VOP_QOS);
61
62 if (!fdt_node_check_compatible(gd->fdt_blob, 0,
63 "rockchip,rk3288-tinker")) {
64 /* set isp qos to higher priority */
65 writel(val, CPU_AXI_QOS_PRIORITY + VIO1_ISP_R_QOS);
66 writel(val, CPU_AXI_QOS_PRIORITY + VIO1_ISP_W0_QOS);
67 writel(val, CPU_AXI_QOS_PRIORITY + VIO1_ISP_W1_QOS);
68 }
69
70 return 0;
71}
72
Kever Yangaa89b552016-08-12 17:58:12 +080073int arch_cpu_init(void)
74{
Kever Yangccab9e72019-07-09 21:58:43 +080075#ifdef CONFIG_SPL_BUILD
76 configure_l2ctlr();
77#else
Kever Yangaa89b552016-08-12 17:58:12 +080078 /* We do some SoC one time setting here. */
Kever Yang070e48b2019-03-29 09:09:03 +080079 struct rk3288_grf * const grf = (void *)GRF_BASE;
Kever Yangaa89b552016-08-12 17:58:12 +080080
81 /* Use rkpwm by default */
Kever Yang070e48b2019-03-29 09:09:03 +080082 rk_setreg(&grf->soc_con2, 1 << 0);
Kever Yang1e7d2be2019-07-22 20:02:10 +080083
84 /*
85 * Disable JTAG on sdmmc0 IO. The SDMMC won't work until this bit is
86 * cleared
87 */
88 rk_clrreg(&grf->soc_con0, 1 << 12);
89
90 rk3288_qos_init();
Kever Yangccab9e72019-07-09 21:58:43 +080091#endif
Kever Yangaa89b552016-08-12 17:58:12 +080092
93 return 0;
94}
Kever Yange83e8852019-03-29 09:09:04 +080095
96#ifdef CONFIG_DEBUG_UART_BOARD_INIT
97void board_debug_uart_init(void)
98{
99 /* Enable early UART on the RK3288 */
100 struct rk3288_grf * const grf = (void *)GRF_BASE;
101
102 rk_clrsetreg(&grf->gpio7ch_iomux, GPIO7C7_MASK << GPIO7C7_SHIFT |
103 GPIO7C6_MASK << GPIO7C6_SHIFT,
104 GPIO7C7_UART2DBG_SOUT << GPIO7C7_SHIFT |
105 GPIO7C6_UART2DBG_SIN << GPIO7C6_SHIFT);
106}
107#endif
Kever Yang88a87bc2019-07-22 20:02:13 +0800108
Kever Yang271318a2019-07-22 20:02:14 +0800109__weak int rk3288_board_late_init(void)
110{
111 return 0;
112}
113
114int rk_board_late_init(void)
115{
Kever Yang271318a2019-07-22 20:02:14 +0800116 return rk3288_board_late_init();
117}
118
Jagan Tekieab5c502020-07-21 12:16:38 +0530119static int ft_rk3288w_setup(void *blob)
120{
121 const char *path;
122 int offs, ret;
123
124 path = "/clock-controller@ff760000";
125 offs = fdt_path_offset(blob, path);
126 if (offs < 0) {
127 debug("failed to found fdt path %s\n", path);
128 return offs;
129 }
130
131 ret = fdt_setprop_string(blob, offs, "compatible", "rockchip,rk3288w-cru");
132 if (ret) {
133 printf("failed to set rk3288w-cru compatible (ret=%d)\n", ret);
134 return ret;
135 }
136
137 return ret;
138}
139
140int ft_board_setup(void *blob, struct bd_info *bd)
141{
142 if (soc_is_rk3288w())
143 return ft_rk3288w_setup(blob);
144
145 return 0;
146}
147
Simon Glass09140112020-05-10 11:40:03 -0600148static int do_clock(struct cmd_tbl *cmdtp, int flag, int argc,
149 char *const argv[])
Kever Yang88a87bc2019-07-22 20:02:13 +0800150{
151 static const struct {
152 char *name;
153 int id;
154 } clks[] = {
155 { "osc", CLK_OSC },
156 { "apll", CLK_ARM },
157 { "dpll", CLK_DDR },
158 { "cpll", CLK_CODEC },
159 { "gpll", CLK_GENERAL },
160#ifdef CONFIG_ROCKCHIP_RK3036
161 { "mpll", CLK_NEW },
162#else
163 { "npll", CLK_NEW },
164#endif
165 };
166 int ret, i;
167 struct udevice *dev;
168
169 ret = rockchip_get_clk(&dev);
170 if (ret) {
171 printf("clk-uclass not found\n");
172 return 0;
173 }
174
175 for (i = 0; i < ARRAY_SIZE(clks); i++) {
176 struct clk clk;
177 ulong rate;
178
179 clk.id = clks[i].id;
180 ret = clk_request(dev, &clk);
181 if (ret < 0)
182 continue;
183
184 rate = clk_get_rate(&clk);
185 printf("%s: %lu\n", clks[i].name, rate);
186
187 clk_free(&clk);
188 }
189
190 return 0;
191}
192
193U_BOOT_CMD(
194 clock, 2, 1, do_clock,
195 "display information about clocks",
196 ""
197);