@@ -1999,6 +1999,105 @@ static void __unused phb4_dump_peltv(struct phb4 *p)
}
}
+static struct ioda_table {
+ int index;
+ const char *name;
+} ioda_table_list[] = {
+ { IODA3_TBL_LIST, "list", },
+ { IODA3_TBL_MIST, "mist", },
+ { IODA3_TBL_RCAM, "rcam", },
+ { IODA3_TBL_MRT, "mrt", },
+ { IODA3_TBL_PESTA, "pesta", },
+ { IODA3_TBL_PESTB, "pestb", },
+ { IODA3_TBL_TVT, "tvt", },
+ { IODA3_TBL_TCAM, "tcam", },
+ { IODA3_TBL_TDR, "tdr", },
+ { IODA3_TBL_MBT, "mbt", },
+ { IODA3_TBL_MDT, "mdt", },
+ { IODA3_TBL_PEEV, "peev", },
+};
+
+static int64_t phb4_fake_scom_write(struct scom_controller *scom,
+ uint32_t chipid, uint64_t pcbaddr,
+ uint64_t val)
+{
+ (void) val;
+ (void) chipid;
+ (void) pcbaddr;
+ (void) scom;
+
+ return 0;
+}
+
+static int64_t phb4_fake_scom_read(struct scom_controller *scom,
+ uint32_t chipid, uint64_t pcbaddr,
+ uint64_t *val)
+{
+ struct phb4 *p = scom->private;
+
+ phb_lock(&p->phb);
+
+ if (chipid == p->chip_id) {
+ // FIXME: broken for the RC config space regs
+ *val = phb4_read_reg(p, pcbaddr);
+ } else {
+ /* otherwise it's an IODA reg, so go read that */
+ phb4_ioda_sel(p, chipid & 0x1f, pcbaddr, false);
+ *val = phb4_read_reg(p, PHB_IODA_DATA0);
+ }
+
+ phb_unlock(&p->phb);
+ return OPAL_SUCCESS;
+}
+
+static void phb4_register_fake_scom(struct phb4 *p)
+{
+ struct scom_controller *scom = zalloc(sizeof(*scom));
+ struct dt_node *regs, *n;
+ uint32_t chip_id;
+ int i;
+
+ if (!scom)
+ return;
+
+ chip_id = (0x2 << 28) | (p->phb.opal_id << 8);
+
+ /*
+ * FIXME: We probably want to have seperate "chip ids" for each
+ * ioda table so we can give each register range a sensible
+ * name.
+ */
+
+ regs = dt_new(p->phb.dt_node, "regs");
+ dt_add_property(regs, "scom-controller", NULL, 0);
+ dt_add_property_cells(regs, "ibm,chip-id", chip_id);
+
+ for (i = 0; i < ARRAY_SIZE(ioda_table_list); i++) {
+ int index = ioda_table_list[i].index;
+ struct scom_controller *scom;
+
+ scom = zalloc(sizeof(*scom));
+ if (!scom)
+ continue;
+
+ scom->private = p;
+ scom->part_id = chip_id | index;
+ scom->read = phb4_fake_scom_read;
+ scom->write = phb4_fake_scom_write;
+
+ if (scom_register(scom)) {
+ PHBERR(p, "Unable to add SCOM for IODA table %s\n",
+ ioda_table_list[i].name);
+ free(scom);
+ continue;
+ }
+
+ n = dt_new_addr(regs, ioda_table_list[i].name, index);
+ dt_add_property_cells(n, "ibm,chip-id", chip_id | index);
+ dt_add_property(n, "scom-controller", NULL, 0);
+ }
+}
+
static void __unused phb4_dump_ioda_table(struct phb4 *p, int table)
{
const char *name;
@@ -5814,6 +5913,9 @@ static void phb4_create(struct dt_node *np)
dt_add_property_string(np, "status", "okay");
+ if (nvram_query_eq_dangerous("ioda-scoms", "yes"))
+ phb4_register_fake_scom(p);
+
return;
failed: