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

ppc/pnv: extend XSCOM core support for POWER9



Provide a new class attribute to define XSCOM operations per CPU
family and add a couple of XSCOM addresses controlling the power
management states of the core on POWER9.

Signed-off-by: default avatarCédric Le Goater <clg@kaod.org>
Message-Id: <20190307223548.20516-11-clg@kaod.org>
Signed-off-by: default avatarDavid Gibson <david@gibson.dropbear.id.au>
parent 6598a70d
Loading
Loading
Loading
Loading
+87 −13
Original line number Diff line number Diff line
@@ -60,7 +60,7 @@ static void pnv_cpu_reset(void *opaque)
#define PNV_XSCOM_EX_DTS_RESULT0     0x50000
#define PNV_XSCOM_EX_DTS_RESULT1     0x50001

static uint64_t pnv_core_xscom_read(void *opaque, hwaddr addr,
static uint64_t pnv_core_power8_xscom_read(void *opaque, hwaddr addr,
                                           unsigned int width)
{
    uint32_t offset = addr >> 3;
@@ -82,16 +82,74 @@ static uint64_t pnv_core_xscom_read(void *opaque, hwaddr addr,
    return val;
}

static void pnv_core_xscom_write(void *opaque, hwaddr addr, uint64_t val,
static void pnv_core_power8_xscom_write(void *opaque, hwaddr addr, uint64_t val,
                                        unsigned int width)
{
    qemu_log_mask(LOG_UNIMP, "Warning: writing to reg=0x%" HWADDR_PRIx "\n",
                  addr);
}

static const MemoryRegionOps pnv_core_xscom_ops = {
    .read = pnv_core_xscom_read,
    .write = pnv_core_xscom_write,
static const MemoryRegionOps pnv_core_power8_xscom_ops = {
    .read = pnv_core_power8_xscom_read,
    .write = pnv_core_power8_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,
};


/*
 * POWER9 core controls
 */
#define PNV9_XSCOM_EC_PPM_SPECIAL_WKUP_HYP 0xf010d
#define PNV9_XSCOM_EC_PPM_SPECIAL_WKUP_OTR 0xf010a

static uint64_t pnv_core_power9_xscom_read(void *opaque, hwaddr addr,
                                           unsigned int width)
{
    uint32_t offset = addr >> 3;
    uint64_t val = 0;

    /* The result should be 38 C */
    switch (offset) {
    case PNV_XSCOM_EX_DTS_RESULT0:
        val = 0x26f024f023f0000ull;
        break;
    case PNV_XSCOM_EX_DTS_RESULT1:
        val = 0x24f000000000000ull;
        break;
    case PNV9_XSCOM_EC_PPM_SPECIAL_WKUP_HYP:
    case PNV9_XSCOM_EC_PPM_SPECIAL_WKUP_OTR:
        val = 0x0;
        break;
    default:
        qemu_log_mask(LOG_UNIMP, "Warning: reading reg=0x%" HWADDR_PRIx "\n",
                  addr);
    }

    return val;
}

static void pnv_core_power9_xscom_write(void *opaque, hwaddr addr, uint64_t val,
                                        unsigned int width)
{
    uint32_t offset = addr >> 3;

    switch (offset) {
    case PNV9_XSCOM_EC_PPM_SPECIAL_WKUP_HYP:
    case PNV9_XSCOM_EC_PPM_SPECIAL_WKUP_OTR:
        break;
    default:
        qemu_log_mask(LOG_UNIMP, "Warning: writing to reg=0x%" HWADDR_PRIx "\n",
                      addr);
    }
}

static const MemoryRegionOps pnv_core_power9_xscom_ops = {
    .read = pnv_core_power9_xscom_read,
    .write = pnv_core_power9_xscom_write,
    .valid.min_access_size = 8,
    .valid.max_access_size = 8,
    .impl.min_access_size = 8,
@@ -138,6 +196,7 @@ static void pnv_realize_vcpu(PowerPCCPU *cpu, PnvChip *chip, Error **errp)
static void pnv_core_realize(DeviceState *dev, Error **errp)
{
    PnvCore *pc = PNV_CORE(OBJECT(dev));
    PnvCoreClass *pcc = PNV_CORE_GET_CLASS(pc);
    CPUCore *cc = CPU_CORE(OBJECT(dev));
    const char *typename = pnv_core_cpu_typename(pc);
    Error *local_err = NULL;
@@ -180,7 +239,7 @@ static void pnv_core_realize(DeviceState *dev, Error **errp)
    }

    snprintf(name, sizeof(name), "xscom-core.%d", cc->core_id);
    pnv_xscom_region_init(&pc->xscom_regs, OBJECT(dev), &pnv_core_xscom_ops,
    pnv_xscom_region_init(&pc->xscom_regs, OBJECT(dev), pcc->xscom_ops,
                          pc, name, PNV_XSCOM_EX_SIZE);
    return;

@@ -222,6 +281,20 @@ static Property pnv_core_properties[] = {
    DEFINE_PROP_END_OF_LIST(),
};

static void pnv_core_power8_class_init(ObjectClass *oc, void *data)
{
    PnvCoreClass *pcc = PNV_CORE_CLASS(oc);

    pcc->xscom_ops = &pnv_core_power8_xscom_ops;
}

static void pnv_core_power9_class_init(ObjectClass *oc, void *data)
{
    PnvCoreClass *pcc = PNV_CORE_CLASS(oc);

    pcc->xscom_ops = &pnv_core_power9_xscom_ops;
}

static void pnv_core_class_init(ObjectClass *oc, void *data)
{
    DeviceClass *dc = DEVICE_CLASS(oc);
@@ -231,10 +304,11 @@ static void pnv_core_class_init(ObjectClass *oc, void *data)
    dc->props = pnv_core_properties;
}

#define DEFINE_PNV_CORE_TYPE(cpu_model)         \
#define DEFINE_PNV_CORE_TYPE(family, cpu_model) \
    {                                           \
        .parent = TYPE_PNV_CORE,                \
        .name = PNV_CORE_TYPE_NAME(cpu_model),  \
        .class_init = pnv_core_##family##_class_init, \
    }

static const TypeInfo pnv_core_infos[] = {
@@ -246,10 +320,10 @@ static const TypeInfo pnv_core_infos[] = {
        .class_init = pnv_core_class_init,
        .abstract       = true,
    },
    DEFINE_PNV_CORE_TYPE("power8e_v2.1"),
    DEFINE_PNV_CORE_TYPE("power8_v2.0"),
    DEFINE_PNV_CORE_TYPE("power8nvl_v1.0"),
    DEFINE_PNV_CORE_TYPE("power9_v2.0"),
    DEFINE_PNV_CORE_TYPE(power8, "power8e_v2.1"),
    DEFINE_PNV_CORE_TYPE(power8, "power8_v2.0"),
    DEFINE_PNV_CORE_TYPE(power8, "power8nvl_v1.0"),
    DEFINE_PNV_CORE_TYPE(power9, "power9_v2.0"),
};

DEFINE_TYPES(pnv_core_infos)
+2 −0
Original line number Diff line number Diff line
@@ -42,6 +42,8 @@ typedef struct PnvCore {

typedef struct PnvCoreClass {
    DeviceClass parent_class;

    const MemoryRegionOps *xscom_ops;
} PnvCoreClass;

#define PNV_CORE_TYPE_SUFFIX "-" TYPE_PNV_CORE