12e192b24SSimon Glass /* 22e192b24SSimon Glass * Copyright (c) 2015 Google, Inc 32e192b24SSimon Glass * Written by Simon Glass <sjg@chromium.org> 4*320eca5cSÁlvaro Fernández Rojas * Copyright (c) 2017 Álvaro Fernández Rojas <noltari@gmail.com> 52e192b24SSimon Glass * 62e192b24SSimon Glass * SPDX-License-Identifier: GPL-2.0+ 72e192b24SSimon Glass */ 82e192b24SSimon Glass 92e192b24SSimon Glass #include <common.h> 102e192b24SSimon Glass #include <command.h> 112e192b24SSimon Glass #include <cpu.h> 122e192b24SSimon Glass #include <dm.h> 132e192b24SSimon Glass #include <errno.h> 142e192b24SSimon Glass 152e192b24SSimon Glass static const char *cpu_feature_name[CPU_FEAT_COUNT] = { 162e192b24SSimon Glass "L1 cache", 172e192b24SSimon Glass "MMU", 18740d5d34SSimon Glass "Microcode", 1922c2c179SÁlvaro Fernández Rojas "Device ID", 202e192b24SSimon Glass }; 212e192b24SSimon Glass 222e192b24SSimon Glass static int print_cpu_list(bool detail) 232e192b24SSimon Glass { 242e192b24SSimon Glass struct udevice *dev; 252e192b24SSimon Glass char buf[100]; 262e192b24SSimon Glass 27*320eca5cSÁlvaro Fernández Rojas for (uclass_first_device(UCLASS_CPU, &dev); 28*320eca5cSÁlvaro Fernández Rojas dev; 29*320eca5cSÁlvaro Fernández Rojas uclass_next_device(&dev)) { 302e192b24SSimon Glass struct cpu_platdata *plat = dev_get_parent_platdata(dev); 312e192b24SSimon Glass struct cpu_info info; 32*320eca5cSÁlvaro Fernández Rojas bool first = true; 33*320eca5cSÁlvaro Fernández Rojas int ret, i; 342e192b24SSimon Glass 352e192b24SSimon Glass ret = cpu_get_desc(dev, buf, sizeof(buf)); 362e192b24SSimon Glass printf("%3d: %-10s %s\n", dev->seq, dev->name, 372e192b24SSimon Glass ret ? "<no description>" : buf); 382e192b24SSimon Glass if (!detail) 392e192b24SSimon Glass continue; 402e192b24SSimon Glass ret = cpu_get_info(dev, &info); 412e192b24SSimon Glass if (ret) { 422e192b24SSimon Glass printf("\t(no detail available"); 432e192b24SSimon Glass if (ret != -ENOSYS) 44*320eca5cSÁlvaro Fernández Rojas printf(": err=%d", ret); 452e192b24SSimon Glass printf(")\n"); 462e192b24SSimon Glass continue; 472e192b24SSimon Glass } 482e192b24SSimon Glass printf("\tID = %d, freq = ", plat->cpu_id); 492e192b24SSimon Glass print_freq(info.cpu_freq, ""); 502e192b24SSimon Glass for (i = 0; i < CPU_FEAT_COUNT; i++) { 512e192b24SSimon Glass if (info.features & (1 << i)) { 522e192b24SSimon Glass printf("%s%s", first ? ": " : ", ", 532e192b24SSimon Glass cpu_feature_name[i]); 542e192b24SSimon Glass first = false; 552e192b24SSimon Glass } 562e192b24SSimon Glass } 572e192b24SSimon Glass printf("\n"); 58*320eca5cSÁlvaro Fernández Rojas if (info.features & (1 << CPU_FEAT_UCODE)) 59740d5d34SSimon Glass printf("\tMicrocode version %#x\n", 60740d5d34SSimon Glass plat->ucode_version); 61740d5d34SSimon Glass if (info.features & (1 << CPU_FEAT_DEVICE_ID)) 62740d5d34SSimon Glass printf("\tDevice ID %#lx\n", plat->device_id); 632e192b24SSimon Glass } 642e192b24SSimon Glass 652e192b24SSimon Glass return 0; 662e192b24SSimon Glass } 672e192b24SSimon Glass 68*320eca5cSÁlvaro Fernández Rojas static int do_cpu_list(cmd_tbl_t *cmdtp, int flag, int argc, 69*320eca5cSÁlvaro Fernández Rojas char *const argv[]) 702e192b24SSimon Glass { 712e192b24SSimon Glass if (print_cpu_list(false)) 722e192b24SSimon Glass return CMD_RET_FAILURE; 732e192b24SSimon Glass 742e192b24SSimon Glass return 0; 752e192b24SSimon Glass } 762e192b24SSimon Glass 772e192b24SSimon Glass static int do_cpu_detail(cmd_tbl_t *cmdtp, int flag, int argc, 782e192b24SSimon Glass char *const argv[]) 792e192b24SSimon Glass { 802e192b24SSimon Glass if (print_cpu_list(true)) 812e192b24SSimon Glass return CMD_RET_FAILURE; 822e192b24SSimon Glass 832e192b24SSimon Glass return 0; 842e192b24SSimon Glass } 852e192b24SSimon Glass 862e192b24SSimon Glass static cmd_tbl_t cmd_cpu_sub[] = { 872e192b24SSimon Glass U_BOOT_CMD_MKENT(list, 2, 1, do_cpu_list, "", ""), 882e192b24SSimon Glass U_BOOT_CMD_MKENT(detail, 4, 0, do_cpu_detail, "", ""), 892e192b24SSimon Glass }; 902e192b24SSimon Glass 912e192b24SSimon Glass /* 922e192b24SSimon Glass * Process a cpu sub-command 932e192b24SSimon Glass */ 942e192b24SSimon Glass static int do_cpu(cmd_tbl_t *cmdtp, int flag, int argc, 952e192b24SSimon Glass char * const argv[]) 962e192b24SSimon Glass { 972e192b24SSimon Glass cmd_tbl_t *c = NULL; 982e192b24SSimon Glass 992e192b24SSimon Glass /* Strip off leading 'cpu' command argument */ 1002e192b24SSimon Glass argc--; 1012e192b24SSimon Glass argv++; 1022e192b24SSimon Glass 1032e192b24SSimon Glass if (argc) 104*320eca5cSÁlvaro Fernández Rojas c = find_cmd_tbl(argv[0], cmd_cpu_sub, 105*320eca5cSÁlvaro Fernández Rojas ARRAY_SIZE(cmd_cpu_sub)); 1062e192b24SSimon Glass 1072e192b24SSimon Glass if (c) 1082e192b24SSimon Glass return c->cmd(cmdtp, flag, argc, argv); 1092e192b24SSimon Glass else 1102e192b24SSimon Glass return CMD_RET_USAGE; 1112e192b24SSimon Glass } 1122e192b24SSimon Glass 1132e192b24SSimon Glass U_BOOT_CMD( 1142e192b24SSimon Glass cpu, 2, 1, do_cpu, 1152e192b24SSimon Glass "display information about CPUs", 1162e192b24SSimon Glass "list - list available CPUs\n" 1172e192b24SSimon Glass "cpu detail - show CPU detail" 1182e192b24SSimon Glass ); 119