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