xref: /openbmc/u-boot/board/cavium/thunderx/atf.c (revision ad3098f7)
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 DECLARE_GLOBAL_DATA_PTR;
20 
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(&regs);
30 
31 	return regs.regs[0];
32 }
33 
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(&regs);
43 
44 	return regs.regs[0];
45 }
46 
47 ssize_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 
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(&regs);
65 
66 	return regs.regs[0];
67 }
68 
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(&regs);
77 
78 	return regs.regs[0];
79 }
80 
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(&regs);
91 
92 	return regs.regs[0];
93 }
94 
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(&regs);
105 
106 	return regs.regs[0];
107 }
108 
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(&regs);
116 
117 	return regs.regs[0];
118 }
119 
120 ssize_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 
130 ssize_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 
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(&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 
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(&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 
179 static void atf_print_uid(void)
180 {
181 }
182 
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 
229 int do_atf(cmd_tbl_t *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