xref: /rk3399_ARM-atf/plat/hisilicon/hikey960/hikey960_io_storage.c (revision 5e3325e73c0aca2934982cb10b881064d9b657f1)
12f2abcf4SHaojian Zhuang /*
22f2abcf4SHaojian Zhuang  * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
32f2abcf4SHaojian Zhuang  *
42f2abcf4SHaojian Zhuang  * SPDX-License-Identifier: BSD-3-Clause
52f2abcf4SHaojian Zhuang  */
62f2abcf4SHaojian Zhuang 
72f2abcf4SHaojian Zhuang #include <arch_helpers.h>
82f2abcf4SHaojian Zhuang #include <assert.h>
92f2abcf4SHaojian Zhuang #include <debug.h>
102f2abcf4SHaojian Zhuang #include <errno.h>
112f2abcf4SHaojian Zhuang #include <firmware_image_package.h>
122f2abcf4SHaojian Zhuang #include <io_block.h>
132f2abcf4SHaojian Zhuang #include <io_driver.h>
142f2abcf4SHaojian Zhuang #include <io_fip.h>
152f2abcf4SHaojian Zhuang #include <io_memmap.h>
162f2abcf4SHaojian Zhuang #include <io_storage.h>
172f2abcf4SHaojian Zhuang #include <mmio.h>
182f2abcf4SHaojian Zhuang #include <platform_def.h>
192f2abcf4SHaojian Zhuang #include <semihosting.h>	/* For FOPEN_MODE_... */
202f2abcf4SHaojian Zhuang #include <string.h>
212f2abcf4SHaojian Zhuang #include <ufs.h>
222f2abcf4SHaojian Zhuang 
232f2abcf4SHaojian Zhuang struct plat_io_policy {
242f2abcf4SHaojian Zhuang 	uintptr_t *dev_handle;
252f2abcf4SHaojian Zhuang 	uintptr_t image_spec;
262f2abcf4SHaojian Zhuang 	int (*check)(const uintptr_t spec);
272f2abcf4SHaojian Zhuang };
282f2abcf4SHaojian Zhuang 
292f2abcf4SHaojian Zhuang static const io_dev_connector_t *ufs_dev_con, *fip_dev_con;
302f2abcf4SHaojian Zhuang static uintptr_t ufs_dev_handle, fip_dev_handle;
312f2abcf4SHaojian Zhuang 
322f2abcf4SHaojian Zhuang static int check_ufs(const uintptr_t spec);
332f2abcf4SHaojian Zhuang static int check_fip(const uintptr_t spec);
342f2abcf4SHaojian Zhuang size_t ufs_read_lun3_blks(int lba, uintptr_t buf, size_t size);
352f2abcf4SHaojian Zhuang size_t ufs_write_lun3_blks(int lba, const uintptr_t buf, size_t size);
362f2abcf4SHaojian Zhuang 
372f2abcf4SHaojian Zhuang static const io_block_spec_t ufs_fip_spec = {
382f2abcf4SHaojian Zhuang 	.offset		= HIKEY960_FIP_BASE,
392f2abcf4SHaojian Zhuang 	.length		= HIKEY960_FIP_MAX_SIZE,
402f2abcf4SHaojian Zhuang };
412f2abcf4SHaojian Zhuang 
422f2abcf4SHaojian Zhuang static const io_block_spec_t ufs_data_spec = {
432f2abcf4SHaojian Zhuang 	.offset		= 0,
442f2abcf4SHaojian Zhuang 	.length		= 256 << 20,
452f2abcf4SHaojian Zhuang };
462f2abcf4SHaojian Zhuang 
472f2abcf4SHaojian Zhuang static const io_block_dev_spec_t ufs_dev_spec = {
482f2abcf4SHaojian Zhuang 	/* It's used as temp buffer in block driver. */
492f2abcf4SHaojian Zhuang 	.buffer		= {
502f2abcf4SHaojian Zhuang 		.offset	= HIKEY960_UFS_DATA_BASE,
512f2abcf4SHaojian Zhuang 		.length	= HIKEY960_UFS_DATA_SIZE,
522f2abcf4SHaojian Zhuang 	},
532f2abcf4SHaojian Zhuang 	.ops		= {
542f2abcf4SHaojian Zhuang 		.read	= ufs_read_lun3_blks,
552f2abcf4SHaojian Zhuang 		.write	= ufs_write_lun3_blks,
562f2abcf4SHaojian Zhuang 	},
572f2abcf4SHaojian Zhuang 	.block_size	= UFS_BLOCK_SIZE,
582f2abcf4SHaojian Zhuang };
592f2abcf4SHaojian Zhuang 
602f2abcf4SHaojian Zhuang static const io_uuid_spec_t bl2_uuid_spec = {
612f2abcf4SHaojian Zhuang 	.uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2,
622f2abcf4SHaojian Zhuang };
632f2abcf4SHaojian Zhuang 
642f2abcf4SHaojian Zhuang static const io_uuid_spec_t scp_bl2_uuid_spec = {
652f2abcf4SHaojian Zhuang 	.uuid = UUID_SCP_FIRMWARE_SCP_BL2,
662f2abcf4SHaojian Zhuang };
672f2abcf4SHaojian Zhuang 
682f2abcf4SHaojian Zhuang static const io_uuid_spec_t bl31_uuid_spec = {
692f2abcf4SHaojian Zhuang 	.uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31,
702f2abcf4SHaojian Zhuang };
712f2abcf4SHaojian Zhuang 
72*5e3325e7SVictor Chong static const io_uuid_spec_t bl32_uuid_spec = {
73*5e3325e7SVictor Chong 	.uuid = UUID_SECURE_PAYLOAD_BL32,
74*5e3325e7SVictor Chong };
75*5e3325e7SVictor Chong 
762f2abcf4SHaojian Zhuang static const io_uuid_spec_t bl33_uuid_spec = {
772f2abcf4SHaojian Zhuang 	.uuid = UUID_NON_TRUSTED_FIRMWARE_BL33,
782f2abcf4SHaojian Zhuang };
792f2abcf4SHaojian Zhuang 
802f2abcf4SHaojian Zhuang static const struct plat_io_policy policies[] = {
812f2abcf4SHaojian Zhuang 	[FIP_IMAGE_ID] = {
822f2abcf4SHaojian Zhuang 		&ufs_dev_handle,
832f2abcf4SHaojian Zhuang 		(uintptr_t)&ufs_fip_spec,
842f2abcf4SHaojian Zhuang 		check_ufs
852f2abcf4SHaojian Zhuang 	},
862f2abcf4SHaojian Zhuang 	[BL2_IMAGE_ID] = {
872f2abcf4SHaojian Zhuang 		&fip_dev_handle,
882f2abcf4SHaojian Zhuang 		(uintptr_t)&bl2_uuid_spec,
892f2abcf4SHaojian Zhuang 		check_fip
902f2abcf4SHaojian Zhuang 	},
912f2abcf4SHaojian Zhuang 	[SCP_BL2_IMAGE_ID] = {
922f2abcf4SHaojian Zhuang 		&fip_dev_handle,
932f2abcf4SHaojian Zhuang 		(uintptr_t)&scp_bl2_uuid_spec,
942f2abcf4SHaojian Zhuang 		check_fip
952f2abcf4SHaojian Zhuang 	},
962f2abcf4SHaojian Zhuang 	[BL31_IMAGE_ID] = {
972f2abcf4SHaojian Zhuang 		&fip_dev_handle,
982f2abcf4SHaojian Zhuang 		(uintptr_t)&bl31_uuid_spec,
992f2abcf4SHaojian Zhuang 		check_fip
1002f2abcf4SHaojian Zhuang 	},
101*5e3325e7SVictor Chong 	[BL32_IMAGE_ID] = {
102*5e3325e7SVictor Chong 		&fip_dev_handle,
103*5e3325e7SVictor Chong 		(uintptr_t)&bl32_uuid_spec,
104*5e3325e7SVictor Chong 		check_fip
105*5e3325e7SVictor Chong 	},
1062f2abcf4SHaojian Zhuang 	[BL33_IMAGE_ID] = {
1072f2abcf4SHaojian Zhuang 		&fip_dev_handle,
1082f2abcf4SHaojian Zhuang 		(uintptr_t)&bl33_uuid_spec,
1092f2abcf4SHaojian Zhuang 		check_fip
1102f2abcf4SHaojian Zhuang 	},
1112f2abcf4SHaojian Zhuang 	[BL2U_IMAGE_ID] = {
1122f2abcf4SHaojian Zhuang 		&ufs_dev_handle,
1132f2abcf4SHaojian Zhuang 		(uintptr_t)&ufs_data_spec,
1142f2abcf4SHaojian Zhuang 		check_ufs
1152f2abcf4SHaojian Zhuang 	}
1162f2abcf4SHaojian Zhuang };
1172f2abcf4SHaojian Zhuang 
1182f2abcf4SHaojian Zhuang static int check_ufs(const uintptr_t spec)
1192f2abcf4SHaojian Zhuang {
1202f2abcf4SHaojian Zhuang 	int result;
1212f2abcf4SHaojian Zhuang 	uintptr_t local_handle;
1222f2abcf4SHaojian Zhuang 
1232f2abcf4SHaojian Zhuang 	result = io_dev_init(ufs_dev_handle, (uintptr_t)NULL);
1242f2abcf4SHaojian Zhuang 	if (result == 0) {
1252f2abcf4SHaojian Zhuang 		result = io_open(ufs_dev_handle, spec, &local_handle);
1262f2abcf4SHaojian Zhuang 		if (result == 0)
1272f2abcf4SHaojian Zhuang 			io_close(local_handle);
1282f2abcf4SHaojian Zhuang 	}
1292f2abcf4SHaojian Zhuang 	return result;
1302f2abcf4SHaojian Zhuang }
1312f2abcf4SHaojian Zhuang 
1322f2abcf4SHaojian Zhuang static int check_fip(const uintptr_t spec)
1332f2abcf4SHaojian Zhuang {
1342f2abcf4SHaojian Zhuang 	int result;
1352f2abcf4SHaojian Zhuang 	uintptr_t local_image_handle;
1362f2abcf4SHaojian Zhuang 
1372f2abcf4SHaojian Zhuang 	/* See if a Firmware Image Package is available */
1382f2abcf4SHaojian Zhuang 	result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID);
1392f2abcf4SHaojian Zhuang 	if (result == 0) {
1402f2abcf4SHaojian Zhuang 		result = io_open(fip_dev_handle, spec, &local_image_handle);
1412f2abcf4SHaojian Zhuang 		if (result == 0) {
1422f2abcf4SHaojian Zhuang 			VERBOSE("Using FIP\n");
1432f2abcf4SHaojian Zhuang 			io_close(local_image_handle);
1442f2abcf4SHaojian Zhuang 		}
1452f2abcf4SHaojian Zhuang 	}
1462f2abcf4SHaojian Zhuang 	return result;
1472f2abcf4SHaojian Zhuang }
1482f2abcf4SHaojian Zhuang 
1492f2abcf4SHaojian Zhuang void hikey960_io_setup(void)
1502f2abcf4SHaojian Zhuang {
1512f2abcf4SHaojian Zhuang 	int result;
1522f2abcf4SHaojian Zhuang 
1532f2abcf4SHaojian Zhuang 	result = register_io_dev_block(&ufs_dev_con);
1542f2abcf4SHaojian Zhuang 	assert(result == 0);
1552f2abcf4SHaojian Zhuang 
1562f2abcf4SHaojian Zhuang 	result = register_io_dev_fip(&fip_dev_con);
1572f2abcf4SHaojian Zhuang 	assert(result == 0);
1582f2abcf4SHaojian Zhuang 
1592f2abcf4SHaojian Zhuang 	result = io_dev_open(ufs_dev_con, (uintptr_t)&ufs_dev_spec,
1602f2abcf4SHaojian Zhuang 			     &ufs_dev_handle);
1612f2abcf4SHaojian Zhuang 	assert(result == 0);
1622f2abcf4SHaojian Zhuang 
1632f2abcf4SHaojian Zhuang 	result = io_dev_open(fip_dev_con, (uintptr_t)NULL, &fip_dev_handle);
1642f2abcf4SHaojian Zhuang 	assert(result == 0);
1652f2abcf4SHaojian Zhuang 
1662f2abcf4SHaojian Zhuang 	/* Ignore improbable errors in release builds */
1672f2abcf4SHaojian Zhuang 	(void)result;
1682f2abcf4SHaojian Zhuang }
1692f2abcf4SHaojian Zhuang 
1702f2abcf4SHaojian Zhuang /* Return an IO device handle and specification which can be used to access
1712f2abcf4SHaojian Zhuang  * an image. Use this to enforce platform load policy
1722f2abcf4SHaojian Zhuang  */
1732f2abcf4SHaojian Zhuang int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
1742f2abcf4SHaojian Zhuang 			  uintptr_t *image_spec)
1752f2abcf4SHaojian Zhuang {
1762f2abcf4SHaojian Zhuang 	int result;
1772f2abcf4SHaojian Zhuang 	const struct plat_io_policy *policy;
1782f2abcf4SHaojian Zhuang 
1792f2abcf4SHaojian Zhuang 	assert(image_id < ARRAY_SIZE(policies));
1802f2abcf4SHaojian Zhuang 
1812f2abcf4SHaojian Zhuang 	policy = &policies[image_id];
1822f2abcf4SHaojian Zhuang 	result = policy->check(policy->image_spec);
1832f2abcf4SHaojian Zhuang 	assert(result == 0);
1842f2abcf4SHaojian Zhuang 
1852f2abcf4SHaojian Zhuang 	*image_spec = policy->image_spec;
1862f2abcf4SHaojian Zhuang 	*dev_handle = *(policy->dev_handle);
1872f2abcf4SHaojian Zhuang 
1882f2abcf4SHaojian Zhuang 	return result;
1892f2abcf4SHaojian Zhuang }
1902f2abcf4SHaojian Zhuang 
1912f2abcf4SHaojian Zhuang size_t ufs_read_lun3_blks(int lba, uintptr_t buf, size_t size)
1922f2abcf4SHaojian Zhuang {
1932f2abcf4SHaojian Zhuang 	return ufs_read_blocks(3, lba, buf, size);
1942f2abcf4SHaojian Zhuang }
1952f2abcf4SHaojian Zhuang 
1962f2abcf4SHaojian Zhuang size_t ufs_write_lun3_blks(int lba, const uintptr_t buf, size_t size)
1972f2abcf4SHaojian Zhuang {
1982f2abcf4SHaojian Zhuang 	return ufs_write_blocks(3, lba, buf, size);
1992f2abcf4SHaojian Zhuang }
200