diff options
Diffstat (limited to 'hw/ppc')
-rw-r--r-- | hw/ppc/pnv.c | 28 |
1 files changed, 28 insertions, 0 deletions
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index c0e34fffbc..bb4d00e266 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -1432,6 +1432,10 @@ static void pnv_chip_power9_instance_init(Object *obj) object_initialize_child(obj, "pec[*]", &chip9->pecs[i], TYPE_PNV_PHB4_PEC); } + + for (i = 0; i < pcc->i2c_num_engines; i++) { + object_initialize_child(obj, "i2c[*]", &chip9->i2c[i], TYPE_PNV_I2C); + } } static void pnv_chip_quad_realize_one(PnvChip *chip, PnvQuad *eq, @@ -1504,6 +1508,7 @@ static void pnv_chip_power9_realize(DeviceState *dev, Error **errp) PnvChip *chip = PNV_CHIP(dev); Pnv9Psi *psi9 = &chip9->psi; Error *local_err = NULL; + int i; /* XSCOM bridge is first */ pnv_xscom_init(chip, PNV9_XSCOM_SIZE, PNV9_XSCOM_BASE(chip)); @@ -1602,6 +1607,27 @@ static void pnv_chip_power9_realize(DeviceState *dev, Error **errp) error_propagate(errp, local_err); return; } + + /* + * I2C + */ + for (i = 0; i < pcc->i2c_num_engines; i++) { + Object *obj = OBJECT(&chip9->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, PNV9_XSCOM_I2CM_BASE + + chip9->i2c[i].engine * PNV9_XSCOM_I2CM_SIZE, + &chip9->i2c[i].xscom_regs); + qdev_connect_gpio_out(DEVICE(&chip9->i2c[i]), 0, + qdev_get_gpio_in(DEVICE(&chip9->psi), + PSIHB9_IRQ_SBE_I2C)); + } } static uint32_t pnv_chip_power9_xscom_pcba(PnvChip *chip, uint64_t addr) @@ -1629,6 +1655,8 @@ static void pnv_chip_power9_class_init(ObjectClass *klass, void *data) k->xscom_pcba = pnv_chip_power9_xscom_pcba; dc->desc = "PowerNV Chip POWER9"; k->num_pecs = PNV9_CHIP_MAX_PEC; + k->i2c_num_engines = PNV9_CHIP_MAX_I2C; + k->i2c_num_ports = PNV9_CHIP_MAX_I2C_PORTS; device_class_set_parent_realize(dc, pnv_chip_power9_realize, &k->parent_realize); |