diff options
Diffstat (limited to 'hw/ppc/pnv.c')
| -rw-r--r-- | hw/ppc/pnv.c | 131 |
1 files changed, 127 insertions, 4 deletions
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index 0297871bdd..0b47b92baa 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -790,6 +790,7 @@ static void pnv_init(MachineState *machine) const char *bios_name = machine->firmware ?: FW_FILE_NAME; PnvMachineState *pnv = PNV_MACHINE(machine); MachineClass *mc = MACHINE_GET_CLASS(machine); + PnvMachineClass *pmc = PNV_MACHINE_GET_CLASS(machine); char *fw_filename; long fw_size; uint64_t chip_ram_start = 0; @@ -979,6 +980,13 @@ static void pnv_init(MachineState *machine) */ pnv->powerdown_notifier.notify = pnv_powerdown_notify; qemu_register_powerdown_notifier(&pnv->powerdown_notifier); + + /* + * Create/Connect any machine-specific I2C devices + */ + if (pmc->i2c_init) { + pmc->i2c_init(pnv); + } } /* @@ -1419,6 +1427,8 @@ static void pnv_chip_power9_instance_init(Object *obj) object_initialize_child(obj, "lpc", &chip9->lpc, TYPE_PNV9_LPC); + object_initialize_child(obj, "chiptod", &chip9->chiptod, TYPE_PNV9_CHIPTOD); + object_initialize_child(obj, "occ", &chip9->occ, TYPE_PNV9_OCC); object_initialize_child(obj, "sbe", &chip9->sbe, TYPE_PNV9_SBE); @@ -1565,6 +1575,19 @@ static void pnv_chip_power9_realize(DeviceState *dev, Error **errp) chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0", (uint64_t) PNV9_LPCM_BASE(chip)); + /* ChipTOD */ + object_property_set_bool(OBJECT(&chip9->chiptod), "primary", + chip->chip_id == 0, &error_abort); + object_property_set_bool(OBJECT(&chip9->chiptod), "secondary", + chip->chip_id == 1, &error_abort); + object_property_set_link(OBJECT(&chip9->chiptod), "chip", OBJECT(chip), + &error_abort); + if (!qdev_realize(DEVICE(&chip9->chiptod), NULL, errp)) { + return; + } + pnv_xscom_add_subregion(chip, PNV9_XSCOM_CHIPTOD_BASE, + &chip9->chiptod.xscom_regs); + /* Create the simplified OCC model */ if (!qdev_realize(DEVICE(&chip9->occ), NULL, errp)) { return; @@ -1677,9 +1700,13 @@ static void pnv_chip_power10_instance_init(Object *obj) "xive-fabric"); object_initialize_child(obj, "psi", &chip10->psi, TYPE_PNV10_PSI); object_initialize_child(obj, "lpc", &chip10->lpc, TYPE_PNV10_LPC); + object_initialize_child(obj, "chiptod", &chip10->chiptod, + TYPE_PNV10_CHIPTOD); object_initialize_child(obj, "occ", &chip10->occ, TYPE_PNV10_OCC); object_initialize_child(obj, "sbe", &chip10->sbe, TYPE_PNV10_SBE); object_initialize_child(obj, "homer", &chip10->homer, TYPE_PNV10_HOMER); + object_initialize_child(obj, "n1-chiplet", &chip10->n1_chiplet, + TYPE_PNV_N1_CHIPLET); chip->num_pecs = pcc->num_pecs; @@ -1810,6 +1837,19 @@ static void pnv_chip_power10_realize(DeviceState *dev, Error **errp) chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0", (uint64_t) PNV10_LPCM_BASE(chip)); + /* ChipTOD */ + object_property_set_bool(OBJECT(&chip10->chiptod), "primary", + chip->chip_id == 0, &error_abort); + object_property_set_bool(OBJECT(&chip10->chiptod), "secondary", + chip->chip_id == 1, &error_abort); + object_property_set_link(OBJECT(&chip10->chiptod), "chip", OBJECT(chip), + &error_abort); + if (!qdev_realize(DEVICE(&chip10->chiptod), NULL, errp)) { + return; + } + pnv_xscom_add_subregion(chip, PNV10_XSCOM_CHIPTOD_BASE, + &chip10->chiptod.xscom_regs); + /* Create the simplified OCC model */ if (!qdev_realize(DEVICE(&chip10->occ), NULL, errp)) { return; @@ -1849,6 +1889,19 @@ static void pnv_chip_power10_realize(DeviceState *dev, Error **errp) memory_region_add_subregion(get_system_memory(), PNV10_HOMER_BASE(chip), &chip10->homer.regs); + /* N1 chiplet */ + if (!qdev_realize(DEVICE(&chip10->n1_chiplet), NULL, errp)) { + return; + } + pnv_xscom_add_subregion(chip, PNV10_XSCOM_N1_CHIPLET_CTRL_REGS_BASE, + &chip10->n1_chiplet.nest_pervasive.xscom_ctrl_regs_mr); + + pnv_xscom_add_subregion(chip, PNV10_XSCOM_N1_PB_SCOM_EQ_BASE, + &chip10->n1_chiplet.xscom_pb_eq_mr); + + pnv_xscom_add_subregion(chip, PNV10_XSCOM_N1_PB_SCOM_ES_BASE, + &chip10->n1_chiplet.xscom_pb_es_mr); + /* PHBs */ pnv_chip_power10_phb_realize(chip, &local_err); if (local_err) { @@ -1879,6 +1932,39 @@ static void pnv_chip_power10_realize(DeviceState *dev, Error **errp) qdev_get_gpio_in(DEVICE(&chip10->psi), PSIHB9_IRQ_SBE_I2C)); } + +} + +static void pnv_rainier_i2c_init(PnvMachineState *pnv) +{ + int i; + for (i = 0; i < pnv->num_chips; i++) { + Pnv10Chip *chip10 = PNV10_CHIP(pnv->chips[i]); + + /* + * Add a PCA9552 I2C device for PCIe hotplug control + * to engine 2, bus 1, address 0x63 + */ + I2CSlave *dev = i2c_slave_create_simple(chip10->i2c[2].busses[1], + "pca9552", 0x63); + + /* + * Connect PCA9552 GPIO pins 0-4 (SLOTx_EN) outputs to GPIO pins 5-9 + * (SLOTx_PG) inputs in order to fake the pgood state of PCIe slots + * after hypervisor code sets a SLOTx_EN pin high. + */ + qdev_connect_gpio_out(DEVICE(dev), 0, qdev_get_gpio_in(DEVICE(dev), 5)); + qdev_connect_gpio_out(DEVICE(dev), 1, qdev_get_gpio_in(DEVICE(dev), 6)); + qdev_connect_gpio_out(DEVICE(dev), 2, qdev_get_gpio_in(DEVICE(dev), 7)); + qdev_connect_gpio_out(DEVICE(dev), 3, qdev_get_gpio_in(DEVICE(dev), 8)); + qdev_connect_gpio_out(DEVICE(dev), 4, qdev_get_gpio_in(DEVICE(dev), 9)); + + /* + * Add a PCA9554 I2C device for cable card presence detection + * to engine 2, bus 1, address 0x25 + */ + i2c_slave_create_simple(chip10->i2c[2].busses[1], "pca9554", 0x25); + } } static uint32_t pnv_chip_power10_xscom_pcba(PnvChip *chip, uint64_t addr) @@ -2035,6 +2121,21 @@ static void pnv_chip_class_init(ObjectClass *klass, void *data) dc->desc = "PowerNV Chip"; } +PnvCore *pnv_chip_find_core(PnvChip *chip, uint32_t core_id) +{ + int i; + + for (i = 0; i < chip->nr_cores; i++) { + PnvCore *pc = chip->cores[i]; + CPUCore *cc = CPU_CORE(pc); + + if (cc->core_id == core_id) { + return pc; + } + } + return NULL; +} + PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir) { int i, j; @@ -2242,8 +2343,6 @@ static void pnv_machine_power9_class_init(ObjectClass *oc, void *data) xfc->match_nvt = pnv_match_nvt; - mc->alias = "powernv"; - pmc->compat = compat; pmc->compat_size = sizeof(compat); pmc->dt_power_mgt = pnv_dt_power_mgt; @@ -2251,7 +2350,7 @@ static void pnv_machine_power9_class_init(ObjectClass *oc, void *data) machine_class_allow_dynamic_sysbus_dev(mc, TYPE_PNV_PHB); } -static void pnv_machine_power10_class_init(ObjectClass *oc, void *data) +static void pnv_machine_p10_common_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc); @@ -2263,10 +2362,11 @@ static void pnv_machine_power10_class_init(ObjectClass *oc, void *data) { TYPE_PNV_PHB_ROOT_PORT, "version", "5" }, }; - mc->desc = "IBM PowerNV (Non-Virtualized) POWER10"; mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power10_v2.0"); compat_props_add(mc->compat_props, phb_compat, G_N_ELEMENTS(phb_compat)); + mc->alias = "powernv"; + pmc->compat = compat; pmc->compat_size = sizeof(compat); pmc->dt_power_mgt = pnv_dt_power_mgt; @@ -2276,6 +2376,24 @@ static void pnv_machine_power10_class_init(ObjectClass *oc, void *data) machine_class_allow_dynamic_sysbus_dev(mc, TYPE_PNV_PHB); } +static void pnv_machine_power10_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + + pnv_machine_p10_common_class_init(oc, data); + mc->desc = "IBM PowerNV (Non-Virtualized) POWER10"; +} + +static void pnv_machine_p10_rainier_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc); + + pnv_machine_p10_common_class_init(oc, data); + mc->desc = "IBM PowerNV (Non-Virtualized) POWER10 Rainier"; + pmc->i2c_init = pnv_rainier_i2c_init; +} + static bool pnv_machine_get_hb(Object *obj, Error **errp) { PnvMachineState *pnv = PNV_MACHINE(obj); @@ -2382,6 +2500,11 @@ static void pnv_machine_class_init(ObjectClass *oc, void *data) static const TypeInfo types[] = { { + .name = MACHINE_TYPE_NAME("powernv10-rainier"), + .parent = MACHINE_TYPE_NAME("powernv10"), + .class_init = pnv_machine_p10_rainier_class_init, + }, + { .name = MACHINE_TYPE_NAME("powernv10"), .parent = TYPE_PNV_MACHINE, .class_init = pnv_machine_power10_class_init, |