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