qemu/hw/pci-host/pnv_phb4_pec.c
<<
>>
Prefs
   1/*
   2 * QEMU PowerPC PowerNV (POWER9) PHB4 model
   3 *
   4 * Copyright (c) 2018-2020, IBM Corporation.
   5 *
   6 * This code is licensed under the GPL version 2 or later. See the
   7 * COPYING file in the top-level directory.
   8 */
   9#include "qemu/osdep.h"
  10#include "qapi/error.h"
  11#include "qemu-common.h"
  12#include "qemu/log.h"
  13#include "target/ppc/cpu.h"
  14#include "hw/ppc/fdt.h"
  15#include "hw/pci-host/pnv_phb4_regs.h"
  16#include "hw/pci-host/pnv_phb4.h"
  17#include "hw/ppc/pnv_xscom.h"
  18#include "hw/pci/pci_bridge.h"
  19#include "hw/pci/pci_bus.h"
  20#include "hw/ppc/pnv.h"
  21#include "hw/qdev-properties.h"
  22
  23#include <libfdt.h>
  24
  25#define phb_pec_error(pec, fmt, ...)                                    \
  26    qemu_log_mask(LOG_GUEST_ERROR, "phb4_pec[%d:%d]: " fmt "\n",        \
  27                  (pec)->chip_id, (pec)->index, ## __VA_ARGS__)
  28
  29
  30static uint64_t pnv_pec_nest_xscom_read(void *opaque, hwaddr addr,
  31                                        unsigned size)
  32{
  33    PnvPhb4PecState *pec = PNV_PHB4_PEC(opaque);
  34    uint32_t reg = addr >> 3;
  35
  36    /* TODO: add list of allowed registers and error out if not */
  37    return pec->nest_regs[reg];
  38}
  39
  40static void pnv_pec_nest_xscom_write(void *opaque, hwaddr addr,
  41                                     uint64_t val, unsigned size)
  42{
  43    PnvPhb4PecState *pec = PNV_PHB4_PEC(opaque);
  44    uint32_t reg = addr >> 3;
  45
  46    switch (reg) {
  47    case PEC_NEST_PBCQ_HW_CONFIG:
  48    case PEC_NEST_DROP_PRIO_CTRL:
  49    case PEC_NEST_PBCQ_ERR_INJECT:
  50    case PEC_NEST_PCI_NEST_CLK_TRACE_CTL:
  51    case PEC_NEST_PBCQ_PMON_CTRL:
  52    case PEC_NEST_PBCQ_PBUS_ADDR_EXT:
  53    case PEC_NEST_PBCQ_PRED_VEC_TIMEOUT:
  54    case PEC_NEST_CAPP_CTRL:
  55    case PEC_NEST_PBCQ_READ_STK_OVR:
  56    case PEC_NEST_PBCQ_WRITE_STK_OVR:
  57    case PEC_NEST_PBCQ_STORE_STK_OVR:
  58    case PEC_NEST_PBCQ_RETRY_BKOFF_CTRL:
  59        pec->nest_regs[reg] = val;
  60        break;
  61    default:
  62        phb_pec_error(pec, "%s @0x%"HWADDR_PRIx"=%"PRIx64"\n", __func__,
  63                      addr, val);
  64    }
  65}
  66
  67static const MemoryRegionOps pnv_pec_nest_xscom_ops = {
  68    .read = pnv_pec_nest_xscom_read,
  69    .write = pnv_pec_nest_xscom_write,
  70    .valid.min_access_size = 8,
  71    .valid.max_access_size = 8,
  72    .impl.min_access_size = 8,
  73    .impl.max_access_size = 8,
  74    .endianness = DEVICE_BIG_ENDIAN,
  75};
  76
  77static uint64_t pnv_pec_pci_xscom_read(void *opaque, hwaddr addr,
  78                                       unsigned size)
  79{
  80    PnvPhb4PecState *pec = PNV_PHB4_PEC(opaque);
  81    uint32_t reg = addr >> 3;
  82
  83    /* TODO: add list of allowed registers and error out if not */
  84    return pec->pci_regs[reg];
  85}
  86
  87static void pnv_pec_pci_xscom_write(void *opaque, hwaddr addr,
  88                                    uint64_t val, unsigned size)
  89{
  90    PnvPhb4PecState *pec = PNV_PHB4_PEC(opaque);
  91    uint32_t reg = addr >> 3;
  92
  93    switch (reg) {
  94    case PEC_PCI_PBAIB_HW_CONFIG:
  95    case PEC_PCI_PBAIB_READ_STK_OVR:
  96        pec->pci_regs[reg] = val;
  97        break;
  98    default:
  99        phb_pec_error(pec, "%s @0x%"HWADDR_PRIx"=%"PRIx64"\n", __func__,
 100                      addr, val);
 101    }
 102}
 103
 104static const MemoryRegionOps pnv_pec_pci_xscom_ops = {
 105    .read = pnv_pec_pci_xscom_read,
 106    .write = pnv_pec_pci_xscom_write,
 107    .valid.min_access_size = 8,
 108    .valid.max_access_size = 8,
 109    .impl.min_access_size = 8,
 110    .impl.max_access_size = 8,
 111    .endianness = DEVICE_BIG_ENDIAN,
 112};
 113
 114static uint64_t pnv_pec_stk_nest_xscom_read(void *opaque, hwaddr addr,
 115                                            unsigned size)
 116{
 117    PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(opaque);
 118    uint32_t reg = addr >> 3;
 119
 120    /* TODO: add list of allowed registers and error out if not */
 121    return stack->nest_regs[reg];
 122}
 123
 124static void pnv_pec_stk_update_map(PnvPhb4PecStack *stack)
 125{
 126    PnvPhb4PecState *pec = stack->pec;
 127    MemoryRegion *sysmem = pec->system_memory;
 128    uint64_t bar_en = stack->nest_regs[PEC_NEST_STK_BAR_EN];
 129    uint64_t bar, mask, size;
 130    char name[64];
 131
 132    /*
 133     * NOTE: This will really not work well if those are remapped
 134     * after the PHB has created its sub regions. We could do better
 135     * if we had a way to resize regions but we don't really care
 136     * that much in practice as the stuff below really only happens
 137     * once early during boot
 138     */
 139
 140    /* Handle unmaps */
 141    if (memory_region_is_mapped(&stack->mmbar0) &&
 142        !(bar_en & PEC_NEST_STK_BAR_EN_MMIO0)) {
 143        memory_region_del_subregion(sysmem, &stack->mmbar0);
 144    }
 145    if (memory_region_is_mapped(&stack->mmbar1) &&
 146        !(bar_en & PEC_NEST_STK_BAR_EN_MMIO1)) {
 147        memory_region_del_subregion(sysmem, &stack->mmbar1);
 148    }
 149    if (memory_region_is_mapped(&stack->phbbar) &&
 150        !(bar_en & PEC_NEST_STK_BAR_EN_PHB)) {
 151        memory_region_del_subregion(sysmem, &stack->phbbar);
 152    }
 153    if (memory_region_is_mapped(&stack->intbar) &&
 154        !(bar_en & PEC_NEST_STK_BAR_EN_INT)) {
 155        memory_region_del_subregion(sysmem, &stack->intbar);
 156    }
 157
 158    /* Update PHB */
 159    pnv_phb4_update_regions(stack);
 160
 161    /* Handle maps */
 162    if (!memory_region_is_mapped(&stack->mmbar0) &&
 163        (bar_en & PEC_NEST_STK_BAR_EN_MMIO0)) {
 164        bar = stack->nest_regs[PEC_NEST_STK_MMIO_BAR0] >> 8;
 165        mask = stack->nest_regs[PEC_NEST_STK_MMIO_BAR0_MASK];
 166        size = ((~mask) >> 8) + 1;
 167        snprintf(name, sizeof(name), "pec-%d.%d-stack-%d-mmio0",
 168                 pec->chip_id, pec->index, stack->stack_no);
 169        memory_region_init(&stack->mmbar0, OBJECT(stack), name, size);
 170        memory_region_add_subregion(sysmem, bar, &stack->mmbar0);
 171        stack->mmio0_base = bar;
 172        stack->mmio0_size = size;
 173    }
 174    if (!memory_region_is_mapped(&stack->mmbar1) &&
 175        (bar_en & PEC_NEST_STK_BAR_EN_MMIO1)) {
 176        bar = stack->nest_regs[PEC_NEST_STK_MMIO_BAR1] >> 8;
 177        mask = stack->nest_regs[PEC_NEST_STK_MMIO_BAR1_MASK];
 178        size = ((~mask) >> 8) + 1;
 179        snprintf(name, sizeof(name), "pec-%d.%d-stack-%d-mmio1",
 180                 pec->chip_id, pec->index, stack->stack_no);
 181        memory_region_init(&stack->mmbar1, OBJECT(stack), name, size);
 182        memory_region_add_subregion(sysmem, bar, &stack->mmbar1);
 183        stack->mmio1_base = bar;
 184        stack->mmio1_size = size;
 185    }
 186    if (!memory_region_is_mapped(&stack->phbbar) &&
 187        (bar_en & PEC_NEST_STK_BAR_EN_PHB)) {
 188        bar = stack->nest_regs[PEC_NEST_STK_PHB_REGS_BAR] >> 8;
 189        size = PNV_PHB4_NUM_REGS << 3;
 190        snprintf(name, sizeof(name), "pec-%d.%d-stack-%d-phb",
 191                 pec->chip_id, pec->index, stack->stack_no);
 192        memory_region_init(&stack->phbbar, OBJECT(stack), name, size);
 193        memory_region_add_subregion(sysmem, bar, &stack->phbbar);
 194    }
 195    if (!memory_region_is_mapped(&stack->intbar) &&
 196        (bar_en & PEC_NEST_STK_BAR_EN_INT)) {
 197        bar = stack->nest_regs[PEC_NEST_STK_INT_BAR] >> 8;
 198        size = PNV_PHB4_MAX_INTs << 16;
 199        snprintf(name, sizeof(name), "pec-%d.%d-stack-%d-int",
 200                 stack->pec->chip_id, stack->pec->index, stack->stack_no);
 201        memory_region_init(&stack->intbar, OBJECT(stack), name, size);
 202        memory_region_add_subregion(sysmem, bar, &stack->intbar);
 203    }
 204
 205    /* Update PHB */
 206    pnv_phb4_update_regions(stack);
 207}
 208
 209static void pnv_pec_stk_nest_xscom_write(void *opaque, hwaddr addr,
 210                                         uint64_t val, unsigned size)
 211{
 212    PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(opaque);
 213    PnvPhb4PecState *pec = stack->pec;
 214    uint32_t reg = addr >> 3;
 215
 216    switch (reg) {
 217    case PEC_NEST_STK_PCI_NEST_FIR:
 218        stack->nest_regs[PEC_NEST_STK_PCI_NEST_FIR] = val;
 219        break;
 220    case PEC_NEST_STK_PCI_NEST_FIR_CLR:
 221        stack->nest_regs[PEC_NEST_STK_PCI_NEST_FIR] &= val;
 222        break;
 223    case PEC_NEST_STK_PCI_NEST_FIR_SET:
 224        stack->nest_regs[PEC_NEST_STK_PCI_NEST_FIR] |= val;
 225        break;
 226    case PEC_NEST_STK_PCI_NEST_FIR_MSK:
 227        stack->nest_regs[PEC_NEST_STK_PCI_NEST_FIR_MSK] = val;
 228        break;
 229    case PEC_NEST_STK_PCI_NEST_FIR_MSKC:
 230        stack->nest_regs[PEC_NEST_STK_PCI_NEST_FIR_MSK] &= val;
 231        break;
 232    case PEC_NEST_STK_PCI_NEST_FIR_MSKS:
 233        stack->nest_regs[PEC_NEST_STK_PCI_NEST_FIR_MSK] |= val;
 234        break;
 235    case PEC_NEST_STK_PCI_NEST_FIR_ACT0:
 236    case PEC_NEST_STK_PCI_NEST_FIR_ACT1:
 237        stack->nest_regs[reg] = val;
 238        break;
 239    case PEC_NEST_STK_PCI_NEST_FIR_WOF:
 240        stack->nest_regs[reg] = 0;
 241        break;
 242    case PEC_NEST_STK_ERR_REPORT_0:
 243    case PEC_NEST_STK_ERR_REPORT_1:
 244    case PEC_NEST_STK_PBCQ_GNRL_STATUS:
 245        /* Flag error ? */
 246        break;
 247    case PEC_NEST_STK_PBCQ_MODE:
 248        stack->nest_regs[reg] = val & 0xff00000000000000ull;
 249        break;
 250    case PEC_NEST_STK_MMIO_BAR0:
 251    case PEC_NEST_STK_MMIO_BAR0_MASK:
 252    case PEC_NEST_STK_MMIO_BAR1:
 253    case PEC_NEST_STK_MMIO_BAR1_MASK:
 254        if (stack->nest_regs[PEC_NEST_STK_BAR_EN] &
 255            (PEC_NEST_STK_BAR_EN_MMIO0 |
 256             PEC_NEST_STK_BAR_EN_MMIO1)) {
 257            phb_pec_error(pec, "Changing enabled BAR unsupported\n");
 258        }
 259        stack->nest_regs[reg] = val & 0xffffffffff000000ull;
 260        break;
 261    case PEC_NEST_STK_PHB_REGS_BAR:
 262        if (stack->nest_regs[PEC_NEST_STK_BAR_EN] & PEC_NEST_STK_BAR_EN_PHB) {
 263            phb_pec_error(pec, "Changing enabled BAR unsupported\n");
 264        }
 265        stack->nest_regs[reg] = val & 0xffffffffffc00000ull;
 266        break;
 267    case PEC_NEST_STK_INT_BAR:
 268        if (stack->nest_regs[PEC_NEST_STK_BAR_EN] & PEC_NEST_STK_BAR_EN_INT) {
 269            phb_pec_error(pec, "Changing enabled BAR unsupported\n");
 270        }
 271        stack->nest_regs[reg] = val & 0xfffffff000000000ull;
 272        break;
 273    case PEC_NEST_STK_BAR_EN:
 274        stack->nest_regs[reg] = val & 0xf000000000000000ull;
 275        pnv_pec_stk_update_map(stack);
 276        break;
 277    case PEC_NEST_STK_DATA_FRZ_TYPE:
 278    case PEC_NEST_STK_PBCQ_TUN_BAR:
 279        /* Not used for now */
 280        stack->nest_regs[reg] = val;
 281        break;
 282    default:
 283        qemu_log_mask(LOG_UNIMP, "phb4_pec: nest_xscom_write 0x%"HWADDR_PRIx
 284                      "=%"PRIx64"\n", addr, val);
 285    }
 286}
 287
 288static const MemoryRegionOps pnv_pec_stk_nest_xscom_ops = {
 289    .read = pnv_pec_stk_nest_xscom_read,
 290    .write = pnv_pec_stk_nest_xscom_write,
 291    .valid.min_access_size = 8,
 292    .valid.max_access_size = 8,
 293    .impl.min_access_size = 8,
 294    .impl.max_access_size = 8,
 295    .endianness = DEVICE_BIG_ENDIAN,
 296};
 297
 298static uint64_t pnv_pec_stk_pci_xscom_read(void *opaque, hwaddr addr,
 299                                           unsigned size)
 300{
 301    PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(opaque);
 302    uint32_t reg = addr >> 3;
 303
 304    /* TODO: add list of allowed registers and error out if not */
 305    return stack->pci_regs[reg];
 306}
 307
 308static void pnv_pec_stk_pci_xscom_write(void *opaque, hwaddr addr,
 309                                        uint64_t val, unsigned size)
 310{
 311    PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(opaque);
 312    uint32_t reg = addr >> 3;
 313
 314    switch (reg) {
 315    case PEC_PCI_STK_PCI_FIR:
 316        stack->nest_regs[reg] = val;
 317        break;
 318    case PEC_PCI_STK_PCI_FIR_CLR:
 319        stack->nest_regs[PEC_PCI_STK_PCI_FIR] &= val;
 320        break;
 321    case PEC_PCI_STK_PCI_FIR_SET:
 322        stack->nest_regs[PEC_PCI_STK_PCI_FIR] |= val;
 323        break;
 324    case PEC_PCI_STK_PCI_FIR_MSK:
 325        stack->nest_regs[reg] = val;
 326        break;
 327    case PEC_PCI_STK_PCI_FIR_MSKC:
 328        stack->nest_regs[PEC_PCI_STK_PCI_FIR_MSK] &= val;
 329        break;
 330    case PEC_PCI_STK_PCI_FIR_MSKS:
 331        stack->nest_regs[PEC_PCI_STK_PCI_FIR_MSK] |= val;
 332        break;
 333    case PEC_PCI_STK_PCI_FIR_ACT0:
 334    case PEC_PCI_STK_PCI_FIR_ACT1:
 335        stack->nest_regs[reg] = val;
 336        break;
 337    case PEC_PCI_STK_PCI_FIR_WOF:
 338        stack->nest_regs[reg] = 0;
 339        break;
 340    case PEC_PCI_STK_ETU_RESET:
 341        stack->nest_regs[reg] = val & 0x8000000000000000ull;
 342        /* TODO: Implement reset */
 343        break;
 344    case PEC_PCI_STK_PBAIB_ERR_REPORT:
 345        break;
 346    case PEC_PCI_STK_PBAIB_TX_CMD_CRED:
 347    case PEC_PCI_STK_PBAIB_TX_DAT_CRED:
 348        stack->nest_regs[reg] = val;
 349        break;
 350    default:
 351        qemu_log_mask(LOG_UNIMP, "phb4_pec_stk: pci_xscom_write 0x%"HWADDR_PRIx
 352                      "=%"PRIx64"\n", addr, val);
 353    }
 354}
 355
 356static const MemoryRegionOps pnv_pec_stk_pci_xscom_ops = {
 357    .read = pnv_pec_stk_pci_xscom_read,
 358    .write = pnv_pec_stk_pci_xscom_write,
 359    .valid.min_access_size = 8,
 360    .valid.max_access_size = 8,
 361    .impl.min_access_size = 8,
 362    .impl.max_access_size = 8,
 363    .endianness = DEVICE_BIG_ENDIAN,
 364};
 365
 366static void pnv_pec_instance_init(Object *obj)
 367{
 368    PnvPhb4PecState *pec = PNV_PHB4_PEC(obj);
 369    int i;
 370
 371    for (i = 0; i < PHB4_PEC_MAX_STACKS; i++) {
 372        object_initialize_child(obj, "stack[*]", &pec->stacks[i],
 373                                sizeof(pec->stacks[i]), TYPE_PNV_PHB4_PEC_STACK,
 374                                &error_abort, NULL);
 375    }
 376}
 377
 378static void pnv_pec_realize(DeviceState *dev, Error **errp)
 379{
 380    PnvPhb4PecState *pec = PNV_PHB4_PEC(dev);
 381    Error *local_err = NULL;
 382    char name[64];
 383    int i;
 384
 385    assert(pec->system_memory);
 386
 387    /* Create stacks */
 388    for (i = 0; i < pec->num_stacks; i++) {
 389        PnvPhb4PecStack *stack = &pec->stacks[i];
 390        Object *stk_obj = OBJECT(stack);
 391
 392        object_property_set_int(stk_obj, i, "stack-no", &error_abort);
 393        object_property_set_link(stk_obj, OBJECT(pec), "pec", &error_abort);
 394        object_property_set_bool(stk_obj, true, "realized", &local_err);
 395        if (local_err) {
 396            error_propagate(errp, local_err);
 397            return;
 398        }
 399    }
 400
 401    /* Initialize the XSCOM regions for the PEC registers */
 402    snprintf(name, sizeof(name), "xscom-pec-%d.%d-nest", pec->chip_id,
 403             pec->index);
 404    pnv_xscom_region_init(&pec->nest_regs_mr, OBJECT(dev),
 405                          &pnv_pec_nest_xscom_ops, pec, name,
 406                          PHB4_PEC_NEST_REGS_COUNT);
 407
 408    snprintf(name, sizeof(name), "xscom-pec-%d.%d-pci", pec->chip_id,
 409             pec->index);
 410    pnv_xscom_region_init(&pec->pci_regs_mr, OBJECT(dev),
 411                          &pnv_pec_pci_xscom_ops, pec, name,
 412                          PHB4_PEC_PCI_REGS_COUNT);
 413}
 414
 415static int pnv_pec_dt_xscom(PnvXScomInterface *dev, void *fdt,
 416                            int xscom_offset)
 417{
 418    PnvPhb4PecState *pec = PNV_PHB4_PEC(dev);
 419    PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(dev);
 420    uint32_t nbase = pecc->xscom_nest_base(pec);
 421    uint32_t pbase = pecc->xscom_pci_base(pec);
 422    int offset, i;
 423    char *name;
 424    uint32_t reg[] = {
 425        cpu_to_be32(nbase),
 426        cpu_to_be32(pecc->xscom_nest_size),
 427        cpu_to_be32(pbase),
 428        cpu_to_be32(pecc->xscom_pci_size),
 429    };
 430
 431    name = g_strdup_printf("pbcq@%x", nbase);
 432    offset = fdt_add_subnode(fdt, xscom_offset, name);
 433    _FDT(offset);
 434    g_free(name);
 435
 436    _FDT((fdt_setprop(fdt, offset, "reg", reg, sizeof(reg))));
 437
 438    _FDT((fdt_setprop_cell(fdt, offset, "ibm,pec-index", pec->index)));
 439    _FDT((fdt_setprop_cell(fdt, offset, "#address-cells", 1)));
 440    _FDT((fdt_setprop_cell(fdt, offset, "#size-cells", 0)));
 441    _FDT((fdt_setprop(fdt, offset, "compatible", pecc->compat,
 442                      pecc->compat_size)));
 443
 444    for (i = 0; i < pec->num_stacks; i++) {
 445        PnvPhb4PecStack *stack = &pec->stacks[i];
 446        PnvPHB4 *phb = &stack->phb;
 447        int stk_offset;
 448
 449        name = g_strdup_printf("stack@%x", i);
 450        stk_offset = fdt_add_subnode(fdt, offset, name);
 451        _FDT(stk_offset);
 452        g_free(name);
 453        _FDT((fdt_setprop(fdt, stk_offset, "compatible", pecc->stk_compat,
 454                          pecc->stk_compat_size)));
 455        _FDT((fdt_setprop_cell(fdt, stk_offset, "reg", i)));
 456        _FDT((fdt_setprop_cell(fdt, stk_offset, "ibm,phb-index", phb->phb_id)));
 457    }
 458
 459    return 0;
 460}
 461
 462static Property pnv_pec_properties[] = {
 463        DEFINE_PROP_UINT32("index", PnvPhb4PecState, index, 0),
 464        DEFINE_PROP_UINT32("num-stacks", PnvPhb4PecState, num_stacks, 0),
 465        DEFINE_PROP_UINT32("chip-id", PnvPhb4PecState, chip_id, 0),
 466        DEFINE_PROP_LINK("system-memory", PnvPhb4PecState, system_memory,
 467                     TYPE_MEMORY_REGION, MemoryRegion *),
 468        DEFINE_PROP_END_OF_LIST(),
 469};
 470
 471static uint32_t pnv_pec_xscom_pci_base(PnvPhb4PecState *pec)
 472{
 473    return PNV9_XSCOM_PEC_PCI_BASE + 0x1000000 * pec->index;
 474}
 475
 476static uint32_t pnv_pec_xscom_nest_base(PnvPhb4PecState *pec)
 477{
 478    return PNV9_XSCOM_PEC_NEST_BASE + 0x400 * pec->index;
 479}
 480
 481static void pnv_pec_class_init(ObjectClass *klass, void *data)
 482{
 483    DeviceClass *dc = DEVICE_CLASS(klass);
 484    PnvXScomInterfaceClass *xdc = PNV_XSCOM_INTERFACE_CLASS(klass);
 485    PnvPhb4PecClass *pecc = PNV_PHB4_PEC_CLASS(klass);
 486    static const char compat[] = "ibm,power9-pbcq";
 487    static const char stk_compat[] = "ibm,power9-phb-stack";
 488
 489    xdc->dt_xscom = pnv_pec_dt_xscom;
 490
 491    dc->realize = pnv_pec_realize;
 492    device_class_set_props(dc, pnv_pec_properties);
 493    dc->user_creatable = false;
 494
 495    pecc->xscom_nest_base = pnv_pec_xscom_nest_base;
 496    pecc->xscom_pci_base  = pnv_pec_xscom_pci_base;
 497    pecc->xscom_nest_size = PNV9_XSCOM_PEC_NEST_SIZE;
 498    pecc->xscom_pci_size  = PNV9_XSCOM_PEC_PCI_SIZE;
 499    pecc->compat = compat;
 500    pecc->compat_size = sizeof(compat);
 501    pecc->stk_compat = stk_compat;
 502    pecc->stk_compat_size = sizeof(stk_compat);
 503}
 504
 505static const TypeInfo pnv_pec_type_info = {
 506    .name          = TYPE_PNV_PHB4_PEC,
 507    .parent        = TYPE_DEVICE,
 508    .instance_size = sizeof(PnvPhb4PecState),
 509    .instance_init = pnv_pec_instance_init,
 510    .class_init    = pnv_pec_class_init,
 511    .class_size    = sizeof(PnvPhb4PecClass),
 512    .interfaces    = (InterfaceInfo[]) {
 513        { TYPE_PNV_XSCOM_INTERFACE },
 514        { }
 515    }
 516};
 517
 518static void pnv_pec_stk_instance_init(Object *obj)
 519{
 520    PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(obj);
 521
 522    object_initialize_child(obj, "phb", &stack->phb, sizeof(stack->phb),
 523                            TYPE_PNV_PHB4, &error_abort, NULL);
 524}
 525
 526static void pnv_pec_stk_realize(DeviceState *dev, Error **errp)
 527{
 528    PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(dev);
 529    PnvPhb4PecState *pec = stack->pec;
 530    char name[64];
 531
 532    assert(pec);
 533
 534    /* Initialize the XSCOM regions for the stack registers */
 535    snprintf(name, sizeof(name), "xscom-pec-%d.%d-nest-stack-%d",
 536             pec->chip_id, pec->index, stack->stack_no);
 537    pnv_xscom_region_init(&stack->nest_regs_mr, OBJECT(stack),
 538                          &pnv_pec_stk_nest_xscom_ops, stack, name,
 539                          PHB4_PEC_NEST_STK_REGS_COUNT);
 540
 541    snprintf(name, sizeof(name), "xscom-pec-%d.%d-pci-stack-%d",
 542             pec->chip_id, pec->index, stack->stack_no);
 543    pnv_xscom_region_init(&stack->pci_regs_mr, OBJECT(stack),
 544                          &pnv_pec_stk_pci_xscom_ops, stack, name,
 545                          PHB4_PEC_PCI_STK_REGS_COUNT);
 546
 547    /* PHB pass-through */
 548    snprintf(name, sizeof(name), "xscom-pec-%d.%d-pci-stack-%d-phb",
 549             pec->chip_id, pec->index, stack->stack_no);
 550    pnv_xscom_region_init(&stack->phb_regs_mr, OBJECT(&stack->phb),
 551                          &pnv_phb4_xscom_ops, &stack->phb, name, 0x40);
 552
 553    /*
 554     * Let the machine/chip realize the PHB object to customize more
 555     * easily some fields
 556     */
 557}
 558
 559static Property pnv_pec_stk_properties[] = {
 560        DEFINE_PROP_UINT32("stack-no", PnvPhb4PecStack, stack_no, 0),
 561        DEFINE_PROP_LINK("pec", PnvPhb4PecStack, pec, TYPE_PNV_PHB4_PEC,
 562                         PnvPhb4PecState *),
 563        DEFINE_PROP_END_OF_LIST(),
 564};
 565
 566static void pnv_pec_stk_class_init(ObjectClass *klass, void *data)
 567{
 568    DeviceClass *dc = DEVICE_CLASS(klass);
 569
 570    device_class_set_props(dc, pnv_pec_stk_properties);
 571    dc->realize = pnv_pec_stk_realize;
 572    dc->user_creatable = false;
 573
 574    /* TODO: reset regs ? */
 575}
 576
 577static const TypeInfo pnv_pec_stk_type_info = {
 578    .name          = TYPE_PNV_PHB4_PEC_STACK,
 579    .parent        = TYPE_DEVICE,
 580    .instance_size = sizeof(PnvPhb4PecStack),
 581    .instance_init = pnv_pec_stk_instance_init,
 582    .class_init    = pnv_pec_stk_class_init,
 583    .interfaces    = (InterfaceInfo[]) {
 584        { TYPE_PNV_XSCOM_INTERFACE },
 585        { }
 586    }
 587};
 588
 589static void pnv_pec_register_types(void)
 590{
 591    type_register_static(&pnv_pec_type_info);
 592    type_register_static(&pnv_pec_stk_type_info);
 593}
 594
 595type_init(pnv_pec_register_types);
 596