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#include "sysemu/sysemu.h"
  23
  24#include <libfdt.h>
  25
  26#define phb_pec_error(pec, fmt, ...)                                    \
  27    qemu_log_mask(LOG_GUEST_ERROR, "phb4_pec[%d:%d]: " fmt "\n",        \
  28                  (pec)->chip_id, (pec)->index, ## __VA_ARGS__)
  29
  30
  31static uint64_t pnv_pec_nest_xscom_read(void *opaque, hwaddr addr,
  32                                        unsigned size)
  33{
  34    PnvPhb4PecState *pec = PNV_PHB4_PEC(opaque);
  35    uint32_t reg = addr >> 3;
  36
  37    /* TODO: add list of allowed registers and error out if not */
  38    return pec->nest_regs[reg];
  39}
  40
  41static void pnv_pec_nest_xscom_write(void *opaque, hwaddr addr,
  42                                     uint64_t val, unsigned size)
  43{
  44    PnvPhb4PecState *pec = PNV_PHB4_PEC(opaque);
  45    uint32_t reg = addr >> 3;
  46
  47    switch (reg) {
  48    case PEC_NEST_PBCQ_HW_CONFIG:
  49    case PEC_NEST_DROP_PRIO_CTRL:
  50    case PEC_NEST_PBCQ_ERR_INJECT:
  51    case PEC_NEST_PCI_NEST_CLK_TRACE_CTL:
  52    case PEC_NEST_PBCQ_PMON_CTRL:
  53    case PEC_NEST_PBCQ_PBUS_ADDR_EXT:
  54    case PEC_NEST_PBCQ_PRED_VEC_TIMEOUT:
  55    case PEC_NEST_CAPP_CTRL:
  56    case PEC_NEST_PBCQ_READ_STK_OVR:
  57    case PEC_NEST_PBCQ_WRITE_STK_OVR:
  58    case PEC_NEST_PBCQ_STORE_STK_OVR:
  59    case PEC_NEST_PBCQ_RETRY_BKOFF_CTRL:
  60        pec->nest_regs[reg] = val;
  61        break;
  62    default:
  63        phb_pec_error(pec, "%s @0x%"HWADDR_PRIx"=%"PRIx64"\n", __func__,
  64                      addr, val);
  65    }
  66}
  67
  68static const MemoryRegionOps pnv_pec_nest_xscom_ops = {
  69    .read = pnv_pec_nest_xscom_read,
  70    .write = pnv_pec_nest_xscom_write,
  71    .valid.min_access_size = 8,
  72    .valid.max_access_size = 8,
  73    .impl.min_access_size = 8,
  74    .impl.max_access_size = 8,
  75    .endianness = DEVICE_BIG_ENDIAN,
  76};
  77
  78static uint64_t pnv_pec_pci_xscom_read(void *opaque, hwaddr addr,
  79                                       unsigned size)
  80{
  81    PnvPhb4PecState *pec = PNV_PHB4_PEC(opaque);
  82    uint32_t reg = addr >> 3;
  83
  84    /* TODO: add list of allowed registers and error out if not */
  85    return pec->pci_regs[reg];
  86}
  87
  88static void pnv_pec_pci_xscom_write(void *opaque, hwaddr addr,
  89                                    uint64_t val, unsigned size)
  90{
  91    PnvPhb4PecState *pec = PNV_PHB4_PEC(opaque);
  92    uint32_t reg = addr >> 3;
  93
  94    switch (reg) {
  95    case PEC_PCI_PBAIB_HW_CONFIG:
  96    case PEC_PCI_PBAIB_READ_STK_OVR:
  97        pec->pci_regs[reg] = val;
  98        break;
  99    default:
 100        phb_pec_error(pec, "%s @0x%"HWADDR_PRIx"=%"PRIx64"\n", __func__,
 101                      addr, val);
 102    }
 103}
 104
 105static const MemoryRegionOps pnv_pec_pci_xscom_ops = {
 106    .read = pnv_pec_pci_xscom_read,
 107    .write = pnv_pec_pci_xscom_write,
 108    .valid.min_access_size = 8,
 109    .valid.max_access_size = 8,
 110    .impl.min_access_size = 8,
 111    .impl.max_access_size = 8,
 112    .endianness = DEVICE_BIG_ENDIAN,
 113};
 114
 115static void pnv_pec_default_phb_realize(PnvPhb4PecState *pec,
 116                                        int stack_no,
 117                                        Error **errp)
 118{
 119    PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec);
 120    PnvPHB4 *phb = PNV_PHB4(qdev_new(pecc->phb_type));
 121    int phb_id = pnv_phb4_pec_get_phb_id(pec, stack_no);
 122
 123    object_property_add_child(OBJECT(pec), "phb[*]", OBJECT(phb));
 124    object_property_set_link(OBJECT(phb), "pec", OBJECT(pec),
 125                             &error_abort);
 126    object_property_set_int(OBJECT(phb), "chip-id", pec->chip_id,
 127                            &error_fatal);
 128    object_property_set_int(OBJECT(phb), "index", phb_id,
 129                            &error_fatal);
 130
 131    if (!sysbus_realize(SYS_BUS_DEVICE(phb), errp)) {
 132        return;
 133    }
 134
 135    /* Add a single Root port if running with defaults */
 136    pnv_phb_attach_root_port(PCI_HOST_BRIDGE(phb), pecc->rp_model);
 137}
 138
 139static void pnv_pec_realize(DeviceState *dev, Error **errp)
 140{
 141    PnvPhb4PecState *pec = PNV_PHB4_PEC(dev);
 142    PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec);
 143    char name[64];
 144    int i;
 145
 146    if (pec->index >= PNV_CHIP_GET_CLASS(pec->chip)->num_pecs) {
 147        error_setg(errp, "invalid PEC index: %d", pec->index);
 148        return;
 149    }
 150
 151    pec->num_phbs = pecc->num_phbs[pec->index];
 152
 153    /* Create PHBs if running with defaults */
 154    for (i = 0; i < pec->num_phbs; i++) {
 155        pnv_pec_default_phb_realize(pec, i, errp);
 156    }
 157
 158    /* Initialize the XSCOM regions for the PEC registers */
 159    snprintf(name, sizeof(name), "xscom-pec-%d.%d-nest", pec->chip_id,
 160             pec->index);
 161    pnv_xscom_region_init(&pec->nest_regs_mr, OBJECT(dev),
 162                          &pnv_pec_nest_xscom_ops, pec, name,
 163                          PHB4_PEC_NEST_REGS_COUNT);
 164
 165    snprintf(name, sizeof(name), "xscom-pec-%d.%d-pci", pec->chip_id,
 166             pec->index);
 167    pnv_xscom_region_init(&pec->pci_regs_mr, OBJECT(dev),
 168                          &pnv_pec_pci_xscom_ops, pec, name,
 169                          PHB4_PEC_PCI_REGS_COUNT);
 170}
 171
 172static int pnv_pec_dt_xscom(PnvXScomInterface *dev, void *fdt,
 173                            int xscom_offset)
 174{
 175    PnvPhb4PecState *pec = PNV_PHB4_PEC(dev);
 176    PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(dev);
 177    uint32_t nbase = pecc->xscom_nest_base(pec);
 178    uint32_t pbase = pecc->xscom_pci_base(pec);
 179    int offset, i;
 180    char *name;
 181    uint32_t reg[] = {
 182        cpu_to_be32(nbase),
 183        cpu_to_be32(pecc->xscom_nest_size),
 184        cpu_to_be32(pbase),
 185        cpu_to_be32(pecc->xscom_pci_size),
 186    };
 187
 188    name = g_strdup_printf("pbcq@%x", nbase);
 189    offset = fdt_add_subnode(fdt, xscom_offset, name);
 190    _FDT(offset);
 191    g_free(name);
 192
 193    _FDT((fdt_setprop(fdt, offset, "reg", reg, sizeof(reg))));
 194
 195    _FDT((fdt_setprop_cell(fdt, offset, "ibm,pec-index", pec->index)));
 196    _FDT((fdt_setprop_cell(fdt, offset, "#address-cells", 1)));
 197    _FDT((fdt_setprop_cell(fdt, offset, "#size-cells", 0)));
 198    _FDT((fdt_setprop(fdt, offset, "compatible", pecc->compat,
 199                      pecc->compat_size)));
 200
 201    for (i = 0; i < pec->num_phbs; i++) {
 202        int phb_id = pnv_phb4_pec_get_phb_id(pec, i);
 203        int stk_offset;
 204
 205        name = g_strdup_printf("stack@%x", i);
 206        stk_offset = fdt_add_subnode(fdt, offset, name);
 207        _FDT(stk_offset);
 208        g_free(name);
 209        _FDT((fdt_setprop(fdt, stk_offset, "compatible", pecc->stk_compat,
 210                          pecc->stk_compat_size)));
 211        _FDT((fdt_setprop_cell(fdt, stk_offset, "reg", i)));
 212        _FDT((fdt_setprop_cell(fdt, stk_offset, "ibm,phb-index", phb_id)));
 213    }
 214
 215    return 0;
 216}
 217
 218static Property pnv_pec_properties[] = {
 219        DEFINE_PROP_UINT32("index", PnvPhb4PecState, index, 0),
 220        DEFINE_PROP_UINT32("chip-id", PnvPhb4PecState, chip_id, 0),
 221        DEFINE_PROP_LINK("chip", PnvPhb4PecState, chip, TYPE_PNV_CHIP,
 222                         PnvChip *),
 223        DEFINE_PROP_END_OF_LIST(),
 224};
 225
 226static uint32_t pnv_pec_xscom_pci_base(PnvPhb4PecState *pec)
 227{
 228    return PNV9_XSCOM_PEC_PCI_BASE + 0x1000000 * pec->index;
 229}
 230
 231static uint32_t pnv_pec_xscom_nest_base(PnvPhb4PecState *pec)
 232{
 233    return PNV9_XSCOM_PEC_NEST_BASE + 0x400 * pec->index;
 234}
 235
 236/*
 237 * PEC0 -> 1 phb
 238 * PEC1 -> 2 phb
 239 * PEC2 -> 3 phbs
 240 */
 241static const uint32_t pnv_pec_num_phbs[] = { 1, 2, 3 };
 242
 243static void pnv_pec_class_init(ObjectClass *klass, void *data)
 244{
 245    DeviceClass *dc = DEVICE_CLASS(klass);
 246    PnvXScomInterfaceClass *xdc = PNV_XSCOM_INTERFACE_CLASS(klass);
 247    PnvPhb4PecClass *pecc = PNV_PHB4_PEC_CLASS(klass);
 248    static const char compat[] = "ibm,power9-pbcq";
 249    static const char stk_compat[] = "ibm,power9-phb-stack";
 250
 251    xdc->dt_xscom = pnv_pec_dt_xscom;
 252
 253    dc->realize = pnv_pec_realize;
 254    device_class_set_props(dc, pnv_pec_properties);
 255    dc->user_creatable = false;
 256
 257    pecc->xscom_nest_base = pnv_pec_xscom_nest_base;
 258    pecc->xscom_pci_base  = pnv_pec_xscom_pci_base;
 259    pecc->xscom_nest_size = PNV9_XSCOM_PEC_NEST_SIZE;
 260    pecc->xscom_pci_size  = PNV9_XSCOM_PEC_PCI_SIZE;
 261    pecc->compat = compat;
 262    pecc->compat_size = sizeof(compat);
 263    pecc->stk_compat = stk_compat;
 264    pecc->stk_compat_size = sizeof(stk_compat);
 265    pecc->version = PNV_PHB4_VERSION;
 266    pecc->phb_type = TYPE_PNV_PHB4;
 267    pecc->num_phbs = pnv_pec_num_phbs;
 268    pecc->rp_model = TYPE_PNV_PHB4_ROOT_PORT;
 269}
 270
 271static const TypeInfo pnv_pec_type_info = {
 272    .name          = TYPE_PNV_PHB4_PEC,
 273    .parent        = TYPE_DEVICE,
 274    .instance_size = sizeof(PnvPhb4PecState),
 275    .class_init    = pnv_pec_class_init,
 276    .class_size    = sizeof(PnvPhb4PecClass),
 277    .interfaces    = (InterfaceInfo[]) {
 278        { TYPE_PNV_XSCOM_INTERFACE },
 279        { }
 280    }
 281};
 282
 283/*
 284 * POWER10 definitions
 285 */
 286
 287static uint32_t pnv_phb5_pec_xscom_pci_base(PnvPhb4PecState *pec)
 288{
 289    return PNV10_XSCOM_PEC_PCI_BASE + 0x1000000 * pec->index;
 290}
 291
 292static uint32_t pnv_phb5_pec_xscom_nest_base(PnvPhb4PecState *pec)
 293{
 294    /* index goes down ... */
 295    return PNV10_XSCOM_PEC_NEST_BASE - 0x1000000 * pec->index;
 296}
 297
 298/*
 299 * PEC0 -> 3 stacks
 300 * PEC1 -> 3 stacks
 301 */
 302static const uint32_t pnv_phb5_pec_num_stacks[] = { 3, 3 };
 303
 304static void pnv_phb5_pec_class_init(ObjectClass *klass, void *data)
 305{
 306    PnvPhb4PecClass *pecc = PNV_PHB4_PEC_CLASS(klass);
 307    static const char compat[] = "ibm,power10-pbcq";
 308    static const char stk_compat[] = "ibm,power10-phb-stack";
 309
 310    pecc->xscom_nest_base = pnv_phb5_pec_xscom_nest_base;
 311    pecc->xscom_pci_base  = pnv_phb5_pec_xscom_pci_base;
 312    pecc->xscom_nest_size = PNV10_XSCOM_PEC_NEST_SIZE;
 313    pecc->xscom_pci_size  = PNV10_XSCOM_PEC_PCI_SIZE;
 314    pecc->compat = compat;
 315    pecc->compat_size = sizeof(compat);
 316    pecc->stk_compat = stk_compat;
 317    pecc->stk_compat_size = sizeof(stk_compat);
 318    pecc->version = PNV_PHB5_VERSION;
 319    pecc->phb_type = TYPE_PNV_PHB5;
 320    pecc->num_phbs = pnv_phb5_pec_num_stacks;
 321    pecc->rp_model = TYPE_PNV_PHB5_ROOT_PORT;
 322}
 323
 324static const TypeInfo pnv_phb5_pec_type_info = {
 325    .name          = TYPE_PNV_PHB5_PEC,
 326    .parent        = TYPE_PNV_PHB4_PEC,
 327    .instance_size = sizeof(PnvPhb4PecState),
 328    .class_init    = pnv_phb5_pec_class_init,
 329    .class_size    = sizeof(PnvPhb4PecClass),
 330    .interfaces    = (InterfaceInfo[]) {
 331        { TYPE_PNV_XSCOM_INTERFACE },
 332        { }
 333    }
 334};
 335
 336static void pnv_pec_register_types(void)
 337{
 338    type_register_static(&pnv_pec_type_info);
 339    type_register_static(&pnv_phb5_pec_type_info);
 340}
 341
 342type_init(pnv_pec_register_types);
 343