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