1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2015 Google, Inc
4  * Written by Simon Glass <sjg@chromium.org>
5  * Copyright (c) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
6  */
7 
8 #include <common.h>
9 #include <command.h>
10 #include <cpu.h>
11 #include <display_options.h>
12 #include <dm.h>
13 #include <errno.h>
14 
15 static const char *cpu_feature_name[CPU_FEAT_COUNT] = {
16 	"L1 cache",
17 	"MMU",
18 	"Microcode",
19 	"Device ID",
20 };
21 
print_cpu_list(bool detail)22 static int print_cpu_list(bool detail)
23 {
24 	struct udevice *dev;
25 	char buf[100];
26 
27 	for (uclass_first_device(UCLASS_CPU, &dev);
28 		     dev;
29 		     uclass_next_device(&dev)) {
30 		struct cpu_plat *plat = dev_get_parent_plat(dev);
31 		struct cpu_info info;
32 		bool first = true;
33 		int ret, i;
34 
35 		ret = cpu_get_desc(dev, buf, sizeof(buf));
36 		printf("%3d: %-10s %s\n", dev_seq(dev), dev->name,
37 		       ret ? "<no description>" : buf);
38 		if (!detail)
39 			continue;
40 		ret = cpu_get_info(dev, &info);
41 		if (ret) {
42 			printf("\t(no detail available");
43 			if (ret != -ENOSYS)
44 				printf(": err=%d", ret);
45 			printf(")\n");
46 			continue;
47 		}
48 		printf("\tID = %d, freq = ", plat->cpu_id);
49 		print_freq(info.cpu_freq, "");
50 		for (i = 0; i < CPU_FEAT_COUNT; i++) {
51 			if (info.features & (1 << i)) {
52 				printf("%s%s", first ? ": " : ", ",
53 				       cpu_feature_name[i]);
54 				first = false;
55 			}
56 		}
57 		printf("\n");
58 		if (info.features & (1 << CPU_FEAT_UCODE))
59 			printf("\tMicrocode version %#x\n",
60 			       plat->ucode_version);
61 		if (info.features & (1 << CPU_FEAT_DEVICE_ID))
62 			printf("\tDevice ID %#lx\n", plat->device_id);
63 	}
64 
65 	return 0;
66 }
67 
do_cpu_list(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])68 static int do_cpu_list(struct cmd_tbl *cmdtp, int flag, int argc,
69 		       char *const argv[])
70 {
71 	if (print_cpu_list(false))
72 		return CMD_RET_FAILURE;
73 
74 	return 0;
75 }
76 
do_cpu_detail(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])77 static int do_cpu_detail(struct cmd_tbl *cmdtp, int flag, int argc,
78 			 char *const argv[])
79 {
80 	if (print_cpu_list(true))
81 		return CMD_RET_FAILURE;
82 
83 	return 0;
84 }
85 
86 #if IS_ENABLED(CONFIG_SYS_LONGHELP)
87 static char cpu_help_text[] =
88 	"list	- list available CPUs\n"
89 	"cpu detail	- show CPU detail"
90 	;
91 #endif
92 
93 U_BOOT_CMD_WITH_SUBCMDS(cpu, "display information about CPUs", cpu_help_text,
94 	U_BOOT_SUBCMD_MKENT(list, 1, 1, do_cpu_list),
95 	U_BOOT_SUBCMD_MKENT(detail, 1, 0, do_cpu_detail));
96