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