summaryrefslogtreecommitdiff
path: root/src/mainboard/prodrive/atlas/vpd.c
diff options
context:
space:
mode:
authorAngel Pons <th3fanbus@gmail.com>2023-03-22 13:25:09 +0100
committerLean Sheng Tan <sheng.tan@9elements.com>2023-03-24 16:39:17 +0000
commit56c1c4dff9c7ccd8968a3e32be800375bf3d5b78 (patch)
treef8614b97e6f66a63fe48cc1558f7e4dc37b12bea /src/mainboard/prodrive/atlas/vpd.c
parent964079f77cced3aedc468a888b6b6f32cfbec7c9 (diff)
mb/prodrive/atlas: Implement initial VPD support
Atlas stores VPD (Vital Product Data) in an I2C EEPROM, which is only connected to the EC. In order for the host (x86) to be able to access the VPD, the EC reads the EEPROM contents into a buffer in EC RAM and provides the host with read-only access to this EC RAM buffer through EMI (Embedded Memory Interface) 0. The VPD layout is designed to be extensible yet backwards compatible. The code in coreboot uses the revision field to know which fields are valid, and will populate the rest with fallback values. Use the serial number and part number in VPD to populate SMBIOS tables. Change-Id: I2d3d70fee22548daa73ef98af56c98e950dc5e9d Signed-off-by: Angel Pons <th3fanbus@gmail.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/73937 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Lean Sheng Tan <sheng.tan@9elements.com>
Diffstat (limited to 'src/mainboard/prodrive/atlas/vpd.c')
-rw-r--r--src/mainboard/prodrive/atlas/vpd.c60
1 files changed, 60 insertions, 0 deletions
diff --git a/src/mainboard/prodrive/atlas/vpd.c b/src/mainboard/prodrive/atlas/vpd.c
new file mode 100644
index 0000000000..12371f71e6
--- /dev/null
+++ b/src/mainboard/prodrive/atlas/vpd.c
@@ -0,0 +1,60 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <console/console.h>
+#include <string.h>
+#include <types.h>
+
+#include "ec.h"
+#include "mainboard.h"
+#include "vpd.h"
+
+const union emi_eeprom_vpd *get_emi_eeprom_vpd(void)
+{
+ static union emi_eeprom_vpd vpd = {0};
+
+ /* Check if cached VPD is valid */
+ if (vpd.header.revision == VPD_LATEST_REVISION)
+ return &vpd;
+
+ ec_emi_read(vpd.raw, EMI_0_IO_BASE_ADDR, 0, 0, sizeof(vpd.raw));
+
+ /* If the magic value doesn't match, consider EEPROM VPD unreliable */
+ if (vpd.header.magic != VPD_MAGIC) {
+ printk(BIOS_WARNING, "Atlas VPD: Bad magic value, using fallback defaults\n");
+ vpd.header.revision = 0;
+ } else {
+ printk(BIOS_DEBUG, "Atlas VPD: Got revision %u from EC\n", vpd.header.revision);
+ }
+
+ /*
+ * For backwards compatibility, if the VPD from the EC is an older
+ * version, uprev it to the latest version coreboot knows about by
+ * filling in the remaining fields with default values. Should the
+ * EC provide a newer VPD revision, coreboot would downgrade it to
+ * the latest version it knows about as the VPD layout is designed
+ * to be backwards compatible.
+ *
+ * Whenever the value of `VPD_LATEST_REVISION` is incremented, add
+ * a new `case` label just before the `default` label that matches
+ * the second latest revision to initialise the newly-added fields
+ * of the VPD structure with a reasonable fallback value. Note the
+ * intentional falling through.
+ */
+ switch (vpd.header.revision) {
+ case 0:
+ memset(vpd.raw, 0, sizeof(vpd.raw));
+ vpd.header.magic = VPD_MAGIC;
+ vpd.serial_number[0] = '\0';
+ vpd.part_number[0] = '\0';
+ vpd.profile = ATLAS_PROF_UNPROGRAMMED;
+ __fallthrough;
+ default:
+ /* Ensure serial numbers are NULL-terminated, update revision last */
+ vpd.serial_number[ATLAS_SN_PN_LENGTH - 1] = '\0';
+ vpd.part_number[ATLAS_SN_PN_LENGTH - 1] = '\0';
+ vpd.header.revision = VPD_LATEST_REVISION;
+ break;
+ }
+
+ return &vpd;
+}