ea2f2bade00a47d0eb61e650be847ab0cde177fb
[oweals/u-boot.git] / board / cavium / thunderx / atf.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /**
3  * (C) Copyright 2014, Cavium Inc.
4 **/
5
6 #include <common.h>
7 #include <asm/cache.h>
8 #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
19 ssize_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
32 ssize_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
45 ssize_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
55 ssize_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
67 ssize_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
79 ssize_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
93 ssize_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
107 ssize_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
118 ssize_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
128 ssize_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
138 ssize_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
161 static 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
177 static void atf_print_uid(void)
178 {
179 }
180
181 static 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
227 int 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
294 U_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