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", 17740d5d34SSimon Glass "Microcode", 18*22c2c179SÁlvaro Fernández Rojas "Device ID", 192e192b24SSimon Glass }; 202e192b24SSimon Glass 212e192b24SSimon Glass static int print_cpu_list(bool detail) 222e192b24SSimon Glass { 232e192b24SSimon Glass struct udevice *dev; 242e192b24SSimon Glass struct uclass *uc; 252e192b24SSimon Glass char buf[100]; 262e192b24SSimon Glass int ret; 272e192b24SSimon Glass 282e192b24SSimon Glass ret = uclass_get(UCLASS_CPU, &uc); 292e192b24SSimon Glass if (ret) { 302e192b24SSimon Glass printf("Cannot find CPU uclass\n"); 312e192b24SSimon Glass return ret; 322e192b24SSimon Glass } 332e192b24SSimon Glass uclass_foreach_dev(dev, uc) { 342e192b24SSimon Glass struct cpu_platdata *plat = dev_get_parent_platdata(dev); 352e192b24SSimon Glass struct cpu_info info; 362e192b24SSimon Glass bool first; 372e192b24SSimon Glass int i; 382e192b24SSimon Glass 392e192b24SSimon Glass ret = cpu_get_desc(dev, buf, sizeof(buf)); 402e192b24SSimon Glass printf("%3d: %-10s %s\n", dev->seq, dev->name, 412e192b24SSimon Glass ret ? "<no description>" : buf); 422e192b24SSimon Glass if (!detail) 432e192b24SSimon Glass continue; 442e192b24SSimon Glass ret = cpu_get_info(dev, &info); 452e192b24SSimon Glass if (ret) { 462e192b24SSimon Glass printf("\t(no detail available"); 472e192b24SSimon Glass if (ret != -ENOSYS) 482e192b24SSimon Glass printf(": err=%d\n", ret); 492e192b24SSimon Glass printf(")\n"); 502e192b24SSimon Glass continue; 512e192b24SSimon Glass } 522e192b24SSimon Glass printf("\tID = %d, freq = ", plat->cpu_id); 532e192b24SSimon Glass print_freq(info.cpu_freq, ""); 542e192b24SSimon Glass first = true; 552e192b24SSimon Glass for (i = 0; i < CPU_FEAT_COUNT; i++) { 562e192b24SSimon Glass if (info.features & (1 << i)) { 572e192b24SSimon Glass printf("%s%s", first ? ": " : ", ", 582e192b24SSimon Glass cpu_feature_name[i]); 592e192b24SSimon Glass first = false; 602e192b24SSimon Glass } 612e192b24SSimon Glass } 622e192b24SSimon Glass printf("\n"); 63740d5d34SSimon Glass if (info.features & (1 << CPU_FEAT_UCODE)) { 64740d5d34SSimon Glass printf("\tMicrocode version %#x\n", 65740d5d34SSimon Glass plat->ucode_version); 66740d5d34SSimon Glass } 67740d5d34SSimon Glass if (info.features & (1 << CPU_FEAT_DEVICE_ID)) 68740d5d34SSimon Glass printf("\tDevice ID %#lx\n", plat->device_id); 692e192b24SSimon Glass } 702e192b24SSimon Glass 712e192b24SSimon Glass return 0; 722e192b24SSimon Glass } 732e192b24SSimon Glass 742e192b24SSimon Glass static int do_cpu_list(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 752e192b24SSimon Glass { 762e192b24SSimon Glass if (print_cpu_list(false)) 772e192b24SSimon Glass return CMD_RET_FAILURE; 782e192b24SSimon Glass 792e192b24SSimon Glass return 0; 802e192b24SSimon Glass } 812e192b24SSimon Glass 822e192b24SSimon Glass static int do_cpu_detail(cmd_tbl_t *cmdtp, int flag, int argc, 832e192b24SSimon Glass char *const argv[]) 842e192b24SSimon Glass { 852e192b24SSimon Glass if (print_cpu_list(true)) 862e192b24SSimon Glass return CMD_RET_FAILURE; 872e192b24SSimon Glass 882e192b24SSimon Glass return 0; 892e192b24SSimon Glass } 902e192b24SSimon Glass 912e192b24SSimon Glass static cmd_tbl_t cmd_cpu_sub[] = { 922e192b24SSimon Glass U_BOOT_CMD_MKENT(list, 2, 1, do_cpu_list, "", ""), 932e192b24SSimon Glass U_BOOT_CMD_MKENT(detail, 4, 0, do_cpu_detail, "", ""), 942e192b24SSimon Glass }; 952e192b24SSimon Glass 962e192b24SSimon Glass /* 972e192b24SSimon Glass * Process a cpu sub-command 982e192b24SSimon Glass */ 992e192b24SSimon Glass static int do_cpu(cmd_tbl_t *cmdtp, int flag, int argc, 1002e192b24SSimon Glass char * const argv[]) 1012e192b24SSimon Glass { 1022e192b24SSimon Glass cmd_tbl_t *c = NULL; 1032e192b24SSimon Glass 1042e192b24SSimon Glass /* Strip off leading 'cpu' command argument */ 1052e192b24SSimon Glass argc--; 1062e192b24SSimon Glass argv++; 1072e192b24SSimon Glass 1082e192b24SSimon Glass if (argc) 1092e192b24SSimon Glass c = find_cmd_tbl(argv[0], cmd_cpu_sub, ARRAY_SIZE(cmd_cpu_sub)); 1102e192b24SSimon Glass 1112e192b24SSimon Glass if (c) 1122e192b24SSimon Glass return c->cmd(cmdtp, flag, argc, argv); 1132e192b24SSimon Glass else 1142e192b24SSimon Glass return CMD_RET_USAGE; 1152e192b24SSimon Glass } 1162e192b24SSimon Glass 1172e192b24SSimon Glass U_BOOT_CMD( 1182e192b24SSimon Glass cpu, 2, 1, do_cpu, 1192e192b24SSimon Glass "display information about CPUs", 1202e192b24SSimon Glass "list - list available CPUs\n" 1212e192b24SSimon Glass "cpu detail - show CPU detail" 1222e192b24SSimon Glass ); 123