1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2016 Rockchip Electronics Co., Ltd
4  */
5 #include <common.h>
6 #include <command.h>
7 #include <dm.h>
8 #include <env.h>
9 #include <clk.h>
10 #include <init.h>
11 #include <malloc.h>
12 #include <asm/armv7.h>
13 #include <asm/global_data.h>
14 #include <asm/io.h>
15 #include <asm/arch-rockchip/bootrom.h>
16 #include <asm/arch-rockchip/clock.h>
17 #include <asm/arch-rockchip/cpu_rk3288.h>
18 #include <asm/arch-rockchip/cru.h>
19 #include <asm/arch-rockchip/hardware.h>
20 #include <asm/arch-rockchip/grf_rk3288.h>
21 #include <asm/arch-rockchip/pmu_rk3288.h>
22 #include <asm/arch-rockchip/qos_rk3288.h>
23 #include <asm/arch-rockchip/sdram.h>
24 #include <linux/err.h>
25 
26 DECLARE_GLOBAL_DATA_PTR;
27 
28 #define GRF_BASE	0xff770000
29 
30 const char * const boot_devices[BROM_LAST_BOOTSOURCE + 1] = {
31 	[BROM_BOOTSOURCE_EMMC] = "/dwmmc@ff0f0000",
32 	[BROM_BOOTSOURCE_SD] = "/dwmmc@ff0c0000",
33 };
34 
35 #ifdef CONFIG_SPL_BUILD
configure_l2ctlr(void)36 static 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 
rk3288_qos_init(void)56 int 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 
arch_cpu_init(void)74 int arch_cpu_init(void)
75 {
76 #ifdef CONFIG_SPL_BUILD
77 	configure_l2ctlr();
78 #else
79 	/* We do some SoC one time setting here. */
80 	struct rk3288_grf * const grf = (void *)GRF_BASE;
81 
82 	/* Use rkpwm by default */
83 	rk_setreg(&grf->soc_con2, 1 << 0);
84 
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();
92 #endif
93 
94 	return 0;
95 }
96 
97 #ifdef CONFIG_DEBUG_UART_BOARD_INIT
board_debug_uart_init(void)98 void 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
109 
rk3288_board_late_init(void)110 __weak int rk3288_board_late_init(void)
111 {
112 	return 0;
113 }
114 
rk_board_late_init(void)115 int rk_board_late_init(void)
116 {
117 	return rk3288_board_late_init();
118 }
119 
ft_rk3288w_setup(void * blob)120 static 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 
ft_board_setup(void * blob,struct bd_info * bd)141 int ft_board_setup(void *blob, struct bd_info *bd)
142 {
143 	if (soc_is_rk3288w())
144 		return ft_rk3288w_setup(blob);
145 
146 	return 0;
147 }
148 
do_clock(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])149 static int do_clock(struct cmd_tbl *cmdtp, int flag, int argc,
150 		    char *const argv[])
151 {
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);
187 
188 		clk_free(&clk);
189 	}
190 
191 	return 0;
192 }
193 
194 U_BOOT_CMD(
195 	clock, 2, 1, do_clock,
196 	"display information about clocks",
197 	""
198 );
199