]>
Commit | Line | Data |
---|---|---|
2444dae5 SG |
1 | /* |
2 | * (C) Copyright 2015 Google, Inc | |
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> | |
13 | #include <ram.h> | |
14 | #include <spl.h> | |
15 | #include <asm/gpio.h> | |
16 | #include <asm/io.h> | |
17 | #include <asm/arch/clock.h> | |
18 | #include <asm/arch/hardware.h> | |
19 | #include <asm/arch/periph.h> | |
20 | #include <asm/arch/sdram.h> | |
cc2244b8 | 21 | #include <asm/arch/timer.h> |
2444dae5 SG |
22 | #include <dm/pinctrl.h> |
23 | #include <dm/root.h> | |
24 | #include <dm/test.h> | |
25 | #include <dm/util.h> | |
26 | #include <power/regulator.h> | |
27 | ||
28 | DECLARE_GLOBAL_DATA_PTR; | |
29 | ||
30 | u32 spl_boot_device(void) | |
31 | { | |
6afc4661 | 32 | #if !CONFIG_IS_ENABLED(OF_PLATDATA) |
2444dae5 SG |
33 | const void *blob = gd->fdt_blob; |
34 | struct udevice *dev; | |
35 | const char *bootdev; | |
36 | int node; | |
37 | int ret; | |
38 | ||
39 | bootdev = fdtdec_get_config_string(blob, "u-boot,boot0"); | |
40 | debug("Boot device %s\n", bootdev); | |
41 | if (!bootdev) | |
42 | goto fallback; | |
43 | ||
44 | node = fdt_path_offset(blob, bootdev); | |
45 | if (node < 0) { | |
46 | debug("node=%d\n", node); | |
47 | goto fallback; | |
48 | } | |
49 | ret = device_get_global_by_of_offset(node, &dev); | |
50 | if (ret) { | |
51 | debug("device at node %s/%d not found: %d\n", bootdev, node, | |
52 | ret); | |
53 | goto fallback; | |
54 | } | |
55 | debug("Found device %s\n", dev->name); | |
56 | switch (device_get_uclass_id(dev)) { | |
57 | case UCLASS_SPI_FLASH: | |
58 | return BOOT_DEVICE_SPI; | |
59 | case UCLASS_MMC: | |
60 | return BOOT_DEVICE_MMC1; | |
61 | default: | |
62 | debug("Booting from device uclass '%s' not supported\n", | |
63 | dev_get_uclass_name(dev)); | |
64 | } | |
65 | ||
66 | fallback: | |
6afc4661 | 67 | #endif |
2444dae5 SG |
68 | return BOOT_DEVICE_MMC1; |
69 | } | |
70 | ||
2b1cdafa | 71 | u32 spl_boot_mode(const u32 boot_device) |
2444dae5 SG |
72 | { |
73 | return MMCSD_MODE_RAW; | |
74 | } | |
75 | ||
76 | /* read L2 control register (L2CTLR) */ | |
77 | static inline uint32_t read_l2ctlr(void) | |
78 | { | |
79 | uint32_t val = 0; | |
80 | ||
81 | asm volatile ("mrc p15, 1, %0, c9, c0, 2" : "=r" (val)); | |
82 | ||
83 | return val; | |
84 | } | |
85 | ||
86 | /* write L2 control register (L2CTLR) */ | |
87 | static inline void write_l2ctlr(uint32_t val) | |
88 | { | |
89 | /* | |
90 | * Note: L2CTLR can only be written when the L2 memory system | |
91 | * is idle, ie before the MMU is enabled. | |
92 | */ | |
93 | asm volatile("mcr p15, 1, %0, c9, c0, 2" : : "r" (val) : "memory"); | |
94 | isb(); | |
95 | } | |
96 | ||
97 | static void configure_l2ctlr(void) | |
98 | { | |
99 | uint32_t l2ctlr; | |
100 | ||
101 | l2ctlr = read_l2ctlr(); | |
102 | l2ctlr &= 0xfffc0000; /* clear bit0~bit17 */ | |
103 | ||
104 | /* | |
105 | * Data RAM write latency: 2 cycles | |
106 | * Data RAM read latency: 2 cycles | |
107 | * Data RAM setup latency: 1 cycle | |
108 | * Tag RAM write latency: 1 cycle | |
109 | * Tag RAM read latency: 1 cycle | |
110 | * Tag RAM setup latency: 1 cycle | |
111 | */ | |
112 | l2ctlr |= (1 << 3 | 1 << 0); | |
113 | write_l2ctlr(l2ctlr); | |
114 | } | |
115 | ||
f23cf909 | 116 | #ifdef CONFIG_SPL_MMC_SUPPORT |
2444dae5 SG |
117 | static int configure_emmc(struct udevice *pinctrl) |
118 | { | |
119 | struct gpio_desc desc; | |
120 | int ret; | |
121 | ||
122 | pinctrl_request_noflags(pinctrl, PERIPH_ID_EMMC); | |
123 | ||
124 | /* | |
125 | * TODO(sjg@chromium.org): Pick this up from device tree or perhaps | |
126 | * use the EMMC_PWREN setting. | |
127 | */ | |
128 | ret = dm_gpio_lookup_name("D9", &desc); | |
129 | if (ret) { | |
130 | debug("gpio ret=%d\n", ret); | |
131 | return ret; | |
132 | } | |
133 | ret = dm_gpio_request(&desc, "emmc_pwren"); | |
134 | if (ret) { | |
135 | debug("gpio_request ret=%d\n", ret); | |
136 | return ret; | |
137 | } | |
138 | ret = dm_gpio_set_dir_flags(&desc, GPIOD_IS_OUT); | |
139 | if (ret) { | |
140 | debug("gpio dir ret=%d\n", ret); | |
141 | return ret; | |
142 | } | |
143 | ret = dm_gpio_set_value(&desc, 1); | |
144 | if (ret) { | |
145 | debug("gpio value ret=%d\n", ret); | |
146 | return ret; | |
147 | } | |
148 | ||
149 | return 0; | |
150 | } | |
f23cf909 | 151 | #endif |
b47ea792 | 152 | extern void back_to_bootrom(void); |
2444dae5 SG |
153 | void board_init_f(ulong dummy) |
154 | { | |
155 | struct udevice *pinctrl; | |
156 | struct udevice *dev; | |
157 | int ret; | |
158 | ||
159 | /* Example code showing how to enable the debug UART on RK3288 */ | |
160 | #ifdef EARLY_UART | |
161 | #include <asm/arch/grf_rk3288.h> | |
162 | /* Enable early UART on the RK3288 */ | |
163 | #define GRF_BASE 0xff770000 | |
164 | struct rk3288_grf * const grf = (void *)GRF_BASE; | |
165 | ||
166 | rk_clrsetreg(&grf->gpio7ch_iomux, GPIO7C7_MASK << GPIO7C7_SHIFT | | |
167 | GPIO7C6_MASK << GPIO7C6_SHIFT, | |
168 | GPIO7C7_UART2DBG_SOUT << GPIO7C7_SHIFT | | |
169 | GPIO7C6_UART2DBG_SIN << GPIO7C6_SHIFT); | |
170 | /* | |
171 | * Debug UART can be used from here if required: | |
172 | * | |
173 | * debug_uart_init(); | |
174 | * printch('a'); | |
175 | * printhex8(0x1234); | |
176 | * printascii("string"); | |
177 | */ | |
178 | debug_uart_init(); | |
179 | #endif | |
180 | ||
181 | ret = spl_init(); | |
182 | if (ret) { | |
183 | debug("spl_init() failed: %d\n", ret); | |
184 | hang(); | |
185 | } | |
186 | ||
cc2244b8 | 187 | rockchip_timer_init(); |
2444dae5 SG |
188 | configure_l2ctlr(); |
189 | ||
190 | ret = uclass_get_device(UCLASS_CLK, 0, &dev); | |
191 | if (ret) { | |
192 | debug("CLK init failed: %d\n", ret); | |
193 | return; | |
194 | } | |
195 | ||
196 | ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl); | |
197 | if (ret) { | |
198 | debug("Pinctrl init failed: %d\n", ret); | |
199 | return; | |
200 | } | |
201 | ||
202 | ret = uclass_get_device(UCLASS_RAM, 0, &dev); | |
203 | if (ret) { | |
204 | debug("DRAM init failed: %d\n", ret); | |
205 | return; | |
206 | } | |
b47ea792 XZ |
207 | #ifdef CONFIG_ROCKCHIP_SPL_BACK_TO_BROM |
208 | back_to_bootrom(); | |
209 | #endif | |
2444dae5 SG |
210 | } |
211 | ||
212 | static int setup_led(void) | |
213 | { | |
214 | #ifdef CONFIG_SPL_LED | |
215 | struct udevice *dev; | |
216 | char *led_name; | |
217 | int ret; | |
218 | ||
219 | led_name = fdtdec_get_config_string(gd->fdt_blob, "u-boot,boot-led"); | |
220 | if (!led_name) | |
221 | return 0; | |
222 | ret = led_get_by_label(led_name, &dev); | |
223 | if (ret) { | |
224 | debug("%s: get=%d\n", __func__, ret); | |
225 | return ret; | |
226 | } | |
227 | ret = led_set_on(dev, 1); | |
228 | if (ret) | |
229 | return ret; | |
230 | #endif | |
231 | ||
232 | return 0; | |
233 | } | |
234 | ||
235 | void spl_board_init(void) | |
236 | { | |
237 | struct udevice *pinctrl; | |
238 | int ret; | |
239 | ||
240 | ret = setup_led(); | |
241 | ||
242 | if (ret) { | |
243 | debug("LED ret=%d\n", ret); | |
244 | hang(); | |
245 | } | |
246 | ||
247 | ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl); | |
248 | if (ret) { | |
249 | debug("%s: Cannot find pinctrl device\n", __func__); | |
250 | goto err; | |
251 | } | |
f23cf909 | 252 | #ifdef CONFIG_SPL_MMC_SUPPORT |
6efeeea7 | 253 | if (!IS_ENABLED(CONFIG_TARGET_ROCK2) && |
744368d6 XZ |
254 | !IS_ENABLED(CONFIG_TARGET_FIREFLY_RK3288) && |
255 | !IS_ENABLED(CONFIG_TARGET_EVB_RK3288)) { | |
6efeeea7 SG |
256 | ret = pinctrl_request_noflags(pinctrl, PERIPH_ID_SDCARD); |
257 | if (ret) { | |
258 | debug("%s: Failed to set up SD card\n", __func__); | |
259 | goto err; | |
260 | } | |
261 | ret = configure_emmc(pinctrl); | |
262 | if (ret) { | |
263 | debug("%s: Failed to set up eMMC\n", __func__); | |
264 | goto err; | |
265 | } | |
2444dae5 | 266 | } |
f23cf909 | 267 | #endif |
2444dae5 SG |
268 | |
269 | /* Enable debug UART */ | |
270 | ret = pinctrl_request_noflags(pinctrl, PERIPH_ID_UART_DBG); | |
271 | if (ret) { | |
272 | debug("%s: Failed to set up console UART\n", __func__); | |
273 | goto err; | |
274 | } | |
275 | ||
276 | preloader_console_init(); | |
277 | return; | |
278 | err: | |
279 | printf("spl_board_init: Error %d\n", ret); | |
280 | ||
281 | /* No way to report error here */ | |
282 | hang(); | |
283 | } | |
ad443b72 SG |
284 | |
285 | void lowlevel_init(void) | |
286 | { | |
287 | } |