blob: fdbd4bfd035b09362a56fa88cd739618593f9cff [file] [log] [blame]
Yann Gautier4b0c72a2018-07-16 10:54:09 +02001/*
2 * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <arch_helpers.h>
8#include <assert.h>
9#include <boot_api.h>
10#include <debug.h>
Yann Gautier8244e1d2018-10-15 09:36:58 +020011#include <io_block.h>
Yann Gautier4b0c72a2018-07-16 10:54:09 +020012#include <io_driver.h>
13#include <io_dummy.h>
Yann Gautier8244e1d2018-10-15 09:36:58 +020014#include <io_mmc.h>
15#include <io_stm32image.h>
Yann Gautier4b0c72a2018-07-16 10:54:09 +020016#include <io_storage.h>
Yann Gautier8244e1d2018-10-15 09:36:58 +020017#include <mmc.h>
Yann Gautier4b0c72a2018-07-16 10:54:09 +020018#include <mmio.h>
Yann Gautier8244e1d2018-10-15 09:36:58 +020019#include <partition.h>
Yann Gautier4b0c72a2018-07-16 10:54:09 +020020#include <platform.h>
21#include <platform_def.h>
Yann Gautier8244e1d2018-10-15 09:36:58 +020022#include <stm32_sdmmc2.h>
Yann Gautier4b0c72a2018-07-16 10:54:09 +020023#include <stm32mp1_private.h>
24#include <stm32mp1_rcc.h>
25#include <string.h>
26#include <utils.h>
27
28/* IO devices */
29static const io_dev_connector_t *dummy_dev_con;
30static uintptr_t dummy_dev_handle;
31static uintptr_t dummy_dev_spec;
32
Yann Gautier8244e1d2018-10-15 09:36:58 +020033static uintptr_t image_dev_handle;
34
35static io_block_spec_t gpt_block_spec = {
36 .offset = 0,
37 .length = 34 * MMC_BLOCK_SIZE, /* Size of GPT table */
38};
39
Yann Gautierf9af3bc2018-11-09 15:57:18 +010040static uint32_t block_buffer[MMC_BLOCK_SIZE] __aligned(MMC_BLOCK_SIZE);
Yann Gautier8244e1d2018-10-15 09:36:58 +020041
42static const io_block_dev_spec_t mmc_block_dev_spec = {
43 /* It's used as temp buffer in block driver */
44 .buffer = {
45 .offset = (size_t)&block_buffer,
46 .length = MMC_BLOCK_SIZE,
47 },
48 .ops = {
49 .read = mmc_read_blocks,
50 .write = NULL,
51 },
52 .block_size = MMC_BLOCK_SIZE,
53};
54
55static uintptr_t storage_dev_handle;
56static const io_dev_connector_t *mmc_dev_con;
57
58#define IMG_IDX_BL33 0
59
60static const struct stm32image_part_info bl33_partition_spec = {
61 .name = BL33_IMAGE_NAME,
62 .binary_type = BL33_BINARY_TYPE,
63};
64
65static struct stm32image_device_info stm32image_dev_info_spec = {
66 .lba_size = MMC_BLOCK_SIZE,
67 .part_info[IMG_IDX_BL33] = {
68 .name = BL33_IMAGE_NAME,
69 .binary_type = BL33_BINARY_TYPE,
70 },
71};
72
73static io_block_spec_t stm32image_block_spec;
74
75static const io_dev_connector_t *stm32image_dev_con;
76
Yann Gautier4b0c72a2018-07-16 10:54:09 +020077static const io_block_spec_t bl32_block_spec = {
78 .offset = BL32_BASE,
79 .length = STM32MP1_BL32_SIZE
80};
81
82static const io_block_spec_t bl2_block_spec = {
83 .offset = BL2_BASE,
84 .length = STM32MP1_BL2_SIZE,
85};
86
87static int open_dummy(const uintptr_t spec);
Yann Gautier8244e1d2018-10-15 09:36:58 +020088static int open_image(const uintptr_t spec);
89static int open_storage(const uintptr_t spec);
Yann Gautier4b0c72a2018-07-16 10:54:09 +020090
91struct plat_io_policy {
92 uintptr_t *dev_handle;
93 uintptr_t image_spec;
94 int (*check)(const uintptr_t spec);
95};
96
97static const struct plat_io_policy policies[] = {
98 [BL2_IMAGE_ID] = {
99 .dev_handle = &dummy_dev_handle,
100 .image_spec = (uintptr_t)&bl2_block_spec,
101 .check = open_dummy
102 },
103 [BL32_IMAGE_ID] = {
104 .dev_handle = &dummy_dev_handle,
105 .image_spec = (uintptr_t)&bl32_block_spec,
106 .check = open_dummy
107 },
Yann Gautier8244e1d2018-10-15 09:36:58 +0200108 [BL33_IMAGE_ID] = {
109 .dev_handle = &image_dev_handle,
110 .image_spec = (uintptr_t)&bl33_partition_spec,
111 .check = open_image
112 },
113 [GPT_IMAGE_ID] = {
114 .dev_handle = &storage_dev_handle,
115 .image_spec = (uintptr_t)&gpt_block_spec,
116 .check = open_storage
117 },
118 [STM32_IMAGE_ID] = {
119 .dev_handle = &storage_dev_handle,
120 .image_spec = (uintptr_t)&stm32image_block_spec,
121 .check = open_storage
122 }
Yann Gautier4b0c72a2018-07-16 10:54:09 +0200123};
124
125static int open_dummy(const uintptr_t spec)
126{
127 return io_dev_init(dummy_dev_handle, 0);
128}
129
Yann Gautier8244e1d2018-10-15 09:36:58 +0200130static int open_image(const uintptr_t spec)
131{
132 return io_dev_init(image_dev_handle, 0);
133}
134
135static int open_storage(const uintptr_t spec)
136{
137 return io_dev_init(storage_dev_handle, 0);
138}
139
Yann Gautier4b0c72a2018-07-16 10:54:09 +0200140static void print_boot_device(boot_api_context_t *boot_context)
141{
142 switch (boot_context->boot_interface_selected) {
143 case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD:
144 INFO("Using SDMMC\n");
145 break;
146 case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC:
147 INFO("Using EMMC\n");
148 break;
149 default:
150 ERROR("Boot interface not found\n");
151 panic();
152 break;
153 }
154
155 if (boot_context->boot_interface_instance != 0U) {
156 INFO(" Instance %d\n", boot_context->boot_interface_instance);
157 }
158}
159
160static void print_reset_reason(void)
161{
162 uint32_t rstsr = mmio_read_32(RCC_BASE + RCC_MP_RSTSCLRR);
163
164 if (rstsr == 0U) {
165 WARN("Reset reason unknown\n");
166 return;
167 }
168
169 INFO("Reset reason (0x%x):\n", rstsr);
170
171 if ((rstsr & RCC_MP_RSTSCLRR_PADRSTF) == 0U) {
172 if ((rstsr & RCC_MP_RSTSCLRR_STDBYRSTF) != 0U) {
173 INFO("System exits from STANDBY\n");
174 return;
175 }
176
177 if ((rstsr & RCC_MP_RSTSCLRR_CSTDBYRSTF) != 0U) {
178 INFO("MPU exits from CSTANDBY\n");
179 return;
180 }
181 }
182
183 if ((rstsr & RCC_MP_RSTSCLRR_PORRSTF) != 0U) {
184 INFO(" Power-on Reset (rst_por)\n");
185 return;
186 }
187
188 if ((rstsr & RCC_MP_RSTSCLRR_BORRSTF) != 0U) {
189 INFO(" Brownout Reset (rst_bor)\n");
190 return;
191 }
192
193 if ((rstsr & RCC_MP_RSTSCLRR_MPSYSRSTF) != 0U) {
194 INFO(" System reset generated by MPU (MPSYSRST)\n");
195 return;
196 }
197
198 if ((rstsr & RCC_MP_RSTSCLRR_HCSSRSTF) != 0U) {
199 INFO(" Reset due to a clock failure on HSE\n");
200 return;
201 }
202
203 if ((rstsr & RCC_MP_RSTSCLRR_IWDG1RSTF) != 0U) {
204 INFO(" IWDG1 Reset (rst_iwdg1)\n");
205 return;
206 }
207
208 if ((rstsr & RCC_MP_RSTSCLRR_IWDG2RSTF) != 0U) {
209 INFO(" IWDG2 Reset (rst_iwdg2)\n");
210 return;
211 }
212
213 if ((rstsr & RCC_MP_RSTSCLRR_PADRSTF) != 0U) {
214 INFO(" Pad Reset from NRST\n");
215 return;
216 }
217
218 if ((rstsr & RCC_MP_RSTSCLRR_VCORERSTF) != 0U) {
219 INFO(" Reset due to a failure of VDD_CORE\n");
220 return;
221 }
222
223 ERROR(" Unidentified reset reason\n");
224}
225
226void stm32mp1_io_setup(void)
227{
228 int io_result __unused;
Yann Gautier8244e1d2018-10-15 09:36:58 +0200229 struct stm32_sdmmc2_params params;
230 struct mmc_device_info device_info;
231 uintptr_t mmc_default_instance;
Yann Gautier4b0c72a2018-07-16 10:54:09 +0200232 boot_api_context_t *boot_context =
233 (boot_api_context_t *)stm32mp1_get_boot_ctx_address();
234
235 print_reset_reason();
236
237 print_boot_device(boot_context);
238
239 if ((boot_context->boot_partition_used_toboot == 1U) ||
240 (boot_context->boot_partition_used_toboot == 2U)) {
241 INFO("Boot used partition fsbl%d\n",
242 boot_context->boot_partition_used_toboot);
243 }
244
245 io_result = register_io_dev_dummy(&dummy_dev_con);
246 assert(io_result == 0);
247
248 io_result = io_dev_open(dummy_dev_con, dummy_dev_spec,
249 &dummy_dev_handle);
250 assert(io_result == 0);
Yann Gautier8244e1d2018-10-15 09:36:58 +0200251
252 switch (boot_context->boot_interface_selected) {
253 case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD:
254 case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC:
255 dmb();
256
257 memset(&params, 0, sizeof(struct stm32_sdmmc2_params));
258
259 if (boot_context->boot_interface_selected ==
260 BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC) {
261 device_info.mmc_dev_type = MMC_IS_EMMC;
262 mmc_default_instance = STM32MP1_SDMMC2_BASE;
263 } else {
264 device_info.mmc_dev_type = MMC_IS_SD;
265 mmc_default_instance = STM32MP1_SDMMC1_BASE;
266 }
267
268 switch (boot_context->boot_interface_instance) {
269 case 1:
270 params.reg_base = STM32MP1_SDMMC1_BASE;
271 break;
272 case 2:
273 params.reg_base = STM32MP1_SDMMC2_BASE;
274 break;
275 case 3:
276 params.reg_base = STM32MP1_SDMMC3_BASE;
277 break;
278 default:
279 WARN("SDMMC instance not found, using default\n");
280 params.reg_base = mmc_default_instance;
281 break;
282 }
283
284 params.device_info = &device_info;
285 stm32_sdmmc2_mmc_init(&params);
286
287 /* Open MMC as a block device to read GPT table */
288 io_result = register_io_dev_block(&mmc_dev_con);
289 if (io_result != 0) {
290 panic();
291 }
292
293 io_result = io_dev_open(mmc_dev_con,
294 (uintptr_t)&mmc_block_dev_spec,
295 &storage_dev_handle);
296 assert(io_result == 0);
297
298 partition_init(GPT_IMAGE_ID);
299
300 io_result = io_dev_close(storage_dev_handle);
301 assert(io_result == 0);
302
303 stm32image_dev_info_spec.device_size =
304 stm32_sdmmc2_mmc_get_device_size();
305 stm32image_dev_info_spec.part_info[IMG_IDX_BL33].part_offset =
306 get_partition_entry(BL33_IMAGE_NAME)->start;
307 stm32image_dev_info_spec.part_info[IMG_IDX_BL33].bkp_offset =
308 get_partition_entry(BL33_IMAGE_NAME)->length;
309
310 stm32image_block_spec.offset = 0;
311 stm32image_block_spec.length =
312 get_partition_entry(BL33_IMAGE_NAME)->length;
313
314 /*
315 * Re-open MMC with io_mmc, for better perfs compared to
316 * io_block.
317 */
318 io_result = register_io_dev_mmc(&mmc_dev_con);
319 assert(io_result == 0);
320
321 io_result = io_dev_open(mmc_dev_con, 0, &storage_dev_handle);
322 assert(io_result == 0);
323
324 io_result = register_io_dev_stm32image(&stm32image_dev_con);
325 assert(io_result == 0);
326
327 io_result = io_dev_open(stm32image_dev_con,
328 (uintptr_t)&stm32image_dev_info_spec,
329 &image_dev_handle);
330 assert(io_result == 0);
331 break;
332
333 default:
334 ERROR("Boot interface %d not supported\n",
335 boot_context->boot_interface_selected);
336 break;
337 }
Yann Gautier4b0c72a2018-07-16 10:54:09 +0200338}
339
340/*
341 * Return an IO device handle and specification which can be used to access
342 * an image. Use this to enforce platform load policy.
343 */
344int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
345 uintptr_t *image_spec)
346{
347 int rc;
348 const struct plat_io_policy *policy;
349
350 assert(image_id < ARRAY_SIZE(policies));
351
352 policy = &policies[image_id];
353 rc = policy->check(policy->image_spec);
354 if (rc == 0) {
355 *image_spec = policy->image_spec;
356 *dev_handle = *(policy->dev_handle);
357 }
358
359 return rc;
360}