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