xref: /rk3399_ARM-atf/plat/hisilicon/hikey960/hikey960_io_storage.c (revision 2f2abcf4ba37bdd1332111c240961aae509c5d9c)
1*2f2abcf4SHaojian Zhuang /*
2*2f2abcf4SHaojian Zhuang  * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
3*2f2abcf4SHaojian Zhuang  *
4*2f2abcf4SHaojian Zhuang  * SPDX-License-Identifier: BSD-3-Clause
5*2f2abcf4SHaojian Zhuang  */
6*2f2abcf4SHaojian Zhuang 
7*2f2abcf4SHaojian Zhuang #include <arch_helpers.h>
8*2f2abcf4SHaojian Zhuang #include <assert.h>
9*2f2abcf4SHaojian Zhuang #include <debug.h>
10*2f2abcf4SHaojian Zhuang #include <errno.h>
11*2f2abcf4SHaojian Zhuang #include <firmware_image_package.h>
12*2f2abcf4SHaojian Zhuang #include <io_block.h>
13*2f2abcf4SHaojian Zhuang #include <io_driver.h>
14*2f2abcf4SHaojian Zhuang #include <io_fip.h>
15*2f2abcf4SHaojian Zhuang #include <io_memmap.h>
16*2f2abcf4SHaojian Zhuang #include <io_storage.h>
17*2f2abcf4SHaojian Zhuang #include <mmio.h>
18*2f2abcf4SHaojian Zhuang #include <platform_def.h>
19*2f2abcf4SHaojian Zhuang #include <semihosting.h>	/* For FOPEN_MODE_... */
20*2f2abcf4SHaojian Zhuang #include <string.h>
21*2f2abcf4SHaojian Zhuang #include <ufs.h>
22*2f2abcf4SHaojian Zhuang 
23*2f2abcf4SHaojian Zhuang struct plat_io_policy {
24*2f2abcf4SHaojian Zhuang 	uintptr_t *dev_handle;
25*2f2abcf4SHaojian Zhuang 	uintptr_t image_spec;
26*2f2abcf4SHaojian Zhuang 	int (*check)(const uintptr_t spec);
27*2f2abcf4SHaojian Zhuang };
28*2f2abcf4SHaojian Zhuang 
29*2f2abcf4SHaojian Zhuang static const io_dev_connector_t *ufs_dev_con, *fip_dev_con;
30*2f2abcf4SHaojian Zhuang static uintptr_t ufs_dev_handle, fip_dev_handle;
31*2f2abcf4SHaojian Zhuang 
32*2f2abcf4SHaojian Zhuang static int check_ufs(const uintptr_t spec);
33*2f2abcf4SHaojian Zhuang static int check_fip(const uintptr_t spec);
34*2f2abcf4SHaojian Zhuang size_t ufs_read_lun3_blks(int lba, uintptr_t buf, size_t size);
35*2f2abcf4SHaojian Zhuang size_t ufs_write_lun3_blks(int lba, const uintptr_t buf, size_t size);
36*2f2abcf4SHaojian Zhuang 
37*2f2abcf4SHaojian Zhuang static const io_block_spec_t ufs_fip_spec = {
38*2f2abcf4SHaojian Zhuang 	.offset		= HIKEY960_FIP_BASE,
39*2f2abcf4SHaojian Zhuang 	.length		= HIKEY960_FIP_MAX_SIZE,
40*2f2abcf4SHaojian Zhuang };
41*2f2abcf4SHaojian Zhuang 
42*2f2abcf4SHaojian Zhuang static const io_block_spec_t ufs_data_spec = {
43*2f2abcf4SHaojian Zhuang 	.offset		= 0,
44*2f2abcf4SHaojian Zhuang 	.length		= 256 << 20,
45*2f2abcf4SHaojian Zhuang };
46*2f2abcf4SHaojian Zhuang 
47*2f2abcf4SHaojian Zhuang static const io_block_dev_spec_t ufs_dev_spec = {
48*2f2abcf4SHaojian Zhuang 	/* It's used as temp buffer in block driver. */
49*2f2abcf4SHaojian Zhuang 	.buffer		= {
50*2f2abcf4SHaojian Zhuang 		.offset	= HIKEY960_UFS_DATA_BASE,
51*2f2abcf4SHaojian Zhuang 		.length	= HIKEY960_UFS_DATA_SIZE,
52*2f2abcf4SHaojian Zhuang 	},
53*2f2abcf4SHaojian Zhuang 	.ops		= {
54*2f2abcf4SHaojian Zhuang 		.read	= ufs_read_lun3_blks,
55*2f2abcf4SHaojian Zhuang 		.write	= ufs_write_lun3_blks,
56*2f2abcf4SHaojian Zhuang 	},
57*2f2abcf4SHaojian Zhuang 	.block_size	= UFS_BLOCK_SIZE,
58*2f2abcf4SHaojian Zhuang };
59*2f2abcf4SHaojian Zhuang 
60*2f2abcf4SHaojian Zhuang static const io_uuid_spec_t bl2_uuid_spec = {
61*2f2abcf4SHaojian Zhuang 	.uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2,
62*2f2abcf4SHaojian Zhuang };
63*2f2abcf4SHaojian Zhuang 
64*2f2abcf4SHaojian Zhuang static const io_uuid_spec_t scp_bl2_uuid_spec = {
65*2f2abcf4SHaojian Zhuang 	.uuid = UUID_SCP_FIRMWARE_SCP_BL2,
66*2f2abcf4SHaojian Zhuang };
67*2f2abcf4SHaojian Zhuang 
68*2f2abcf4SHaojian Zhuang static const io_uuid_spec_t bl31_uuid_spec = {
69*2f2abcf4SHaojian Zhuang 	.uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31,
70*2f2abcf4SHaojian Zhuang };
71*2f2abcf4SHaojian Zhuang 
72*2f2abcf4SHaojian Zhuang static const io_uuid_spec_t bl33_uuid_spec = {
73*2f2abcf4SHaojian Zhuang 	.uuid = UUID_NON_TRUSTED_FIRMWARE_BL33,
74*2f2abcf4SHaojian Zhuang };
75*2f2abcf4SHaojian Zhuang 
76*2f2abcf4SHaojian Zhuang static const struct plat_io_policy policies[] = {
77*2f2abcf4SHaojian Zhuang 	[FIP_IMAGE_ID] = {
78*2f2abcf4SHaojian Zhuang 		&ufs_dev_handle,
79*2f2abcf4SHaojian Zhuang 		(uintptr_t)&ufs_fip_spec,
80*2f2abcf4SHaojian Zhuang 		check_ufs
81*2f2abcf4SHaojian Zhuang 	},
82*2f2abcf4SHaojian Zhuang 	[BL2_IMAGE_ID] = {
83*2f2abcf4SHaojian Zhuang 		&fip_dev_handle,
84*2f2abcf4SHaojian Zhuang 		(uintptr_t)&bl2_uuid_spec,
85*2f2abcf4SHaojian Zhuang 		check_fip
86*2f2abcf4SHaojian Zhuang 	},
87*2f2abcf4SHaojian Zhuang 	[SCP_BL2_IMAGE_ID] = {
88*2f2abcf4SHaojian Zhuang 		&fip_dev_handle,
89*2f2abcf4SHaojian Zhuang 		(uintptr_t)&scp_bl2_uuid_spec,
90*2f2abcf4SHaojian Zhuang 		check_fip
91*2f2abcf4SHaojian Zhuang 	},
92*2f2abcf4SHaojian Zhuang 	[BL31_IMAGE_ID] = {
93*2f2abcf4SHaojian Zhuang 		&fip_dev_handle,
94*2f2abcf4SHaojian Zhuang 		(uintptr_t)&bl31_uuid_spec,
95*2f2abcf4SHaojian Zhuang 		check_fip
96*2f2abcf4SHaojian Zhuang 	},
97*2f2abcf4SHaojian Zhuang 	[BL33_IMAGE_ID] = {
98*2f2abcf4SHaojian Zhuang 		&fip_dev_handle,
99*2f2abcf4SHaojian Zhuang 		(uintptr_t)&bl33_uuid_spec,
100*2f2abcf4SHaojian Zhuang 		check_fip
101*2f2abcf4SHaojian Zhuang 	},
102*2f2abcf4SHaojian Zhuang 	[BL2U_IMAGE_ID] = {
103*2f2abcf4SHaojian Zhuang 		&ufs_dev_handle,
104*2f2abcf4SHaojian Zhuang 		(uintptr_t)&ufs_data_spec,
105*2f2abcf4SHaojian Zhuang 		check_ufs
106*2f2abcf4SHaojian Zhuang 	}
107*2f2abcf4SHaojian Zhuang };
108*2f2abcf4SHaojian Zhuang 
109*2f2abcf4SHaojian Zhuang static int check_ufs(const uintptr_t spec)
110*2f2abcf4SHaojian Zhuang {
111*2f2abcf4SHaojian Zhuang 	int result;
112*2f2abcf4SHaojian Zhuang 	uintptr_t local_handle;
113*2f2abcf4SHaojian Zhuang 
114*2f2abcf4SHaojian Zhuang 	result = io_dev_init(ufs_dev_handle, (uintptr_t)NULL);
115*2f2abcf4SHaojian Zhuang 	if (result == 0) {
116*2f2abcf4SHaojian Zhuang 		result = io_open(ufs_dev_handle, spec, &local_handle);
117*2f2abcf4SHaojian Zhuang 		if (result == 0)
118*2f2abcf4SHaojian Zhuang 			io_close(local_handle);
119*2f2abcf4SHaojian Zhuang 	}
120*2f2abcf4SHaojian Zhuang 	return result;
121*2f2abcf4SHaojian Zhuang }
122*2f2abcf4SHaojian Zhuang 
123*2f2abcf4SHaojian Zhuang static int check_fip(const uintptr_t spec)
124*2f2abcf4SHaojian Zhuang {
125*2f2abcf4SHaojian Zhuang 	int result;
126*2f2abcf4SHaojian Zhuang 	uintptr_t local_image_handle;
127*2f2abcf4SHaojian Zhuang 
128*2f2abcf4SHaojian Zhuang 	/* See if a Firmware Image Package is available */
129*2f2abcf4SHaojian Zhuang 	result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID);
130*2f2abcf4SHaojian Zhuang 	if (result == 0) {
131*2f2abcf4SHaojian Zhuang 		result = io_open(fip_dev_handle, spec, &local_image_handle);
132*2f2abcf4SHaojian Zhuang 		if (result == 0) {
133*2f2abcf4SHaojian Zhuang 			VERBOSE("Using FIP\n");
134*2f2abcf4SHaojian Zhuang 			io_close(local_image_handle);
135*2f2abcf4SHaojian Zhuang 		}
136*2f2abcf4SHaojian Zhuang 	}
137*2f2abcf4SHaojian Zhuang 	return result;
138*2f2abcf4SHaojian Zhuang }
139*2f2abcf4SHaojian Zhuang 
140*2f2abcf4SHaojian Zhuang void hikey960_io_setup(void)
141*2f2abcf4SHaojian Zhuang {
142*2f2abcf4SHaojian Zhuang 	int result;
143*2f2abcf4SHaojian Zhuang 
144*2f2abcf4SHaojian Zhuang 	result = register_io_dev_block(&ufs_dev_con);
145*2f2abcf4SHaojian Zhuang 	assert(result == 0);
146*2f2abcf4SHaojian Zhuang 
147*2f2abcf4SHaojian Zhuang 	result = register_io_dev_fip(&fip_dev_con);
148*2f2abcf4SHaojian Zhuang 	assert(result == 0);
149*2f2abcf4SHaojian Zhuang 
150*2f2abcf4SHaojian Zhuang 	result = io_dev_open(ufs_dev_con, (uintptr_t)&ufs_dev_spec,
151*2f2abcf4SHaojian Zhuang 			     &ufs_dev_handle);
152*2f2abcf4SHaojian Zhuang 	assert(result == 0);
153*2f2abcf4SHaojian Zhuang 
154*2f2abcf4SHaojian Zhuang 	result = io_dev_open(fip_dev_con, (uintptr_t)NULL, &fip_dev_handle);
155*2f2abcf4SHaojian Zhuang 	assert(result == 0);
156*2f2abcf4SHaojian Zhuang 
157*2f2abcf4SHaojian Zhuang 	/* Ignore improbable errors in release builds */
158*2f2abcf4SHaojian Zhuang 	(void)result;
159*2f2abcf4SHaojian Zhuang }
160*2f2abcf4SHaojian Zhuang 
161*2f2abcf4SHaojian Zhuang /* Return an IO device handle and specification which can be used to access
162*2f2abcf4SHaojian Zhuang  * an image. Use this to enforce platform load policy
163*2f2abcf4SHaojian Zhuang  */
164*2f2abcf4SHaojian Zhuang int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
165*2f2abcf4SHaojian Zhuang 			  uintptr_t *image_spec)
166*2f2abcf4SHaojian Zhuang {
167*2f2abcf4SHaojian Zhuang 	int result;
168*2f2abcf4SHaojian Zhuang 	const struct plat_io_policy *policy;
169*2f2abcf4SHaojian Zhuang 
170*2f2abcf4SHaojian Zhuang 	assert(image_id < ARRAY_SIZE(policies));
171*2f2abcf4SHaojian Zhuang 
172*2f2abcf4SHaojian Zhuang 	policy = &policies[image_id];
173*2f2abcf4SHaojian Zhuang 	result = policy->check(policy->image_spec);
174*2f2abcf4SHaojian Zhuang 	assert(result == 0);
175*2f2abcf4SHaojian Zhuang 
176*2f2abcf4SHaojian Zhuang 	*image_spec = policy->image_spec;
177*2f2abcf4SHaojian Zhuang 	*dev_handle = *(policy->dev_handle);
178*2f2abcf4SHaojian Zhuang 
179*2f2abcf4SHaojian Zhuang 	return result;
180*2f2abcf4SHaojian Zhuang }
181*2f2abcf4SHaojian Zhuang 
182*2f2abcf4SHaojian Zhuang size_t ufs_read_lun3_blks(int lba, uintptr_t buf, size_t size)
183*2f2abcf4SHaojian Zhuang {
184*2f2abcf4SHaojian Zhuang 	return ufs_read_blocks(3, lba, buf, size);
185*2f2abcf4SHaojian Zhuang }
186*2f2abcf4SHaojian Zhuang 
187*2f2abcf4SHaojian Zhuang size_t ufs_write_lun3_blks(int lba, const uintptr_t buf, size_t size)
188*2f2abcf4SHaojian Zhuang {
189*2f2abcf4SHaojian Zhuang 	return ufs_write_blocks(3, lba, buf, size);
190*2f2abcf4SHaojian Zhuang }
191