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(®s);
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(®s);
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(®s);
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(®s);
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(®s);
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(®s);
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(®s);
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(®s);
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(®s);
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(®s);
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(®s);
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(®s);
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(®s);
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