@@ -53,7 +53,6 @@ typedef struct PnvChip {
uint64_t cores_mask;
void *cores;
- hwaddr xscom_base;
MemoryRegion xscom_mmio;
MemoryRegion xscom;
AddressSpace xscom_as;
@@ -64,6 +63,18 @@ typedef struct PnvChip {
PnvOCC occ;
} PnvChip;
+typedef enum PnvPhysMapType {
+ PNV_MAP_XSCOM,
+ PNV_MAP_ICP,
+ PNV_MAP_PSIHB,
+ PNV_MAP_PSIHB_FSP,
+} PnvPhysMapType;
+
+typedef struct PnvPhysMapEntry {
+ uint64_t base;
+ uint64_t size;
+} PnvPhysMapEntry;
+
typedef struct PnvChipClass {
/*< private >*/
SysBusDeviceClass parent_class;
@@ -73,9 +84,10 @@ typedef struct PnvChipClass {
uint64_t chip_cfam_id;
uint64_t cores_mask;
- hwaddr xscom_base;
+ const PnvPhysMapEntry *phys_map;
uint32_t (*core_pir)(PnvChip *chip, uint32_t core_id);
+ uint64_t (*map_base)(const PnvChip *chip, PnvPhysMapType type);
} PnvChipClass;
#define PNV_CHIP_TYPE_SUFFIX "-" TYPE_PNV_CHIP
@@ -159,9 +171,21 @@ void pnv_bmc_powerdown(IPMIBmc *bmc);
/*
* POWER8 MMIO base addresses
*/
-#define PNV_XSCOM_SIZE 0x800000000ull
-#define PNV_XSCOM_BASE(chip) \
- (chip->xscom_base + ((uint64_t)(chip)->chip_id) * PNV_XSCOM_SIZE)
+static inline uint64_t pnv_map_size(const PnvChip *chip, PnvPhysMapType type)
+{
+ PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
+ const PnvPhysMapEntry *map = &pcc->phys_map[type];
+
+ return map->size;
+}
+
+static inline uint64_t pnv_map_base(const PnvChip *chip, PnvPhysMapType type)
+{
+ return PNV_CHIP_GET_CLASS(chip)->map_base(chip, type);
+}
+
+#define PNV_XSCOM_SIZE(chip) pnv_map_size(chip, PNV_MAP_XSCOM)
+#define PNV_XSCOM_BASE(chip) pnv_map_base(chip, PNV_MAP_XSCOM)
/*
* XSCOM 0x20109CA defines the ICP BAR:
@@ -177,18 +201,13 @@ void pnv_bmc_powerdown(IPMIBmc *bmc);
* 0xffffe02200000000 -> 0x0003ffff80800000
* 0xffffe02600000000 -> 0x0003ffff80900000
*/
-#define PNV_ICP_SIZE 0x0000000000100000ull
-#define PNV_ICP_BASE(chip) \
- (0x0003ffff80000000ull + (uint64_t) PNV_CHIP_INDEX(chip) * PNV_ICP_SIZE)
-
+#define PNV_ICP_SIZE(chip) pnv_map_size(chip, PNV_MAP_ICP)
+#define PNV_ICP_BASE(chip) pnv_map_base(chip, PNV_MAP_ICP)
-#define PNV_PSIHB_SIZE 0x0000000000100000ull
-#define PNV_PSIHB_BASE(chip) \
- (0x0003fffe80000000ull + (uint64_t)PNV_CHIP_INDEX(chip) * PNV_PSIHB_SIZE)
+#define PNV_PSIHB_SIZE(chip) pnv_map_size(chip, PNV_MAP_PSIHB)
+#define PNV_PSIHB_BASE(chip) pnv_map_base(chip, PNV_MAP_PSIHB)
-#define PNV_PSIHB_FSP_SIZE 0x0000000100000000ull
-#define PNV_PSIHB_FSP_BASE(chip) \
- (0x0003ffe000000000ull + (uint64_t)PNV_CHIP_INDEX(chip) * \
- PNV_PSIHB_FSP_SIZE)
+#define PNV_PSIHB_FSP_SIZE(chip) pnv_map_size(chip, PNV_MAP_PSIHB_FSP)
+#define PNV_PSIHB_FSP_BASE(chip) pnv_map_base(chip, PNV_MAP_PSIHB_FSP)
#endif /* _PPC_PNV_H */
@@ -712,6 +712,24 @@ static uint32_t pnv_chip_core_pir_p9(PnvChip *chip, uint32_t core_id)
*/
#define POWER9_CORE_MASK (0xffffffffffffffull)
+/*
+ * POWER8 MMIOs
+ */
+static const PnvPhysMapEntry pnv_chip_power8_phys_map[] = {
+ [PNV_MAP_XSCOM] = { 0x0003fc0000000000ull, 0x0000000800000000ull },
+ [PNV_MAP_ICP] = { 0x0003ffff80000000ull, 0x0000000000100000ull },
+ [PNV_MAP_PSIHB] = { 0x0003fffe80000000ull, 0x0000000000100000ull },
+ [PNV_MAP_PSIHB_FSP] = { 0x0003ffe000000000ull, 0x0000000100000000ull },
+};
+
+static uint64_t pnv_chip_map_base_p8(const PnvChip *chip, PnvPhysMapType type)
+{
+ PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
+ const PnvPhysMapEntry *map = &pcc->phys_map[type];
+
+ return map->base + chip->chip_id * map->size;
+}
+
static void pnv_chip_power8e_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@@ -721,7 +739,8 @@ static void pnv_chip_power8e_class_init(ObjectClass *klass, void *data)
k->chip_cfam_id = 0x221ef04980000000ull; /* P8 Murano DD2.1 */
k->cores_mask = POWER8E_CORE_MASK;
k->core_pir = pnv_chip_core_pir_p8;
- k->xscom_base = 0x003fc0000000000ull;
+ k->map_base = pnv_chip_map_base_p8;
+ k->phys_map = pnv_chip_power8_phys_map;
dc->desc = "PowerNV Chip POWER8E";
}
@@ -734,7 +753,8 @@ static void pnv_chip_power8_class_init(ObjectClass *klass, void *data)
k->chip_cfam_id = 0x220ea04980000000ull; /* P8 Venice DD2.0 */
k->cores_mask = POWER8_CORE_MASK;
k->core_pir = pnv_chip_core_pir_p8;
- k->xscom_base = 0x003fc0000000000ull;
+ k->map_base = pnv_chip_map_base_p8;
+ k->phys_map = pnv_chip_power8_phys_map;
dc->desc = "PowerNV Chip POWER8";
}
@@ -747,10 +767,27 @@ static void pnv_chip_power8nvl_class_init(ObjectClass *klass, void *data)
k->chip_cfam_id = 0x120d304980000000ull; /* P8 Naples DD1.0 */
k->cores_mask = POWER8_CORE_MASK;
k->core_pir = pnv_chip_core_pir_p8;
- k->xscom_base = 0x003fc0000000000ull;
+ k->map_base = pnv_chip_map_base_p8;
+ k->phys_map = pnv_chip_power8_phys_map;
dc->desc = "PowerNV Chip POWER8NVL";
}
+/*
+ * POWER9 MMIOs
+ */
+static const PnvPhysMapEntry pnv_chip_power9_phys_map[] = {
+ [PNV_MAP_XSCOM] = { 0x000603fc00000000ull, 0x0000000400000000ull },
+};
+
+/* Each chip has a 4TB range for its MMIOs */
+static uint64_t pnv_chip_map_base_p9(const PnvChip *chip, PnvPhysMapType type)
+{
+ PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
+ const PnvPhysMapEntry *map = &pcc->phys_map[type];
+
+ return map->base + ((uint64_t) chip->chip_id << 42);
+}
+
static void pnv_chip_power9_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@@ -760,7 +797,8 @@ static void pnv_chip_power9_class_init(ObjectClass *klass, void *data)
k->chip_cfam_id = 0x220d104900008000ull; /* P9 Nimbus DD2.0 */
k->cores_mask = POWER9_CORE_MASK;
k->core_pir = pnv_chip_core_pir_p9;
- k->xscom_base = 0x00603fc00000000ull;
+ k->map_base = pnv_chip_map_base_p9;
+ k->phys_map = pnv_chip_power9_phys_map;
dc->desc = "PowerNV Chip POWER9";
}
@@ -797,15 +835,14 @@ static void pnv_chip_core_sanitize(PnvChip *chip, Error **errp)
static void pnv_chip_init(Object *obj)
{
PnvChip *chip = PNV_CHIP(obj);
- PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
-
- chip->xscom_base = pcc->xscom_base;
object_initialize(&chip->lpc, sizeof(chip->lpc), TYPE_PNV_LPC);
object_property_add_child(obj, "lpc", OBJECT(&chip->lpc), NULL);
object_initialize(&chip->psi, sizeof(chip->psi), TYPE_PNV_PSI);
object_property_add_child(obj, "psi", OBJECT(&chip->psi), NULL);
+ object_property_add_const_link(OBJECT(&chip->psi), "chip", obj,
+ &error_abort);
object_property_add_const_link(OBJECT(&chip->psi), "xics",
OBJECT(qdev_get_machine()), &error_abort);
@@ -829,7 +866,7 @@ static void pnv_chip_icp_realize(PnvChip *chip, Error **errp)
XICSFabric *xi = XICS_FABRIC(qdev_get_machine());
name = g_strdup_printf("icp-%x", chip->chip_id);
- memory_region_init(&chip->icp_mmio, OBJECT(chip), name, PNV_ICP_SIZE);
+ memory_region_init(&chip->icp_mmio, OBJECT(chip), name, PNV_ICP_SIZE(chip));
sysbus_init_mmio(SYS_BUS_DEVICE(chip), &chip->icp_mmio);
g_free(name);
@@ -465,11 +465,20 @@ static void pnv_psi_realize(DeviceState *dev, Error **errp)
Object *obj;
Error *err = NULL;
unsigned int i;
+ PnvChip *chip;
+
+ obj = object_property_get_link(OBJECT(dev), "chip", &err);
+ if (!obj) {
+ error_propagate(errp, err);
+ error_prepend(errp, "required link 'chip' not found: ");
+ return;
+ }
+ chip = PNV_CHIP(obj);
obj = object_property_get_link(OBJECT(dev), "xics", &err);
if (!obj) {
- error_setg(errp, "%s: required link 'xics' not found: %s",
- __func__, error_get_pretty(err));
+ error_propagate(errp, err);
+ error_prepend(errp, "required link 'xics' not found: ");
return;
}
@@ -497,7 +506,7 @@ static void pnv_psi_realize(DeviceState *dev, Error **errp)
/* Initialize MMIO region */
memory_region_init_io(&psi->regs_mr, OBJECT(dev), &psi_mmio_ops, psi,
- "psihb", PNV_PSIHB_SIZE);
+ "psihb", PNV_PSIHB_SIZE(chip));
/* Default BAR for MMIO region */
pnv_psi_set_bar(psi, psi->bar | PSIHB_BAR_EN);
@@ -50,7 +50,7 @@ static void xscom_complete(CPUState *cs, uint64_t hmer_bits)
static uint32_t pnv_xscom_pcba(PnvChip *chip, uint64_t addr)
{
- addr &= (PNV_XSCOM_SIZE - 1);
+ addr &= (PNV_XSCOM_SIZE(chip) - 1);
if (pnv_chip_is_power9(chip)) {
return addr >> 3;
@@ -179,10 +179,10 @@ void pnv_xscom_realize(PnvChip *chip, Error **errp)
name = g_strdup_printf("xscom-%x", chip->chip_id);
memory_region_init_io(&chip->xscom_mmio, OBJECT(chip), &pnv_xscom_ops,
- chip, name, PNV_XSCOM_SIZE);
+ chip, name, PNV_XSCOM_SIZE(chip));
sysbus_init_mmio(sbd, &chip->xscom_mmio);
- memory_region_init(&chip->xscom, OBJECT(chip), name, PNV_XSCOM_SIZE);
+ memory_region_init(&chip->xscom, OBJECT(chip), name, PNV_XSCOM_SIZE(chip));
address_space_init(&chip->xscom_as, &chip->xscom, name);
g_free(name);
}
@@ -225,7 +225,7 @@ static const char compat_p9[] = "ibm,power9-xscom\0ibm,xscom";
int pnv_dt_xscom(PnvChip *chip, void *fdt, int root_offset)
{
uint64_t reg[] = { cpu_to_be64(PNV_XSCOM_BASE(chip)),
- cpu_to_be64(PNV_XSCOM_SIZE) };
+ cpu_to_be64(PNV_XSCOM_SIZE(chip)) };
int xscom_offset;
ForeachPopulateArgs args;
char *name;