[v2,2/2] hdata: Parse SPD data

Message ID 20171013112119.30164-2-hegdevasant@linux.vnet.ibm.com
State New
Headers show
Series
  • [v2,1/2] hdata: Add memory hierarchy under xscom node
Related show

Commit Message

Vasant Hegde Oct. 13, 2017, 11:21 a.m.
Parse SPD data and populate device tree.

list of properites parsing from SPD:
-----------------------------------
[root@ltc-wspoon dimm@d00f]# lsprop .
memory-id        0000000c (12)      <-- DIMM type
product-version  00000032 (50)	    <-- Module Revision Code
device_type      "memory-dimm-ddr4"
serial-number    15d9acb6 (366587062)
status           "okay"
size             00004000 (16384)
phandle          000000bd (189)
ibm,loc-code     "UOPWR.0000000-Node0-DIMM7"
part-number      "36ASF2G72PZ-2G6B2   "
reg              0000d007 (53255)
name             "dimm"
manufacturer-id  0000802c (32812)    <-- Vendor ID, we can get vendor name from this ID

Also update documentation.

Signed-off-by: Vasant Hegde <hegdevasant@linux.vnet.ibm.com>
---
Changes in v2:
  - Added few more properties
  - Updated documentation

-Vasant

 doc/device-tree/memory-hierarchy.rst | 24 +++++++++++++++++
 hdata/memory.c                       | 50 +++++++++++++++++++++++++++++++++++-
 2 files changed, 73 insertions(+), 1 deletion(-)
 create mode 100644 doc/device-tree/memory-hierarchy.rst

Patch

diff --git a/doc/device-tree/memory-hierarchy.rst b/doc/device-tree/memory-hierarchy.rst
new file mode 100644
index 0000000..1da0c54
--- /dev/null
+++ b/doc/device-tree/memory-hierarchy.rst
@@ -0,0 +1,24 @@ 
+P9 memory hierarchy
+-------------------
+P9 Nimbus supports direct attached DDR memory through 4 DDR ports per side
+of the processor. Device tree contains memory hierarchy so that one can
+traverse from chip to DIMM like below:
+
+  xscom@<addr>/mcbist@<mcbist_id>/mcs@<mcs_id>/mca@<mca_id>/dimm@<resource_id>
+
+Example of dimm node:
+.. code-block:: dts
+
+  dimm@d00e {
+          memory-id = <0xc>; /* DRAM Device Type. 0xc = DDR4 */
+          product-version = <0x32>; /* Module Revision Code */
+          device_type = "memory-dimm-ddr4";
+          serial-number = <0x15d9ad1c>;
+          status = "okay";
+          size = <0x4000>;
+          phandle = <0xd2>;
+          ibm,loc-code = "UOPWR.0000000-Node0-DIMM14";
+          part-number = "36ASF2G72PZ-2G6B2   ";
+          reg = <0xd00e>;
+          manufacturer-id = <0x802c>; /* Vendor ID, we can get vendor name from this ID */
+  };
diff --git a/hdata/memory.c b/hdata/memory.c
index 74eedff..27dc559 100644
--- a/hdata/memory.c
+++ b/hdata/memory.c
@@ -319,16 +319,56 @@  static void vpd_add_ram_area(const struct HDIF_common_hdr *msarea)
 	}
 }
 
+static void vpd_parse_spd(struct dt_node *dimm, const char *spd, u32 size)
+{
+	u16 *vendor;
+	u32 *sn;
+
+	/* SPD is too small */
+	if (size < 512) {
+		prlog(PR_WARNING, "MSVPD: Invalid SPD size. "
+		      "Expected 512 bytes, got %d\n", size);
+		return;
+	}
+
+	/* Supports DDR4 format pasing only */
+	if (spd[0x2] < 0xc) {
+		prlog(PR_WARNING,
+		      "MSVPD: SPD format (%x) not supported\n", spd[0x2]);
+		return;
+	}
+
+	dt_add_property_string(dimm, "device_type", "memory-dimm-ddr4");
+
+	/* DRAM device type */
+	dt_add_property_cells(dimm, "memory-id", spd[0x2]);
+
+	/* Module revision code */
+	dt_add_property_cells(dimm, "product-version", spd[0x15d]);
+
+	/* Serial number */
+	sn = (u32 *)&spd[0x145];
+	dt_add_property_cells(dimm, "serial-number", be32_to_cpu(*sn));
+
+	/* Part number */
+	dt_add_property_nstr(dimm, "part-number", &spd[0x149], 20);
+
+	/* Module manufacturer ID */
+	vendor = (u16 *)&spd[0x140];
+	dt_add_property_cells(dimm, "manufacturer-id", be16_to_cpu(*vendor));
+}
+
 static void add_mca_dimm_info(struct dt_node *mca,
 			      const struct HDIF_common_hdr *msarea)
 {
-	unsigned int i;
+	unsigned int i, size;
 	const struct HDIF_child_ptr *ramptr;
 	const struct HDIF_common_hdr *ramarea;
 	const struct spira_fru_id *fru_id;
 	const struct HDIF_ram_area_id *ram_id;
 	const struct HDIF_ram_area_size *ram_area_sz;
 	struct dt_node *dimm;
+	const void *vpd_blob;
 
 	ramptr = HDIF_child_arr(msarea, 0);
 	if (!CHECK_SPPTR(ramptr)) {
@@ -373,6 +413,14 @@  static void add_mca_dimm_info(struct dt_node *mca,
 			dt_add_property_string(dimm, "status", "okay");
 		else
 			dt_add_property_string(dimm, "status", "disabled");
+
+		vpd_blob = HDIF_get_idata(ramarea, 1, &size);
+		if (!CHECK_SPPTR(vpd_blob))
+			continue;
+		if (vpd_valid(vpd_blob, size))
+			vpd_data_parse(dimm, vpd_blob, size);
+		else
+			vpd_parse_spd(dimm, vpd_blob, size);
 	}
 }