1 // SPDX-License-Identifier: GPL-2.0+
2 /**
3 * (C) Copyright 2014, Cavium Inc.
4 **/
5
6 #include <common.h>
7 #include <command.h>
8 #include <asm/cache.h>
9 #include <asm/io.h>
10 #include <asm/ptrace.h>
11
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
atf_read_mmc(uintptr_t offset,void * buffer,size_t size)21 ssize_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(®s);
30
31 return regs.regs[0];
32 }
33
atf_read_nor(uintptr_t offset,void * buffer,size_t size)34 ssize_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(®s);
43
44 return regs.regs[0];
45 }
46
atf_get_pcount(void)47 ssize_t atf_get_pcount(void)
48 {
49 struct pt_regs regs;
50 regs.regs[0] = THUNDERX_PART_COUNT;
51
52 smc_call(®s);
53
54 return regs.regs[0];
55 }
56
atf_get_part(struct storage_partition * part,unsigned int index)57 ssize_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(®s);
65
66 return regs.regs[0];
67 }
68
atf_erase_nor(uintptr_t offset,size_t size)69 ssize_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(®s);
77
78 return regs.regs[0];
79 }
80
atf_write_nor(uintptr_t offset,const void * buffer,size_t size)81 ssize_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(®s);
91
92 return regs.regs[0];
93 }
94
atf_write_mmc(uintptr_t offset,const void * buffer,size_t size)95 ssize_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(®s);
105
106 return regs.regs[0];
107 }
108
atf_dram_size(unsigned int node)109 ssize_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(®s);
116
117 return regs.regs[0];
118 }
119
atf_node_count(void)120 ssize_t atf_node_count(void)
121 {
122 struct pt_regs regs;
123 regs.regs[0] = THUNDERX_NODE_COUNT;
124
125 smc_call(®s);
126
127 return regs.regs[0];
128 }
129
atf_env_count(void)130 ssize_t atf_env_count(void)
131 {
132 struct pt_regs regs;
133 regs.regs[0] = THUNDERX_ENV_COUNT;
134
135 smc_call(®s);
136
137 return regs.regs[0];
138 }
139
atf_env_string(size_t index,char * str)140 ssize_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(®s);
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
atf_print_ver(void)163 static void atf_print_ver(void)
164 {
165 struct pt_regs regs;
166 regs.regs[0] = ARM_STD_SVC_VERSION;
167
168 smc_call(®s);
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(®s);
175
176 printf("ThunderX OEM ver: %ld.%ld\n", regs.regs[0], regs.regs[1]);
177 }
178
atf_print_uid(void)179 static void atf_print_uid(void)
180 {
181 }
182
atf_print_part_table(void)183 static void atf_print_part_table(void)
184 {
185 size_t pcount;
186 unsigned long i;
187 int ret;
188 char *ptype;
189
190 struct storage_partition *part = (void *)CONFIG_SYS_LOWMEM_BASE;
191
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
do_atf(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])229 int do_atf(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
230 {
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")) {
238 buffer = (void *)simple_strtoul(argv[2], NULL, 16);
239 offset = simple_strtoul(argv[3], NULL, 10);
240 size = simple_strtoul(argv[4], NULL, 10);
241
242 ret = atf_read_mmc(offset, buffer, size);
243 } else if ((argc == 5) && !strcmp(argv[1], "readnor")) {
244 buffer = (void *)simple_strtoul(argv[2], NULL, 16);
245 offset = simple_strtoul(argv[3], NULL, 10);
246 size = simple_strtoul(argv[4], NULL, 10);
247
248 ret = atf_read_nor(offset, buffer, size);
249 } else if ((argc == 5) && !strcmp(argv[1], "writemmc")) {
250 buffer = (void *)simple_strtoul(argv[2], NULL, 16);
251 offset = simple_strtoul(argv[3], NULL, 10);
252 size = simple_strtoul(argv[4], NULL, 10);
253
254 ret = atf_write_mmc(offset, buffer, size);
255 } else if ((argc == 5) && !strcmp(argv[1], "writenor")) {
256 buffer = (void *)simple_strtoul(argv[2], NULL, 16);
257 offset = simple_strtoul(argv[3], NULL, 10);
258 size = simple_strtoul(argv[4], NULL, 10);
259
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")) {
264 offset = simple_strtoul(argv[2], NULL, 10);
265 size = simple_strtoul(argv[3], NULL, 10);
266
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")) {
272 index = simple_strtoul(argv[2], NULL, 10);
273 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")) {
279 node = simple_strtoul(argv[2], NULL, 10);
280 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
296 U_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
313