xref: /rk3399_ARM-atf/plat/hisilicon/hikey960/hikey960_io_storage.c (revision 6311f63de02ee04d93016242977ade4727089de8)
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 bl33_uuid_spec = {
73 	.uuid = UUID_NON_TRUSTED_FIRMWARE_BL33,
74 };
75 
76 static const struct plat_io_policy policies[] = {
77 	[FIP_IMAGE_ID] = {
78 		&ufs_dev_handle,
79 		(uintptr_t)&ufs_fip_spec,
80 		check_ufs
81 	},
82 	[BL2_IMAGE_ID] = {
83 		&fip_dev_handle,
84 		(uintptr_t)&bl2_uuid_spec,
85 		check_fip
86 	},
87 	[SCP_BL2_IMAGE_ID] = {
88 		&fip_dev_handle,
89 		(uintptr_t)&scp_bl2_uuid_spec,
90 		check_fip
91 	},
92 	[BL31_IMAGE_ID] = {
93 		&fip_dev_handle,
94 		(uintptr_t)&bl31_uuid_spec,
95 		check_fip
96 	},
97 	[BL33_IMAGE_ID] = {
98 		&fip_dev_handle,
99 		(uintptr_t)&bl33_uuid_spec,
100 		check_fip
101 	},
102 	[BL2U_IMAGE_ID] = {
103 		&ufs_dev_handle,
104 		(uintptr_t)&ufs_data_spec,
105 		check_ufs
106 	}
107 };
108 
109 static int check_ufs(const uintptr_t spec)
110 {
111 	int result;
112 	uintptr_t local_handle;
113 
114 	result = io_dev_init(ufs_dev_handle, (uintptr_t)NULL);
115 	if (result == 0) {
116 		result = io_open(ufs_dev_handle, spec, &local_handle);
117 		if (result == 0)
118 			io_close(local_handle);
119 	}
120 	return result;
121 }
122 
123 static int check_fip(const uintptr_t spec)
124 {
125 	int result;
126 	uintptr_t local_image_handle;
127 
128 	/* See if a Firmware Image Package is available */
129 	result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID);
130 	if (result == 0) {
131 		result = io_open(fip_dev_handle, spec, &local_image_handle);
132 		if (result == 0) {
133 			VERBOSE("Using FIP\n");
134 			io_close(local_image_handle);
135 		}
136 	}
137 	return result;
138 }
139 
140 void hikey960_io_setup(void)
141 {
142 	int result;
143 
144 	result = register_io_dev_block(&ufs_dev_con);
145 	assert(result == 0);
146 
147 	result = register_io_dev_fip(&fip_dev_con);
148 	assert(result == 0);
149 
150 	result = io_dev_open(ufs_dev_con, (uintptr_t)&ufs_dev_spec,
151 			     &ufs_dev_handle);
152 	assert(result == 0);
153 
154 	result = io_dev_open(fip_dev_con, (uintptr_t)NULL, &fip_dev_handle);
155 	assert(result == 0);
156 
157 	/* Ignore improbable errors in release builds */
158 	(void)result;
159 }
160 
161 /* Return an IO device handle and specification which can be used to access
162  * an image. Use this to enforce platform load policy
163  */
164 int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
165 			  uintptr_t *image_spec)
166 {
167 	int result;
168 	const struct plat_io_policy *policy;
169 
170 	assert(image_id < ARRAY_SIZE(policies));
171 
172 	policy = &policies[image_id];
173 	result = policy->check(policy->image_spec);
174 	assert(result == 0);
175 
176 	*image_spec = policy->image_spec;
177 	*dev_handle = *(policy->dev_handle);
178 
179 	return result;
180 }
181 
182 size_t ufs_read_lun3_blks(int lba, uintptr_t buf, size_t size)
183 {
184 	return ufs_read_blocks(3, lba, buf, size);
185 }
186 
187 size_t ufs_write_lun3_blks(int lba, const uintptr_t buf, size_t size)
188 {
189 	return ufs_write_blocks(3, lba, buf, size);
190 }
191