Skip to content

Commit

Permalink
ppc/pnv: Add model for POWER10 PHB5 PCIe Host bridge
Browse files Browse the repository at this point in the history
PHB4 and PHB5 are very similar. Use the PHB4 models with some minor
adjustements in a subclass for P10.

Signed-off-by: Cédric Le Goater <clg@kaod.org>
  • Loading branch information
legoater committed Mar 2, 2022
1 parent ae4c68e commit 623575e
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 0 deletions.
20 changes: 20 additions & 0 deletions hw/pci-host/pnv_phb4.c
Expand Up @@ -1812,9 +1812,29 @@ static const TypeInfo pnv_phb4_root_port_info = {
.class_init = pnv_phb4_root_port_class_init,
};

static void pnv_phb5_root_port_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);

dc->desc = "IBM PHB5 PCIE Root Port";
dc->user_creatable = true;

k->vendor_id = PCI_VENDOR_ID_IBM;
k->device_id = PNV_PHB5_DEVICE_ID;
}

static const TypeInfo pnv_phb5_root_port_info = {
.name = TYPE_PNV_PHB5_ROOT_PORT,
.parent = TYPE_PNV_PHB4_ROOT_PORT,
.instance_size = sizeof(PnvPHB4RootPort),
.class_init = pnv_phb5_root_port_class_init,
};

static void pnv_phb4_register_types(void)
{
type_register_static(&pnv_phb4_root_bus_info);
type_register_static(&pnv_phb5_root_port_info);
type_register_static(&pnv_phb4_root_port_info);
type_register_static(&pnv_phb4_type_info);
type_register_static(&pnv_phb4_iommu_memory_region_info);
Expand Down
53 changes: 53 additions & 0 deletions hw/pci-host/pnv_phb4_pec.c
Expand Up @@ -281,9 +281,62 @@ static const TypeInfo pnv_pec_type_info = {
}
};

/*
* POWER10 definitions
*/

static uint32_t pnv_phb5_pec_xscom_pci_base(PnvPhb4PecState *pec)
{
return PNV10_XSCOM_PEC_PCI_BASE + 0x1000000 * pec->index;
}

static uint32_t pnv_phb5_pec_xscom_nest_base(PnvPhb4PecState *pec)
{
/* index goes down ... */
return PNV10_XSCOM_PEC_NEST_BASE - 0x1000000 * pec->index;
}

/*
* PEC0 -> 3 stacks
* PEC1 -> 3 stacks
*/
static const uint32_t pnv_phb5_pec_num_stacks[] = { 3, 3 };

static void pnv_phb5_pec_class_init(ObjectClass *klass, void *data)
{
PnvPhb4PecClass *pecc = PNV_PHB4_PEC_CLASS(klass);
static const char compat[] = "ibm,power10-pbcq";
static const char stk_compat[] = "ibm,power10-phb-stack";

pecc->xscom_nest_base = pnv_phb5_pec_xscom_nest_base;
pecc->xscom_pci_base = pnv_phb5_pec_xscom_pci_base;
pecc->xscom_nest_size = PNV10_XSCOM_PEC_NEST_SIZE;
pecc->xscom_pci_size = PNV10_XSCOM_PEC_PCI_SIZE;
pecc->compat = compat;
pecc->compat_size = sizeof(compat);
pecc->stk_compat = stk_compat;
pecc->stk_compat_size = sizeof(stk_compat);
pecc->version = PNV_PHB5_VERSION;
pecc->num_phbs = pnv_phb5_pec_num_stacks;
pecc->rp_model = TYPE_PNV_PHB5_ROOT_PORT;
}

static const TypeInfo pnv_phb5_pec_type_info = {
.name = TYPE_PNV_PHB5_PEC,
.parent = TYPE_PNV_PHB4_PEC,
.instance_size = sizeof(PnvPhb4PecState),
.class_init = pnv_phb5_pec_class_init,
.class_size = sizeof(PnvPhb4PecClass),
.interfaces = (InterfaceInfo[]) {
{ TYPE_PNV_XSCOM_INTERFACE },
{ }
}
};

static void pnv_pec_register_types(void)
{
type_register_static(&pnv_pec_type_info);
type_register_static(&pnv_phb5_pec_type_info);
}

type_init(pnv_pec_register_types);
51 changes: 51 additions & 0 deletions hw/ppc/pnv.c
Expand Up @@ -727,6 +727,9 @@ static void pnv_chip_power10_pic_print_info(PnvChip *chip, Monitor *mon)

pnv_xive2_pic_print_info(&chip10->xive, mon);
pnv_psi_pic_print_info(&chip10->psi, mon);

object_child_foreach_recursive(OBJECT(chip),
pnv_chip_power9_pic_print_info_child, mon);
}

/* Always give the first 1GB to chip 0 else we won't boot */
Expand Down Expand Up @@ -1581,14 +1584,26 @@ static void pnv_chip_power9_class_init(ObjectClass *klass, void *data)

static void pnv_chip_power10_instance_init(Object *obj)
{
PnvChip *chip = PNV_CHIP(obj);
Pnv10Chip *chip10 = PNV10_CHIP(obj);
PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj);
int i;

object_initialize_child(obj, "xive", &chip10->xive, TYPE_PNV_XIVE2);
object_property_add_alias(obj, "xive-fabric", OBJECT(&chip10->xive),
"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, "occ", &chip10->occ, TYPE_PNV10_OCC);

if (defaults_enabled()) {
chip->num_pecs = pcc->num_pecs;
}

for (i = 0; i < chip->num_pecs; i++) {
object_initialize_child(obj, "pec[*]", &chip10->pecs[i],
TYPE_PNV_PHB5_PEC);
}
}

static void pnv_chip_power10_quad_realize(Pnv10Chip *chip10, Error **errp)
Expand All @@ -1609,6 +1624,34 @@ static void pnv_chip_power10_quad_realize(Pnv10Chip *chip10, Error **errp)
}
}

static void pnv_chip_power10_phb_realize(PnvChip *chip, Error **errp)
{
Pnv10Chip *chip10 = PNV10_CHIP(chip);
int i;

for (i = 0; i < chip->num_pecs; i++) {
PnvPhb4PecState *pec = &chip10->pecs[i];
PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec);
uint32_t pec_nest_base;
uint32_t pec_pci_base;

object_property_set_int(OBJECT(pec), "index", i, &error_fatal);
object_property_set_int(OBJECT(pec), "chip-id", chip->chip_id,
&error_fatal);
object_property_set_link(OBJECT(pec), "chip", OBJECT(chip),
&error_fatal);
if (!qdev_realize(DEVICE(pec), NULL, errp)) {
return;
}

pec_nest_base = pecc->xscom_nest_base(pec);
pec_pci_base = pecc->xscom_pci_base(pec);

pnv_xscom_add_subregion(chip, pec_nest_base, &pec->nest_regs_mr);
pnv_xscom_add_subregion(chip, pec_pci_base, &pec->pci_regs_mr);
}
}

static void pnv_chip_power10_realize(DeviceState *dev, Error **errp)
{
PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
Expand Down Expand Up @@ -1687,6 +1730,13 @@ static void pnv_chip_power10_realize(DeviceState *dev, Error **errp)
}
pnv_xscom_add_subregion(chip, PNV10_XSCOM_OCC_BASE,
&chip10->occ.xscom_regs);

/* PHBs */
pnv_chip_power10_phb_realize(chip, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
}
}

static uint32_t pnv_chip_power10_xscom_pcba(PnvChip *chip, uint64_t addr)
Expand All @@ -1713,6 +1763,7 @@ static void pnv_chip_power10_class_init(ObjectClass *klass, void *data)
k->xscom_core_base = pnv_chip_power10_xscom_core_base;
k->xscom_pcba = pnv_chip_power10_xscom_pcba;
dc->desc = "PowerNV Chip POWER10";
k->num_pecs = PNV10_CHIP_MAX_PEC;

device_class_set_parent_realize(dc, pnv_chip_power10_realize,
&k->parent_realize);
Expand Down
12 changes: 12 additions & 0 deletions include/hw/pci-host/pnv_phb4.h
Expand Up @@ -49,6 +49,7 @@ typedef struct PnvPhb4DMASpace {
*/
#define TYPE_PNV_PHB4_ROOT_BUS "pnv-phb4-root"
#define TYPE_PNV_PHB4_ROOT_PORT "pnv-phb4-root-port"
#define TYPE_PNV_PHB5_ROOT_PORT "pnv-phb5-root-port"

typedef struct PnvPHB4RootPort {
PCIESlot parent_obj;
Expand Down Expand Up @@ -206,4 +207,15 @@ struct PnvPhb4PecClass {
const char *rp_model;
};

/*
* POWER10 definitions
*/

#define PNV_PHB5_VERSION 0x000000a500000001ull
#define PNV_PHB5_DEVICE_ID 0x0652

#define TYPE_PNV_PHB5_PEC "pnv-phb5-pec"
#define PNV_PHB5_PEC(obj) \
OBJECT_CHECK(PnvPhb4PecState, (obj), TYPE_PNV_PHB5_PEC)

#endif /* PCI_HOST_PNV_PHB4_H */
3 changes: 3 additions & 0 deletions include/hw/ppc/pnv.h
Expand Up @@ -132,6 +132,9 @@ struct Pnv10Chip {

uint32_t nr_quads;
PnvQuad *quads;

#define PNV10_CHIP_MAX_PEC 2
PnvPhb4PecState pecs[PNV10_CHIP_MAX_PEC];
};

#define PNV10_PIR2FUSEDCORE(pir) (((pir) >> 3) & 0xf)
Expand Down
6 changes: 6 additions & 0 deletions include/hw/ppc/pnv_xscom.h
Expand Up @@ -137,6 +137,12 @@ struct PnvXScomInterfaceClass {
#define PNV10_XSCOM_XIVE2_BASE 0x2010800
#define PNV10_XSCOM_XIVE2_SIZE 0x400

#define PNV10_XSCOM_PEC_NEST_BASE 0x3011800 /* index goes downwards ... */
#define PNV10_XSCOM_PEC_NEST_SIZE 0x100

#define PNV10_XSCOM_PEC_PCI_BASE 0x8010800 /* index goes upwards ... */
#define PNV10_XSCOM_PEC_PCI_SIZE 0x200

void pnv_xscom_realize(PnvChip *chip, uint64_t size, Error **errp);
int pnv_dt_xscom(PnvChip *chip, void *fdt, int root_offset,
uint64_t xscom_base, uint64_t xscom_size,
Expand Down

0 comments on commit 623575e

Please sign in to comment.