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