summaryrefslogtreecommitdiffstats
path: root/hw/pci-host/pnv_phb4_pec.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/pci-host/pnv_phb4_pec.c')
-rw-r--r--hw/pci-host/pnv_phb4_pec.c347
1 files changed, 24 insertions, 323 deletions
diff --git a/hw/pci-host/pnv_phb4_pec.c b/hw/pci-host/pnv_phb4_pec.c
index f3e4fa0c82..7fe7f1f007 100644
--- a/hw/pci-host/pnv_phb4_pec.c
+++ b/hw/pci-host/pnv_phb4_pec.c
@@ -19,6 +19,7 @@
#include "hw/pci/pci_bus.h"
#include "hw/ppc/pnv.h"
#include "hw/qdev-properties.h"
+#include "sysemu/sysemu.h"
#include <libfdt.h>
@@ -111,258 +112,6 @@ static const MemoryRegionOps pnv_pec_pci_xscom_ops = {
.endianness = DEVICE_BIG_ENDIAN,
};
-static uint64_t pnv_pec_stk_nest_xscom_read(void *opaque, hwaddr addr,
- unsigned size)
-{
- PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(opaque);
- uint32_t reg = addr >> 3;
-
- /* TODO: add list of allowed registers and error out if not */
- return stack->nest_regs[reg];
-}
-
-static void pnv_pec_stk_update_map(PnvPhb4PecStack *stack)
-{
- PnvPhb4PecState *pec = stack->pec;
- MemoryRegion *sysmem = get_system_memory();
- uint64_t bar_en = stack->nest_regs[PEC_NEST_STK_BAR_EN];
- uint64_t bar, mask, size;
- char name[64];
-
- /*
- * NOTE: This will really not work well if those are remapped
- * after the PHB has created its sub regions. We could do better
- * if we had a way to resize regions but we don't really care
- * that much in practice as the stuff below really only happens
- * once early during boot
- */
-
- /* Handle unmaps */
- if (memory_region_is_mapped(&stack->mmbar0) &&
- !(bar_en & PEC_NEST_STK_BAR_EN_MMIO0)) {
- memory_region_del_subregion(sysmem, &stack->mmbar0);
- }
- if (memory_region_is_mapped(&stack->mmbar1) &&
- !(bar_en & PEC_NEST_STK_BAR_EN_MMIO1)) {
- memory_region_del_subregion(sysmem, &stack->mmbar1);
- }
- if (memory_region_is_mapped(&stack->phbbar) &&
- !(bar_en & PEC_NEST_STK_BAR_EN_PHB)) {
- memory_region_del_subregion(sysmem, &stack->phbbar);
- }
- if (memory_region_is_mapped(&stack->intbar) &&
- !(bar_en & PEC_NEST_STK_BAR_EN_INT)) {
- memory_region_del_subregion(sysmem, &stack->intbar);
- }
-
- /* Update PHB */
- pnv_phb4_update_regions(stack);
-
- /* Handle maps */
- if (!memory_region_is_mapped(&stack->mmbar0) &&
- (bar_en & PEC_NEST_STK_BAR_EN_MMIO0)) {
- bar = stack->nest_regs[PEC_NEST_STK_MMIO_BAR0] >> 8;
- mask = stack->nest_regs[PEC_NEST_STK_MMIO_BAR0_MASK];
- size = ((~mask) >> 8) + 1;
- snprintf(name, sizeof(name), "pec-%d.%d-stack-%d-mmio0",
- pec->chip_id, pec->index, stack->stack_no);
- memory_region_init(&stack->mmbar0, OBJECT(stack), name, size);
- memory_region_add_subregion(sysmem, bar, &stack->mmbar0);
- stack->mmio0_base = bar;
- stack->mmio0_size = size;
- }
- if (!memory_region_is_mapped(&stack->mmbar1) &&
- (bar_en & PEC_NEST_STK_BAR_EN_MMIO1)) {
- bar = stack->nest_regs[PEC_NEST_STK_MMIO_BAR1] >> 8;
- mask = stack->nest_regs[PEC_NEST_STK_MMIO_BAR1_MASK];
- size = ((~mask) >> 8) + 1;
- snprintf(name, sizeof(name), "pec-%d.%d-stack-%d-mmio1",
- pec->chip_id, pec->index, stack->stack_no);
- memory_region_init(&stack->mmbar1, OBJECT(stack), name, size);
- memory_region_add_subregion(sysmem, bar, &stack->mmbar1);
- stack->mmio1_base = bar;
- stack->mmio1_size = size;
- }
- if (!memory_region_is_mapped(&stack->phbbar) &&
- (bar_en & PEC_NEST_STK_BAR_EN_PHB)) {
- bar = stack->nest_regs[PEC_NEST_STK_PHB_REGS_BAR] >> 8;
- size = PNV_PHB4_NUM_REGS << 3;
- snprintf(name, sizeof(name), "pec-%d.%d-stack-%d-phb",
- pec->chip_id, pec->index, stack->stack_no);
- memory_region_init(&stack->phbbar, OBJECT(stack), name, size);
- memory_region_add_subregion(sysmem, bar, &stack->phbbar);
- }
- if (!memory_region_is_mapped(&stack->intbar) &&
- (bar_en & PEC_NEST_STK_BAR_EN_INT)) {
- bar = stack->nest_regs[PEC_NEST_STK_INT_BAR] >> 8;
- size = PNV_PHB4_MAX_INTs << 16;
- snprintf(name, sizeof(name), "pec-%d.%d-stack-%d-int",
- stack->pec->chip_id, stack->pec->index, stack->stack_no);
- memory_region_init(&stack->intbar, OBJECT(stack), name, size);
- memory_region_add_subregion(sysmem, bar, &stack->intbar);
- }
-
- /* Update PHB */
- pnv_phb4_update_regions(stack);
-}
-
-static void pnv_pec_stk_nest_xscom_write(void *opaque, hwaddr addr,
- uint64_t val, unsigned size)
-{
- PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(opaque);
- PnvPhb4PecState *pec = stack->pec;
- uint32_t reg = addr >> 3;
-
- switch (reg) {
- case PEC_NEST_STK_PCI_NEST_FIR:
- stack->nest_regs[PEC_NEST_STK_PCI_NEST_FIR] = val;
- break;
- case PEC_NEST_STK_PCI_NEST_FIR_CLR:
- stack->nest_regs[PEC_NEST_STK_PCI_NEST_FIR] &= val;
- break;
- case PEC_NEST_STK_PCI_NEST_FIR_SET:
- stack->nest_regs[PEC_NEST_STK_PCI_NEST_FIR] |= val;
- break;
- case PEC_NEST_STK_PCI_NEST_FIR_MSK:
- stack->nest_regs[PEC_NEST_STK_PCI_NEST_FIR_MSK] = val;
- break;
- case PEC_NEST_STK_PCI_NEST_FIR_MSKC:
- stack->nest_regs[PEC_NEST_STK_PCI_NEST_FIR_MSK] &= val;
- break;
- case PEC_NEST_STK_PCI_NEST_FIR_MSKS:
- stack->nest_regs[PEC_NEST_STK_PCI_NEST_FIR_MSK] |= val;
- break;
- case PEC_NEST_STK_PCI_NEST_FIR_ACT0:
- case PEC_NEST_STK_PCI_NEST_FIR_ACT1:
- stack->nest_regs[reg] = val;
- break;
- case PEC_NEST_STK_PCI_NEST_FIR_WOF:
- stack->nest_regs[reg] = 0;
- break;
- case PEC_NEST_STK_ERR_REPORT_0:
- case PEC_NEST_STK_ERR_REPORT_1:
- case PEC_NEST_STK_PBCQ_GNRL_STATUS:
- /* Flag error ? */
- break;
- case PEC_NEST_STK_PBCQ_MODE:
- stack->nest_regs[reg] = val & 0xff00000000000000ull;
- break;
- case PEC_NEST_STK_MMIO_BAR0:
- case PEC_NEST_STK_MMIO_BAR0_MASK:
- case PEC_NEST_STK_MMIO_BAR1:
- case PEC_NEST_STK_MMIO_BAR1_MASK:
- if (stack->nest_regs[PEC_NEST_STK_BAR_EN] &
- (PEC_NEST_STK_BAR_EN_MMIO0 |
- PEC_NEST_STK_BAR_EN_MMIO1)) {
- phb_pec_error(pec, "Changing enabled BAR unsupported\n");
- }
- stack->nest_regs[reg] = val & 0xffffffffff000000ull;
- break;
- case PEC_NEST_STK_PHB_REGS_BAR:
- if (stack->nest_regs[PEC_NEST_STK_BAR_EN] & PEC_NEST_STK_BAR_EN_PHB) {
- phb_pec_error(pec, "Changing enabled BAR unsupported\n");
- }
- stack->nest_regs[reg] = val & 0xffffffffffc00000ull;
- break;
- case PEC_NEST_STK_INT_BAR:
- if (stack->nest_regs[PEC_NEST_STK_BAR_EN] & PEC_NEST_STK_BAR_EN_INT) {
- phb_pec_error(pec, "Changing enabled BAR unsupported\n");
- }
- stack->nest_regs[reg] = val & 0xfffffff000000000ull;
- break;
- case PEC_NEST_STK_BAR_EN:
- stack->nest_regs[reg] = val & 0xf000000000000000ull;
- pnv_pec_stk_update_map(stack);
- break;
- case PEC_NEST_STK_DATA_FRZ_TYPE:
- case PEC_NEST_STK_PBCQ_TUN_BAR:
- /* Not used for now */
- stack->nest_regs[reg] = val;
- break;
- default:
- qemu_log_mask(LOG_UNIMP, "phb4_pec: nest_xscom_write 0x%"HWADDR_PRIx
- "=%"PRIx64"\n", addr, val);
- }
-}
-
-static const MemoryRegionOps pnv_pec_stk_nest_xscom_ops = {
- .read = pnv_pec_stk_nest_xscom_read,
- .write = pnv_pec_stk_nest_xscom_write,
- .valid.min_access_size = 8,
- .valid.max_access_size = 8,
- .impl.min_access_size = 8,
- .impl.max_access_size = 8,
- .endianness = DEVICE_BIG_ENDIAN,
-};
-
-static uint64_t pnv_pec_stk_pci_xscom_read(void *opaque, hwaddr addr,
- unsigned size)
-{
- PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(opaque);
- uint32_t reg = addr >> 3;
-
- /* TODO: add list of allowed registers and error out if not */
- return stack->pci_regs[reg];
-}
-
-static void pnv_pec_stk_pci_xscom_write(void *opaque, hwaddr addr,
- uint64_t val, unsigned size)
-{
- PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(opaque);
- uint32_t reg = addr >> 3;
-
- switch (reg) {
- case PEC_PCI_STK_PCI_FIR:
- stack->nest_regs[reg] = val;
- break;
- case PEC_PCI_STK_PCI_FIR_CLR:
- stack->nest_regs[PEC_PCI_STK_PCI_FIR] &= val;
- break;
- case PEC_PCI_STK_PCI_FIR_SET:
- stack->nest_regs[PEC_PCI_STK_PCI_FIR] |= val;
- break;
- case PEC_PCI_STK_PCI_FIR_MSK:
- stack->nest_regs[reg] = val;
- break;
- case PEC_PCI_STK_PCI_FIR_MSKC:
- stack->nest_regs[PEC_PCI_STK_PCI_FIR_MSK] &= val;
- break;
- case PEC_PCI_STK_PCI_FIR_MSKS:
- stack->nest_regs[PEC_PCI_STK_PCI_FIR_MSK] |= val;
- break;
- case PEC_PCI_STK_PCI_FIR_ACT0:
- case PEC_PCI_STK_PCI_FIR_ACT1:
- stack->nest_regs[reg] = val;
- break;
- case PEC_PCI_STK_PCI_FIR_WOF:
- stack->nest_regs[reg] = 0;
- break;
- case PEC_PCI_STK_ETU_RESET:
- stack->nest_regs[reg] = val & 0x8000000000000000ull;
- /* TODO: Implement reset */
- break;
- case PEC_PCI_STK_PBAIB_ERR_REPORT:
- break;
- case PEC_PCI_STK_PBAIB_TX_CMD_CRED:
- case PEC_PCI_STK_PBAIB_TX_DAT_CRED:
- stack->nest_regs[reg] = val;
- break;
- default:
- qemu_log_mask(LOG_UNIMP, "phb4_pec_stk: pci_xscom_write 0x%"HWADDR_PRIx
- "=%"PRIx64"\n", addr, val);
- }
-}
-
-static const MemoryRegionOps pnv_pec_stk_pci_xscom_ops = {
- .read = pnv_pec_stk_pci_xscom_read,
- .write = pnv_pec_stk_pci_xscom_write,
- .valid.min_access_size = 8,
- .valid.max_access_size = 8,
- .impl.min_access_size = 8,
- .impl.max_access_size = 8,
- .endianness = DEVICE_BIG_ENDIAN,
-};
-
static void pnv_pec_instance_init(Object *obj)
{
PnvPhb4PecState *pec = PNV_PHB4_PEC(obj);
@@ -374,19 +123,6 @@ static void pnv_pec_instance_init(Object *obj)
}
}
-static int pnv_pec_phb_offset(PnvPhb4PecState *pec)
-{
- PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec);
- int index = pec->index;
- int offset = 0;
-
- while (index--) {
- offset += pecc->num_stacks[index];
- }
-
- return offset;
-}
-
static void pnv_pec_realize(DeviceState *dev, Error **errp)
{
PnvPhb4PecState *pec = PNV_PHB4_PEC(dev);
@@ -405,10 +141,8 @@ static void pnv_pec_realize(DeviceState *dev, Error **errp)
for (i = 0; i < pec->num_stacks; i++) {
PnvPhb4PecStack *stack = &pec->stacks[i];
Object *stk_obj = OBJECT(stack);
- int phb_id = pnv_pec_phb_offset(pec) + i;
object_property_set_int(stk_obj, "stack-no", i, &error_abort);
- object_property_set_int(stk_obj, "phb-id", phb_id, &error_abort);
object_property_set_link(stk_obj, "pec", OBJECT(pec), &error_abort);
if (!qdev_realize(DEVICE(stk_obj), NULL, errp)) {
return;
@@ -462,8 +196,7 @@ static int pnv_pec_dt_xscom(PnvXScomInterface *dev, void *fdt,
pecc->compat_size)));
for (i = 0; i < pec->num_stacks; i++) {
- PnvPhb4PecStack *stack = &pec->stacks[i];
- PnvPHB4 *phb = &stack->phb;
+ int phb_id = pnv_phb4_pec_get_phb_id(pec, i);
int stk_offset;
name = g_strdup_printf("stack@%x", i);
@@ -473,7 +206,7 @@ static int pnv_pec_dt_xscom(PnvXScomInterface *dev, void *fdt,
_FDT((fdt_setprop(fdt, stk_offset, "compatible", pecc->stk_compat,
pecc->stk_compat_size)));
_FDT((fdt_setprop_cell(fdt, stk_offset, "reg", i)));
- _FDT((fdt_setprop_cell(fdt, stk_offset, "ibm,phb-index", phb->phb_id)));
+ _FDT((fdt_setprop_cell(fdt, stk_offset, "ibm,phb-index", phb_id)));
}
return 0;
@@ -543,69 +276,38 @@ static const TypeInfo pnv_pec_type_info = {
}
};
-static void pnv_pec_stk_instance_init(Object *obj)
+static void pnv_pec_stk_default_phb_realize(PnvPhb4PecStack *stack,
+ Error **errp)
{
- PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(obj);
-
- object_initialize_child(obj, "phb", &stack->phb, TYPE_PNV_PHB4);
- object_property_add_alias(obj, "phb-id", OBJECT(&stack->phb), "index");
-}
-
-static void pnv_pec_stk_realize(DeviceState *dev, Error **errp)
-{
- PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(dev);
PnvPhb4PecState *pec = stack->pec;
PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec);
- PnvChip *chip = pec->chip;
- uint32_t pec_nest_base;
- uint32_t pec_pci_base;
- char name[64];
-
- assert(pec);
-
- /* Initialize the XSCOM regions for the stack registers */
- snprintf(name, sizeof(name), "xscom-pec-%d.%d-nest-stack-%d",
- pec->chip_id, pec->index, stack->stack_no);
- pnv_xscom_region_init(&stack->nest_regs_mr, OBJECT(stack),
- &pnv_pec_stk_nest_xscom_ops, stack, name,
- PHB4_PEC_NEST_STK_REGS_COUNT);
-
- snprintf(name, sizeof(name), "xscom-pec-%d.%d-pci-stack-%d",
- pec->chip_id, pec->index, stack->stack_no);
- pnv_xscom_region_init(&stack->pci_regs_mr, OBJECT(stack),
- &pnv_pec_stk_pci_xscom_ops, stack, name,
- PHB4_PEC_PCI_STK_REGS_COUNT);
+ int phb_id = pnv_phb4_pec_get_phb_id(pec, stack->stack_no);
- /* PHB pass-through */
- snprintf(name, sizeof(name), "xscom-pec-%d.%d-pci-stack-%d-phb",
- pec->chip_id, pec->index, stack->stack_no);
- pnv_xscom_region_init(&stack->phb_regs_mr, OBJECT(&stack->phb),
- &pnv_phb4_xscom_ops, &stack->phb, name, 0x40);
+ stack->phb = PNV_PHB4(qdev_new(TYPE_PNV_PHB4));
- object_property_set_int(OBJECT(&stack->phb), "chip-id", pec->chip_id,
+ object_property_set_int(OBJECT(stack->phb), "chip-id", pec->chip_id,
&error_fatal);
- object_property_set_int(OBJECT(&stack->phb), "version", pecc->version,
+ object_property_set_int(OBJECT(stack->phb), "index", phb_id,
&error_fatal);
- object_property_set_link(OBJECT(&stack->phb), "stack", OBJECT(stack),
+ object_property_set_int(OBJECT(stack->phb), "version", pecc->version,
+ &error_fatal);
+ object_property_set_link(OBJECT(stack->phb), "stack", OBJECT(stack),
&error_abort);
- if (!sysbus_realize(SYS_BUS_DEVICE(&stack->phb), errp)) {
+
+ if (!sysbus_realize(SYS_BUS_DEVICE(stack->phb), errp)) {
+ return;
+ }
+}
+
+static void pnv_pec_stk_realize(DeviceState *dev, Error **errp)
+{
+ PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(dev);
+
+ if (!defaults_enabled()) {
return;
}
- pec_nest_base = pecc->xscom_nest_base(pec);
- pec_pci_base = pecc->xscom_pci_base(pec);
-
- /* Populate the XSCOM address space. */
- pnv_xscom_add_subregion(chip,
- pec_nest_base + 0x40 * (stack->stack_no + 1),
- &stack->nest_regs_mr);
- pnv_xscom_add_subregion(chip,
- pec_pci_base + 0x40 * (stack->stack_no + 1),
- &stack->pci_regs_mr);
- pnv_xscom_add_subregion(chip,
- pec_pci_base + PNV9_XSCOM_PEC_PCI_STK0 +
- 0x40 * stack->stack_no,
- &stack->phb_regs_mr);
+ pnv_pec_stk_default_phb_realize(stack, errp);
}
static Property pnv_pec_stk_properties[] = {
@@ -630,7 +332,6 @@ static const TypeInfo pnv_pec_stk_type_info = {
.name = TYPE_PNV_PHB4_PEC_STACK,
.parent = TYPE_DEVICE,
.instance_size = sizeof(PnvPhb4PecStack),
- .instance_init = pnv_pec_stk_instance_init,
.class_init = pnv_pec_stk_class_init,
.interfaces = (InterfaceInfo[]) {
{ TYPE_PNV_XSCOM_INTERFACE },