mosys: Add herobrine memory support
BUG=b:177917361
TEST=mosys -v -v -v -v memory spd print all
Cq-Depend: chrome-internal:4710395
Change-Id: I936bf8fc66a2cb5853cd206a1d82d80bdc846d95
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/mosys/+/3422166
Reviewed-by: Julius Werner <jwerner@chromium.org>
Reviewed-by: Jack Rosenthal <jrosenth@chromium.org>
Reviewed-by: Jian-Jia Su <jjsu@chromium.org>
Tested-by: Bob Moragues <moragues@chromium.org>
Commit-Queue: Jian-Jia Su <jjsu@chromium.org>
diff --git a/include/lib/fdt.h b/include/lib/fdt.h
index 6bde94d..52e6677 100644
--- a/include/lib/fdt.h
+++ b/include/lib/fdt.h
@@ -44,6 +44,20 @@
extern int fdt_get_ram_code(uint32_t *ram_code);
/*
+ * fdt_get_ram_manufacturer_id - Get RAM manufacturer id from device tree
+ *
+ * returns 0 to indicate success, <0 to indicate failure.
+ */
+extern int fdt_get_ram_manufacturer_id(uint8_t *manufacturer_id);
+
+/*
+ * fdt_get_ram_revision_id - Get the two byte RAM revision id from device tree
+ *
+ * returns 0 to indicate success, <0 to indicate failure.
+ */
+extern int fdt_get_ram_revision_id(uint8_t *revision_id1, uint8_t *revision_id2);
+
+/*
* fdt_get_board_id - Obtain board ID code from FDT board-id node
*
* returns 0 to indicate success, <0 to indicate failure.
diff --git a/include/lib/lpddr_ids.h b/include/lib/lpddr_ids.h
new file mode 100644
index 0000000..33ae4ce
--- /dev/null
+++ b/include/lib/lpddr_ids.h
@@ -0,0 +1,13 @@
+/* Copyright 2022 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef LPDDR_IDS_H
+#define LPDDR_IDS_H
+
+#include "lib/nonspd.h"
+
+extern const struct nonspd_mem_info *lpddr_info_from_fdt_ids(void);
+
+#endif /* LPDDR_IDS_H */
diff --git a/include/lib/nonspd_modules.h b/include/lib/nonspd_modules.h
index d3cbb1e..66c0e62 100644
--- a/include/lib/nonspd_modules.h
+++ b/include/lib/nonspd_modules.h
@@ -37,6 +37,7 @@
extern const struct nonspd_mem_info micron_lpddr4x_mt53e1g32d2np_046wta;
extern const struct nonspd_mem_info micron_lpddr4x_mt53e1g32d2np_046wtb;
extern const struct nonspd_mem_info micron_lpddr4x_mt53e2g32d4nq_046wta;
+extern const struct nonspd_mem_info micron_lpddr4x_mt53e2g32d4nq_046wtc;
extern const struct nonspd_mem_info micron_lpddr4x_mt53e512m32d1np_046wtb;
extern const struct nonspd_mem_info micron_lpddr4x_mt53e512m32d2np_046;
extern const struct nonspd_mem_info micron_lpddr4x_mt53d1g32d4dt_046wtd;
@@ -56,6 +57,7 @@
extern const struct nonspd_mem_info samsung_lpddr4x_k4ube3d4ab_mgcl;
extern const struct nonspd_mem_info samsung_lpddr4x_k4ube3d4aa_mgcr;
extern const struct nonspd_mem_info samsung_lpddr4x_k4uce3q4aa_mgcr;
+extern const struct nonspd_mem_info samsung_lpddr4x_k4uce3q4ab_mgcl;
extern const struct nonspd_mem_info sandisk_lpddr4x_sdada4cr_128g;
extern const struct nonspd_mem_info foresee_lpddr4x_feprf6432_58a1930;
extern const struct nonspd_mem_info foresee_lpddr4x_flxc2004g_n1;
diff --git a/lib/file/fdt.c b/lib/file/fdt.c
index 82f9f4f..468dea8 100644
--- a/lib/file/fdt.c
+++ b/lib/file/fdt.c
@@ -52,6 +52,10 @@
#define FDT_BOARD_ID_PATH "firmware/coreboot/board-id"
#define FDT_SKU_ID_PATH "firmware/coreboot/sku-id"
+#define LPDDR3_MFG_ID_PATH "lpddr3/manufacturer_id"
+#define LPDDR3_REV_ID_PATH "lpddr3/revision_id"
+
+
/* returns number of bytes read or -1 to indicate error */
static ssize_t fdt_read_node(const char *path, char *buf, size_t buf_sz)
{
@@ -96,6 +100,60 @@
return 0;
}
+/*
+ * get_ram_manufacturer_id - Get RAM manufacturer id from device tree
+ *
+ * returns 0 to indicate success, <0 to indicate failure.
+ */
+
+int fdt_get_ram_manufacturer_id(uint8_t *manufacturer_id)
+{
+ uint32_t buf[2];
+
+ if (fdt_read_node(LPDDR3_MFG_ID_PATH, (char *)buf, sizeof(buf)) < sizeof(uint32_t)) {
+ lprintf(LOG_ERR,
+ "%s: Error when reading Manufacturer ID\n",
+ __func__);
+ return -1;
+ }
+
+ *manufacturer_id = ntohl(buf[0]);
+
+ lprintf(LOG_DEBUG,
+ "%s: manufacturer_id: %#02x\n",
+ __func__,
+ *manufacturer_id);
+ return 0;
+}
+
+/*
+ * get_ram_revision_id - Get RAM revision id from device tree
+ *
+ * returns 0 to indicate success, <0 to indicate failure.
+ */
+
+int fdt_get_ram_revision_id(uint8_t *revision_id1, uint8_t *revision_id2)
+{
+ uint32_t buf[3];
+
+ if (fdt_read_node(LPDDR3_REV_ID_PATH, (char *)buf, sizeof(buf)) < sizeof(uint32_t) * 2) {
+ lprintf(LOG_ERR,
+ "%s: Error when reading Revision ID\n",
+ __func__);
+ return -1;
+ }
+
+ *revision_id1 = ntohl(buf[0]);
+ *revision_id2 = ntohl(buf[1]);
+
+ lprintf(LOG_DEBUG,
+ "%s: revision_id: %#02x %#02x\n",
+ __func__,
+ *revision_id1,
+ *revision_id2);
+ return 0;
+}
+
int fdt_get_board_id(uint32_t *board_id)
{
if (fdt_get_uint32_val(FDT_BOARD_ID_PATH, board_id) < 0) {
diff --git a/lib/spd/lpddr_ids.c b/lib/spd/lpddr_ids.c
new file mode 100644
index 0000000..44cfc1e
--- /dev/null
+++ b/lib/spd/lpddr_ids.c
@@ -0,0 +1,74 @@
+/* Copyright 2022 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "lib/lpddr_ids.h"
+
+#include "lib/fdt.h"
+#include <stdbool.h>
+#include "lib/nonspd.h"
+#include "lib/nonspd_modules.h"
+
+enum herobrine_ram_manufacturer {
+ SAMSUNG = 0x01,
+ HYNIX = 0x06,
+ MICRON = 0xff,
+};
+
+const static struct {
+ uint8_t manufacturer;
+ uint8_t revision1;
+ uint8_t revision2;
+ const struct nonspd_mem_info *mem_info;
+} ddr_table[] = {
+ /* Current used components */
+ { HYNIX, 0x06, 0x06, &hynix_lpddr4x_h9hcnnnfammlxr_nee },
+ { MICRON, 0x07, 0x07, µn_lpddr4x_mt53e2g32d4nq_046wtc},
+
+ /* Placeholder for other AVL components in DLM */
+ { HYNIX, 0x00, 0x00, &hynix_lpddr4x_h54g68cyrbx248 },
+ { SAMSUNG, 0x00, 0x00, &samsung_lpddr4x_k4uce3q4ab_mgcl },
+};
+
+const struct nonspd_mem_info *lpddr_info_from_fdt_ids(void)
+{
+ static const struct nonspd_mem_info *lpddr_mem_info;
+
+ static bool ran_once;
+
+ uint8_t ram_manufacturer;
+ uint8_t ram_revision1;
+ uint8_t ram_revision2;
+
+ if (ran_once)
+ return lpddr_mem_info;
+
+ ran_once = true;
+
+ if (fdt_get_ram_manufacturer_id(&ram_manufacturer) < 0) {
+ lprintf(LOG_ERR,
+ "%s: Unable to obtain RAM manufacturer_id.\n",
+ __func__);
+ return lpddr_mem_info;
+ }
+ if (fdt_get_ram_revision_id(&ram_revision1, &ram_revision2) < 0) {
+ lprintf(LOG_ERR, "%s: Unable to obtain RAM revision_id.\n",
+ __func__);
+ return lpddr_mem_info;
+ }
+
+ for (int i = 0; i < ARRAY_SIZE(ddr_table); i++) {
+ if ((ddr_table[i].manufacturer == ram_manufacturer) &&
+ (ddr_table[i].revision1 == ram_revision1) &&
+ (ddr_table[i].revision2 == ram_revision2)) {
+ lpddr_mem_info = ddr_table[i].mem_info;
+ return lpddr_mem_info;
+ }
+ }
+ lprintf(LOG_ERR,
+ "%s: Unrecognized configuration: Manufacturer ID: %#02x Revision ID: %#02x %#02x\n",
+ __func__, ram_manufacturer, ram_revision1, ram_revision2);
+
+ return lpddr_mem_info;
+}
diff --git a/lib/spd/meson.build b/lib/spd/meson.build
index be77d09..9a32726 100644
--- a/lib/spd/meson.build
+++ b/lib/spd/meson.build
@@ -2,4 +2,5 @@
'nonspd_modules.c',
'nonspd.c',
'jedec_id.c',
+ 'lpddr_ids.c',
)
diff --git a/lib/spd/nonspd_modules.c b/lib/spd/nonspd_modules.c
index bbd7cad..d833f4b 100644
--- a/lib/spd/nonspd_modules.c
+++ b/lib/spd/nonspd_modules.c
@@ -377,6 +377,19 @@
.part_num = "MT53E2G32D4NQ-46WT:A",
};
+const struct nonspd_mem_info micron_lpddr4x_mt53e2g32d4nq_046wtc = {
+ .dram_type = SPD_DRAM_TYPE_LPDDR4X,
+
+ .module_size_mbits = 65536,
+ .num_ranks = 2,
+ .device_width = 32,
+
+ .module_mfg_id = MFGID_MICRON,
+ .dram_mfg_id = MFGID_MICRON,
+
+ .part_num = "MT53E2G32D4NQ-46WT:C",
+};
+
const struct nonspd_mem_info micron_lpddr4x_mt53e512m32d1np_046wtb = {
.dram_type = SPD_DRAM_TYPE_LPDDR4X,
@@ -598,6 +611,19 @@
.part_num = "K4UCE3Q4AA-MGCR",
};
+const struct nonspd_mem_info samsung_lpddr4x_k4uce3q4ab_mgcl = {
+ .dram_type = SPD_DRAM_TYPE_LPDDR4X,
+
+ .module_size_mbits = 65536,
+ .num_ranks = 2,
+ .device_width = 32,
+
+ .module_mfg_id = MFGID_SAMSUNG,
+ .dram_mfg_id = MFGID_SAMSUNG,
+
+ .part_num = "K4UCE3Q4AB-MGCL",
+};
+
const struct nonspd_mem_info sandisk_lpddr4x_sdada4cr_128g = {
.dram_type = SPD_DRAM_TYPE_LPDDR4X,
diff --git a/platform/arm/herobrine/herobrine.c b/platform/arm/herobrine/herobrine.c
index a240531..ae00818 100644
--- a/platform/arm/herobrine/herobrine.c
+++ b/platform/arm/herobrine/herobrine.c
@@ -8,10 +8,12 @@
#include "lib/sku.h"
#include "mosys/command_list.h"
#include "mosys/platform.h"
+#include "herobrine.h"
/* TODO(b:177917361): Add &cmd_memory */
static struct platform_cmd *herobrine_sub[] = {
&cmd_ec,
+ &cmd_memory,
&cmd_pd,
&cmd_platform,
NULL
@@ -19,13 +21,14 @@
/* TODO(b:177917361): add .memory */
static struct platform_cb herobrine_cb = {
- .ec = &cros_ec_cb,
- .sys = &fdt_sysinfo_cb,
+ .ec = &cros_ec_cb,
+ .memory = &herobrine_memory_cb,
+ .sys = &fdt_sysinfo_cb,
};
static struct platform_intf platform_herobrine = {
- .type = PLATFORM_ARMV8,
- .sub = herobrine_sub,
- .cb = &herobrine_cb,
+ .type = PLATFORM_ARMV8,
+ .sub = herobrine_sub,
+ .cb = &herobrine_cb,
};
REGISTER_PLATFORM(platform_herobrine, "Herobrine");
diff --git a/platform/arm/herobrine/herobrine.h b/platform/arm/herobrine/herobrine.h
new file mode 100644
index 0000000..c12f6c4
--- /dev/null
+++ b/platform/arm/herobrine/herobrine.h
@@ -0,0 +1,14 @@
+/* Copyright 2022 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GOOGLE_HEROBRINE_H
+#define GOOGLE_HEROBRINE_H
+
+#include "mosys/platform.h"
+
+/* platform callbacks */
+extern struct memory_cb herobrine_memory_cb;
+
+#endif /* GOOGLE_HEROBRIBNE_H */
diff --git a/platform/arm/herobrine/memory.c b/platform/arm/herobrine/memory.c
new file mode 100644
index 0000000..e04e572
--- /dev/null
+++ b/platform/arm/herobrine/memory.c
@@ -0,0 +1,38 @@
+/* Copyright 2022 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "lib/fdt.h"
+#include "lib/lpddr_ids.h"
+#include "lib/nonspd.h"
+#include "mosys/platform.h"
+#include "herobrine.h"
+
+/*
+ * dimm_count - return total number of dimm slots
+ *
+ * @intf: platform interface
+ *
+ * returns dimm slot count
+ */
+static int dimm_count(struct platform_intf *intf)
+{
+ return 1;
+}
+
+static int get_mem_info(struct platform_intf *intf, int dimm,
+ const struct nonspd_mem_info **info)
+{
+ *info = lpddr_info_from_fdt_ids();
+
+ if (*info)
+ return 0;
+ else
+ return -1;
+}
+
+struct memory_cb herobrine_memory_cb = {
+ .dimm_count = &dimm_count,
+ .nonspd_mem_info = &get_mem_info,
+};
diff --git a/platform/arm/herobrine/meson.build b/platform/arm/herobrine/meson.build
index 5021365..e532a57 100644
--- a/platform/arm/herobrine/meson.build
+++ b/platform/arm/herobrine/meson.build
@@ -1,3 +1,4 @@
platform_support_src += files(
+ 'memory.c',
'herobrine.c',
)