blob: 99104274f725df8dd530ec1c942cb83fbb14740f [file] [log] [blame]
Simon Glass052a03e2020-11-05 06:32:11 -07001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright 2020 Google LLC
4 * Written by Simon Glass <sjg@chromium.org>
5 */
6
Simon Glass052a03e2020-11-05 06:32:11 -07007#include <dm.h>
Raymond Mao8fe07312024-12-06 14:54:21 -08008#include <smbios_plat.h>
Simon Glass052a03e2020-11-05 06:32:11 -07009#include <sysinfo.h>
10
Raymond Mao8fe07312024-12-06 14:54:21 -080011/* platform information storage */
12struct processor_info processor_info;
13struct cache_info cache_info[SYSINFO_CACHE_LVL_MAX];
14struct sysinfo_plat sysinfo_smbios_p = {
15 /* Processor Information */
16 .processor = &processor_info,
17 /* Cache Information */
18 .cache = &cache_info[0],
19};
20
21/* structure for smbios private data storage */
22struct sysinfo_plat_priv {
23 struct processor_info *t4;
24 struct smbios_type7 t7[SYSINFO_CACHE_LVL_MAX];
25 u16 cache_handles[SYSINFO_CACHE_LVL_MAX];
26 u8 cache_level;
27};
28
29static void smbios_cache_info_dump(struct smbios_type7 *cache_info)
30{
31 log_debug("SMBIOS Type 7 (Cache Information):\n");
32 log_debug("Cache Configuration: 0x%04x\n", cache_info->config.data);
33 log_debug("Maximum Cache Size: %u KB\n", cache_info->max_size.data);
34 log_debug("Installed Size: %u KB\n", cache_info->inst_size.data);
35 log_debug("Supported SRAM Type: 0x%04x\n",
36 cache_info->supp_sram_type.data);
37 log_debug("Current SRAM Type: 0x%04x\n",
38 cache_info->curr_sram_type.data);
39 log_debug("Cache Speed: %u\n", cache_info->speed);
40 log_debug("Error Correction Type: %u\n", cache_info->err_corr_type);
41 log_debug("System Cache Type: %u\n", cache_info->sys_cache_type);
42 log_debug("Associativity: %u\n", cache_info->associativity);
43 log_debug("Maximum Cache Size 2: %u KB\n", cache_info->max_size2.data);
44 log_debug("Installed Cache Size 2: %u KB\n",
45 cache_info->inst_size2.data);
46}
47
48/* weak function for the platforms not yet supported */
49__weak int sysinfo_get_cache_info(u8 level, struct cache_info *cache_info)
50{
51 return -ENOSYS;
52}
53
54__weak int sysinfo_get_processor_info(struct processor_info *pinfo)
55{
56 return -ENOSYS;
57}
58
59void sysinfo_cache_info_default(struct cache_info *ci)
60{
61 memset(ci, 0, sizeof(*ci));
62 ci->config.data = SMBIOS_CACHE_LOCATE_UNKNOWN | SMBIOS_CACHE_OP_UND;
63 ci->supp_sram_type.fields.unknown = 1;
64 ci->curr_sram_type.fields.unknown = 1;
65 ci->speed = SMBIOS_CACHE_SPEED_UNKNOWN;
66 ci->err_corr_type = SMBIOS_CACHE_ERRCORR_UNKNOWN;
67 ci->cache_type = SMBIOS_CACHE_SYSCACHE_TYPE_UNKNOWN;
68}
69
70static int sysinfo_plat_detect(struct udevice *dev)
71{
72 return 0;
73}
74
75static int sysinfo_plat_get_str(struct udevice *dev, int id,
76 size_t size, char *val)
77{
78 struct sysinfo_plat_priv *priv = dev_get_priv(dev);
79 const char *str = NULL;
80
81 switch (id) {
82 case SYSID_SM_PROCESSOR_MANUFACT:
83 str = priv->t4->manufacturer;
84 break;
85 default:
86 break;
87 }
88
89 if (!str)
90 return -ENOSYS;
91
92 strlcpy(val, str, size);
93
94 return 0;
95}
96
97static int sysinfo_plat_get_int(struct udevice *dev, int id, int *val)
98{
99 struct sysinfo_plat_priv *priv = dev_get_priv(dev);
100 u8 i;
101
102 if (id >= SYSID_SM_CACHE_INFO_START &&
103 id <= SYSID_SM_CACHE_INFO_END) {
104 /* For smbios type 7 */
105 for (i = 0; i < priv->cache_level; i++) {
106 switch (id - i) {
107 case SYSID_SM_CACHE_MAX_SIZE:
108 *val = priv->t7[i].max_size.data;
109 return 0;
110 case SYSID_SM_CACHE_INST_SIZE:
111 *val = priv->t7[i].inst_size.data;
112 return 0;
113 case SYSID_SM_CACHE_SCACHE_TYPE:
114 *val = priv->t7[i].sys_cache_type;
115 return 0;
116 case SYSID_SM_CACHE_ASSOC:
117 *val = priv->t7[i].associativity;
118 return 0;
119 case SYSID_SM_CACHE_MAX_SIZE2:
120 *val = priv->t7[i].max_size2.data;
121 return 0;
122 case SYSID_SM_CACHE_INST_SIZE2:
123 *val = priv->t7[i].inst_size2.data;
124 return 0;
125 default:
126 break;
127 }
128 }
129 return -ENOSYS;
130 }
131
132 switch (id) {
133 case SYSID_SM_PROCESSOR_CORE_CNT:
134 *val = priv->t4->core_count;
135 break;
136 case SYSID_SM_PROCESSOR_CORE_EN:
137 *val = priv->t4->core_enabled;
138 break;
139 case SYSID_SM_PROCESSOR_CHARA:
140 *val = priv->t4->characteristics;
141 break;
142 case SYSID_SM_CACHE_LEVEL:
143 if (!priv->cache_level) /* No cache detected */
144 return -ENOSYS;
145 *val = priv->cache_level - 1;
146 break;
147 default:
148 return -ENOSYS;
149 }
150
151 return 0;
152}
153
154static int sysinfo_plat_get_data(struct udevice *dev, int id, void **buf,
155 size_t *size)
156{
157 struct sysinfo_plat_priv *priv = dev_get_priv(dev);
158
159 switch (id) {
160 case SYSID_SM_PROCESSOR_ID:
161 *buf = priv->t4->id;
162 *size = sizeof(priv->t4->id);
163 break;
164 case SYSID_SM_CACHE_HANDLE:
165 *buf = &priv->cache_handles[0];
166 *size = sizeof(priv->cache_handles);
167 break;
168 default:
169 return -EOPNOTSUPP;
170 }
171 return 0;
172}
173
174static int sysinfo_plat_probe(struct udevice *dev)
175{
176 struct sysinfo_plat_priv *priv = dev_get_priv(dev);
177 struct sysinfo_plat *plat = &sysinfo_smbios_p;
178 u8 level;
179
180 if (!sysinfo_get_processor_info(plat->processor))
181 priv->t4 = plat->processor;
182
183 for (level = 0; level < SYSINFO_CACHE_LVL_MAX; level++) {
184 struct cache_info *pcache = plat->cache + level;
185
186 if (sysinfo_get_cache_info(level, pcache))
187 break; /* no more levels */
188
189 /*
190 * Fill in the SMBIOS type 7 structure,
191 * skip the header members (type, length, handle),
192 * and the ones in DT smbios node.
193 */
194 priv->t7[level].sys_cache_type = pcache->cache_type;
195 priv->t7[level].associativity = pcache->associativity;
196
197 if (pcache->max_size > SMBIOS_CACHE_SIZE_EXT_KB) {
198 priv->t7[level].max_size.data = 0xFFFF;
199 priv->t7[level].max_size2.fields.size =
200 pcache->max_size / 64;
201 priv->t7[level].max_size2.fields.granu =
202 SMBIOS_CACHE_GRANU_64K;
203 } else {
204 priv->t7[level].max_size.fields.size = pcache->max_size;
205 priv->t7[level].max_size.fields.granu =
206 SMBIOS_CACHE_GRANU_1K;
207 priv->t7[level].max_size2.data = 0;
208 }
209 if (pcache->inst_size > SMBIOS_CACHE_SIZE_EXT_KB) {
210 priv->t7[level].inst_size.data = 0xFFFF;
211 priv->t7[level].inst_size2.fields.size =
212 pcache->inst_size / 64;
213 priv->t7[level].inst_size2.fields.granu =
214 SMBIOS_CACHE_GRANU_64K;
215 } else {
216 priv->t7[level].inst_size.fields.size =
217 pcache->inst_size;
218 priv->t7[level].inst_size.fields.granu =
219 SMBIOS_CACHE_GRANU_1K;
220 priv->t7[level].inst_size2.data = 0;
221 }
222 smbios_cache_info_dump(&priv->t7[level]);
223 }
224 if (!level) /* no cache detected */
225 return -ENOSYS;
226
227 priv->cache_level = level;
228
229 return 0;
230}
231
Simon Glass052a03e2020-11-05 06:32:11 -0700232static const struct udevice_id sysinfo_smbios_ids[] = {
233 { .compatible = "u-boot,sysinfo-smbios" },
234 { /* sentinel */ }
235};
236
237static const struct sysinfo_ops sysinfo_smbios_ops = {
Raymond Mao8fe07312024-12-06 14:54:21 -0800238 .detect = sysinfo_plat_detect,
239 .get_str = sysinfo_plat_get_str,
240 .get_int = sysinfo_plat_get_int,
241 .get_data = sysinfo_plat_get_data,
Simon Glass052a03e2020-11-05 06:32:11 -0700242};
243
244U_BOOT_DRIVER(sysinfo_smbios) = {
245 .name = "sysinfo_smbios",
246 .id = UCLASS_SYSINFO,
247 .of_match = sysinfo_smbios_ids,
248 .ops = &sysinfo_smbios_ops,
Raymond Mao8fe07312024-12-06 14:54:21 -0800249 .priv_auto = sizeof(struct sysinfo_plat_priv),
250 .probe = sysinfo_plat_probe,
Simon Glass052a03e2020-11-05 06:32:11 -0700251};