blob: 70cf500291214ab96c3e5cc97e46b0799f1aa67d [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 */
Tom Riniabb9a042024-05-18 20:20:43 -06005#include <common.h>
Simon Glassed38aef2020-05-10 11:40:03 -06006#include <command.h>
Kever Yangbbea4932019-07-22 20:02:13 +08007#include <dm.h>
Simon Glass5e6201b2019-08-01 09:46:51 -06008#include <env.h>
Kever Yangbbea4932019-07-22 20:02:13 +08009#include <clk.h>
Simon Glassa7b51302019-11-14 12:57:46 -070010#include <init.h>
Simon Glass9bc15642020-02-03 07:36:16 -070011#include <malloc.h>
Kever Yang1f145142019-07-09 21:58:44 +080012#include <asm/armv7.h>
Simon Glass3ba929a2020-10-30 21:38:53 -060013#include <asm/global_data.h>
Kever Yang882b2a42019-07-22 19:59:30 +080014#include <asm/arch-rockchip/bootrom.h>
Kever Yangbbea4932019-07-22 20:02:13 +080015#include <asm/arch-rockchip/clock.h>
Jagan Tekif461f452020-07-21 12:16:38 +053016#include <asm/arch-rockchip/cpu_rk3288.h>
Jagan Teki783acfd2020-01-09 14:22:17 +053017#include <asm/arch-rockchip/cru.h>
Kever Yang9fbe17c2019-03-28 11:01:23 +080018#include <asm/arch-rockchip/hardware.h>
Kever Yang655f2a72019-03-29 09:09:03 +080019#include <asm/arch-rockchip/grf_rk3288.h>
Kever Yang66dd5942019-07-22 19:59:26 +080020#include <asm/arch-rockchip/pmu_rk3288.h>
Kever Yangd1078ea2019-07-22 20:02:10 +080021#include <asm/arch-rockchip/qos_rk3288.h>
Kever Yange47db832019-11-15 11:04:33 +080022#include <asm/arch-rockchip/sdram.h>
Simon Glassd66c5f72020-02-03 07:36:15 -070023#include <linux/err.h>
Kever Yang66dd5942019-07-22 19:59:26 +080024
25DECLARE_GLOBAL_DATA_PTR;
Kever Yang52ead2f2016-08-12 17:58:12 +080026
Kever Yang655f2a72019-03-29 09:09:03 +080027#define GRF_BASE 0xff770000
Kever Yang52ead2f2016-08-12 17:58:12 +080028
Kever Yang882b2a42019-07-22 19:59:30 +080029const char * const boot_devices[BROM_LAST_BOOTSOURCE + 1] = {
Johan Jonkerf05aa9d2022-04-15 23:21:43 +020030 [BROM_BOOTSOURCE_EMMC] = "/mmc@ff0f0000",
Jonas Karlman746a77e2024-03-22 20:50:22 +000031 [BROM_BOOTSOURCE_SPINOR] = "/spi@ff130000/flash@0",
Johan Jonkerf05aa9d2022-04-15 23:21:43 +020032 [BROM_BOOTSOURCE_SD] = "/mmc@ff0c0000",
Kever Yang882b2a42019-07-22 19:59:30 +080033};
34
Kever Yang1f145142019-07-09 21:58:44 +080035#ifdef CONFIG_SPL_BUILD
36static void configure_l2ctlr(void)
37{
38 u32 l2ctlr;
39
40 l2ctlr = read_l2ctlr();
41 l2ctlr &= 0xfffc0000; /* clear bit0~bit17 */
42
43 /*
44 * Data RAM write latency: 2 cycles
45 * Data RAM read latency: 2 cycles
46 * Data RAM setup latency: 1 cycle
47 * Tag RAM write latency: 1 cycle
48 * Tag RAM read latency: 1 cycle
49 * Tag RAM setup latency: 1 cycle
50 */
51 l2ctlr |= (1 << 3 | 1 << 0);
52 write_l2ctlr(l2ctlr);
53}
54#endif
55
Kever Yangd1078ea2019-07-22 20:02:10 +080056int rk3288_qos_init(void)
57{
58 int val = 2 << PRIORITY_HIGH_SHIFT | 2 << PRIORITY_LOW_SHIFT;
59 /* set vop qos to higher priority */
60 writel(val, CPU_AXI_QOS_PRIORITY + VIO0_VOP_QOS);
61 writel(val, CPU_AXI_QOS_PRIORITY + VIO1_VOP_QOS);
62
63 if (!fdt_node_check_compatible(gd->fdt_blob, 0,
64 "rockchip,rk3288-tinker")) {
65 /* set isp qos to higher priority */
66 writel(val, CPU_AXI_QOS_PRIORITY + VIO1_ISP_R_QOS);
67 writel(val, CPU_AXI_QOS_PRIORITY + VIO1_ISP_W0_QOS);
68 writel(val, CPU_AXI_QOS_PRIORITY + VIO1_ISP_W1_QOS);
69 }
70
71 return 0;
72}
73
Kever Yang52ead2f2016-08-12 17:58:12 +080074int arch_cpu_init(void)
75{
Kever Yanga3eff932019-07-09 21:58:43 +080076#ifdef CONFIG_SPL_BUILD
77 configure_l2ctlr();
78#else
Kever Yang52ead2f2016-08-12 17:58:12 +080079 /* We do some SoC one time setting here. */
Kever Yang655f2a72019-03-29 09:09:03 +080080 struct rk3288_grf * const grf = (void *)GRF_BASE;
Kever Yang52ead2f2016-08-12 17:58:12 +080081
82 /* Use rkpwm by default */
Kever Yang655f2a72019-03-29 09:09:03 +080083 rk_setreg(&grf->soc_con2, 1 << 0);
Kever Yangd1078ea2019-07-22 20:02:10 +080084
85 /*
86 * Disable JTAG on sdmmc0 IO. The SDMMC won't work until this bit is
87 * cleared
88 */
89 rk_clrreg(&grf->soc_con0, 1 << 12);
90
91 rk3288_qos_init();
Kever Yanga3eff932019-07-09 21:58:43 +080092#endif
Kever Yang52ead2f2016-08-12 17:58:12 +080093
94 return 0;
95}
Kever Yangabfed9b2019-03-29 09:09:04 +080096
97#ifdef CONFIG_DEBUG_UART_BOARD_INIT
98void board_debug_uart_init(void)
99{
100 /* Enable early UART on the RK3288 */
101 struct rk3288_grf * const grf = (void *)GRF_BASE;
102
103 rk_clrsetreg(&grf->gpio7ch_iomux, GPIO7C7_MASK << GPIO7C7_SHIFT |
104 GPIO7C6_MASK << GPIO7C6_SHIFT,
105 GPIO7C7_UART2DBG_SOUT << GPIO7C7_SHIFT |
106 GPIO7C6_UART2DBG_SIN << GPIO7C6_SHIFT);
107}
108#endif
Kever Yangbbea4932019-07-22 20:02:13 +0800109
Kever Yangb7da2712019-07-22 20:02:14 +0800110__weak int rk3288_board_late_init(void)
111{
112 return 0;
113}
114
115int rk_board_late_init(void)
116{
Kever Yangb7da2712019-07-22 20:02:14 +0800117 return rk3288_board_late_init();
118}
119
Jagan Tekif461f452020-07-21 12:16:38 +0530120static int ft_rk3288w_setup(void *blob)
121{
122 const char *path;
123 int offs, ret;
124
125 path = "/clock-controller@ff760000";
126 offs = fdt_path_offset(blob, path);
127 if (offs < 0) {
128 debug("failed to found fdt path %s\n", path);
129 return offs;
130 }
131
132 ret = fdt_setprop_string(blob, offs, "compatible", "rockchip,rk3288w-cru");
133 if (ret) {
134 printf("failed to set rk3288w-cru compatible (ret=%d)\n", ret);
135 return ret;
136 }
137
138 return ret;
139}
140
John Keepingd5cb7712023-02-23 19:28:51 +0000141int ft_system_setup(void *blob, struct bd_info *bd)
Jagan Tekif461f452020-07-21 12:16:38 +0530142{
143 if (soc_is_rk3288w())
144 return ft_rk3288w_setup(blob);
145
146 return 0;
147}
148
Simon Glassed38aef2020-05-10 11:40:03 -0600149static int do_clock(struct cmd_tbl *cmdtp, int flag, int argc,
150 char *const argv[])
Kever Yangbbea4932019-07-22 20:02:13 +0800151{
152 static const struct {
153 char *name;
154 int id;
155 } clks[] = {
156 { "osc", CLK_OSC },
157 { "apll", CLK_ARM },
158 { "dpll", CLK_DDR },
159 { "cpll", CLK_CODEC },
160 { "gpll", CLK_GENERAL },
161#ifdef CONFIG_ROCKCHIP_RK3036
162 { "mpll", CLK_NEW },
163#else
164 { "npll", CLK_NEW },
165#endif
166 };
167 int ret, i;
168 struct udevice *dev;
169
170 ret = rockchip_get_clk(&dev);
171 if (ret) {
172 printf("clk-uclass not found\n");
173 return 0;
174 }
175
176 for (i = 0; i < ARRAY_SIZE(clks); i++) {
177 struct clk clk;
178 ulong rate;
179
180 clk.id = clks[i].id;
181 ret = clk_request(dev, &clk);
182 if (ret < 0)
183 continue;
184
185 rate = clk_get_rate(&clk);
186 printf("%s: %lu\n", clks[i].name, rate);
Kever Yangbbea4932019-07-22 20:02:13 +0800187 }
188
189 return 0;
190}
191
192U_BOOT_CMD(
193 clock, 2, 1, do_clock,
194 "display information about clocks",
195 ""
196);