hw/ppc/pnv.c | 29 +++++++++++++++++++++++++++++
include/hw/ppc/pnv_chip.h | 4 ++++
include/hw/ppc/pnv_xscom.h | 3 +++
3 files changed, 36 insertions(+)
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index e0b3478325..2655b6e506 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -1695,6 +1695,10 @@ static void pnv_chip_power10_instance_init(Object *obj)
object_initialize_child(obj, "pec[*]", &chip10->pecs[i],
TYPE_PNV_PHB5_PEC);
}
+
+ for (i = 0; i < pcc->i2c_num_engines; i++) {
+ object_initialize_child(obj, "i2c[*]", &chip10->i2c[i], TYPE_PNV_I2C);
+ }
}
static void pnv_chip_power10_quad_realize(Pnv10Chip *chip10, Error **errp)
@@ -1753,6 +1757,7 @@ static void pnv_chip_power10_realize(DeviceState *dev,
Error **errp)
PnvChip *chip = PNV_CHIP(dev);
Pnv10Chip *chip10 = PNV10_CHIP(dev);
Error *local_err = NULL;
+ int i;
/* XSCOM bridge is first */
pnv_xscom_realize(chip, PNV10_XSCOM_SIZE, &local_err);
@@ -1863,6 +1868,28 @@ static void pnv_chip_power10_realize(DeviceState *dev,
Error **errp)
error_propagate(errp, local_err);
return;
}
+
+
+ /*
+ * I2C
+ */
+ for (i = 0; i < pcc->i2c_num_engines; i++) {
+ Object *obj = OBJECT(&chip10->i2c[i]);
+
+ object_property_set_int(obj, "engine", i + 1, &error_fatal);
+ object_property_set_int(obj, "num-busses", pcc->i2c_num_ports,
+ &error_fatal);
+ object_property_set_link(obj, "chip", OBJECT(chip), &error_abort);
+ if (!qdev_realize(DEVICE(obj), NULL, errp)) {
+ return;
+ }
+ pnv_xscom_add_subregion(chip, PNV10_XSCOM_I2CM_BASE +
+ chip10->i2c[i].engine * PNV10_XSCOM_I2CM_SIZE,
+ &chip10->i2c[i].xscom_regs);
+ qdev_connect_gpio_out(DEVICE(&chip10->i2c[i]), 0,
+ qdev_get_gpio_in(DEVICE(&chip10->psi),
+ PSIHB9_IRQ_SBE_I2C));
+ }
}
static uint32_t pnv_chip_power10_xscom_pcba(PnvChip *chip, uint64_t addr)
@@ -1890,6 +1917,8 @@ static void pnv_chip_power10_class_init(ObjectClass
*klass, void *data)
k->xscom_pcba = pnv_chip_power10_xscom_pcba;
dc->desc = "PowerNV Chip POWER10";
k->num_pecs = PNV10_CHIP_MAX_PEC;
+ k->i2c_num_engines = PNV10_CHIP_MAX_I2C;
+ k->i2c_num_ports = PNV10_CHIP_MAX_I2C_PORTS;
device_class_set_parent_realize(dc, pnv_chip_power10_realize,
&k->parent_realize);
diff --git a/include/hw/ppc/pnv_chip.h b/include/hw/ppc/pnv_chip.h
index 90cfbad1a5..5815d96ecf 100644
--- a/include/hw/ppc/pnv_chip.h
+++ b/include/hw/ppc/pnv_chip.h
@@ -120,6 +120,10 @@ struct Pnv10Chip {
#define PNV10_CHIP_MAX_PEC 2
PnvPhb4PecState pecs[PNV10_CHIP_MAX_PEC];
+
+#define PNV10_CHIP_MAX_I2C 4
+#define PNV10_CHIP_MAX_I2C_PORTS 2
+ PnvI2C i2c[PNV10_CHIP_MAX_I2C];
};
#define PNV10_PIR2FUSEDCORE(pir) (((pir) >> 3) & 0xf)
diff --git a/include/hw/ppc/pnv_xscom.h b/include/hw/ppc/pnv_xscom.h
index 0c8b873c4c..2b607b22c9 100644
--- a/include/hw/ppc/pnv_xscom.h
+++ b/include/hw/ppc/pnv_xscom.h
@@ -152,6 +152,9 @@ struct PnvXScomInterfaceClass {
#define PNV10_XSCOM_PSIHB_BASE 0x3011D00
#define PNV10_XSCOM_PSIHB_SIZE 0x100
+#define PNV10_XSCOM_I2CM_BASE PNV9_XSCOM_I2CM_BASE
+#define PNV10_XSCOM_I2CM_SIZE PNV9_XSCOM_I2CM_SIZE
+
#define PNV10_XSCOM_OCC_BASE PNV9_XSCOM_OCC_BASE
#define PNV10_XSCOM_OCC_SIZE PNV9_XSCOM_OCC_SIZE