12e192b24SSimon Glass /* 22e192b24SSimon Glass * Copyright (c) 2015 Google, Inc 32e192b24SSimon Glass * Written by Simon Glass <sjg@chromium.org> 42e192b24SSimon Glass * 52e192b24SSimon Glass * SPDX-License-Identifier: GPL-2.0+ 62e192b24SSimon Glass */ 72e192b24SSimon Glass 82e192b24SSimon Glass #include <common.h> 92e192b24SSimon Glass #include <command.h> 102e192b24SSimon Glass #include <cpu.h> 112e192b24SSimon Glass #include <dm.h> 122e192b24SSimon Glass #include <errno.h> 132e192b24SSimon Glass 142e192b24SSimon Glass static const char *cpu_feature_name[CPU_FEAT_COUNT] = { 152e192b24SSimon Glass "L1 cache", 162e192b24SSimon Glass "MMU", 17*740d5d34SSimon Glass "Microcode", 182e192b24SSimon Glass }; 192e192b24SSimon Glass 202e192b24SSimon Glass static int print_cpu_list(bool detail) 212e192b24SSimon Glass { 222e192b24SSimon Glass struct udevice *dev; 232e192b24SSimon Glass struct uclass *uc; 242e192b24SSimon Glass char buf[100]; 252e192b24SSimon Glass int ret; 262e192b24SSimon Glass 272e192b24SSimon Glass ret = uclass_get(UCLASS_CPU, &uc); 282e192b24SSimon Glass if (ret) { 292e192b24SSimon Glass printf("Cannot find CPU uclass\n"); 302e192b24SSimon Glass return ret; 312e192b24SSimon Glass } 322e192b24SSimon Glass uclass_foreach_dev(dev, uc) { 332e192b24SSimon Glass struct cpu_platdata *plat = dev_get_parent_platdata(dev); 342e192b24SSimon Glass struct cpu_info info; 352e192b24SSimon Glass bool first; 362e192b24SSimon Glass int i; 372e192b24SSimon Glass 382e192b24SSimon Glass ret = cpu_get_desc(dev, buf, sizeof(buf)); 392e192b24SSimon Glass printf("%3d: %-10s %s\n", dev->seq, dev->name, 402e192b24SSimon Glass ret ? "<no description>" : buf); 412e192b24SSimon Glass if (!detail) 422e192b24SSimon Glass continue; 432e192b24SSimon Glass ret = cpu_get_info(dev, &info); 442e192b24SSimon Glass if (ret) { 452e192b24SSimon Glass printf("\t(no detail available"); 462e192b24SSimon Glass if (ret != -ENOSYS) 472e192b24SSimon Glass printf(": err=%d\n", ret); 482e192b24SSimon Glass printf(")\n"); 492e192b24SSimon Glass continue; 502e192b24SSimon Glass } 512e192b24SSimon Glass printf("\tID = %d, freq = ", plat->cpu_id); 522e192b24SSimon Glass print_freq(info.cpu_freq, ""); 532e192b24SSimon Glass first = true; 542e192b24SSimon Glass for (i = 0; i < CPU_FEAT_COUNT; i++) { 552e192b24SSimon Glass if (info.features & (1 << i)) { 562e192b24SSimon Glass printf("%s%s", first ? ": " : ", ", 572e192b24SSimon Glass cpu_feature_name[i]); 582e192b24SSimon Glass first = false; 592e192b24SSimon Glass } 602e192b24SSimon Glass } 612e192b24SSimon Glass printf("\n"); 62*740d5d34SSimon Glass if (info.features & (1 << CPU_FEAT_UCODE)) { 63*740d5d34SSimon Glass printf("\tMicrocode version %#x\n", 64*740d5d34SSimon Glass plat->ucode_version); 65*740d5d34SSimon Glass } 66*740d5d34SSimon Glass if (info.features & (1 << CPU_FEAT_DEVICE_ID)) 67*740d5d34SSimon Glass printf("\tDevice ID %#lx\n", plat->device_id); 682e192b24SSimon Glass } 692e192b24SSimon Glass 702e192b24SSimon Glass return 0; 712e192b24SSimon Glass } 722e192b24SSimon Glass 732e192b24SSimon Glass static int do_cpu_list(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 742e192b24SSimon Glass { 752e192b24SSimon Glass if (print_cpu_list(false)) 762e192b24SSimon Glass return CMD_RET_FAILURE; 772e192b24SSimon Glass 782e192b24SSimon Glass return 0; 792e192b24SSimon Glass } 802e192b24SSimon Glass 812e192b24SSimon Glass static int do_cpu_detail(cmd_tbl_t *cmdtp, int flag, int argc, 822e192b24SSimon Glass char *const argv[]) 832e192b24SSimon Glass { 842e192b24SSimon Glass if (print_cpu_list(true)) 852e192b24SSimon Glass return CMD_RET_FAILURE; 862e192b24SSimon Glass 872e192b24SSimon Glass return 0; 882e192b24SSimon Glass } 892e192b24SSimon Glass 902e192b24SSimon Glass static cmd_tbl_t cmd_cpu_sub[] = { 912e192b24SSimon Glass U_BOOT_CMD_MKENT(list, 2, 1, do_cpu_list, "", ""), 922e192b24SSimon Glass U_BOOT_CMD_MKENT(detail, 4, 0, do_cpu_detail, "", ""), 932e192b24SSimon Glass }; 942e192b24SSimon Glass 952e192b24SSimon Glass /* 962e192b24SSimon Glass * Process a cpu sub-command 972e192b24SSimon Glass */ 982e192b24SSimon Glass static int do_cpu(cmd_tbl_t *cmdtp, int flag, int argc, 992e192b24SSimon Glass char * const argv[]) 1002e192b24SSimon Glass { 1012e192b24SSimon Glass cmd_tbl_t *c = NULL; 1022e192b24SSimon Glass 1032e192b24SSimon Glass /* Strip off leading 'cpu' command argument */ 1042e192b24SSimon Glass argc--; 1052e192b24SSimon Glass argv++; 1062e192b24SSimon Glass 1072e192b24SSimon Glass if (argc) 1082e192b24SSimon Glass c = find_cmd_tbl(argv[0], cmd_cpu_sub, ARRAY_SIZE(cmd_cpu_sub)); 1092e192b24SSimon Glass 1102e192b24SSimon Glass if (c) 1112e192b24SSimon Glass return c->cmd(cmdtp, flag, argc, argv); 1122e192b24SSimon Glass else 1132e192b24SSimon Glass return CMD_RET_USAGE; 1142e192b24SSimon Glass } 1152e192b24SSimon Glass 1162e192b24SSimon Glass U_BOOT_CMD( 1172e192b24SSimon Glass cpu, 2, 1, do_cpu, 1182e192b24SSimon Glass "display information about CPUs", 1192e192b24SSimon Glass "list - list available CPUs\n" 1202e192b24SSimon Glass "cpu detail - show CPU detail" 1212e192b24SSimon Glass ); 122