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