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