1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+ 2900f88f3SSergey Temerkhanov /** 3900f88f3SSergey Temerkhanov * (C) Copyright 2014, Cavium Inc. 4900f88f3SSergey Temerkhanov **/ 5900f88f3SSergey Temerkhanov 6900f88f3SSergey Temerkhanov #include <common.h> 7900f88f3SSergey Temerkhanov #include <asm/io.h> 8900f88f3SSergey Temerkhanov 9900f88f3SSergey Temerkhanov #include <asm/system.h> 10900f88f3SSergey Temerkhanov #include <cavium/thunderx_svc.h> 11900f88f3SSergey Temerkhanov #include <cavium/atf.h> 12900f88f3SSergey Temerkhanov #include <cavium/atf_part.h> 13900f88f3SSergey Temerkhanov 14900f88f3SSergey Temerkhanov #include <asm/psci.h> 15900f88f3SSergey Temerkhanov 16900f88f3SSergey Temerkhanov #include <malloc.h> 17900f88f3SSergey Temerkhanov 18900f88f3SSergey Temerkhanov ssize_t atf_read_mmc(uintptr_t offset, void *buffer, size_t size) 19900f88f3SSergey Temerkhanov { 20900f88f3SSergey Temerkhanov struct pt_regs regs; 21900f88f3SSergey Temerkhanov regs.regs[0] = THUNDERX_MMC_READ; 22900f88f3SSergey Temerkhanov regs.regs[1] = offset; 23900f88f3SSergey Temerkhanov regs.regs[2] = size; 24900f88f3SSergey Temerkhanov regs.regs[3] = (uintptr_t)buffer; 25900f88f3SSergey Temerkhanov 26900f88f3SSergey Temerkhanov smc_call(®s); 27900f88f3SSergey Temerkhanov 28900f88f3SSergey Temerkhanov return regs.regs[0]; 29900f88f3SSergey Temerkhanov } 30900f88f3SSergey Temerkhanov 31900f88f3SSergey Temerkhanov ssize_t atf_read_nor(uintptr_t offset, void *buffer, size_t size) 32900f88f3SSergey Temerkhanov { 33900f88f3SSergey Temerkhanov struct pt_regs regs; 34900f88f3SSergey Temerkhanov regs.regs[0] = THUNDERX_NOR_READ; 35900f88f3SSergey Temerkhanov regs.regs[1] = offset; 36900f88f3SSergey Temerkhanov regs.regs[2] = size; 37900f88f3SSergey Temerkhanov regs.regs[3] = (uintptr_t)buffer; 38900f88f3SSergey Temerkhanov 39900f88f3SSergey Temerkhanov smc_call(®s); 40900f88f3SSergey Temerkhanov 41900f88f3SSergey Temerkhanov return regs.regs[0]; 42900f88f3SSergey Temerkhanov } 43900f88f3SSergey Temerkhanov 44900f88f3SSergey Temerkhanov ssize_t atf_get_pcount(void) 45900f88f3SSergey Temerkhanov { 46900f88f3SSergey Temerkhanov struct pt_regs regs; 47900f88f3SSergey Temerkhanov regs.regs[0] = THUNDERX_PART_COUNT; 48900f88f3SSergey Temerkhanov 49900f88f3SSergey Temerkhanov smc_call(®s); 50900f88f3SSergey Temerkhanov 51900f88f3SSergey Temerkhanov return regs.regs[0]; 52900f88f3SSergey Temerkhanov } 53900f88f3SSergey Temerkhanov 54900f88f3SSergey Temerkhanov ssize_t atf_get_part(struct storage_partition *part, unsigned int index) 55900f88f3SSergey Temerkhanov { 56900f88f3SSergey Temerkhanov struct pt_regs regs; 57900f88f3SSergey Temerkhanov regs.regs[0] = THUNDERX_GET_PART; 58900f88f3SSergey Temerkhanov regs.regs[1] = (uintptr_t)part; 59900f88f3SSergey Temerkhanov regs.regs[2] = index; 60900f88f3SSergey Temerkhanov 61900f88f3SSergey Temerkhanov smc_call(®s); 62900f88f3SSergey Temerkhanov 63900f88f3SSergey Temerkhanov return regs.regs[0]; 64900f88f3SSergey Temerkhanov } 65900f88f3SSergey Temerkhanov 66900f88f3SSergey Temerkhanov ssize_t atf_erase_nor(uintptr_t offset, size_t size) 67900f88f3SSergey Temerkhanov { 68900f88f3SSergey Temerkhanov struct pt_regs regs; 69900f88f3SSergey Temerkhanov 70900f88f3SSergey Temerkhanov regs.regs[0] = THUNDERX_NOR_ERASE; 71900f88f3SSergey Temerkhanov regs.regs[1] = offset; 72900f88f3SSergey Temerkhanov 73900f88f3SSergey Temerkhanov smc_call(®s); 74900f88f3SSergey Temerkhanov 75900f88f3SSergey Temerkhanov return regs.regs[0]; 76900f88f3SSergey Temerkhanov } 77900f88f3SSergey Temerkhanov 78900f88f3SSergey Temerkhanov ssize_t atf_write_nor(uintptr_t offset, const void *buffer, size_t size) 79900f88f3SSergey Temerkhanov { 80900f88f3SSergey Temerkhanov struct pt_regs regs; 81900f88f3SSergey Temerkhanov 82900f88f3SSergey Temerkhanov regs.regs[0] = THUNDERX_NOR_WRITE; 83900f88f3SSergey Temerkhanov regs.regs[1] = offset; 84900f88f3SSergey Temerkhanov regs.regs[2] = size; 85900f88f3SSergey Temerkhanov regs.regs[3] = (uintptr_t)buffer; 86900f88f3SSergey Temerkhanov 87900f88f3SSergey Temerkhanov smc_call(®s); 88900f88f3SSergey Temerkhanov 89900f88f3SSergey Temerkhanov return regs.regs[0]; 90900f88f3SSergey Temerkhanov } 91900f88f3SSergey Temerkhanov 92900f88f3SSergey Temerkhanov ssize_t atf_write_mmc(uintptr_t offset, const void *buffer, size_t size) 93900f88f3SSergey Temerkhanov { 94900f88f3SSergey Temerkhanov struct pt_regs regs; 95900f88f3SSergey Temerkhanov 96900f88f3SSergey Temerkhanov regs.regs[0] = THUNDERX_MMC_WRITE; 97900f88f3SSergey Temerkhanov regs.regs[1] = offset; 98900f88f3SSergey Temerkhanov regs.regs[2] = size; 99900f88f3SSergey Temerkhanov regs.regs[3] = (uintptr_t)buffer; 100900f88f3SSergey Temerkhanov 101900f88f3SSergey Temerkhanov smc_call(®s); 102900f88f3SSergey Temerkhanov 103900f88f3SSergey Temerkhanov return regs.regs[0]; 104900f88f3SSergey Temerkhanov } 105900f88f3SSergey Temerkhanov 106900f88f3SSergey Temerkhanov ssize_t atf_dram_size(unsigned int node) 107900f88f3SSergey Temerkhanov { 108900f88f3SSergey Temerkhanov struct pt_regs regs; 109900f88f3SSergey Temerkhanov regs.regs[0] = THUNDERX_DRAM_SIZE; 110900f88f3SSergey Temerkhanov regs.regs[1] = node; 111900f88f3SSergey Temerkhanov 112900f88f3SSergey Temerkhanov smc_call(®s); 113900f88f3SSergey Temerkhanov 114900f88f3SSergey Temerkhanov return regs.regs[0]; 115900f88f3SSergey Temerkhanov } 116900f88f3SSergey Temerkhanov 117900f88f3SSergey Temerkhanov ssize_t atf_node_count(void) 118900f88f3SSergey Temerkhanov { 119900f88f3SSergey Temerkhanov struct pt_regs regs; 120900f88f3SSergey Temerkhanov regs.regs[0] = THUNDERX_NODE_COUNT; 121900f88f3SSergey Temerkhanov 122900f88f3SSergey Temerkhanov smc_call(®s); 123900f88f3SSergey Temerkhanov 124900f88f3SSergey Temerkhanov return regs.regs[0]; 125900f88f3SSergey Temerkhanov } 126900f88f3SSergey Temerkhanov 127900f88f3SSergey Temerkhanov ssize_t atf_env_count(void) 128900f88f3SSergey Temerkhanov { 129900f88f3SSergey Temerkhanov struct pt_regs regs; 130900f88f3SSergey Temerkhanov regs.regs[0] = THUNDERX_ENV_COUNT; 131900f88f3SSergey Temerkhanov 132900f88f3SSergey Temerkhanov smc_call(®s); 133900f88f3SSergey Temerkhanov 134900f88f3SSergey Temerkhanov return regs.regs[0]; 135900f88f3SSergey Temerkhanov } 136900f88f3SSergey Temerkhanov 137900f88f3SSergey Temerkhanov ssize_t atf_env_string(size_t index, char *str) 138900f88f3SSergey Temerkhanov { 139900f88f3SSergey Temerkhanov uint64_t *buf = (void *)str; 140900f88f3SSergey Temerkhanov struct pt_regs regs; 141900f88f3SSergey Temerkhanov regs.regs[0] = THUNDERX_ENV_STRING; 142900f88f3SSergey Temerkhanov regs.regs[1] = index; 143900f88f3SSergey Temerkhanov 144900f88f3SSergey Temerkhanov smc_call(®s); 145900f88f3SSergey Temerkhanov 146900f88f3SSergey Temerkhanov if (regs.regs > 0) { 147900f88f3SSergey Temerkhanov buf[0] = regs.regs[0]; 148900f88f3SSergey Temerkhanov buf[1] = regs.regs[1]; 149900f88f3SSergey Temerkhanov buf[2] = regs.regs[2]; 150900f88f3SSergey Temerkhanov buf[3] = regs.regs[3]; 151900f88f3SSergey Temerkhanov 152900f88f3SSergey Temerkhanov return 1; 153900f88f3SSergey Temerkhanov } else { 154900f88f3SSergey Temerkhanov return regs.regs[0]; 155900f88f3SSergey Temerkhanov } 156900f88f3SSergey Temerkhanov } 157900f88f3SSergey Temerkhanov 158900f88f3SSergey Temerkhanov #ifdef CONFIG_CMD_ATF 159900f88f3SSergey Temerkhanov 160900f88f3SSergey Temerkhanov static void atf_print_ver(void) 161900f88f3SSergey Temerkhanov { 162900f88f3SSergey Temerkhanov struct pt_regs regs; 163900f88f3SSergey Temerkhanov regs.regs[0] = ARM_STD_SVC_VERSION; 164900f88f3SSergey Temerkhanov 165900f88f3SSergey Temerkhanov smc_call(®s); 166900f88f3SSergey Temerkhanov 167900f88f3SSergey Temerkhanov printf("ARM Std FW version: %ld.%ld\n", regs.regs[0], regs.regs[1]); 168900f88f3SSergey Temerkhanov 169900f88f3SSergey Temerkhanov regs.regs[0] = THUNDERX_SVC_VERSION; 170900f88f3SSergey Temerkhanov 171900f88f3SSergey Temerkhanov smc_call(®s); 172900f88f3SSergey Temerkhanov 173900f88f3SSergey Temerkhanov printf("ThunderX OEM ver: %ld.%ld\n", regs.regs[0], regs.regs[1]); 174900f88f3SSergey Temerkhanov } 175900f88f3SSergey Temerkhanov 176900f88f3SSergey Temerkhanov static void atf_print_uid(void) 177900f88f3SSergey Temerkhanov { 178900f88f3SSergey Temerkhanov } 179900f88f3SSergey Temerkhanov 180900f88f3SSergey Temerkhanov static void atf_print_part_table(void) 181900f88f3SSergey Temerkhanov { 182900f88f3SSergey Temerkhanov size_t pcount; 183900f88f3SSergey Temerkhanov unsigned long i; 184900f88f3SSergey Temerkhanov int ret; 185900f88f3SSergey Temerkhanov char *ptype; 186900f88f3SSergey Temerkhanov 187900f88f3SSergey Temerkhanov struct storage_partition *part = (void *)CONFIG_SYS_LOWMEM_BASE; 188900f88f3SSergey Temerkhanov 189900f88f3SSergey Temerkhanov pcount = atf_get_pcount(); 190900f88f3SSergey Temerkhanov 191900f88f3SSergey Temerkhanov printf("Partition count: %lu\n\n", pcount); 192900f88f3SSergey Temerkhanov printf("%10s %10s %10s\n", "Type", "Size", "Offset"); 193900f88f3SSergey Temerkhanov 194900f88f3SSergey Temerkhanov for (i = 0; i < pcount; i++) { 195900f88f3SSergey Temerkhanov ret = atf_get_part(part, i); 196900f88f3SSergey Temerkhanov 197900f88f3SSergey Temerkhanov if (ret < 0) { 198900f88f3SSergey Temerkhanov printf("Uknown error while reading partition: %d\n", 199900f88f3SSergey Temerkhanov ret); 200900f88f3SSergey Temerkhanov return; 201900f88f3SSergey Temerkhanov } 202900f88f3SSergey Temerkhanov 203900f88f3SSergey Temerkhanov switch (part->type) { 204900f88f3SSergey Temerkhanov case PARTITION_NBL1FW_REST: 205900f88f3SSergey Temerkhanov ptype = "NBL1FW"; 206900f88f3SSergey Temerkhanov break; 207900f88f3SSergey Temerkhanov case PARTITION_BL2_BL31: 208900f88f3SSergey Temerkhanov ptype = "BL2_BL31"; 209900f88f3SSergey Temerkhanov break; 210900f88f3SSergey Temerkhanov case PARTITION_UBOOT: 211900f88f3SSergey Temerkhanov ptype = "BOOTLDR"; 212900f88f3SSergey Temerkhanov break; 213900f88f3SSergey Temerkhanov case PARTITION_KERNEL: 214900f88f3SSergey Temerkhanov ptype = "KERNEL"; 215900f88f3SSergey Temerkhanov break; 216900f88f3SSergey Temerkhanov case PARTITION_DEVICE_TREE: 217900f88f3SSergey Temerkhanov ptype = "DEVTREE"; 218900f88f3SSergey Temerkhanov break; 219900f88f3SSergey Temerkhanov default: 220900f88f3SSergey Temerkhanov ptype = "UNKNOWN"; 221900f88f3SSergey Temerkhanov } 222900f88f3SSergey Temerkhanov printf("%10s %10d %10lx\n", ptype, part->size, part->offset); 223900f88f3SSergey Temerkhanov } 224900f88f3SSergey Temerkhanov } 225900f88f3SSergey Temerkhanov 226900f88f3SSergey Temerkhanov int do_atf(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 227900f88f3SSergey Temerkhanov { 228900f88f3SSergey Temerkhanov ssize_t ret; 229900f88f3SSergey Temerkhanov size_t size, offset; 230900f88f3SSergey Temerkhanov void *buffer = 0; 231900f88f3SSergey Temerkhanov unsigned int index, node; 232900f88f3SSergey Temerkhanov char str[4 * sizeof(uint64_t)]; 233900f88f3SSergey Temerkhanov 234900f88f3SSergey Temerkhanov if ((argc == 5) && !strcmp(argv[1], "readmmc")) { 235900f88f3SSergey Temerkhanov buffer = (void *)simple_strtoul(argv[2], NULL, 16); 236900f88f3SSergey Temerkhanov offset = simple_strtoul(argv[3], NULL, 10); 237900f88f3SSergey Temerkhanov size = simple_strtoul(argv[4], NULL, 10); 238900f88f3SSergey Temerkhanov 239900f88f3SSergey Temerkhanov ret = atf_read_mmc(offset, buffer, size); 240900f88f3SSergey Temerkhanov } else if ((argc == 5) && !strcmp(argv[1], "readnor")) { 241900f88f3SSergey Temerkhanov buffer = (void *)simple_strtoul(argv[2], NULL, 16); 242900f88f3SSergey Temerkhanov offset = simple_strtoul(argv[3], NULL, 10); 243900f88f3SSergey Temerkhanov size = simple_strtoul(argv[4], NULL, 10); 244900f88f3SSergey Temerkhanov 245900f88f3SSergey Temerkhanov ret = atf_read_nor(offset, buffer, size); 246900f88f3SSergey Temerkhanov } else if ((argc == 5) && !strcmp(argv[1], "writemmc")) { 247900f88f3SSergey Temerkhanov buffer = (void *)simple_strtoul(argv[2], NULL, 16); 248900f88f3SSergey Temerkhanov offset = simple_strtoul(argv[3], NULL, 10); 249900f88f3SSergey Temerkhanov size = simple_strtoul(argv[4], NULL, 10); 250900f88f3SSergey Temerkhanov 251900f88f3SSergey Temerkhanov ret = atf_write_mmc(offset, buffer, size); 252900f88f3SSergey Temerkhanov } else if ((argc == 5) && !strcmp(argv[1], "writenor")) { 253900f88f3SSergey Temerkhanov buffer = (void *)simple_strtoul(argv[2], NULL, 16); 254900f88f3SSergey Temerkhanov offset = simple_strtoul(argv[3], NULL, 10); 255900f88f3SSergey Temerkhanov size = simple_strtoul(argv[4], NULL, 10); 256900f88f3SSergey Temerkhanov 257900f88f3SSergey Temerkhanov ret = atf_write_nor(offset, buffer, size); 258900f88f3SSergey Temerkhanov } else if ((argc == 2) && !strcmp(argv[1], "part")) { 259900f88f3SSergey Temerkhanov atf_print_part_table(); 260900f88f3SSergey Temerkhanov } else if ((argc == 4) && !strcmp(argv[1], "erasenor")) { 261900f88f3SSergey Temerkhanov offset = simple_strtoul(argv[2], NULL, 10); 262900f88f3SSergey Temerkhanov size = simple_strtoul(argv[3], NULL, 10); 263900f88f3SSergey Temerkhanov 264900f88f3SSergey Temerkhanov ret = atf_erase_nor(offset, size); 265900f88f3SSergey Temerkhanov } else if ((argc == 2) && !strcmp(argv[1], "envcount")) { 266900f88f3SSergey Temerkhanov ret = atf_env_count(); 267900f88f3SSergey Temerkhanov printf("Number of environment strings: %zd\n", ret); 268900f88f3SSergey Temerkhanov } else if ((argc == 3) && !strcmp(argv[1], "envstring")) { 269900f88f3SSergey Temerkhanov index = simple_strtoul(argv[2], NULL, 10); 270900f88f3SSergey Temerkhanov ret = atf_env_string(index, str); 271900f88f3SSergey Temerkhanov if (ret > 0) 272900f88f3SSergey Temerkhanov printf("Environment string %d: %s\n", index, str); 273900f88f3SSergey Temerkhanov else 274900f88f3SSergey Temerkhanov printf("Return code: %zd\n", ret); 275900f88f3SSergey Temerkhanov } else if ((argc == 3) && !strcmp(argv[1], "dramsize")) { 276900f88f3SSergey Temerkhanov node = simple_strtoul(argv[2], NULL, 10); 277900f88f3SSergey Temerkhanov ret = atf_dram_size(node); 278900f88f3SSergey Temerkhanov printf("DRAM size: %zd Mbytes\n", ret >> 20); 279900f88f3SSergey Temerkhanov } else if ((argc == 2) && !strcmp(argv[1], "nodes")) { 280900f88f3SSergey Temerkhanov ret = atf_node_count(); 281900f88f3SSergey Temerkhanov printf("Nodes count: %zd\n", ret); 282900f88f3SSergey Temerkhanov } else if ((argc == 2) && !strcmp(argv[1], "ver")) { 283900f88f3SSergey Temerkhanov atf_print_ver(); 284900f88f3SSergey Temerkhanov } else if ((argc == 2) && !strcmp(argv[1], "uid")) { 285900f88f3SSergey Temerkhanov atf_print_uid(); 286900f88f3SSergey Temerkhanov } else { 287900f88f3SSergey Temerkhanov return CMD_RET_USAGE; 288900f88f3SSergey Temerkhanov } 289900f88f3SSergey Temerkhanov 290900f88f3SSergey Temerkhanov return 0; 291900f88f3SSergey Temerkhanov } 292900f88f3SSergey Temerkhanov 293900f88f3SSergey Temerkhanov U_BOOT_CMD( 294900f88f3SSergey Temerkhanov atf, 10, 1, do_atf, 295900f88f3SSergey Temerkhanov "issue calls to ATF", 296900f88f3SSergey Temerkhanov "\t readmmc addr offset size - read MMC card\n" 297900f88f3SSergey Temerkhanov "\t readnor addr offset size - read NOR flash\n" 298900f88f3SSergey Temerkhanov "\t writemmc addr offset size - write MMC card\n" 299900f88f3SSergey Temerkhanov "\t writenor addr offset size - write NOR flash\n" 300900f88f3SSergey Temerkhanov "\t erasenor offset size - erase NOR flash\n" 301900f88f3SSergey Temerkhanov "\t nodes - number of nodes\n" 302900f88f3SSergey Temerkhanov "\t dramsize node - size of DRAM attached to node\n" 303900f88f3SSergey Temerkhanov "\t envcount - number of environment strings\n" 304900f88f3SSergey Temerkhanov "\t envstring index - print the environment string\n" 305900f88f3SSergey Temerkhanov "\t part - print MMC partition table\n" 306900f88f3SSergey Temerkhanov "\t ver - print ATF call set versions\n" 307900f88f3SSergey Temerkhanov ); 308900f88f3SSergey Temerkhanov 309900f88f3SSergey Temerkhanov #endif 310