
The type 4 table generation code is very x86 centric today. Refactor things out into the device model cpu class to allow the tables to get generated for other architectures as well.
Signed-off-by: Alexander Graf agraf@suse.de
---
v3 -> v4:
- Use device model
v4 -> v5:
- s/get_info/get_vendor/ typo - s/smbios_write_type4_arch/smbios_write_type4_dm/ --- arch/x86/cpu/baytrail/cpu.c | 1 + arch/x86/cpu/broadwell/cpu.c | 1 + arch/x86/cpu/cpu_x86.c | 13 ++++++++++ arch/x86/cpu/ivybridge/model_206ax.c | 1 + arch/x86/include/asm/cpu_x86.h | 12 +++++++++ drivers/cpu/cpu-uclass.c | 10 ++++++++ include/cpu.h | 20 +++++++++++++++ include/smbios.h | 3 +++ lib/smbios.c | 49 ++++++++++++++++++++++++++---------- 9 files changed, 97 insertions(+), 13 deletions(-)
diff --git a/arch/x86/cpu/baytrail/cpu.c b/arch/x86/cpu/baytrail/cpu.c index b1faf8c..c454db0 100644 --- a/arch/x86/cpu/baytrail/cpu.c +++ b/arch/x86/cpu/baytrail/cpu.c @@ -141,6 +141,7 @@ static const struct cpu_ops cpu_x86_baytrail_ops = { .get_desc = cpu_x86_get_desc, .get_info = baytrail_get_info, .get_count = baytrail_get_count, + .get_vendor = cpu_x86_get_vendor, };
static const struct udevice_id cpu_x86_baytrail_ids[] = { diff --git a/arch/x86/cpu/broadwell/cpu.c b/arch/x86/cpu/broadwell/cpu.c index 3ba21aa..6977e86 100644 --- a/arch/x86/cpu/broadwell/cpu.c +++ b/arch/x86/cpu/broadwell/cpu.c @@ -743,6 +743,7 @@ static const struct cpu_ops cpu_x86_broadwell_ops = { .get_desc = cpu_x86_get_desc, .get_info = broadwell_get_info, .get_count = broadwell_get_count, + .get_vendor = cpu_x86_get_vendor, };
static const struct udevice_id cpu_x86_broadwell_ids[] = { diff --git a/arch/x86/cpu/cpu_x86.c b/arch/x86/cpu/cpu_x86.c index 0941041..3b0458d 100644 --- a/arch/x86/cpu/cpu_x86.c +++ b/arch/x86/cpu/cpu_x86.c @@ -15,9 +15,21 @@ DECLARE_GLOBAL_DATA_PTR; int cpu_x86_bind(struct udevice *dev) { struct cpu_platdata *plat = dev_get_parent_platdata(dev); + struct cpuid_result res;
plat->cpu_id = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "intel,apic-id", -1); + plat->family = gd->arch.x86; + res = cpuid(1); + plat->id[0] = res.eax; + plat->id[1] = res.edx; + + return 0; +} + +int cpu_x86_get_vendor(struct udevice *dev, const char **vendor) +{ + *vendor = cpu_vendor_name(gd->arch.x86_vendor);
return 0; } @@ -60,6 +72,7 @@ static int cpu_x86_get_count(struct udevice *dev) static const struct cpu_ops cpu_x86_ops = { .get_desc = cpu_x86_get_desc, .get_count = cpu_x86_get_count, + .get_vendor = cpu_x86_get_vendor, };
static const struct udevice_id cpu_x86_ids[] = { diff --git a/arch/x86/cpu/ivybridge/model_206ax.c b/arch/x86/cpu/ivybridge/model_206ax.c index 38e244b..d8eb2e7 100644 --- a/arch/x86/cpu/ivybridge/model_206ax.c +++ b/arch/x86/cpu/ivybridge/model_206ax.c @@ -478,6 +478,7 @@ static const struct cpu_ops cpu_x86_model_206ax_ops = { .get_desc = cpu_x86_get_desc, .get_info = model_206ax_get_info, .get_count = model_206ax_get_count, + .get_vendor = cpu_x86_get_vendor, };
static const struct udevice_id cpu_x86_model_206ax_ids[] = { diff --git a/arch/x86/include/asm/cpu_x86.h b/arch/x86/include/asm/cpu_x86.h index 1940480..79aaf2d 100644 --- a/arch/x86/include/asm/cpu_x86.h +++ b/arch/x86/include/asm/cpu_x86.h @@ -31,4 +31,16 @@ int cpu_x86_bind(struct udevice *dev); */ int cpu_x86_get_desc(struct udevice *dev, char *buf, int size);
+/** + * cpu_x86_get_vendor() - Get a vendor string for an x86 CPU + * + * This uses cpu_vendor_name() and is suitable to use as the get_vendor() + * method for the CPU uclass. + * + * @dev: Device to check (UCLASS_CPU) + * @vendor: Pointer to vendor string pointer + * @return: 0 if OK, -ve on error + */ +int cpu_x86_get_vendor(struct udevice *dev, const char **vendor); + #endif /* _ASM_CPU_X86_H */ diff --git a/drivers/cpu/cpu-uclass.c b/drivers/cpu/cpu-uclass.c index 7660f99..b25c3b4 100644 --- a/drivers/cpu/cpu-uclass.c +++ b/drivers/cpu/cpu-uclass.c @@ -44,6 +44,16 @@ int cpu_get_count(struct udevice *dev) return ops->get_count(dev); }
+int cpu_get_vendor(struct udevice *dev, const char **vendor) +{ + struct cpu_ops *ops = cpu_get_ops(dev); + + if (!ops->vendor) + return -ENOSYS; + + return ops->get_vendor(dev, vendor); +} + U_BOOT_DRIVER(cpu_bus) = { .name = "cpu_bus", .id = UCLASS_SIMPLE_BUS, diff --git a/include/cpu.h b/include/cpu.h index bda5315..2285aee 100644 --- a/include/cpu.h +++ b/include/cpu.h @@ -21,6 +21,8 @@ struct cpu_platdata { int cpu_id; int ucode_version; ulong device_id; + u16 family; + u32 id[2]; };
/* CPU features - mostly just a placeholder for now */ @@ -71,6 +73,15 @@ struct cpu_ops { * @return CPU count if OK, -ve on error */ int (*get_count)(struct udevice *dev); + + /** + * get_vendor() - Get vendor name of a CPU + * + * @dev: Device to check (UCLASS_CPU) + * @vendor: Pointer to put the pointer to the vendor string + * @return 0 if OK, -ve on error + */ + int (*get_vendor)(struct udevice *dev, const char **vendor); };
#define cpu_get_ops(dev) ((struct cpu_ops *)(dev)->driver->ops) @@ -102,4 +113,13 @@ int cpu_get_info(struct udevice *dev, struct cpu_info *info); */ int cpu_get_count(struct udevice *dev);
+/** + * cpu_get_vendor() - Get vendor name of a CPU + * + * @dev: Device to check (UCLASS_CPU) + * @vendor: Pointer to put the pointer to the vendor string + * @return 0 if OK, -ve on error + */ +int cpu_get_vendor(struct udevice *dev, const char **vendor); + #endif diff --git a/include/smbios.h b/include/smbios.h index 5962d4c..3cbc687 100644 --- a/include/smbios.h +++ b/include/smbios.h @@ -139,6 +139,9 @@ struct __packed smbios_type3 { #define SMBIOS_PROCESSOR_STATUS_ENABLED 1 #define SMBIOS_PROCESSOR_UPGRADE_NONE 6
+#define SMBIOS_PROCESSOR_FAMILY_OTHER 1 +#define SMBIOS_PROCESSOR_FAMILY_UNKNOWN 2 + struct __packed smbios_type4 { u8 type; u8 length; diff --git a/lib/smbios.c b/lib/smbios.c index 8dfd486..6e8f00a 100644 --- a/lib/smbios.c +++ b/lib/smbios.c @@ -10,7 +10,11 @@ #include <smbios.h> #include <tables_csum.h> #include <version.h> -#include <asm/cpu.h> +#ifdef CONFIG_CPU +#include <cpu.h> +#include <dm.h> +#include <dm/uclass-internal.h> +#endif
DECLARE_GLOBAL_DATA_PTR;
@@ -152,26 +156,45 @@ static int smbios_write_type3(uintptr_t *current, int handle) return len; }
+static void smbios_write_type4_dm(struct smbios_type4 *t) +{ + u16 processor_family = SMBIOS_PROCESSOR_FAMILY_UNKNOWN; + const char *vendor = "Unknown"; + const char *name = "Unknown"; + +#ifdef CONFIG_CPU + char processor_name[49]; + struct udevice *dev = NULL; + + uclass_find_first_device(UCLASS_CPU, &dev); + if (dev) { + struct cpu_platdata *plat = dev_get_parent_platdata(dev); + + if (plat->family) + processor_family = plat->family; + t->processor_id[0] = plat->id[0]; + t->processor_id[1] = plat->id[1]; + + cpu_get_vendor(dev, &vendor); + if (!cpu_get_desc(dev, processor_name, sizeof(processor_name))) + name = processor_name; + } +#endif + + t->processor_family = processor_family; + t->processor_manufacturer = smbios_add_string(t->eos, vendor); + t->processor_version = smbios_add_string(t->eos, name); +} + static int smbios_write_type4(uintptr_t *current, int handle) { struct smbios_type4 *t = (struct smbios_type4 *)*current; int len = sizeof(struct smbios_type4); - const char *vendor; - char *name; - char processor_name[CPU_MAX_NAME_LEN]; - struct cpuid_result res;
memset(t, 0, sizeof(struct smbios_type4)); fill_smbios_header(t, SMBIOS_PROCESSOR_INFORMATION, len, handle); t->processor_type = SMBIOS_PROCESSOR_TYPE_CENTRAL; - t->processor_family = gd->arch.x86; - vendor = cpu_vendor_name(gd->arch.x86_vendor); - t->processor_manufacturer = smbios_add_string(t->eos, vendor); - res = cpuid(1); - t->processor_id[0] = res.eax; - t->processor_id[1] = res.edx; - name = cpu_get_name(processor_name); - t->processor_version = smbios_add_string(t->eos, name); + smbios_write_type4_dm(t); t->status = SMBIOS_PROCESSOR_STATUS_ENABLED; t->processor_upgrade = SMBIOS_PROCESSOR_UPGRADE_NONE; t->l1_cache_handle = 0xffff;