blob: 57d97e599e66edbc19e8021330e814a4473bb195 [file] [log] [blame]
Haojian Zhuang602362d2017-06-01 12:15:14 +08001/*
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
23struct plat_io_policy {
24 uintptr_t *dev_handle;
25 uintptr_t image_spec;
26 int (*check)(const uintptr_t spec);
27};
28
29static const io_dev_connector_t *ufs_dev_con, *fip_dev_con;
30static uintptr_t ufs_dev_handle, fip_dev_handle;
31
32static int check_ufs(const uintptr_t spec);
33static int check_fip(const uintptr_t spec);
34size_t ufs_read_lun3_blks(int lba, uintptr_t buf, size_t size);
35size_t ufs_write_lun3_blks(int lba, const uintptr_t buf, size_t size);
36
37static const io_block_spec_t ufs_fip_spec = {
38 .offset = HIKEY960_FIP_BASE,
39 .length = HIKEY960_FIP_MAX_SIZE,
40};
41
42static const io_block_spec_t ufs_data_spec = {
43 .offset = 0,
44 .length = 256 << 20,
45};
46
47static 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
60static const io_uuid_spec_t bl2_uuid_spec = {
61 .uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2,
62};
63
64static const io_uuid_spec_t scp_bl2_uuid_spec = {
65 .uuid = UUID_SCP_FIRMWARE_SCP_BL2,
66};
67
68static const io_uuid_spec_t bl31_uuid_spec = {
69 .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31,
70};
71
Victor Chong91287682017-05-28 00:14:37 +090072static const io_uuid_spec_t bl32_uuid_spec = {
73 .uuid = UUID_SECURE_PAYLOAD_BL32,
74};
75
Haojian Zhuang602362d2017-06-01 12:15:14 +080076static const io_uuid_spec_t bl33_uuid_spec = {
77 .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33,
78};
79
80static 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 },
Victor Chong91287682017-05-28 00:14:37 +0900101 [BL32_IMAGE_ID] = {
102 &fip_dev_handle,
103 (uintptr_t)&bl32_uuid_spec,
104 check_fip
105 },
Haojian Zhuang602362d2017-06-01 12:15:14 +0800106 [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
118static 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
132static 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
149void 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 */
173int 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
191size_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
196size_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}