xref: /rk3399_ARM-atf/plat/st/common/bl2_io_storage.c (revision 570442281400c3fea280ef45fdc4c92ec864e494)
1c9d75b3cSYann Gautier /*
2c9d75b3cSYann Gautier  * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
3c9d75b3cSYann Gautier  *
4c9d75b3cSYann Gautier  * SPDX-License-Identifier: BSD-3-Clause
5c9d75b3cSYann Gautier  */
6c9d75b3cSYann Gautier 
7c9d75b3cSYann Gautier #include <assert.h>
8c9d75b3cSYann Gautier #include <string.h>
9c9d75b3cSYann Gautier 
10c9d75b3cSYann Gautier #include <platform_def.h>
11c9d75b3cSYann Gautier 
12c9d75b3cSYann Gautier #include <arch_helpers.h>
13c9d75b3cSYann Gautier #include <common/debug.h>
14c9d75b3cSYann Gautier #include <drivers/io/io_block.h>
15c9d75b3cSYann Gautier #include <drivers/io/io_driver.h>
16c9d75b3cSYann Gautier #include <drivers/io/io_dummy.h>
1712e21dfdSLionel Debieve #include <drivers/io/io_mtd.h>
18c9d75b3cSYann Gautier #include <drivers/io/io_storage.h>
19c9d75b3cSYann Gautier #include <drivers/mmc.h>
20c9d75b3cSYann Gautier #include <drivers/partition/partition.h>
2112e21dfdSLionel Debieve #include <drivers/raw_nand.h>
22*57044228SLionel Debieve #include <drivers/spi_nand.h>
23c9d75b3cSYann Gautier #include <drivers/st/io_mmc.h>
24c9d75b3cSYann Gautier #include <drivers/st/io_stm32image.h>
2512e21dfdSLionel Debieve #include <drivers/st/stm32_fmc2_nand.h>
26*57044228SLionel Debieve #include <drivers/st/stm32_qspi.h>
27c9d75b3cSYann Gautier #include <drivers/st/stm32_sdmmc2.h>
28c9d75b3cSYann Gautier #include <lib/mmio.h>
29c9d75b3cSYann Gautier #include <lib/utils.h>
30c9d75b3cSYann Gautier #include <plat/common/platform.h>
31c9d75b3cSYann Gautier 
32c9d75b3cSYann Gautier /* IO devices */
33c9d75b3cSYann Gautier static const io_dev_connector_t *dummy_dev_con;
34c9d75b3cSYann Gautier static uintptr_t dummy_dev_handle;
35c9d75b3cSYann Gautier static uintptr_t dummy_dev_spec;
36c9d75b3cSYann Gautier 
37c9d75b3cSYann Gautier static uintptr_t image_dev_handle;
3846554b64SNicolas Le Bayon static uintptr_t storage_dev_handle;
39c9d75b3cSYann Gautier 
4046554b64SNicolas Le Bayon #if STM32MP_SDMMC || STM32MP_EMMC
41c9d75b3cSYann Gautier static io_block_spec_t gpt_block_spec = {
42c9d75b3cSYann Gautier 	.offset = 0,
43c9d75b3cSYann Gautier 	.length = 34 * MMC_BLOCK_SIZE, /* Size of GPT table */
44c9d75b3cSYann Gautier };
45c9d75b3cSYann Gautier 
46c9d75b3cSYann Gautier static uint32_t block_buffer[MMC_BLOCK_SIZE] __aligned(MMC_BLOCK_SIZE);
47c9d75b3cSYann Gautier 
48c9d75b3cSYann Gautier static const io_block_dev_spec_t mmc_block_dev_spec = {
49c9d75b3cSYann Gautier 	/* It's used as temp buffer in block driver */
50c9d75b3cSYann Gautier 	.buffer = {
51c9d75b3cSYann Gautier 		.offset = (size_t)&block_buffer,
52c9d75b3cSYann Gautier 		.length = MMC_BLOCK_SIZE,
53c9d75b3cSYann Gautier 	},
54c9d75b3cSYann Gautier 	.ops = {
55c9d75b3cSYann Gautier 		.read = mmc_read_blocks,
56c9d75b3cSYann Gautier 		.write = NULL,
57c9d75b3cSYann Gautier 	},
58c9d75b3cSYann Gautier 	.block_size = MMC_BLOCK_SIZE,
59c9d75b3cSYann Gautier };
60c9d75b3cSYann Gautier 
61c9d75b3cSYann Gautier static const io_dev_connector_t *mmc_dev_con;
6246554b64SNicolas Le Bayon #endif /* STM32MP_SDMMC || STM32MP_EMMC */
63c9d75b3cSYann Gautier 
6412e21dfdSLionel Debieve #if STM32MP_RAW_NAND
6512e21dfdSLionel Debieve static io_mtd_dev_spec_t nand_dev_spec = {
6612e21dfdSLionel Debieve 	.ops = {
6712e21dfdSLionel Debieve 		.init = nand_raw_init,
6812e21dfdSLionel Debieve 		.read = nand_read,
6912e21dfdSLionel Debieve 	},
7012e21dfdSLionel Debieve };
7112e21dfdSLionel Debieve 
7212e21dfdSLionel Debieve static const io_dev_connector_t *nand_dev_con;
7312e21dfdSLionel Debieve #endif
7412e21dfdSLionel Debieve 
75*57044228SLionel Debieve #if STM32MP_SPI_NAND
76*57044228SLionel Debieve static io_mtd_dev_spec_t spi_nand_dev_spec = {
77*57044228SLionel Debieve 	.ops = {
78*57044228SLionel Debieve 		.init = spi_nand_init,
79*57044228SLionel Debieve 		.read = nand_read,
80*57044228SLionel Debieve 	},
81*57044228SLionel Debieve };
82*57044228SLionel Debieve 
83*57044228SLionel Debieve static const io_dev_connector_t *spi_dev_con;
84*57044228SLionel Debieve #endif
85*57044228SLionel Debieve 
861989a19cSYann Gautier #ifdef AARCH32_SP_OPTEE
871989a19cSYann Gautier static const struct stm32image_part_info optee_header_partition_spec = {
881989a19cSYann Gautier 	.name = OPTEE_HEADER_IMAGE_NAME,
891989a19cSYann Gautier 	.binary_type = OPTEE_HEADER_BINARY_TYPE,
901989a19cSYann Gautier };
911989a19cSYann Gautier 
921989a19cSYann Gautier static const struct stm32image_part_info optee_pager_partition_spec = {
931989a19cSYann Gautier 	.name = OPTEE_PAGER_IMAGE_NAME,
941989a19cSYann Gautier 	.binary_type = OPTEE_PAGER_BINARY_TYPE,
951989a19cSYann Gautier };
961989a19cSYann Gautier 
971989a19cSYann Gautier static const struct stm32image_part_info optee_paged_partition_spec = {
981989a19cSYann Gautier 	.name = OPTEE_PAGED_IMAGE_NAME,
991989a19cSYann Gautier 	.binary_type = OPTEE_PAGED_BINARY_TYPE,
1001989a19cSYann Gautier };
1011989a19cSYann Gautier #else
102c9d75b3cSYann Gautier static const io_block_spec_t bl32_block_spec = {
103c9d75b3cSYann Gautier 	.offset = BL32_BASE,
1043f9c9784SYann Gautier 	.length = STM32MP_BL32_SIZE
105c9d75b3cSYann Gautier };
1061989a19cSYann Gautier #endif
107c9d75b3cSYann Gautier 
108c9d75b3cSYann Gautier static const io_block_spec_t bl2_block_spec = {
109c9d75b3cSYann Gautier 	.offset = BL2_BASE,
1103f9c9784SYann Gautier 	.length = STM32MP_BL2_SIZE,
111c9d75b3cSYann Gautier };
112c9d75b3cSYann Gautier 
113c9d75b3cSYann Gautier static const struct stm32image_part_info bl33_partition_spec = {
114c9d75b3cSYann Gautier 	.name = BL33_IMAGE_NAME,
115c9d75b3cSYann Gautier 	.binary_type = BL33_BINARY_TYPE,
116c9d75b3cSYann Gautier };
117c9d75b3cSYann Gautier 
118c9d75b3cSYann Gautier enum {
119c9d75b3cSYann Gautier 	IMG_IDX_BL33,
1201989a19cSYann Gautier #ifdef AARCH32_SP_OPTEE
1211989a19cSYann Gautier 	IMG_IDX_OPTEE_HEADER,
1221989a19cSYann Gautier 	IMG_IDX_OPTEE_PAGER,
1231989a19cSYann Gautier 	IMG_IDX_OPTEE_PAGED,
1241989a19cSYann Gautier #endif
125c9d75b3cSYann Gautier 	IMG_IDX_NUM
126c9d75b3cSYann Gautier };
127c9d75b3cSYann Gautier 
12846554b64SNicolas Le Bayon static struct stm32image_device_info stm32image_dev_info_spec __unused = {
129c9d75b3cSYann Gautier 	.lba_size = MMC_BLOCK_SIZE,
130c9d75b3cSYann Gautier 	.part_info[IMG_IDX_BL33] = {
131c9d75b3cSYann Gautier 		.name = BL33_IMAGE_NAME,
132c9d75b3cSYann Gautier 		.binary_type = BL33_BINARY_TYPE,
133c9d75b3cSYann Gautier 	},
1341989a19cSYann Gautier #ifdef AARCH32_SP_OPTEE
1351989a19cSYann Gautier 	.part_info[IMG_IDX_OPTEE_HEADER] = {
1361989a19cSYann Gautier 		.name = OPTEE_HEADER_IMAGE_NAME,
1371989a19cSYann Gautier 		.binary_type = OPTEE_HEADER_BINARY_TYPE,
1381989a19cSYann Gautier 	},
1391989a19cSYann Gautier 	.part_info[IMG_IDX_OPTEE_PAGER] = {
1401989a19cSYann Gautier 		.name = OPTEE_PAGER_IMAGE_NAME,
1411989a19cSYann Gautier 		.binary_type = OPTEE_PAGER_BINARY_TYPE,
1421989a19cSYann Gautier 	},
1431989a19cSYann Gautier 	.part_info[IMG_IDX_OPTEE_PAGED] = {
1441989a19cSYann Gautier 		.name = OPTEE_PAGED_IMAGE_NAME,
1451989a19cSYann Gautier 		.binary_type = OPTEE_PAGED_BINARY_TYPE,
1461989a19cSYann Gautier 	},
1471989a19cSYann Gautier #endif
148c9d75b3cSYann Gautier };
149c9d75b3cSYann Gautier 
150c9d75b3cSYann Gautier static io_block_spec_t stm32image_block_spec = {
151c9d75b3cSYann Gautier 	.offset = 0,
152c9d75b3cSYann Gautier 	.length = 0,
153c9d75b3cSYann Gautier };
154c9d75b3cSYann Gautier 
15546554b64SNicolas Le Bayon static const io_dev_connector_t *stm32image_dev_con __unused;
156c9d75b3cSYann Gautier 
157c9d75b3cSYann Gautier static int open_dummy(const uintptr_t spec);
158c9d75b3cSYann Gautier static int open_image(const uintptr_t spec);
159c9d75b3cSYann Gautier static int open_storage(const uintptr_t spec);
160c9d75b3cSYann Gautier 
161c9d75b3cSYann Gautier struct plat_io_policy {
162c9d75b3cSYann Gautier 	uintptr_t *dev_handle;
163c9d75b3cSYann Gautier 	uintptr_t image_spec;
164c9d75b3cSYann Gautier 	int (*check)(const uintptr_t spec);
165c9d75b3cSYann Gautier };
166c9d75b3cSYann Gautier 
167c9d75b3cSYann Gautier static const struct plat_io_policy policies[] = {
168c9d75b3cSYann Gautier 	[BL2_IMAGE_ID] = {
169c9d75b3cSYann Gautier 		.dev_handle = &dummy_dev_handle,
170c9d75b3cSYann Gautier 		.image_spec = (uintptr_t)&bl2_block_spec,
171c9d75b3cSYann Gautier 		.check = open_dummy
172c9d75b3cSYann Gautier 	},
1731989a19cSYann Gautier #ifdef AARCH32_SP_OPTEE
1741989a19cSYann Gautier 	[BL32_IMAGE_ID] = {
1751989a19cSYann Gautier 		.dev_handle = &image_dev_handle,
1761989a19cSYann Gautier 		.image_spec = (uintptr_t)&optee_header_partition_spec,
1771989a19cSYann Gautier 		.check = open_image
1781989a19cSYann Gautier 	},
1791989a19cSYann Gautier 	[BL32_EXTRA1_IMAGE_ID] = {
1801989a19cSYann Gautier 		.dev_handle = &image_dev_handle,
1811989a19cSYann Gautier 		.image_spec = (uintptr_t)&optee_pager_partition_spec,
1821989a19cSYann Gautier 		.check = open_image
1831989a19cSYann Gautier 	},
1841989a19cSYann Gautier 	[BL32_EXTRA2_IMAGE_ID] = {
1851989a19cSYann Gautier 		.dev_handle = &image_dev_handle,
1861989a19cSYann Gautier 		.image_spec = (uintptr_t)&optee_paged_partition_spec,
1871989a19cSYann Gautier 		.check = open_image
1881989a19cSYann Gautier 	},
1891989a19cSYann Gautier #else
190c9d75b3cSYann Gautier 	[BL32_IMAGE_ID] = {
191c9d75b3cSYann Gautier 		.dev_handle = &dummy_dev_handle,
192c9d75b3cSYann Gautier 		.image_spec = (uintptr_t)&bl32_block_spec,
193c9d75b3cSYann Gautier 		.check = open_dummy
194c9d75b3cSYann Gautier 	},
1951989a19cSYann Gautier #endif
196c9d75b3cSYann Gautier 	[BL33_IMAGE_ID] = {
197c9d75b3cSYann Gautier 		.dev_handle = &image_dev_handle,
198c9d75b3cSYann Gautier 		.image_spec = (uintptr_t)&bl33_partition_spec,
199c9d75b3cSYann Gautier 		.check = open_image
200c9d75b3cSYann Gautier 	},
20146554b64SNicolas Le Bayon #if STM32MP_SDMMC || STM32MP_EMMC
202c9d75b3cSYann Gautier 	[GPT_IMAGE_ID] = {
203c9d75b3cSYann Gautier 		.dev_handle = &storage_dev_handle,
204c9d75b3cSYann Gautier 		.image_spec = (uintptr_t)&gpt_block_spec,
205c9d75b3cSYann Gautier 		.check = open_storage
206c9d75b3cSYann Gautier 	},
20746554b64SNicolas Le Bayon #endif
208c9d75b3cSYann Gautier 	[STM32_IMAGE_ID] = {
209c9d75b3cSYann Gautier 		.dev_handle = &storage_dev_handle,
210c9d75b3cSYann Gautier 		.image_spec = (uintptr_t)&stm32image_block_spec,
211c9d75b3cSYann Gautier 		.check = open_storage
212c9d75b3cSYann Gautier 	}
213c9d75b3cSYann Gautier };
214c9d75b3cSYann Gautier 
215c9d75b3cSYann Gautier static int open_dummy(const uintptr_t spec)
216c9d75b3cSYann Gautier {
217c9d75b3cSYann Gautier 	return io_dev_init(dummy_dev_handle, 0);
218c9d75b3cSYann Gautier }
219c9d75b3cSYann Gautier 
220c9d75b3cSYann Gautier static int open_image(const uintptr_t spec)
221c9d75b3cSYann Gautier {
222c9d75b3cSYann Gautier 	return io_dev_init(image_dev_handle, 0);
223c9d75b3cSYann Gautier }
224c9d75b3cSYann Gautier 
225c9d75b3cSYann Gautier static int open_storage(const uintptr_t spec)
226c9d75b3cSYann Gautier {
227c9d75b3cSYann Gautier 	return io_dev_init(storage_dev_handle, 0);
228c9d75b3cSYann Gautier }
229c9d75b3cSYann Gautier 
230c9d75b3cSYann Gautier static void print_boot_device(boot_api_context_t *boot_context)
231c9d75b3cSYann Gautier {
232c9d75b3cSYann Gautier 	switch (boot_context->boot_interface_selected) {
233c9d75b3cSYann Gautier 	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD:
234c9d75b3cSYann Gautier 		INFO("Using SDMMC\n");
235c9d75b3cSYann Gautier 		break;
236c9d75b3cSYann Gautier 	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC:
237c9d75b3cSYann Gautier 		INFO("Using EMMC\n");
238c9d75b3cSYann Gautier 		break;
23912e21dfdSLionel Debieve 	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC:
24012e21dfdSLionel Debieve 		INFO("Using FMC NAND\n");
24112e21dfdSLionel Debieve 		break;
242*57044228SLionel Debieve 	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI:
243*57044228SLionel Debieve 		INFO("Using SPI NAND\n");
244*57044228SLionel Debieve 		break;
245c9d75b3cSYann Gautier 	default:
246c9d75b3cSYann Gautier 		ERROR("Boot interface not found\n");
247c9d75b3cSYann Gautier 		panic();
248c9d75b3cSYann Gautier 		break;
249c9d75b3cSYann Gautier 	}
250c9d75b3cSYann Gautier 
251c9d75b3cSYann Gautier 	if (boot_context->boot_interface_instance != 0U) {
252c9d75b3cSYann Gautier 		INFO("  Instance %d\n", boot_context->boot_interface_instance);
253c9d75b3cSYann Gautier 	}
254c9d75b3cSYann Gautier }
255c9d75b3cSYann Gautier 
25646554b64SNicolas Le Bayon #if STM32MP_SDMMC || STM32MP_EMMC
2570b1aa772SYann Gautier static void boot_mmc(enum mmc_device_type mmc_dev_type,
2580b1aa772SYann Gautier 		     uint16_t boot_interface_instance)
259c9d75b3cSYann Gautier {
260c9d75b3cSYann Gautier 	int io_result __unused;
261c9d75b3cSYann Gautier 	uint8_t idx;
262c9d75b3cSYann Gautier 	struct stm32image_part_info *part;
263c9d75b3cSYann Gautier 	struct stm32_sdmmc2_params params;
264c9d75b3cSYann Gautier 	struct mmc_device_info device_info;
265c9d75b3cSYann Gautier 	const partition_entry_t *entry;
266c9d75b3cSYann Gautier 
26742beea8dSYann Gautier 	zeromem(&device_info, sizeof(struct mmc_device_info));
26842beea8dSYann Gautier 	zeromem(&params, sizeof(struct stm32_sdmmc2_params));
269c9d75b3cSYann Gautier 
2700b1aa772SYann Gautier 	device_info.mmc_dev_type = mmc_dev_type;
271c9d75b3cSYann Gautier 
2720b1aa772SYann Gautier 	switch (boot_interface_instance) {
273c9d75b3cSYann Gautier 	case 1:
2743f9c9784SYann Gautier 		params.reg_base = STM32MP_SDMMC1_BASE;
275c9d75b3cSYann Gautier 		break;
276c9d75b3cSYann Gautier 	case 2:
2773f9c9784SYann Gautier 		params.reg_base = STM32MP_SDMMC2_BASE;
278c9d75b3cSYann Gautier 		break;
279c9d75b3cSYann Gautier 	case 3:
2803f9c9784SYann Gautier 		params.reg_base = STM32MP_SDMMC3_BASE;
281c9d75b3cSYann Gautier 		break;
282c9d75b3cSYann Gautier 	default:
283c9d75b3cSYann Gautier 		WARN("SDMMC instance not found, using default\n");
2840b1aa772SYann Gautier 		if (mmc_dev_type == MMC_IS_SD) {
2850b1aa772SYann Gautier 			params.reg_base = STM32MP_SDMMC1_BASE;
2860b1aa772SYann Gautier 		} else {
2870b1aa772SYann Gautier 			params.reg_base = STM32MP_SDMMC2_BASE;
2880b1aa772SYann Gautier 		}
289c9d75b3cSYann Gautier 		break;
290c9d75b3cSYann Gautier 	}
291c9d75b3cSYann Gautier 
292c9d75b3cSYann Gautier 	params.device_info = &device_info;
293c9d75b3cSYann Gautier 	if (stm32_sdmmc2_mmc_init(&params) != 0) {
2940b1aa772SYann Gautier 		ERROR("SDMMC%u init failed\n", boot_interface_instance);
295c9d75b3cSYann Gautier 		panic();
296c9d75b3cSYann Gautier 	}
297c9d75b3cSYann Gautier 
298c9d75b3cSYann Gautier 	/* Open MMC as a block device to read GPT table */
299c9d75b3cSYann Gautier 	io_result = register_io_dev_block(&mmc_dev_con);
300c9d75b3cSYann Gautier 	if (io_result != 0) {
301c9d75b3cSYann Gautier 		panic();
302c9d75b3cSYann Gautier 	}
303c9d75b3cSYann Gautier 
3040b1aa772SYann Gautier 	io_result = io_dev_open(mmc_dev_con, (uintptr_t)&mmc_block_dev_spec,
305c9d75b3cSYann Gautier 				&storage_dev_handle);
306c9d75b3cSYann Gautier 	assert(io_result == 0);
307c9d75b3cSYann Gautier 
308c9d75b3cSYann Gautier 	partition_init(GPT_IMAGE_ID);
309c9d75b3cSYann Gautier 
310c9d75b3cSYann Gautier 	io_result = io_dev_close(storage_dev_handle);
311c9d75b3cSYann Gautier 	assert(io_result == 0);
312c9d75b3cSYann Gautier 
313c9d75b3cSYann Gautier 	stm32image_dev_info_spec.device_size =
314c9d75b3cSYann Gautier 		stm32_sdmmc2_mmc_get_device_size();
315c9d75b3cSYann Gautier 
316c9d75b3cSYann Gautier 	for (idx = 0U; idx < IMG_IDX_NUM; idx++) {
317c9d75b3cSYann Gautier 		part = &stm32image_dev_info_spec.part_info[idx];
318c9d75b3cSYann Gautier 		entry = get_partition_entry(part->name);
319c9d75b3cSYann Gautier 		if (entry == NULL) {
3200b1aa772SYann Gautier 			ERROR("Partition %s not found\n", part->name);
321c9d75b3cSYann Gautier 			panic();
322c9d75b3cSYann Gautier 		}
323c9d75b3cSYann Gautier 
324c9d75b3cSYann Gautier 		part->part_offset = entry->start;
325c9d75b3cSYann Gautier 		part->bkp_offset = 0U;
326c9d75b3cSYann Gautier 	}
327c9d75b3cSYann Gautier 
328c9d75b3cSYann Gautier 	/*
329c9d75b3cSYann Gautier 	 * Re-open MMC with io_mmc, for better perfs compared to
330c9d75b3cSYann Gautier 	 * io_block.
331c9d75b3cSYann Gautier 	 */
332c9d75b3cSYann Gautier 	io_result = register_io_dev_mmc(&mmc_dev_con);
333c9d75b3cSYann Gautier 	assert(io_result == 0);
334c9d75b3cSYann Gautier 
335c9d75b3cSYann Gautier 	io_result = io_dev_open(mmc_dev_con, 0, &storage_dev_handle);
336c9d75b3cSYann Gautier 	assert(io_result == 0);
337c9d75b3cSYann Gautier 
338c9d75b3cSYann Gautier 	io_result = register_io_dev_stm32image(&stm32image_dev_con);
339c9d75b3cSYann Gautier 	assert(io_result == 0);
340c9d75b3cSYann Gautier 
341c9d75b3cSYann Gautier 	io_result = io_dev_open(stm32image_dev_con,
342c9d75b3cSYann Gautier 				(uintptr_t)&stm32image_dev_info_spec,
343c9d75b3cSYann Gautier 				&image_dev_handle);
344c9d75b3cSYann Gautier 	assert(io_result == 0);
3450b1aa772SYann Gautier }
34646554b64SNicolas Le Bayon #endif /* STM32MP_SDMMC || STM32MP_EMMC */
3470b1aa772SYann Gautier 
34812e21dfdSLionel Debieve #if STM32MP_RAW_NAND
34912e21dfdSLionel Debieve static void boot_fmc2_nand(boot_api_context_t *boot_context)
35012e21dfdSLionel Debieve {
35112e21dfdSLionel Debieve 	int io_result __unused;
35212e21dfdSLionel Debieve 	uint8_t idx;
35312e21dfdSLionel Debieve 	struct stm32image_part_info *part;
35412e21dfdSLionel Debieve 
35512e21dfdSLionel Debieve 	io_result = stm32_fmc2_init();
35612e21dfdSLionel Debieve 	assert(io_result == 0);
35712e21dfdSLionel Debieve 
35812e21dfdSLionel Debieve 	/* Register the IO device on this platform */
35912e21dfdSLionel Debieve 	io_result = register_io_dev_mtd(&nand_dev_con);
36012e21dfdSLionel Debieve 	assert(io_result == 0);
36112e21dfdSLionel Debieve 
36212e21dfdSLionel Debieve 	/* Open connections to device */
36312e21dfdSLionel Debieve 	io_result = io_dev_open(nand_dev_con, (uintptr_t)&nand_dev_spec,
36412e21dfdSLionel Debieve 				&storage_dev_handle);
36512e21dfdSLionel Debieve 	assert(io_result == 0);
36612e21dfdSLionel Debieve 
36712e21dfdSLionel Debieve 	stm32image_dev_info_spec.device_size = nand_dev_spec.device_size;
36812e21dfdSLionel Debieve 
36912e21dfdSLionel Debieve 	idx = IMG_IDX_BL33;
37012e21dfdSLionel Debieve 	part = &stm32image_dev_info_spec.part_info[idx];
37112e21dfdSLionel Debieve 	part->part_offset = STM32MP_NAND_BL33_OFFSET;
37212e21dfdSLionel Debieve 	part->bkp_offset = nand_dev_spec.erase_size;
37312e21dfdSLionel Debieve 
37412e21dfdSLionel Debieve #ifdef AARCH32_SP_OPTEE
37512e21dfdSLionel Debieve 	idx = IMG_IDX_OPTEE_HEADER;
37612e21dfdSLionel Debieve 	part = &stm32image_dev_info_spec.part_info[idx];
37712e21dfdSLionel Debieve 	part->part_offset = STM32MP_NAND_TEEH_OFFSET;
37812e21dfdSLionel Debieve 	part->bkp_offset = nand_dev_spec.erase_size;
37912e21dfdSLionel Debieve 
38012e21dfdSLionel Debieve 	idx = IMG_IDX_OPTEE_PAGED;
38112e21dfdSLionel Debieve 	part = &stm32image_dev_info_spec.part_info[idx];
38212e21dfdSLionel Debieve 	part->part_offset = STM32MP_NAND_TEED_OFFSET;
38312e21dfdSLionel Debieve 	part->bkp_offset = nand_dev_spec.erase_size;
38412e21dfdSLionel Debieve 
38512e21dfdSLionel Debieve 	idx = IMG_IDX_OPTEE_PAGER;
38612e21dfdSLionel Debieve 	part = &stm32image_dev_info_spec.part_info[idx];
38712e21dfdSLionel Debieve 	part->part_offset = STM32MP_NAND_TEEX_OFFSET;
38812e21dfdSLionel Debieve 	part->bkp_offset = nand_dev_spec.erase_size;
38912e21dfdSLionel Debieve #endif
39012e21dfdSLionel Debieve 
39112e21dfdSLionel Debieve 	io_result = register_io_dev_stm32image(&stm32image_dev_con);
39212e21dfdSLionel Debieve 	assert(io_result == 0);
39312e21dfdSLionel Debieve 
39412e21dfdSLionel Debieve 	io_result = io_dev_open(stm32image_dev_con,
39512e21dfdSLionel Debieve 				(uintptr_t)&stm32image_dev_info_spec,
39612e21dfdSLionel Debieve 				&image_dev_handle);
39712e21dfdSLionel Debieve 	assert(io_result == 0);
39812e21dfdSLionel Debieve }
39912e21dfdSLionel Debieve #endif /* STM32MP_RAW_NAND */
40012e21dfdSLionel Debieve 
401*57044228SLionel Debieve #if STM32MP_SPI_NAND
402*57044228SLionel Debieve static void boot_spi_nand(boot_api_context_t *boot_context)
403*57044228SLionel Debieve {
404*57044228SLionel Debieve 	int io_result __unused;
405*57044228SLionel Debieve 	uint8_t idx;
406*57044228SLionel Debieve 	struct stm32image_part_info *part;
407*57044228SLionel Debieve 
408*57044228SLionel Debieve 	io_result = stm32_qspi_init();
409*57044228SLionel Debieve 	assert(io_result == 0);
410*57044228SLionel Debieve 
411*57044228SLionel Debieve 	io_result = register_io_dev_mtd(&spi_dev_con);
412*57044228SLionel Debieve 	assert(io_result == 0);
413*57044228SLionel Debieve 
414*57044228SLionel Debieve 	/* Open connections to device */
415*57044228SLionel Debieve 	io_result = io_dev_open(spi_dev_con,
416*57044228SLionel Debieve 				(uintptr_t)&spi_nand_dev_spec,
417*57044228SLionel Debieve 				&storage_dev_handle);
418*57044228SLionel Debieve 	assert(io_result == 0);
419*57044228SLionel Debieve 
420*57044228SLionel Debieve 	stm32image_dev_info_spec.device_size =
421*57044228SLionel Debieve 		spi_nand_dev_spec.device_size;
422*57044228SLionel Debieve 
423*57044228SLionel Debieve 	idx = IMG_IDX_BL33;
424*57044228SLionel Debieve 	part = &stm32image_dev_info_spec.part_info[idx];
425*57044228SLionel Debieve 	part->part_offset = STM32MP_NAND_BL33_OFFSET;
426*57044228SLionel Debieve 	part->bkp_offset = spi_nand_dev_spec.erase_size;
427*57044228SLionel Debieve 
428*57044228SLionel Debieve #ifdef AARCH32_SP_OPTEE
429*57044228SLionel Debieve 	idx = IMG_IDX_OPTEE_HEADER;
430*57044228SLionel Debieve 	part = &stm32image_dev_info_spec.part_info[idx];
431*57044228SLionel Debieve 	part->part_offset = STM32MP_NAND_TEEH_OFFSET;
432*57044228SLionel Debieve 	part->bkp_offset = spi_nand_dev_spec.erase_size;
433*57044228SLionel Debieve 
434*57044228SLionel Debieve 	idx = IMG_IDX_OPTEE_PAGED;
435*57044228SLionel Debieve 	part = &stm32image_dev_info_spec.part_info[idx];
436*57044228SLionel Debieve 	part->part_offset = STM32MP_NAND_TEED_OFFSET;
437*57044228SLionel Debieve 	part->bkp_offset = spi_nand_dev_spec.erase_size;
438*57044228SLionel Debieve 
439*57044228SLionel Debieve 	idx = IMG_IDX_OPTEE_PAGER;
440*57044228SLionel Debieve 	part = &stm32image_dev_info_spec.part_info[idx];
441*57044228SLionel Debieve 	part->part_offset = STM32MP_NAND_TEEX_OFFSET;
442*57044228SLionel Debieve 	part->bkp_offset = spi_nand_dev_spec.erase_size;
443*57044228SLionel Debieve #endif
444*57044228SLionel Debieve 
445*57044228SLionel Debieve 	io_result = register_io_dev_stm32image(&stm32image_dev_con);
446*57044228SLionel Debieve 	assert(io_result == 0);
447*57044228SLionel Debieve 
448*57044228SLionel Debieve 	io_result = io_dev_open(stm32image_dev_con,
449*57044228SLionel Debieve 				(uintptr_t)&stm32image_dev_info_spec,
450*57044228SLionel Debieve 				&image_dev_handle);
451*57044228SLionel Debieve 	assert(io_result == 0);
452*57044228SLionel Debieve }
453*57044228SLionel Debieve #endif /* STM32MP_SPI_NAND */
454*57044228SLionel Debieve 
4550b1aa772SYann Gautier void stm32mp_io_setup(void)
4560b1aa772SYann Gautier {
4570b1aa772SYann Gautier 	int io_result __unused;
4580b1aa772SYann Gautier 	boot_api_context_t *boot_context =
4590b1aa772SYann Gautier 		(boot_api_context_t *)stm32mp_get_boot_ctx_address();
4600b1aa772SYann Gautier 
4610b1aa772SYann Gautier 	print_boot_device(boot_context);
4620b1aa772SYann Gautier 
4630b1aa772SYann Gautier 	if ((boot_context->boot_partition_used_toboot == 1U) ||
4640b1aa772SYann Gautier 	    (boot_context->boot_partition_used_toboot == 2U)) {
4650b1aa772SYann Gautier 		INFO("Boot used partition fsbl%d\n",
4660b1aa772SYann Gautier 		     boot_context->boot_partition_used_toboot);
4670b1aa772SYann Gautier 	}
4680b1aa772SYann Gautier 
4690b1aa772SYann Gautier 	io_result = register_io_dev_dummy(&dummy_dev_con);
4700b1aa772SYann Gautier 	assert(io_result == 0);
4710b1aa772SYann Gautier 
4720b1aa772SYann Gautier 	io_result = io_dev_open(dummy_dev_con, dummy_dev_spec,
4730b1aa772SYann Gautier 				&dummy_dev_handle);
4740b1aa772SYann Gautier 	assert(io_result == 0);
4750b1aa772SYann Gautier 
4760b1aa772SYann Gautier 	switch (boot_context->boot_interface_selected) {
47746554b64SNicolas Le Bayon #if STM32MP_SDMMC
4780b1aa772SYann Gautier 	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD:
4790b1aa772SYann Gautier 		dmbsy();
4800b1aa772SYann Gautier 		boot_mmc(MMC_IS_SD, boot_context->boot_interface_instance);
4810b1aa772SYann Gautier 		break;
48246554b64SNicolas Le Bayon #endif
48346554b64SNicolas Le Bayon #if STM32MP_EMMC
4840b1aa772SYann Gautier 	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC:
4850b1aa772SYann Gautier 		dmbsy();
4860b1aa772SYann Gautier 		boot_mmc(MMC_IS_EMMC, boot_context->boot_interface_instance);
487c9d75b3cSYann Gautier 		break;
48846554b64SNicolas Le Bayon #endif
48912e21dfdSLionel Debieve #if STM32MP_RAW_NAND
49012e21dfdSLionel Debieve 	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC:
49112e21dfdSLionel Debieve 		dmbsy();
49212e21dfdSLionel Debieve 		boot_fmc2_nand(boot_context);
49312e21dfdSLionel Debieve 		break;
49412e21dfdSLionel Debieve #endif
495*57044228SLionel Debieve #if STM32MP_SPI_NAND
496*57044228SLionel Debieve 	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI:
497*57044228SLionel Debieve 		dmbsy();
498*57044228SLionel Debieve 		boot_spi_nand(boot_context);
499*57044228SLionel Debieve 		break;
500*57044228SLionel Debieve #endif
501c9d75b3cSYann Gautier 
502c9d75b3cSYann Gautier 	default:
503c9d75b3cSYann Gautier 		ERROR("Boot interface %d not supported\n",
504c9d75b3cSYann Gautier 		      boot_context->boot_interface_selected);
505c9d75b3cSYann Gautier 		break;
506c9d75b3cSYann Gautier 	}
507c9d75b3cSYann Gautier }
508c9d75b3cSYann Gautier 
509c9d75b3cSYann Gautier /*
510c9d75b3cSYann Gautier  * Return an IO device handle and specification which can be used to access
511c9d75b3cSYann Gautier  * an image. Use this to enforce platform load policy.
512c9d75b3cSYann Gautier  */
513c9d75b3cSYann Gautier int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
514c9d75b3cSYann Gautier 			  uintptr_t *image_spec)
515c9d75b3cSYann Gautier {
516c9d75b3cSYann Gautier 	int rc;
517c9d75b3cSYann Gautier 	const struct plat_io_policy *policy;
518c9d75b3cSYann Gautier 
519c9d75b3cSYann Gautier 	assert(image_id < ARRAY_SIZE(policies));
520c9d75b3cSYann Gautier 
521c9d75b3cSYann Gautier 	policy = &policies[image_id];
522c9d75b3cSYann Gautier 	rc = policy->check(policy->image_spec);
523c9d75b3cSYann Gautier 	if (rc == 0) {
524c9d75b3cSYann Gautier 		*image_spec = policy->image_spec;
525c9d75b3cSYann Gautier 		*dev_handle = *(policy->dev_handle);
526c9d75b3cSYann Gautier 	}
527c9d75b3cSYann Gautier 
528c9d75b3cSYann Gautier 	return rc;
529c9d75b3cSYann Gautier }
530