blob: ea2f2bade00a47d0eb61e650be847ab0cde177fb [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Sergey Temerkhanov62dce242015-10-14 09:55:51 -07002/**
3 * (C) Copyright 2014, Cavium Inc.
Sergey Temerkhanov62dce242015-10-14 09:55:51 -07004**/
5
6#include <common.h>
Simon Glass274e0b02020-05-10 11:39:56 -06007#include <asm/cache.h>
Sergey Temerkhanov62dce242015-10-14 09:55:51 -07008#include <asm/io.h>
9
10#include <asm/system.h>
11#include <cavium/thunderx_svc.h>
12#include <cavium/atf.h>
13#include <cavium/atf_part.h>
14
15#include <asm/psci.h>
16
17#include <malloc.h>
18
Sergey Temerkhanov62dce242015-10-14 09:55:51 -070019ssize_t atf_read_mmc(uintptr_t offset, void *buffer, size_t size)
20{
21 struct pt_regs regs;
22 regs.regs[0] = THUNDERX_MMC_READ;
23 regs.regs[1] = offset;
24 regs.regs[2] = size;
25 regs.regs[3] = (uintptr_t)buffer;
26
27 smc_call(&regs);
28
29 return regs.regs[0];
30}
31
32ssize_t atf_read_nor(uintptr_t offset, void *buffer, size_t size)
33{
34 struct pt_regs regs;
35 regs.regs[0] = THUNDERX_NOR_READ;
36 regs.regs[1] = offset;
37 regs.regs[2] = size;
38 regs.regs[3] = (uintptr_t)buffer;
39
40 smc_call(&regs);
41
42 return regs.regs[0];
43}
44
45ssize_t atf_get_pcount(void)
46{
47 struct pt_regs regs;
48 regs.regs[0] = THUNDERX_PART_COUNT;
49
50 smc_call(&regs);
51
52 return regs.regs[0];
53}
54
55ssize_t atf_get_part(struct storage_partition *part, unsigned int index)
56{
57 struct pt_regs regs;
58 regs.regs[0] = THUNDERX_GET_PART;
59 regs.regs[1] = (uintptr_t)part;
60 regs.regs[2] = index;
61
62 smc_call(&regs);
63
64 return regs.regs[0];
65}
66
67ssize_t atf_erase_nor(uintptr_t offset, size_t size)
68{
69 struct pt_regs regs;
70
71 regs.regs[0] = THUNDERX_NOR_ERASE;
72 regs.regs[1] = offset;
73
74 smc_call(&regs);
75
76 return regs.regs[0];
77}
78
79ssize_t atf_write_nor(uintptr_t offset, const void *buffer, size_t size)
80{
81 struct pt_regs regs;
82
83 regs.regs[0] = THUNDERX_NOR_WRITE;
84 regs.regs[1] = offset;
85 regs.regs[2] = size;
86 regs.regs[3] = (uintptr_t)buffer;
87
88 smc_call(&regs);
89
90 return regs.regs[0];
91}
92
93ssize_t atf_write_mmc(uintptr_t offset, const void *buffer, size_t size)
94{
95 struct pt_regs regs;
96
97 regs.regs[0] = THUNDERX_MMC_WRITE;
98 regs.regs[1] = offset;
99 regs.regs[2] = size;
100 regs.regs[3] = (uintptr_t)buffer;
101
102 smc_call(&regs);
103
104 return regs.regs[0];
105}
106
107ssize_t atf_dram_size(unsigned int node)
108{
109 struct pt_regs regs;
110 regs.regs[0] = THUNDERX_DRAM_SIZE;
111 regs.regs[1] = node;
112
113 smc_call(&regs);
114
115 return regs.regs[0];
116}
117
118ssize_t atf_node_count(void)
119{
120 struct pt_regs regs;
121 regs.regs[0] = THUNDERX_NODE_COUNT;
122
123 smc_call(&regs);
124
125 return regs.regs[0];
126}
127
128ssize_t atf_env_count(void)
129{
130 struct pt_regs regs;
131 regs.regs[0] = THUNDERX_ENV_COUNT;
132
133 smc_call(&regs);
134
135 return regs.regs[0];
136}
137
138ssize_t atf_env_string(size_t index, char *str)
139{
140 uint64_t *buf = (void *)str;
141 struct pt_regs regs;
142 regs.regs[0] = THUNDERX_ENV_STRING;
143 regs.regs[1] = index;
144
145 smc_call(&regs);
146
147 if (regs.regs > 0) {
148 buf[0] = regs.regs[0];
149 buf[1] = regs.regs[1];
150 buf[2] = regs.regs[2];
151 buf[3] = regs.regs[3];
152
153 return 1;
154 } else {
155 return regs.regs[0];
156 }
157}
158
159#ifdef CONFIG_CMD_ATF
160
161static void atf_print_ver(void)
162{
163 struct pt_regs regs;
164 regs.regs[0] = ARM_STD_SVC_VERSION;
165
166 smc_call(&regs);
167
168 printf("ARM Std FW version: %ld.%ld\n", regs.regs[0], regs.regs[1]);
169
170 regs.regs[0] = THUNDERX_SVC_VERSION;
171
172 smc_call(&regs);
173
174 printf("ThunderX OEM ver: %ld.%ld\n", regs.regs[0], regs.regs[1]);
175}
176
177static void atf_print_uid(void)
178{
179}
180
181static void atf_print_part_table(void)
182{
183 size_t pcount;
184 unsigned long i;
185 int ret;
186 char *ptype;
187
188 struct storage_partition *part = (void *)CONFIG_SYS_LOWMEM_BASE;
189
190 pcount = atf_get_pcount();
191
192 printf("Partition count: %lu\n\n", pcount);
193 printf("%10s %10s %10s\n", "Type", "Size", "Offset");
194
195 for (i = 0; i < pcount; i++) {
196 ret = atf_get_part(part, i);
197
198 if (ret < 0) {
199 printf("Uknown error while reading partition: %d\n",
200 ret);
201 return;
202 }
203
204 switch (part->type) {
205 case PARTITION_NBL1FW_REST:
206 ptype = "NBL1FW";
207 break;
208 case PARTITION_BL2_BL31:
209 ptype = "BL2_BL31";
210 break;
211 case PARTITION_UBOOT:
212 ptype = "BOOTLDR";
213 break;
214 case PARTITION_KERNEL:
215 ptype = "KERNEL";
216 break;
217 case PARTITION_DEVICE_TREE:
218 ptype = "DEVTREE";
219 break;
220 default:
221 ptype = "UNKNOWN";
222 }
223 printf("%10s %10d %10lx\n", ptype, part->size, part->offset);
224 }
225}
226
227int do_atf(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
228{
229 ssize_t ret;
230 size_t size, offset;
231 void *buffer = 0;
232 unsigned int index, node;
233 char str[4 * sizeof(uint64_t)];
234
235 if ((argc == 5) && !strcmp(argv[1], "readmmc")) {
236 buffer = (void *)simple_strtoul(argv[2], NULL, 16);
237 offset = simple_strtoul(argv[3], NULL, 10);
238 size = simple_strtoul(argv[4], NULL, 10);
239
240 ret = atf_read_mmc(offset, buffer, size);
241 } else if ((argc == 5) && !strcmp(argv[1], "readnor")) {
242 buffer = (void *)simple_strtoul(argv[2], NULL, 16);
243 offset = simple_strtoul(argv[3], NULL, 10);
244 size = simple_strtoul(argv[4], NULL, 10);
245
246 ret = atf_read_nor(offset, buffer, size);
247 } else if ((argc == 5) && !strcmp(argv[1], "writemmc")) {
248 buffer = (void *)simple_strtoul(argv[2], NULL, 16);
249 offset = simple_strtoul(argv[3], NULL, 10);
250 size = simple_strtoul(argv[4], NULL, 10);
251
252 ret = atf_write_mmc(offset, buffer, size);
253 } else if ((argc == 5) && !strcmp(argv[1], "writenor")) {
254 buffer = (void *)simple_strtoul(argv[2], NULL, 16);
255 offset = simple_strtoul(argv[3], NULL, 10);
256 size = simple_strtoul(argv[4], NULL, 10);
257
258 ret = atf_write_nor(offset, buffer, size);
259 } else if ((argc == 2) && !strcmp(argv[1], "part")) {
260 atf_print_part_table();
261 } else if ((argc == 4) && !strcmp(argv[1], "erasenor")) {
262 offset = simple_strtoul(argv[2], NULL, 10);
263 size = simple_strtoul(argv[3], NULL, 10);
264
265 ret = atf_erase_nor(offset, size);
266 } else if ((argc == 2) && !strcmp(argv[1], "envcount")) {
267 ret = atf_env_count();
268 printf("Number of environment strings: %zd\n", ret);
269 } else if ((argc == 3) && !strcmp(argv[1], "envstring")) {
270 index = simple_strtoul(argv[2], NULL, 10);
271 ret = atf_env_string(index, str);
272 if (ret > 0)
273 printf("Environment string %d: %s\n", index, str);
274 else
275 printf("Return code: %zd\n", ret);
276 } else if ((argc == 3) && !strcmp(argv[1], "dramsize")) {
277 node = simple_strtoul(argv[2], NULL, 10);
278 ret = atf_dram_size(node);
279 printf("DRAM size: %zd Mbytes\n", ret >> 20);
280 } else if ((argc == 2) && !strcmp(argv[1], "nodes")) {
281 ret = atf_node_count();
282 printf("Nodes count: %zd\n", ret);
283 } else if ((argc == 2) && !strcmp(argv[1], "ver")) {
284 atf_print_ver();
285 } else if ((argc == 2) && !strcmp(argv[1], "uid")) {
286 atf_print_uid();
287 } else {
288 return CMD_RET_USAGE;
289 }
290
291 return 0;
292}
293
294U_BOOT_CMD(
295 atf, 10, 1, do_atf,
296 "issue calls to ATF",
297 "\t readmmc addr offset size - read MMC card\n"
298 "\t readnor addr offset size - read NOR flash\n"
299 "\t writemmc addr offset size - write MMC card\n"
300 "\t writenor addr offset size - write NOR flash\n"
301 "\t erasenor offset size - erase NOR flash\n"
302 "\t nodes - number of nodes\n"
303 "\t dramsize node - size of DRAM attached to node\n"
304 "\t envcount - number of environment strings\n"
305 "\t envstring index - print the environment string\n"
306 "\t part - print MMC partition table\n"
307 "\t ver - print ATF call set versions\n"
308);
309
310#endif