aboutsummaryrefslogtreecommitdiff
path: root/hdata/memory.c
diff options
context:
space:
mode:
Diffstat (limited to 'hdata/memory.c')
-rwxr-xr-x[-rw-r--r--]hdata/memory.c139
1 files changed, 125 insertions, 14 deletions
diff --git a/hdata/memory.c b/hdata/memory.c
index 6d060f7..7ce9275 100644..100755
--- a/hdata/memory.c
+++ b/hdata/memory.c
@@ -55,10 +55,17 @@ struct HDIF_ms_area_address_range {
#define PHYS_ATTR_STATUS_NOT_SAVED 0x08
#define PHYS_ATTR_STATUS_MEM_INVALID 0xff
+/* Memory Controller ID for Nimbus P9 systems */
#define MS_CONTROLLER_MCBIST_ID(id) GETFIELD(PPC_BITMASK32(0, 1), id)
#define MS_CONTROLLER_MCS_ID(id) GETFIELD(PPC_BITMASK32(4, 7), id)
#define MS_CONTROLLER_MCA_ID(id) GETFIELD(PPC_BITMASK32(8, 15), id)
+/* Memory Controller ID for P9 AXONE systems */
+#define MS_CONTROLLER_MC_ID(id) GETFIELD(PPC_BITMASK32(0, 1), id)
+#define MS_CONTROLLER_MI_ID(id) GETFIELD(PPC_BITMASK32(4, 7), id)
+#define MS_CONTROLLER_MCC_ID(id) GETFIELD(PPC_BITMASK32(8, 15), id)
+#define MS_CONTROLLER_OMI_ID(id) GETFIELD(PPC_BITMASK32(16, 31), id)
+
struct HDIF_ms_area_id {
__be16 id;
#define MS_PTYPE_RISER_CARD 0x8000
@@ -73,6 +80,20 @@ struct HDIF_ms_area_id {
__be16 share_id;
} __packed;
+
+// FIXME: it should be 9, current HDATs are broken
+#define MSAREA_IDATA_MMIO_IDX 8
+struct HDIF_ms_area_ocmb_mmio {
+ __be64 range_start;
+ __be64 range_end;
+ __be32 controller_id;
+ __be32 proc_chip_id;
+ __be64 hbrt_id;
+#define OCMB_SCOM_8BYTE_ACCESS PPC_BIT(0)
+#define OCMB_SCOM_4BYTE_ACCESS PPC_BIT(1)
+ __be64 flags;
+} __packed;
+
static void append_chip_id(struct dt_node *mem, u32 id)
{
struct dt_property *prop;
@@ -366,7 +387,7 @@ static void vpd_parse_spd(struct dt_node *dimm, const char *spd, u32 size)
dt_add_property_cells(dimm, "manufacturer-id", be16_to_cpu(*vendor));
}
-static void add_mca_dimm_info(struct dt_node *mca,
+static void add_dimm_info(struct dt_node *parent,
const struct HDIF_common_hdr *msarea)
{
unsigned int i, size;
@@ -394,11 +415,11 @@ static void add_mca_dimm_info(struct dt_node *mca,
continue;
/* Use Resource ID to add dimm node */
- dimm = dt_find_by_name_addr(mca, "dimm",
+ dimm = dt_find_by_name_addr(parent, "dimm",
be16_to_cpu(fru_id->rsrc_id));
if (dimm)
continue;
- dimm= dt_new_addr(mca, "dimm", be16_to_cpu(fru_id->rsrc_id));
+ dimm= dt_new_addr(parent, "dimm", be16_to_cpu(fru_id->rsrc_id));
assert(dimm);
dt_add_property_cells(dimm, "reg", be16_to_cpu(fru_id->rsrc_id));
@@ -439,21 +460,13 @@ static inline void dt_add_mem_reg_property(struct dt_node *node, u64 addr)
dt_add_property_cells(node, "reg", addr);
}
-static void add_memory_controller(const struct HDIF_common_hdr *msarea,
+static void add_memory_controller_p9n(const struct HDIF_common_hdr *msarea,
const struct HDIF_ms_area_address_range *arange)
{
- uint32_t chip_id, version;
+ uint32_t chip_id;
uint32_t controller_id, mcbist_id, mcs_id, mca_id;
struct dt_node *xscom, *mcbist, *mcs, *mca;
- /*
- * Memory hierarchy may change between processor version. Presently
- * it's only creating memory hierarchy for P9 (Nimbus) and P9P (Axone).
- */
- version = PVR_TYPE(mfspr(SPR_PVR));
- if (version != PVR_TYPE_P9 && version != PVR_TYPE_P9P)
- return;
-
chip_id = pcid_to_chip_id(be32_to_cpu(arange->chip));
controller_id = be32_to_cpu(arange->controller_id);
xscom = find_xscom_for_chip(chip_id);
@@ -489,7 +502,103 @@ static void add_memory_controller(const struct HDIF_common_hdr *msarea,
dt_add_mem_reg_property(mca, mca_id);
}
- add_mca_dimm_info(mca, msarea);
+ add_dimm_info(mca, msarea);
+}
+
+static void add_memory_buffer_mmio(const struct HDIF_common_hdr *msarea)
+{
+ const struct HDIF_ms_area_ocmb_mmio *mmio;
+ uint64_t min_addr = ~0ull, hbrt_id = 0;
+ const struct HDIF_array_hdr *array;
+ unsigned int i, count, ranges = 0;
+ struct dt_node *membuf;
+ uint64_t *reg, *flags;
+
+ if (be32_to_cpu(msarea->version) < 0x50) {
+ prlog(PR_WARNING, "MS AREA: Inconsistent MSAREA version %x for P9P system",
+ be32_to_cpu(msarea->version));
+ return;
+ }
+
+ array = HDIF_get_iarray(msarea, MSAREA_IDATA_MMIO_IDX, &count);
+ if (!array || count <= 0) {
+ prerror("MS AREA: No OCMB MMIO array at MS Area %p\n", msarea);
+ return;
+ }
+
+ reg = zalloc(count * 2 * sizeof(*reg));
+ flags = zalloc(count * sizeof(*flags));
+
+ /* grab the hbrt id from the first range. */
+ HDIF_iarray_for_each(array, i, mmio) {
+ hbrt_id = be64_to_cpu(mmio->hbrt_id);
+ break;
+ }
+
+ prlog(PR_DEBUG, "Adding memory buffer MMIO ranges for %"PRIx64"\n",
+ hbrt_id);
+
+ HDIF_iarray_for_each(array, i, mmio) {
+ uint64_t start, end;
+
+ if (hbrt_id != be64_to_cpu(mmio->hbrt_id)) {
+ prerror("HBRT ID mismatch!\n");
+ continue;
+ }
+
+ start = cleanup_addr(be64_to_cpu(mmio->range_start));
+ end = cleanup_addr(be64_to_cpu(mmio->range_end));
+ if (start < min_addr)
+ min_addr = start;
+
+ prlog(PR_DEBUG, " %"PRIx64" - [%016"PRIx64"-%016"PRIx64")\n",
+ hbrt_id, start, end);
+
+ reg[2 * ranges ] = cpu_to_be64(start);
+ reg[2 * ranges + 1] = cpu_to_be64(end - start + 1);
+ flags[ranges] = mmio->flags; /* both are BE */
+ ranges++;
+ }
+
+ membuf = dt_find_by_name_addr(dt_root, "memory-buffer", min_addr);
+ if (membuf) {
+ prerror("attempted to duplicate %s\n", membuf->name);
+ goto out;
+ }
+
+ membuf = dt_new_addr(dt_root, "memory-buffer", min_addr);
+ assert(membuf);
+
+ dt_add_property_string(membuf, "compatible", "ibm,explorer");
+ dt_add_property_cells(membuf, "ibm,chip-id", hbrt_id);
+
+ /*
+ * FIXME: We should probably be sorting the address ranges based
+ * on the starting address.
+ */
+ dt_add_property(membuf, "reg", reg, sizeof(*reg) * 2 * ranges);
+ dt_add_property(membuf, "flags", flags, sizeof(*flags) * ranges);
+
+out:
+ free(flags);
+ free(reg);
+}
+
+static void add_memory_controller(const struct HDIF_common_hdr *msarea,
+ const struct HDIF_ms_area_address_range *arange)
+{
+ const uint32_t version = PVR_TYPE(mfspr(SPR_PVR));
+ /*
+ * Memory hierarchy may change between processor version. Presently
+ * it's only creating memory hierarchy for P9 (Nimbus) and P9P (Axone).
+ */
+
+ if (version == PVR_TYPE_P9)
+ return add_memory_controller_p9n(msarea, arange);
+ else if (version == PVR_TYPE_P9P)
+ return; //return add_memory_controller_p9p(msarea, arange);
+ else
+ return;
}
static void get_msareas(struct dt_node *root,
@@ -569,6 +678,8 @@ static void get_msareas(struct dt_node *root,
/* Add RAM Area VPD */
vpd_add_ram_area(msarea);
+ add_memory_buffer_mmio(msarea);
+
/* This offset is from the arr, not the header! */
arange = (void *)arr + be32_to_cpu(arr->offset);
for (j = 0; j < be32_to_cpu(arr->ecnt); j++) {