xref: /rk3399_ARM-atf/plat/st/common/bl2_io_storage.c (revision 53d5b8ff50d322f764b1f5a8c882b9ee1ba952c9)
1c9d75b3cSYann Gautier /*
2f87de907SNicolas Toromanoff  * Copyright (c) 2015-2022, 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 <arch_helpers.h>
11c9d75b3cSYann Gautier #include <common/debug.h>
1218b415beSYann Gautier #include <common/desc_image_load.h>
138dd75531SSughosh Ganu #include <drivers/fwu/fwu.h>
148dd75531SSughosh Ganu #include <drivers/fwu/fwu_metadata.h>
15c9d75b3cSYann Gautier #include <drivers/io/io_block.h>
16c9d75b3cSYann Gautier #include <drivers/io/io_driver.h>
171d204ee4SYann Gautier #include <drivers/io/io_fip.h>
18fa92fef0SPatrick Delaunay #include <drivers/io/io_memmap.h>
1912e21dfdSLionel Debieve #include <drivers/io/io_mtd.h>
20c9d75b3cSYann Gautier #include <drivers/io/io_storage.h>
21c9d75b3cSYann Gautier #include <drivers/mmc.h>
228dd75531SSughosh Ganu #include <drivers/partition/efi.h>
23c9d75b3cSYann Gautier #include <drivers/partition/partition.h>
2412e21dfdSLionel Debieve #include <drivers/raw_nand.h>
2557044228SLionel Debieve #include <drivers/spi_nand.h>
26b1b218fbSLionel Debieve #include <drivers/spi_nor.h>
27c9d75b3cSYann Gautier #include <drivers/st/io_mmc.h>
2812e21dfdSLionel Debieve #include <drivers/st/stm32_fmc2_nand.h>
2957044228SLionel Debieve #include <drivers/st/stm32_qspi.h>
30c9d75b3cSYann Gautier #include <drivers/st/stm32_sdmmc2.h>
31fa92fef0SPatrick Delaunay #include <drivers/usb_device.h>
32d5a84eeaSYann Gautier #include <lib/fconf/fconf.h>
33c9d75b3cSYann Gautier #include <lib/mmio.h>
34c9d75b3cSYann Gautier #include <lib/utils.h>
35c9d75b3cSYann Gautier #include <plat/common/platform.h>
361d204ee4SYann Gautier #include <tools_share/firmware_image_package.h>
371d204ee4SYann Gautier 
381d204ee4SYann Gautier #include <platform_def.h>
39fa92fef0SPatrick Delaunay #include <stm32cubeprogrammer.h>
401dab28f9SLionel Debieve #include <stm32mp_efi.h>
41d5a84eeaSYann Gautier #include <stm32mp_fconf_getter.h>
42b1391b29SYann Gautier #include <stm32mp_io_storage.h>
43fa92fef0SPatrick Delaunay #include <usb_dfu.h>
44c9d75b3cSYann Gautier 
45c9d75b3cSYann Gautier /* IO devices */
461d204ee4SYann Gautier uintptr_t fip_dev_handle;
471d204ee4SYann Gautier uintptr_t storage_dev_handle;
48c9d75b3cSYann Gautier 
491d204ee4SYann Gautier static const io_dev_connector_t *fip_dev_con;
50c9d75b3cSYann Gautier 
5146554b64SNicolas Le Bayon #if STM32MP_SDMMC || STM32MP_EMMC
52cddf1bd7SYann Gautier static struct mmc_device_info mmc_info;
53c9d75b3cSYann Gautier 
54c9d75b3cSYann Gautier static uint32_t block_buffer[MMC_BLOCK_SIZE] __aligned(MMC_BLOCK_SIZE);
55c9d75b3cSYann Gautier 
5618b415beSYann Gautier static io_block_dev_spec_t mmc_block_dev_spec = {
57c9d75b3cSYann Gautier 	/* It's used as temp buffer in block driver */
58c9d75b3cSYann Gautier 	.buffer = {
59c9d75b3cSYann Gautier 		.offset = (size_t)&block_buffer,
60c9d75b3cSYann Gautier 		.length = MMC_BLOCK_SIZE,
61c9d75b3cSYann Gautier 	},
62c9d75b3cSYann Gautier 	.ops = {
63c9d75b3cSYann Gautier 		.read = mmc_read_blocks,
64c9d75b3cSYann Gautier 		.write = NULL,
65c9d75b3cSYann Gautier 	},
66c9d75b3cSYann Gautier 	.block_size = MMC_BLOCK_SIZE,
67c9d75b3cSYann Gautier };
68c9d75b3cSYann Gautier 
69c9d75b3cSYann Gautier static const io_dev_connector_t *mmc_dev_con;
7046554b64SNicolas Le Bayon #endif /* STM32MP_SDMMC || STM32MP_EMMC */
71c9d75b3cSYann Gautier 
72b1b218fbSLionel Debieve #if STM32MP_SPI_NOR
73b1b218fbSLionel Debieve static io_mtd_dev_spec_t spi_nor_dev_spec = {
74b1b218fbSLionel Debieve 	.ops = {
75b1b218fbSLionel Debieve 		.init = spi_nor_init,
76b1b218fbSLionel Debieve 		.read = spi_nor_read,
77b1b218fbSLionel Debieve 	},
78b1b218fbSLionel Debieve };
79b1b218fbSLionel Debieve #endif
80b1b218fbSLionel Debieve 
8112e21dfdSLionel Debieve #if STM32MP_RAW_NAND
8212e21dfdSLionel Debieve static io_mtd_dev_spec_t nand_dev_spec = {
8312e21dfdSLionel Debieve 	.ops = {
8412e21dfdSLionel Debieve 		.init = nand_raw_init,
8512e21dfdSLionel Debieve 		.read = nand_read,
861d204ee4SYann Gautier 		.seek = nand_seek_bb
8712e21dfdSLionel Debieve 	},
8812e21dfdSLionel Debieve };
8912e21dfdSLionel Debieve 
9012e21dfdSLionel Debieve static const io_dev_connector_t *nand_dev_con;
9112e21dfdSLionel Debieve #endif
9212e21dfdSLionel Debieve 
9357044228SLionel Debieve #if STM32MP_SPI_NAND
9457044228SLionel Debieve static io_mtd_dev_spec_t spi_nand_dev_spec = {
9557044228SLionel Debieve 	.ops = {
9657044228SLionel Debieve 		.init = spi_nand_init,
9757044228SLionel Debieve 		.read = nand_read,
981d204ee4SYann Gautier 		.seek = nand_seek_bb
9957044228SLionel Debieve 	},
10057044228SLionel Debieve };
101b1b218fbSLionel Debieve #endif
10257044228SLionel Debieve 
103b1b218fbSLionel Debieve #if STM32MP_SPI_NAND || STM32MP_SPI_NOR
10457044228SLionel Debieve static const io_dev_connector_t *spi_dev_con;
10557044228SLionel Debieve #endif
10657044228SLionel Debieve 
1079083fa11SPatrick Delaunay #if STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER
108fa92fef0SPatrick Delaunay static const io_dev_connector_t *memmap_dev_con;
109fa92fef0SPatrick Delaunay #endif
110fa92fef0SPatrick Delaunay 
111d5a84eeaSYann Gautier io_block_spec_t image_block_spec = {
1121d204ee4SYann Gautier 	.offset = 0U,
1131d204ee4SYann Gautier 	.length = 0U,
114c9d75b3cSYann Gautier };
115c9d75b3cSYann Gautier 
116d5a84eeaSYann Gautier int open_fip(const uintptr_t spec)
117c9d75b3cSYann Gautier {
1181d204ee4SYann Gautier 	return io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID);
119c9d75b3cSYann Gautier }
120c9d75b3cSYann Gautier 
121d5a84eeaSYann Gautier int open_storage(const uintptr_t spec)
122c9d75b3cSYann Gautier {
123c9d75b3cSYann Gautier 	return io_dev_init(storage_dev_handle, 0);
124c9d75b3cSYann Gautier }
125c9d75b3cSYann Gautier 
12695e4908eSAhmad Fatoum #if STM32MP_EMMC_BOOT
12795e4908eSAhmad Fatoum static uint32_t get_boot_part_fip_header(void)
12895e4908eSAhmad Fatoum {
12995e4908eSAhmad Fatoum 	io_block_spec_t emmc_boot_fip_block_spec = {
13095e4908eSAhmad Fatoum 		.offset = STM32MP_EMMC_BOOT_FIP_OFFSET,
13195e4908eSAhmad Fatoum 		.length = MMC_BLOCK_SIZE, /* We are interested only in first 4 bytes */
13295e4908eSAhmad Fatoum 	};
13395e4908eSAhmad Fatoum 	uint32_t magic = 0U;
13495e4908eSAhmad Fatoum 	int io_result;
13595e4908eSAhmad Fatoum 	size_t bytes_read;
13695e4908eSAhmad Fatoum 	uintptr_t fip_hdr_handle;
13795e4908eSAhmad Fatoum 
13895e4908eSAhmad Fatoum 	io_result = io_open(storage_dev_handle, (uintptr_t)&emmc_boot_fip_block_spec,
13995e4908eSAhmad Fatoum 			    &fip_hdr_handle);
14095e4908eSAhmad Fatoum 	assert(io_result == 0);
14195e4908eSAhmad Fatoum 
14295e4908eSAhmad Fatoum 	io_result = io_read(fip_hdr_handle, (uintptr_t)&magic, sizeof(magic),
14395e4908eSAhmad Fatoum 			    &bytes_read);
14495e4908eSAhmad Fatoum 	if ((io_result != 0) || (bytes_read != sizeof(magic))) {
14595e4908eSAhmad Fatoum 		panic();
14695e4908eSAhmad Fatoum 	}
14795e4908eSAhmad Fatoum 
14895e4908eSAhmad Fatoum 	io_close(fip_hdr_handle);
14995e4908eSAhmad Fatoum 
15095e4908eSAhmad Fatoum 	VERBOSE("%s: eMMC boot magic at offset 256K: %08x\n",
15195e4908eSAhmad Fatoum 		__func__, magic);
15295e4908eSAhmad Fatoum 
15395e4908eSAhmad Fatoum 	return magic;
15495e4908eSAhmad Fatoum }
15595e4908eSAhmad Fatoum #endif
15695e4908eSAhmad Fatoum 
157c9d75b3cSYann Gautier static void print_boot_device(boot_api_context_t *boot_context)
158c9d75b3cSYann Gautier {
159c9d75b3cSYann Gautier 	switch (boot_context->boot_interface_selected) {
160c9d75b3cSYann Gautier 	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD:
161c9d75b3cSYann Gautier 		INFO("Using SDMMC\n");
162c9d75b3cSYann Gautier 		break;
163c9d75b3cSYann Gautier 	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC:
164c9d75b3cSYann Gautier 		INFO("Using EMMC\n");
165c9d75b3cSYann Gautier 		break;
166b1b218fbSLionel Debieve 	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI:
167b1b218fbSLionel Debieve 		INFO("Using QSPI NOR\n");
168b1b218fbSLionel Debieve 		break;
16912e21dfdSLionel Debieve 	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC:
17012e21dfdSLionel Debieve 		INFO("Using FMC NAND\n");
17112e21dfdSLionel Debieve 		break;
17257044228SLionel Debieve 	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI:
17357044228SLionel Debieve 		INFO("Using SPI NAND\n");
17457044228SLionel Debieve 		break;
1759083fa11SPatrick Delaunay 	case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART:
1769083fa11SPatrick Delaunay 		INFO("Using UART\n");
1779083fa11SPatrick Delaunay 		break;
178fa92fef0SPatrick Delaunay 	case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB:
179fa92fef0SPatrick Delaunay 		INFO("Using USB\n");
180fa92fef0SPatrick Delaunay 		break;
181c9d75b3cSYann Gautier 	default:
1821d204ee4SYann Gautier 		ERROR("Boot interface %u not found\n",
1831d204ee4SYann Gautier 		      boot_context->boot_interface_selected);
184c9d75b3cSYann Gautier 		panic();
185c9d75b3cSYann Gautier 		break;
186c9d75b3cSYann Gautier 	}
187c9d75b3cSYann Gautier 
188c9d75b3cSYann Gautier 	if (boot_context->boot_interface_instance != 0U) {
189c9d75b3cSYann Gautier 		INFO("  Instance %d\n", boot_context->boot_interface_instance);
190c9d75b3cSYann Gautier 	}
191c9d75b3cSYann Gautier }
192c9d75b3cSYann Gautier 
19346554b64SNicolas Le Bayon #if STM32MP_SDMMC || STM32MP_EMMC
1940b1aa772SYann Gautier static void boot_mmc(enum mmc_device_type mmc_dev_type,
1950b1aa772SYann Gautier 		     uint16_t boot_interface_instance)
196c9d75b3cSYann Gautier {
197c9d75b3cSYann Gautier 	int io_result __unused;
198c9d75b3cSYann Gautier 	struct stm32_sdmmc2_params params;
199c9d75b3cSYann Gautier 
20042beea8dSYann Gautier 	zeromem(&params, sizeof(struct stm32_sdmmc2_params));
201c9d75b3cSYann Gautier 
202cddf1bd7SYann Gautier 	mmc_info.mmc_dev_type = mmc_dev_type;
203c9d75b3cSYann Gautier 
2040b1aa772SYann Gautier 	switch (boot_interface_instance) {
205c9d75b3cSYann Gautier 	case 1:
2063f9c9784SYann Gautier 		params.reg_base = STM32MP_SDMMC1_BASE;
207c9d75b3cSYann Gautier 		break;
208c9d75b3cSYann Gautier 	case 2:
2093f9c9784SYann Gautier 		params.reg_base = STM32MP_SDMMC2_BASE;
210c9d75b3cSYann Gautier 		break;
211c9d75b3cSYann Gautier 	case 3:
2123f9c9784SYann Gautier 		params.reg_base = STM32MP_SDMMC3_BASE;
213c9d75b3cSYann Gautier 		break;
214c9d75b3cSYann Gautier 	default:
215c9d75b3cSYann Gautier 		WARN("SDMMC instance not found, using default\n");
2160b1aa772SYann Gautier 		if (mmc_dev_type == MMC_IS_SD) {
2170b1aa772SYann Gautier 			params.reg_base = STM32MP_SDMMC1_BASE;
2180b1aa772SYann Gautier 		} else {
2190b1aa772SYann Gautier 			params.reg_base = STM32MP_SDMMC2_BASE;
2200b1aa772SYann Gautier 		}
221c9d75b3cSYann Gautier 		break;
222c9d75b3cSYann Gautier 	}
223c9d75b3cSYann Gautier 
224*53d5b8ffSYann Gautier 	if (mmc_dev_type != MMC_IS_EMMC) {
225*53d5b8ffSYann Gautier 		params.flags = MMC_FLAG_SD_CMD6;
226*53d5b8ffSYann Gautier 	}
227*53d5b8ffSYann Gautier 
228cddf1bd7SYann Gautier 	params.device_info = &mmc_info;
229c9d75b3cSYann Gautier 	if (stm32_sdmmc2_mmc_init(&params) != 0) {
2300b1aa772SYann Gautier 		ERROR("SDMMC%u init failed\n", boot_interface_instance);
231c9d75b3cSYann Gautier 		panic();
232c9d75b3cSYann Gautier 	}
233c9d75b3cSYann Gautier 
23495e4908eSAhmad Fatoum 	/* Open MMC as a block device to read FIP */
235c9d75b3cSYann Gautier 	io_result = register_io_dev_block(&mmc_dev_con);
236c9d75b3cSYann Gautier 	if (io_result != 0) {
237c9d75b3cSYann Gautier 		panic();
238c9d75b3cSYann Gautier 	}
239c9d75b3cSYann Gautier 
2400b1aa772SYann Gautier 	io_result = io_dev_open(mmc_dev_con, (uintptr_t)&mmc_block_dev_spec,
241c9d75b3cSYann Gautier 				&storage_dev_handle);
242c9d75b3cSYann Gautier 	assert(io_result == 0);
24395e4908eSAhmad Fatoum 
24495e4908eSAhmad Fatoum #if STM32MP_EMMC_BOOT
24595e4908eSAhmad Fatoum 	if (mmc_dev_type == MMC_IS_EMMC) {
24695e4908eSAhmad Fatoum 		io_result = mmc_part_switch_current_boot();
24795e4908eSAhmad Fatoum 		assert(io_result == 0);
24895e4908eSAhmad Fatoum 
24995e4908eSAhmad Fatoum 		if (get_boot_part_fip_header() != TOC_HEADER_NAME) {
25095e4908eSAhmad Fatoum 			WARN("%s: Can't find FIP header on eMMC boot partition. Trying GPT\n",
25195e4908eSAhmad Fatoum 			     __func__);
25295e4908eSAhmad Fatoum 			io_result = mmc_part_switch_user();
25395e4908eSAhmad Fatoum 			assert(io_result == 0);
25495e4908eSAhmad Fatoum 			return;
25595e4908eSAhmad Fatoum 		}
25695e4908eSAhmad Fatoum 
25795e4908eSAhmad Fatoum 		VERBOSE("%s: FIP header found on eMMC boot partition\n",
25895e4908eSAhmad Fatoum 			__func__);
25995e4908eSAhmad Fatoum 		image_block_spec.offset = STM32MP_EMMC_BOOT_FIP_OFFSET;
26095e4908eSAhmad Fatoum 	}
26195e4908eSAhmad Fatoum #endif
2620b1aa772SYann Gautier }
26346554b64SNicolas Le Bayon #endif /* STM32MP_SDMMC || STM32MP_EMMC */
2640b1aa772SYann Gautier 
265b1b218fbSLionel Debieve #if STM32MP_SPI_NOR
266b1b218fbSLionel Debieve static void boot_spi_nor(boot_api_context_t *boot_context)
267b1b218fbSLionel Debieve {
268b1b218fbSLionel Debieve 	int io_result __unused;
269b1b218fbSLionel Debieve 
270b1b218fbSLionel Debieve 	io_result = stm32_qspi_init();
271b1b218fbSLionel Debieve 	assert(io_result == 0);
272b1b218fbSLionel Debieve 
273b1b218fbSLionel Debieve 	io_result = register_io_dev_mtd(&spi_dev_con);
274b1b218fbSLionel Debieve 	assert(io_result == 0);
275b1b218fbSLionel Debieve 
276b1b218fbSLionel Debieve 	/* Open connections to device */
277b1b218fbSLionel Debieve 	io_result = io_dev_open(spi_dev_con,
278b1b218fbSLionel Debieve 				(uintptr_t)&spi_nor_dev_spec,
279b1b218fbSLionel Debieve 				&storage_dev_handle);
280b1b218fbSLionel Debieve 	assert(io_result == 0);
281b1b218fbSLionel Debieve }
282b1b218fbSLionel Debieve #endif /* STM32MP_SPI_NOR */
283b1b218fbSLionel Debieve 
28412e21dfdSLionel Debieve #if STM32MP_RAW_NAND
28512e21dfdSLionel Debieve static void boot_fmc2_nand(boot_api_context_t *boot_context)
28612e21dfdSLionel Debieve {
28712e21dfdSLionel Debieve 	int io_result __unused;
28812e21dfdSLionel Debieve 
28912e21dfdSLionel Debieve 	io_result = stm32_fmc2_init();
29012e21dfdSLionel Debieve 	assert(io_result == 0);
29112e21dfdSLionel Debieve 
29212e21dfdSLionel Debieve 	/* Register the IO device on this platform */
29312e21dfdSLionel Debieve 	io_result = register_io_dev_mtd(&nand_dev_con);
29412e21dfdSLionel Debieve 	assert(io_result == 0);
29512e21dfdSLionel Debieve 
29612e21dfdSLionel Debieve 	/* Open connections to device */
29712e21dfdSLionel Debieve 	io_result = io_dev_open(nand_dev_con, (uintptr_t)&nand_dev_spec,
29812e21dfdSLionel Debieve 				&storage_dev_handle);
29912e21dfdSLionel Debieve 	assert(io_result == 0);
30012e21dfdSLionel Debieve }
30112e21dfdSLionel Debieve #endif /* STM32MP_RAW_NAND */
30212e21dfdSLionel Debieve 
30357044228SLionel Debieve #if STM32MP_SPI_NAND
30457044228SLionel Debieve static void boot_spi_nand(boot_api_context_t *boot_context)
30557044228SLionel Debieve {
30657044228SLionel Debieve 	int io_result __unused;
30757044228SLionel Debieve 
30857044228SLionel Debieve 	io_result = stm32_qspi_init();
30957044228SLionel Debieve 	assert(io_result == 0);
31057044228SLionel Debieve 
31157044228SLionel Debieve 	io_result = register_io_dev_mtd(&spi_dev_con);
31257044228SLionel Debieve 	assert(io_result == 0);
31357044228SLionel Debieve 
31457044228SLionel Debieve 	/* Open connections to device */
31557044228SLionel Debieve 	io_result = io_dev_open(spi_dev_con,
31657044228SLionel Debieve 				(uintptr_t)&spi_nand_dev_spec,
31757044228SLionel Debieve 				&storage_dev_handle);
31857044228SLionel Debieve 	assert(io_result == 0);
31957044228SLionel Debieve }
32057044228SLionel Debieve #endif /* STM32MP_SPI_NAND */
32157044228SLionel Debieve 
3229083fa11SPatrick Delaunay #if STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER
323fa92fef0SPatrick Delaunay static void mmap_io_setup(void)
324fa92fef0SPatrick Delaunay {
325fa92fef0SPatrick Delaunay 	int io_result __unused;
326fa92fef0SPatrick Delaunay 
327fa92fef0SPatrick Delaunay 	io_result = register_io_dev_memmap(&memmap_dev_con);
328fa92fef0SPatrick Delaunay 	assert(io_result == 0);
329fa92fef0SPatrick Delaunay 
330fa92fef0SPatrick Delaunay 	io_result = io_dev_open(memmap_dev_con, (uintptr_t)NULL,
331fa92fef0SPatrick Delaunay 				&storage_dev_handle);
332fa92fef0SPatrick Delaunay 	assert(io_result == 0);
333fa92fef0SPatrick Delaunay }
334fa92fef0SPatrick Delaunay 
3359083fa11SPatrick Delaunay #if STM32MP_UART_PROGRAMMER
3369083fa11SPatrick Delaunay static void stm32cubeprogrammer_uart(void)
3379083fa11SPatrick Delaunay {
3389083fa11SPatrick Delaunay 	int ret __unused;
3399083fa11SPatrick Delaunay 	boot_api_context_t *boot_context =
3409083fa11SPatrick Delaunay 		(boot_api_context_t *)stm32mp_get_boot_ctx_address();
3419083fa11SPatrick Delaunay 	uintptr_t uart_base;
3429083fa11SPatrick Delaunay 
3439083fa11SPatrick Delaunay 	uart_base = get_uart_address(boot_context->boot_interface_instance);
3449083fa11SPatrick Delaunay 	ret = stm32cubeprog_uart_load(uart_base, DWL_BUFFER_BASE, DWL_BUFFER_SIZE);
3459083fa11SPatrick Delaunay 	assert(ret == 0);
3469083fa11SPatrick Delaunay }
3479083fa11SPatrick Delaunay #endif
3489083fa11SPatrick Delaunay 
3499083fa11SPatrick Delaunay #if STM32MP_USB_PROGRAMMER
350fa92fef0SPatrick Delaunay static void stm32cubeprogrammer_usb(void)
351fa92fef0SPatrick Delaunay {
352fa92fef0SPatrick Delaunay 	int ret __unused;
353fa92fef0SPatrick Delaunay 	struct usb_handle *pdev;
354fa92fef0SPatrick Delaunay 
355fa92fef0SPatrick Delaunay 	/* Init USB on platform */
356fa92fef0SPatrick Delaunay 	pdev = usb_dfu_plat_init();
357fa92fef0SPatrick Delaunay 
358fa92fef0SPatrick Delaunay 	ret = stm32cubeprog_usb_load(pdev, DWL_BUFFER_BASE, DWL_BUFFER_SIZE);
359fa92fef0SPatrick Delaunay 	assert(ret == 0);
360fa92fef0SPatrick Delaunay }
361fa92fef0SPatrick Delaunay #endif
3629083fa11SPatrick Delaunay #endif /* STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER */
3639083fa11SPatrick Delaunay 
364fa92fef0SPatrick Delaunay 
3650b1aa772SYann Gautier void stm32mp_io_setup(void)
3660b1aa772SYann Gautier {
3670b1aa772SYann Gautier 	int io_result __unused;
3680b1aa772SYann Gautier 	boot_api_context_t *boot_context =
3690b1aa772SYann Gautier 		(boot_api_context_t *)stm32mp_get_boot_ctx_address();
3700b1aa772SYann Gautier 
3710b1aa772SYann Gautier 	print_boot_device(boot_context);
3720b1aa772SYann Gautier 
3730b1aa772SYann Gautier 	if ((boot_context->boot_partition_used_toboot == 1U) ||
3740b1aa772SYann Gautier 	    (boot_context->boot_partition_used_toboot == 2U)) {
3751d204ee4SYann Gautier 		INFO("Boot used partition fsbl%u\n",
3760b1aa772SYann Gautier 		     boot_context->boot_partition_used_toboot);
3770b1aa772SYann Gautier 	}
3780b1aa772SYann Gautier 
3791d204ee4SYann Gautier 	io_result = register_io_dev_fip(&fip_dev_con);
3800b1aa772SYann Gautier 	assert(io_result == 0);
3810b1aa772SYann Gautier 
3821d204ee4SYann Gautier 	io_result = io_dev_open(fip_dev_con, (uintptr_t)NULL,
3831d204ee4SYann Gautier 				&fip_dev_handle);
3840b1aa772SYann Gautier 
3850b1aa772SYann Gautier 	switch (boot_context->boot_interface_selected) {
38646554b64SNicolas Le Bayon #if STM32MP_SDMMC
3870b1aa772SYann Gautier 	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD:
3880b1aa772SYann Gautier 		dmbsy();
3890b1aa772SYann Gautier 		boot_mmc(MMC_IS_SD, boot_context->boot_interface_instance);
3900b1aa772SYann Gautier 		break;
39146554b64SNicolas Le Bayon #endif
39246554b64SNicolas Le Bayon #if STM32MP_EMMC
3930b1aa772SYann Gautier 	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC:
3940b1aa772SYann Gautier 		dmbsy();
3950b1aa772SYann Gautier 		boot_mmc(MMC_IS_EMMC, boot_context->boot_interface_instance);
396c9d75b3cSYann Gautier 		break;
39746554b64SNicolas Le Bayon #endif
398b1b218fbSLionel Debieve #if STM32MP_SPI_NOR
399b1b218fbSLionel Debieve 	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI:
400b1b218fbSLionel Debieve 		dmbsy();
401b1b218fbSLionel Debieve 		boot_spi_nor(boot_context);
402b1b218fbSLionel Debieve 		break;
403b1b218fbSLionel Debieve #endif
40412e21dfdSLionel Debieve #if STM32MP_RAW_NAND
40512e21dfdSLionel Debieve 	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC:
40612e21dfdSLionel Debieve 		dmbsy();
40712e21dfdSLionel Debieve 		boot_fmc2_nand(boot_context);
40812e21dfdSLionel Debieve 		break;
40912e21dfdSLionel Debieve #endif
41057044228SLionel Debieve #if STM32MP_SPI_NAND
41157044228SLionel Debieve 	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI:
41257044228SLionel Debieve 		dmbsy();
41357044228SLionel Debieve 		boot_spi_nand(boot_context);
41457044228SLionel Debieve 		break;
41557044228SLionel Debieve #endif
4169083fa11SPatrick Delaunay #if STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER
4179083fa11SPatrick Delaunay #if STM32MP_UART_PROGRAMMER
4189083fa11SPatrick Delaunay 	case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART:
4199083fa11SPatrick Delaunay #endif
420fa92fef0SPatrick Delaunay #if STM32MP_USB_PROGRAMMER
421fa92fef0SPatrick Delaunay 	case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB:
4229083fa11SPatrick Delaunay #endif
423fa92fef0SPatrick Delaunay 		dmbsy();
424fa92fef0SPatrick Delaunay 		mmap_io_setup();
425fa92fef0SPatrick Delaunay 		break;
426fa92fef0SPatrick Delaunay #endif
427c9d75b3cSYann Gautier 
428c9d75b3cSYann Gautier 	default:
429c9d75b3cSYann Gautier 		ERROR("Boot interface %d not supported\n",
430c9d75b3cSYann Gautier 		      boot_context->boot_interface_selected);
43171693a66SYann Gautier 		panic();
432c9d75b3cSYann Gautier 		break;
433c9d75b3cSYann Gautier 	}
434c9d75b3cSYann Gautier }
435c9d75b3cSYann Gautier 
4361d204ee4SYann Gautier int bl2_plat_handle_pre_image_load(unsigned int image_id)
4371d204ee4SYann Gautier {
4381d204ee4SYann Gautier 	static bool gpt_init_done __unused;
4391d204ee4SYann Gautier 	uint16_t boot_itf = stm32mp_get_boot_itf_selected();
4401d204ee4SYann Gautier 
4411d204ee4SYann Gautier 	switch (boot_itf) {
4421d204ee4SYann Gautier #if STM32MP_SDMMC || STM32MP_EMMC
4431d204ee4SYann Gautier 	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC:
44495e4908eSAhmad Fatoum #if STM32MP_EMMC_BOOT
44595e4908eSAhmad Fatoum 		if (image_block_spec.offset == STM32MP_EMMC_BOOT_FIP_OFFSET) {
44695e4908eSAhmad Fatoum 			break;
44795e4908eSAhmad Fatoum 		}
44895e4908eSAhmad Fatoum #endif
44995e4908eSAhmad Fatoum 		/* fallthrough */
45095e4908eSAhmad Fatoum 	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD:
4511d204ee4SYann Gautier 		if (!gpt_init_done) {
4528dd75531SSughosh Ganu /*
4538dd75531SSughosh Ganu  * With FWU Multi Bank feature enabled, the selection of
4548dd75531SSughosh Ganu  * the image to boot will be done by fwu_init calling the
4558dd75531SSughosh Ganu  * platform hook, plat_fwu_set_images_source.
4568dd75531SSughosh Ganu  */
4578dd75531SSughosh Ganu #if !PSA_FWU_SUPPORT
4581d204ee4SYann Gautier 			const partition_entry_t *entry;
4591dab28f9SLionel Debieve 			const struct efi_guid img_type_guid = STM32MP_FIP_GUID;
4601dab28f9SLionel Debieve 			uuid_t img_type_uuid;
4611d204ee4SYann Gautier 
4621dab28f9SLionel Debieve 			guidcpy(&img_type_uuid, &img_type_guid);
4631d204ee4SYann Gautier 			partition_init(GPT_IMAGE_ID);
4641dab28f9SLionel Debieve 			entry = get_partition_entry_by_type(&img_type_uuid);
4651dab28f9SLionel Debieve 			if (entry == NULL) {
4661d204ee4SYann Gautier 				entry = get_partition_entry(FIP_IMAGE_NAME);
4671d204ee4SYann Gautier 				if (entry == NULL) {
4681d204ee4SYann Gautier 					ERROR("Could NOT find the %s partition!\n",
4691d204ee4SYann Gautier 					      FIP_IMAGE_NAME);
4701dab28f9SLionel Debieve 
4711d204ee4SYann Gautier 					return -ENOENT;
4721d204ee4SYann Gautier 				}
4731dab28f9SLionel Debieve 			}
4741d204ee4SYann Gautier 
4751d204ee4SYann Gautier 			image_block_spec.offset = entry->start;
4761d204ee4SYann Gautier 			image_block_spec.length = entry->length;
4778dd75531SSughosh Ganu #endif
4781d204ee4SYann Gautier 			gpt_init_done = true;
47918b415beSYann Gautier 		} else {
48018b415beSYann Gautier 			bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
4812deff904SYann Gautier 			assert(bl_mem_params != NULL);
48218b415beSYann Gautier 
48318b415beSYann Gautier 			mmc_block_dev_spec.buffer.offset = bl_mem_params->image_info.image_base;
48418b415beSYann Gautier 			mmc_block_dev_spec.buffer.length = bl_mem_params->image_info.image_max_size;
4851d204ee4SYann Gautier 		}
4861d204ee4SYann Gautier 
4871d204ee4SYann Gautier 		break;
4881d204ee4SYann Gautier #endif
4891d204ee4SYann Gautier 
4901d204ee4SYann Gautier #if STM32MP_RAW_NAND || STM32MP_SPI_NAND
4911d204ee4SYann Gautier #if STM32MP_RAW_NAND
4921d204ee4SYann Gautier 	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC:
4931d204ee4SYann Gautier #endif
4941d204ee4SYann Gautier #if STM32MP_SPI_NAND
4951d204ee4SYann Gautier 	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI:
4961d204ee4SYann Gautier #endif
4971d204ee4SYann Gautier 		image_block_spec.offset = STM32MP_NAND_FIP_OFFSET;
4981d204ee4SYann Gautier 		break;
4991d204ee4SYann Gautier #endif
5001d204ee4SYann Gautier 
5011d204ee4SYann Gautier #if STM32MP_SPI_NOR
5021d204ee4SYann Gautier 	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI:
5031d204ee4SYann Gautier 		image_block_spec.offset = STM32MP_NOR_FIP_OFFSET;
5041d204ee4SYann Gautier 		break;
5051d204ee4SYann Gautier #endif
5061d204ee4SYann Gautier 
5079083fa11SPatrick Delaunay #if STM32MP_UART_PROGRAMMER
5089083fa11SPatrick Delaunay 	case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART:
5099083fa11SPatrick Delaunay 		if (image_id == FW_CONFIG_ID) {
5109083fa11SPatrick Delaunay 			stm32cubeprogrammer_uart();
5119083fa11SPatrick Delaunay 			/* FIP loaded at DWL address */
5129083fa11SPatrick Delaunay 			image_block_spec.offset = DWL_BUFFER_BASE;
5139083fa11SPatrick Delaunay 			image_block_spec.length = DWL_BUFFER_SIZE;
5149083fa11SPatrick Delaunay 		}
5159083fa11SPatrick Delaunay 		break;
5169083fa11SPatrick Delaunay #endif
517fa92fef0SPatrick Delaunay #if STM32MP_USB_PROGRAMMER
518fa92fef0SPatrick Delaunay 	case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB:
519fa92fef0SPatrick Delaunay 		if (image_id == FW_CONFIG_ID) {
520fa92fef0SPatrick Delaunay 			stm32cubeprogrammer_usb();
521fa92fef0SPatrick Delaunay 			/* FIP loaded at DWL address */
522fa92fef0SPatrick Delaunay 			image_block_spec.offset = DWL_BUFFER_BASE;
523fa92fef0SPatrick Delaunay 			image_block_spec.length = DWL_BUFFER_SIZE;
524fa92fef0SPatrick Delaunay 		}
525fa92fef0SPatrick Delaunay 		break;
526fa92fef0SPatrick Delaunay #endif
527fa92fef0SPatrick Delaunay 
5281d204ee4SYann Gautier 	default:
5291d204ee4SYann Gautier 		ERROR("FIP Not found\n");
5301d204ee4SYann Gautier 		panic();
5311d204ee4SYann Gautier 	}
5321d204ee4SYann Gautier 
5331d204ee4SYann Gautier 	return 0;
5341d204ee4SYann Gautier }
5351d204ee4SYann Gautier 
536c9d75b3cSYann Gautier /*
537c9d75b3cSYann Gautier  * Return an IO device handle and specification which can be used to access
538c9d75b3cSYann Gautier  * an image. Use this to enforce platform load policy.
539c9d75b3cSYann Gautier  */
540c9d75b3cSYann Gautier int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
541c9d75b3cSYann Gautier 			  uintptr_t *image_spec)
542c9d75b3cSYann Gautier {
543c9d75b3cSYann Gautier 	int rc;
544c9d75b3cSYann Gautier 	const struct plat_io_policy *policy;
545c9d75b3cSYann Gautier 
546d5a84eeaSYann Gautier 	policy = FCONF_GET_PROPERTY(stm32mp, io_policies, image_id);
547c9d75b3cSYann Gautier 	rc = policy->check(policy->image_spec);
548c9d75b3cSYann Gautier 	if (rc == 0) {
549c9d75b3cSYann Gautier 		*image_spec = policy->image_spec;
550c9d75b3cSYann Gautier 		*dev_handle = *(policy->dev_handle);
551c9d75b3cSYann Gautier 	}
552c9d75b3cSYann Gautier 
553c9d75b3cSYann Gautier 	return rc;
554c9d75b3cSYann Gautier }
5558dd75531SSughosh Ganu 
5568dd75531SSughosh Ganu #if (STM32MP_SDMMC || STM32MP_EMMC) && PSA_FWU_SUPPORT
5578dd75531SSughosh Ganu /*
558f87de907SNicolas Toromanoff  * In each boot in non-trial mode, we set the BKP register to
559f87de907SNicolas Toromanoff  * FWU_MAX_TRIAL_REBOOT, and return the active_index from metadata.
560f87de907SNicolas Toromanoff  *
561f87de907SNicolas Toromanoff  * As long as the update agent didn't update the "accepted" field in metadata
562f87de907SNicolas Toromanoff  * (i.e. we are in trial mode), we select the new active_index.
563f87de907SNicolas Toromanoff  * To avoid infinite boot loop at trial boot we decrement a BKP register.
564f87de907SNicolas Toromanoff  * If this counter is 0:
565f87de907SNicolas Toromanoff  *     - an unexpected TAMPER event raised (that resets the BKP registers to 0)
566f87de907SNicolas Toromanoff  *     - a power-off occurs before the update agent was able to update the
567f87de907SNicolas Toromanoff  *       "accepted' field
568f87de907SNicolas Toromanoff  *     - we already boot FWU_MAX_TRIAL_REBOOT times in trial mode.
569f87de907SNicolas Toromanoff  * we select the previous_active_index.
5708dd75531SSughosh Ganu  */
571f87de907SNicolas Toromanoff #define INVALID_BOOT_IDX		0xFFFFFFFF
572f87de907SNicolas Toromanoff 
5738dd75531SSughosh Ganu uint32_t plat_fwu_get_boot_idx(void)
5748dd75531SSughosh Ganu {
575f87de907SNicolas Toromanoff 	/*
576f87de907SNicolas Toromanoff 	 * Select boot index and update boot counter only once per boot
577f87de907SNicolas Toromanoff 	 * even if this function is called several times.
578f87de907SNicolas Toromanoff 	 */
579f87de907SNicolas Toromanoff 	static uint32_t boot_idx = INVALID_BOOT_IDX;
580f87de907SNicolas Toromanoff 	const struct fwu_metadata *data;
5818dd75531SSughosh Ganu 
582f87de907SNicolas Toromanoff 	data = fwu_get_metadata();
5838dd75531SSughosh Ganu 
584f87de907SNicolas Toromanoff 	if (boot_idx == INVALID_BOOT_IDX) {
585f87de907SNicolas Toromanoff 		boot_idx = data->active_index;
586f87de907SNicolas Toromanoff 		if (fwu_is_trial_run_state()) {
587f87de907SNicolas Toromanoff 			if (stm32_get_and_dec_fwu_trial_boot_cnt() == 0U) {
588f87de907SNicolas Toromanoff 				WARN("Trial FWU fails %u times\n",
589f87de907SNicolas Toromanoff 				     FWU_MAX_TRIAL_REBOOT);
590f87de907SNicolas Toromanoff 				boot_idx = data->previous_active_index;
591f87de907SNicolas Toromanoff 			}
592f87de907SNicolas Toromanoff 		} else {
593f87de907SNicolas Toromanoff 			stm32_set_max_fwu_trial_boot_cnt();
594f87de907SNicolas Toromanoff 		}
595f87de907SNicolas Toromanoff 	}
596f87de907SNicolas Toromanoff 
597f87de907SNicolas Toromanoff 	return boot_idx;
5988dd75531SSughosh Ganu }
5998dd75531SSughosh Ganu 
6008dd75531SSughosh Ganu static void *stm32_get_image_spec(const uuid_t *img_type_uuid)
6018dd75531SSughosh Ganu {
6028dd75531SSughosh Ganu 	unsigned int i;
6038dd75531SSughosh Ganu 
6048dd75531SSughosh Ganu 	for (i = 0U; i < MAX_NUMBER_IDS; i++) {
6058dd75531SSughosh Ganu 		if ((guidcmp(&policies[i].img_type_guid, img_type_uuid)) == 0) {
6068dd75531SSughosh Ganu 			return (void *)policies[i].image_spec;
6078dd75531SSughosh Ganu 		}
6088dd75531SSughosh Ganu 	}
6098dd75531SSughosh Ganu 
6108dd75531SSughosh Ganu 	return NULL;
6118dd75531SSughosh Ganu }
6128dd75531SSughosh Ganu 
6138dd75531SSughosh Ganu void plat_fwu_set_images_source(const struct fwu_metadata *metadata)
6148dd75531SSughosh Ganu {
6158dd75531SSughosh Ganu 	unsigned int i;
6168dd75531SSughosh Ganu 	uint32_t boot_idx;
6178dd75531SSughosh Ganu 	const partition_entry_t *entry;
6188dd75531SSughosh Ganu 	const uuid_t *img_type_uuid, *img_uuid;
6198dd75531SSughosh Ganu 	io_block_spec_t *image_spec;
6208dd75531SSughosh Ganu 
6218dd75531SSughosh Ganu 	boot_idx = plat_fwu_get_boot_idx();
6228dd75531SSughosh Ganu 	assert(boot_idx < NR_OF_FW_BANKS);
6238dd75531SSughosh Ganu 
6248dd75531SSughosh Ganu 	for (i = 0U; i < NR_OF_IMAGES_IN_FW_BANK; i++) {
6258dd75531SSughosh Ganu 		img_type_uuid = &metadata->img_entry[i].img_type_uuid;
6268dd75531SSughosh Ganu 		image_spec = stm32_get_image_spec(img_type_uuid);
6278dd75531SSughosh Ganu 		if (image_spec == NULL) {
6288dd75531SSughosh Ganu 			ERROR("Unable to get image spec for the image in the metadata\n");
6298dd75531SSughosh Ganu 			panic();
6308dd75531SSughosh Ganu 		}
6318dd75531SSughosh Ganu 
6328dd75531SSughosh Ganu 		img_uuid =
6338dd75531SSughosh Ganu 			&metadata->img_entry[i].img_props[boot_idx].img_uuid;
6348dd75531SSughosh Ganu 
6358dd75531SSughosh Ganu 		entry = get_partition_entry_by_uuid(img_uuid);
6368dd75531SSughosh Ganu 		if (entry == NULL) {
6378dd75531SSughosh Ganu 			ERROR("Unable to find the partition with the uuid mentioned in metadata\n");
6388dd75531SSughosh Ganu 			panic();
6398dd75531SSughosh Ganu 		}
6408dd75531SSughosh Ganu 
6418dd75531SSughosh Ganu 		image_spec->offset = entry->start;
6428dd75531SSughosh Ganu 		image_spec->length = entry->length;
6438dd75531SSughosh Ganu 	}
6448dd75531SSughosh Ganu }
6450ca180f6SSughosh Ganu 
6460ca180f6SSughosh Ganu static int plat_set_image_source(unsigned int image_id,
6470ca180f6SSughosh Ganu 				 uintptr_t *handle,
6480ca180f6SSughosh Ganu 				 uintptr_t *image_spec,
6490ca180f6SSughosh Ganu 				 const char *part_name)
6500ca180f6SSughosh Ganu {
6510ca180f6SSughosh Ganu 	struct plat_io_policy *policy;
6520ca180f6SSughosh Ganu 	io_block_spec_t *spec;
6530ca180f6SSughosh Ganu 	const partition_entry_t *entry = get_partition_entry(part_name);
6540ca180f6SSughosh Ganu 
6550ca180f6SSughosh Ganu 	if (entry == NULL) {
6560ca180f6SSughosh Ganu 		ERROR("Unable to find the %s partition\n", part_name);
6570ca180f6SSughosh Ganu 		return -ENOENT;
6580ca180f6SSughosh Ganu 	}
6590ca180f6SSughosh Ganu 
6600ca180f6SSughosh Ganu 	policy = &policies[image_id];
6610ca180f6SSughosh Ganu 
6620ca180f6SSughosh Ganu 	spec = (io_block_spec_t *)policy->image_spec;
6630ca180f6SSughosh Ganu 	spec->offset = entry->start;
6640ca180f6SSughosh Ganu 	spec->length = entry->length;
6650ca180f6SSughosh Ganu 
6660ca180f6SSughosh Ganu 	*image_spec = policy->image_spec;
6670ca180f6SSughosh Ganu 	*handle = *policy->dev_handle;
6680ca180f6SSughosh Ganu 
6690ca180f6SSughosh Ganu 	return 0;
6700ca180f6SSughosh Ganu }
6710ca180f6SSughosh Ganu 
6720ca180f6SSughosh Ganu int plat_fwu_set_metadata_image_source(unsigned int image_id,
6730ca180f6SSughosh Ganu 				       uintptr_t *handle,
6740ca180f6SSughosh Ganu 				       uintptr_t *image_spec)
6750ca180f6SSughosh Ganu {
6760ca180f6SSughosh Ganu 	char *part_name;
6770ca180f6SSughosh Ganu 
6780ca180f6SSughosh Ganu 	assert((image_id == FWU_METADATA_IMAGE_ID) ||
6790ca180f6SSughosh Ganu 	       (image_id == BKUP_FWU_METADATA_IMAGE_ID));
6800ca180f6SSughosh Ganu 
6810ca180f6SSughosh Ganu 	partition_init(GPT_IMAGE_ID);
6820ca180f6SSughosh Ganu 
6830ca180f6SSughosh Ganu 	if (image_id == FWU_METADATA_IMAGE_ID) {
6840ca180f6SSughosh Ganu 		part_name = METADATA_PART_1;
6850ca180f6SSughosh Ganu 	} else {
6860ca180f6SSughosh Ganu 		part_name = METADATA_PART_2;
6870ca180f6SSughosh Ganu 	}
6880ca180f6SSughosh Ganu 
6890ca180f6SSughosh Ganu 	return plat_set_image_source(image_id, handle, image_spec,
6900ca180f6SSughosh Ganu 				     part_name);
6910ca180f6SSughosh Ganu }
6928dd75531SSughosh Ganu #endif /* (STM32MP_SDMMC || STM32MP_EMMC) && PSA_FWU_SUPPORT */
693