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