]>
Commit | Line | Data |
---|---|---|
3012a840 KY |
1 | /* |
2 | * (C) Copyright 2016 Rockchip Electronics Co., Ltd | |
3 | * | |
4 | * SPDX-License-Identifier: GPL-2.0+ | |
5 | */ | |
6 | ||
7 | #include <common.h> | |
8 | #include <debug_uart.h> | |
9 | #include <dm.h> | |
10 | #include <fdtdec.h> | |
11 | #include <led.h> | |
12 | #include <malloc.h> | |
d02d11f8 | 13 | #include <mmc.h> |
3012a840 KY |
14 | #include <ram.h> |
15 | #include <spl.h> | |
16 | #include <asm/gpio.h> | |
17 | #include <asm/io.h> | |
18 | #include <asm/arch/clock.h> | |
19 | #include <asm/arch/hardware.h> | |
20 | #include <asm/arch/periph.h> | |
21 | #include <asm/arch/sdram.h> | |
22 | #include <asm/arch/timer.h> | |
23 | #include <dm/pinctrl.h> | |
24 | #include <dm/root.h> | |
25 | #include <dm/test.h> | |
26 | #include <dm/util.h> | |
27 | #include <power/regulator.h> | |
28 | ||
29 | DECLARE_GLOBAL_DATA_PTR; | |
30 | ||
d02d11f8 PT |
31 | #if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_OF_CONTROL) |
32 | static int spl_node_to_boot_device(int node) | |
33 | { | |
34 | struct udevice *parent; | |
35 | ||
36 | /* | |
37 | * This should eventually move into the SPL code, once SPL becomes | |
38 | * aware of the block-device layer. Until then (and to avoid unneeded | |
39 | * delays in getting this feature out, it lives at the board-level). | |
40 | */ | |
41 | if (!uclass_get_device_by_of_offset(UCLASS_MMC, node, &parent)) { | |
42 | struct udevice *dev; | |
43 | struct blk_desc *desc = NULL; | |
44 | ||
45 | for (device_find_first_child(parent, &dev); | |
46 | dev; | |
47 | device_find_next_child(&dev)) { | |
48 | if (device_get_uclass_id(dev) == UCLASS_BLK) { | |
49 | desc = dev_get_uclass_platdata(dev); | |
50 | break; | |
51 | } | |
52 | } | |
53 | ||
54 | if (!desc) | |
55 | return -ENOENT; | |
56 | ||
57 | switch (desc->devnum) { | |
58 | case 0: | |
59 | return BOOT_DEVICE_MMC1; | |
60 | case 1: | |
61 | return BOOT_DEVICE_MMC2; | |
62 | default: | |
63 | return -ENOSYS; | |
64 | } | |
65 | } | |
66 | ||
67 | /* | |
68 | * SPL doesn't differentiate SPI flashes, so we keep the detection | |
69 | * brief and inaccurate... hopefully, the common SPL layer can be | |
70 | * extended with awareness of the BLK layer (and matching OF_CONTROL) | |
71 | * soon. | |
72 | */ | |
73 | if (!uclass_get_device_by_of_offset(UCLASS_SPI_FLASH, node, &parent)) | |
74 | return BOOT_DEVICE_SPI; | |
75 | ||
76 | return -1; | |
77 | } | |
78 | ||
79 | void board_boot_order(u32 *spl_boot_list) | |
80 | { | |
81 | const void *blob = gd->fdt_blob; | |
82 | int chosen_node = fdt_path_offset(blob, "/chosen"); | |
83 | int idx = 0; | |
84 | int elem; | |
85 | int boot_device; | |
86 | int node; | |
87 | const char *conf; | |
88 | ||
89 | if (chosen_node < 0) { | |
90 | debug("%s: /chosen not found, using spl_boot_device()\n", | |
91 | __func__); | |
92 | spl_boot_list[0] = spl_boot_device(); | |
93 | return; | |
94 | } | |
95 | ||
96 | for (elem = 0; | |
97 | (conf = fdt_stringlist_get(blob, chosen_node, | |
98 | "u-boot,spl-boot-order", elem, NULL)); | |
99 | elem++) { | |
100 | /* First check if the list element is an alias */ | |
101 | const char *alias = fdt_get_alias(blob, conf); | |
102 | if (alias) | |
103 | conf = alias; | |
104 | ||
105 | /* Try to resolve the config item (or alias) as a path */ | |
106 | node = fdt_path_offset(blob, conf); | |
107 | if (node < 0) { | |
108 | debug("%s: could not find %s in FDT", __func__, conf); | |
109 | continue; | |
110 | } | |
111 | ||
112 | /* Try to map this back onto SPL boot devices */ | |
113 | boot_device = spl_node_to_boot_device(node); | |
114 | if (boot_device < 0) { | |
115 | debug("%s: could not map node @%x to a boot-device\n", | |
116 | __func__, node); | |
117 | continue; | |
118 | } | |
119 | ||
120 | spl_boot_list[idx++] = boot_device; | |
121 | } | |
122 | ||
123 | /* If we had no matches, fall back to spl_boot_device */ | |
124 | if (idx == 0) | |
125 | spl_boot_list[0] = spl_boot_device(); | |
126 | } | |
127 | #endif | |
128 | ||
3012a840 KY |
129 | u32 spl_boot_device(void) |
130 | { | |
131 | return BOOT_DEVICE_MMC1; | |
132 | } | |
133 | ||
134 | u32 spl_boot_mode(const u32 boot_device) | |
135 | { | |
136 | return MMCSD_MODE_RAW; | |
137 | } | |
138 | ||
139 | #define TIMER_CHN10_BASE 0xff8680a0 | |
140 | #define TIMER_END_COUNT_L 0x00 | |
141 | #define TIMER_END_COUNT_H 0x04 | |
142 | #define TIMER_INIT_COUNT_L 0x10 | |
143 | #define TIMER_INIT_COUNT_H 0x14 | |
144 | #define TIMER_CONTROL_REG 0x1c | |
145 | ||
146 | #define TIMER_EN 0x1 | |
147 | #define TIMER_FMODE (0 << 1) | |
148 | #define TIMER_RMODE (1 << 1) | |
149 | ||
150 | void secure_timer_init(void) | |
151 | { | |
152 | writel(0xffffffff, TIMER_CHN10_BASE + TIMER_END_COUNT_L); | |
153 | writel(0xffffffff, TIMER_CHN10_BASE + TIMER_END_COUNT_H); | |
154 | writel(0, TIMER_CHN10_BASE + TIMER_INIT_COUNT_L); | |
155 | writel(0, TIMER_CHN10_BASE + TIMER_INIT_COUNT_H); | |
156 | writel(TIMER_EN | TIMER_FMODE, TIMER_CHN10_BASE + TIMER_CONTROL_REG); | |
157 | } | |
158 | ||
7ee16de5 PT |
159 | void board_debug_uart_init(void) |
160 | { | |
3012a840 | 161 | #include <asm/arch/grf_rk3399.h> |
3012a840 KY |
162 | #define GRF_BASE 0xff770000 |
163 | struct rk3399_grf_regs * const grf = (void *)GRF_BASE; | |
164 | ||
7ee16de5 PT |
165 | #if defined(CONFIG_DEBUG_UART_BASE) && (CONFIG_DEBUG_UART_BASE == 0xff180000) |
166 | /* Enable early UART0 on the RK3399 */ | |
167 | rk_clrsetreg(&grf->gpio2c_iomux, | |
168 | GRF_GPIO2C0_SEL_MASK, | |
169 | GRF_UART0BT_SIN << GRF_GPIO2C0_SEL_SHIFT); | |
170 | rk_clrsetreg(&grf->gpio2c_iomux, | |
171 | GRF_GPIO2C1_SEL_MASK, | |
172 | GRF_UART0BT_SOUT << GRF_GPIO2C1_SEL_SHIFT); | |
173 | #else | |
174 | /* Enable early UART2 channel C on the RK3399 */ | |
3012a840 KY |
175 | rk_clrsetreg(&grf->gpio4c_iomux, |
176 | GRF_GPIO4C3_SEL_MASK, | |
177 | GRF_UART2DGBC_SIN << GRF_GPIO4C3_SEL_SHIFT); | |
178 | rk_clrsetreg(&grf->gpio4c_iomux, | |
179 | GRF_GPIO4C4_SEL_MASK, | |
180 | GRF_UART2DBGC_SOUT << GRF_GPIO4C4_SEL_SHIFT); | |
181 | /* Set channel C as UART2 input */ | |
182 | rk_clrsetreg(&grf->soc_con7, | |
183 | GRF_UART_DBG_SEL_MASK, | |
184 | GRF_UART_DBG_SEL_C << GRF_UART_DBG_SEL_SHIFT); | |
7ee16de5 PT |
185 | #endif |
186 | } | |
187 | ||
188 | #define GRF_EMMCCORE_CON11 0xff77f02c | |
c4a92151 KY |
189 | #define SGRF_DDR_RGN_CON16 0xff330040 |
190 | #define SGRF_SLV_SECURE_CON4 0xff33e3d0 | |
7ee16de5 PT |
191 | void board_init_f(ulong dummy) |
192 | { | |
193 | struct udevice *pinctrl; | |
194 | struct udevice *dev; | |
195 | int ret; | |
196 | ||
3012a840 KY |
197 | #define EARLY_UART |
198 | #ifdef EARLY_UART | |
199 | /* | |
200 | * Debug UART can be used from here if required: | |
201 | * | |
202 | * debug_uart_init(); | |
203 | * printch('a'); | |
204 | * printhex8(0x1234); | |
205 | * printascii("string"); | |
206 | */ | |
207 | debug_uart_init(); | |
208 | printascii("U-Boot SPL board init"); | |
209 | #endif | |
c4a92151 | 210 | |
3012a840 KY |
211 | /* Emmc clock generator: disable the clock multipilier */ |
212 | rk_clrreg(GRF_EMMCCORE_CON11, 0x0ff); | |
213 | ||
232cf962 | 214 | ret = spl_early_init(); |
3012a840 | 215 | if (ret) { |
232cf962 | 216 | debug("spl_early_init() failed: %d\n", ret); |
3012a840 KY |
217 | hang(); |
218 | } | |
219 | ||
504b9f1a | 220 | /* |
c4a92151 | 221 | * Disable DDR and SRAM security regions. |
504b9f1a PT |
222 | * |
223 | * As we are entered from the BootROM, the region from | |
224 | * 0x0 through 0xfffff (i.e. the first MB of memory) will | |
225 | * be protected. This will cause issues with the DW_MMC | |
226 | * driver, which tries to DMA from/to the stack (likely) | |
227 | * located in this range. | |
228 | */ | |
229 | rk_clrsetreg(SGRF_DDR_RGN_CON16, 0x1FF, 0); | |
c4a92151 | 230 | rk_clrreg(SGRF_SLV_SECURE_CON4, 0x2000); |
504b9f1a | 231 | |
3012a840 KY |
232 | secure_timer_init(); |
233 | ||
234 | ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl); | |
235 | if (ret) { | |
236 | debug("Pinctrl init failed: %d\n", ret); | |
237 | return; | |
238 | } | |
239 | ||
240 | ret = uclass_get_device(UCLASS_RAM, 0, &dev); | |
241 | if (ret) { | |
242 | debug("DRAM init failed: %d\n", ret); | |
243 | return; | |
244 | } | |
245 | } | |
246 | ||
247 | void spl_board_init(void) | |
248 | { | |
249 | struct udevice *pinctrl; | |
250 | int ret; | |
251 | ||
252 | ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl); | |
253 | if (ret) { | |
254 | debug("%s: Cannot find pinctrl device\n", __func__); | |
255 | goto err; | |
256 | } | |
257 | ||
258 | /* Enable debug UART */ | |
259 | ret = pinctrl_request_noflags(pinctrl, PERIPH_ID_UART_DBG); | |
260 | if (ret) { | |
261 | debug("%s: Failed to set up console UART\n", __func__); | |
262 | goto err; | |
263 | } | |
264 | ||
265 | preloader_console_init(); | |
266 | #ifdef CONFIG_ROCKCHIP_SPL_BACK_TO_BROM | |
267 | back_to_bootrom(); | |
268 | #endif | |
504b9f1a | 269 | |
3012a840 KY |
270 | return; |
271 | err: | |
272 | printf("spl_board_init: Error %d\n", ret); | |
273 | ||
274 | /* No way to report error here */ | |
275 | hang(); | |
276 | } | |
277 | ||
278 | #ifdef CONFIG_SPL_LOAD_FIT | |
279 | int board_fit_config_name_match(const char *name) | |
280 | { | |
281 | /* Just empty function now - can't decide what to choose */ | |
282 | debug("%s: %s\n", __func__, name); | |
283 | ||
284 | return 0; | |
285 | } | |
286 | #endif |