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