Commit 6598a70d authored by Cédric Le Goater's avatar Cédric Le Goater Committed by David Gibson
Browse files

ppc/pnv: add a OCC model for POWER9



The OCC on POWER9 is very similar to the one found on POWER8. Provide
the same routines with P9 values for the registers and IRQ number.

Signed-off-by: default avatarCédric Le Goater <clg@kaod.org>
Message-Id: <20190307223548.20516-10-clg@kaod.org>
Signed-off-by: default avatarDavid Gibson <david@gibson.dropbear.id.au>
parent 3233838c
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -956,6 +956,11 @@ static void pnv_chip_power9_instance_init(Object *obj)
                            TYPE_PNV9_LPC, &error_abort, NULL);
    object_property_add_const_link(OBJECT(&chip9->lpc), "psi",
                                   OBJECT(&chip9->psi), &error_abort);

    object_initialize_child(obj, "occ",  &chip9->occ, sizeof(chip9->occ),
                            TYPE_PNV9_OCC, &error_abort, NULL);
    object_property_add_const_link(OBJECT(&chip9->occ), "psi",
                                   OBJECT(&chip9->psi), &error_abort);
}

static void pnv_chip_power9_realize(DeviceState *dev, Error **errp)
@@ -1012,6 +1017,14 @@ static void pnv_chip_power9_realize(DeviceState *dev, Error **errp)

    chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0",
                                            (uint64_t) PNV9_LPCM_BASE(chip));

    /* Create the simplified OCC model */
    object_property_set_bool(OBJECT(&chip9->occ), true, "realized", &local_err);
    if (local_err) {
        error_propagate(errp, local_err);
        return;
    }
    pnv_xscom_add_subregion(chip, PNV9_XSCOM_OCC_BASE, &chip9->occ.xscom_regs);
}

static void pnv_chip_power9_class_init(ObjectClass *klass, void *data)
+72 −0
Original line number Diff line number Diff line
@@ -109,6 +109,77 @@ static const TypeInfo pnv_occ_power8_type_info = {
    .class_init    = pnv_occ_power8_class_init,
};

#define P9_OCB_OCI_OCCMISC              0x6080
#define P9_OCB_OCI_OCCMISC_CLEAR        0x6081
#define P9_OCB_OCI_OCCMISC_OR           0x6082


static uint64_t pnv_occ_power9_xscom_read(void *opaque, hwaddr addr,
                                          unsigned size)
{
    PnvOCC *occ = PNV_OCC(opaque);
    uint32_t offset = addr >> 3;
    uint64_t val = 0;

    switch (offset) {
    case P9_OCB_OCI_OCCMISC:
        val = occ->occmisc;
        break;
    default:
        qemu_log_mask(LOG_UNIMP, "OCC Unimplemented register: Ox%"
                      HWADDR_PRIx "\n", addr >> 3);
    }
    return val;
}

static void pnv_occ_power9_xscom_write(void *opaque, hwaddr addr,
                                       uint64_t val, unsigned size)
{
    PnvOCC *occ = PNV_OCC(opaque);
    uint32_t offset = addr >> 3;

    switch (offset) {
    case P9_OCB_OCI_OCCMISC_CLEAR:
        pnv_occ_set_misc(occ, 0);
        break;
    case P9_OCB_OCI_OCCMISC_OR:
        pnv_occ_set_misc(occ, occ->occmisc | val);
        break;
    case P9_OCB_OCI_OCCMISC:
        pnv_occ_set_misc(occ, val);
       break;
    default:
        qemu_log_mask(LOG_UNIMP, "OCC Unimplemented register: Ox%"
                      HWADDR_PRIx "\n", addr >> 3);
    }
}

static const MemoryRegionOps pnv_occ_power9_xscom_ops = {
    .read = pnv_occ_power9_xscom_read,
    .write = pnv_occ_power9_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_occ_power9_class_init(ObjectClass *klass, void *data)
{
    PnvOCCClass *poc = PNV_OCC_CLASS(klass);

    poc->xscom_size = PNV9_XSCOM_OCC_SIZE;
    poc->xscom_ops = &pnv_occ_power9_xscom_ops;
    poc->psi_irq = PSIHB9_IRQ_OCC;
}

static const TypeInfo pnv_occ_power9_type_info = {
    .name          = TYPE_PNV9_OCC,
    .parent        = TYPE_PNV_OCC,
    .instance_size = sizeof(PnvOCC),
    .class_init    = pnv_occ_power9_class_init,
};

static void pnv_occ_realize(DeviceState *dev, Error **errp)
{
    PnvOCC *occ = PNV_OCC(dev);
@@ -152,6 +223,7 @@ static void pnv_occ_register_types(void)
{
    type_register_static(&pnv_occ_type_info);
    type_register_static(&pnv_occ_power8_type_info);
    type_register_static(&pnv_occ_power9_type_info);
}

type_init(pnv_occ_register_types);
+1 −0
Original line number Diff line number Diff line
@@ -88,6 +88,7 @@ typedef struct Pnv9Chip {
    PnvXive      xive;
    Pnv9Psi      psi;
    PnvLpcController lpc;
    PnvOCC       occ;
} Pnv9Chip;

typedef struct PnvChipClass {
+2 −0
Original line number Diff line number Diff line
@@ -25,6 +25,8 @@
#define PNV_OCC(obj) OBJECT_CHECK(PnvOCC, (obj), TYPE_PNV_OCC)
#define TYPE_PNV8_OCC TYPE_PNV_OCC "-POWER8"
#define PNV8_OCC(obj) OBJECT_CHECK(PnvOCC, (obj), TYPE_PNV8_OCC)
#define TYPE_PNV9_OCC TYPE_PNV_OCC "-POWER9"
#define PNV9_OCC(obj) OBJECT_CHECK(PnvOCC, (obj), TYPE_PNV9_OCC)

typedef struct PnvOCC {
    DeviceState xd;
+3 −0
Original line number Diff line number Diff line
@@ -73,6 +73,9 @@ typedef struct PnvXScomInterfaceClass {
#define PNV_XSCOM_OCC_BASE        0x0066000
#define PNV_XSCOM_OCC_SIZE        0x6000

#define PNV9_XSCOM_OCC_BASE       PNV_XSCOM_OCC_BASE
#define PNV9_XSCOM_OCC_SIZE       0x8000

#define PNV9_XSCOM_PSIHB_BASE     0x5012900
#define PNV9_XSCOM_PSIHB_SIZE     0x100