xref: /openbmc/u-boot/board/cavium/thunderx/atf.c (revision 699e831e158a5846778d8bd6af054d4276277cb6)
1 /**
2  * (C) Copyright 2014, Cavium Inc.
3  *
4  * SPDX-License-Identifier:	GPL-2.0+
5 **/
6 
7 #include <common.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
311