1d2fd9612SCédric Le Goater /*
2d2fd9612SCédric Le Goater * QEMU PowerPC PowerNV CPU Core model
3d2fd9612SCédric Le Goater *
4d2fd9612SCédric Le Goater * Copyright (c) 2016, IBM Corporation.
5d2fd9612SCédric Le Goater *
6d2fd9612SCédric Le Goater * This library is free software; you can redistribute it and/or
7d2fd9612SCédric Le Goater * modify it under the terms of the GNU Lesser General Public License
8f70c5966SChetan Pant * as published by the Free Software Foundation; either version 2.1 of
9d2fd9612SCédric Le Goater * the License, or (at your option) any later version.
10d2fd9612SCédric Le Goater *
11d2fd9612SCédric Le Goater * This library is distributed in the hope that it will be useful, but
12d2fd9612SCédric Le Goater * WITHOUT ANY WARRANTY; without even the implied warranty of
13d2fd9612SCédric Le Goater * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14d2fd9612SCédric Le Goater * Lesser General Public License for more details.
15d2fd9612SCédric Le Goater *
16d2fd9612SCédric Le Goater * You should have received a copy of the GNU Lesser General Public
17d2fd9612SCédric Le Goater * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18d2fd9612SCédric Le Goater */
190b8fa32fSMarkus Armbruster
20d2fd9612SCédric Le Goater #include "qemu/osdep.h"
2171e8a915SMarkus Armbruster #include "sysemu/reset.h"
22d2fd9612SCédric Le Goater #include "qapi/error.h"
2324ece072SCédric Le Goater #include "qemu/log.h"
240b8fa32fSMarkus Armbruster #include "qemu/module.h"
25fcf5ef2aSThomas Huth #include "target/ppc/cpu.h"
26d2fd9612SCédric Le Goater #include "hw/ppc/ppc.h"
27d2fd9612SCédric Le Goater #include "hw/ppc/pnv.h"
282c6fe2e2SMarkus Armbruster #include "hw/ppc/pnv_chip.h"
29d2fd9612SCédric Le Goater #include "hw/ppc/pnv_core.h"
30ec575aa0SCédric Le Goater #include "hw/ppc/pnv_xscom.h"
31960fbd29SCédric Le Goater #include "hw/ppc/xics.h"
32a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h"
33bd4160bcSRichard Henderson #include "helper_regs.h"
34d2fd9612SCédric Le Goater
pnv_core_cpu_typename(PnvCore * pc)3535bdb9deSIgor Mammedov static const char *pnv_core_cpu_typename(PnvCore *pc)
3635bdb9deSIgor Mammedov {
3735bdb9deSIgor Mammedov const char *core_type = object_class_get_name(object_get_class(OBJECT(pc)));
3835bdb9deSIgor Mammedov int len = strlen(core_type) - strlen(PNV_CORE_TYPE_SUFFIX);
3935bdb9deSIgor Mammedov char *s = g_strdup_printf(POWERPC_CPU_TYPE_NAME("%.*s"), len, core_type);
4035bdb9deSIgor Mammedov const char *cpu_type = object_class_get_name(object_class_by_name(s));
4135bdb9deSIgor Mammedov g_free(s);
4235bdb9deSIgor Mammedov return cpu_type;
4335bdb9deSIgor Mammedov }
4435bdb9deSIgor Mammedov
pnv_core_cpu_reset(PnvCore * pc,PowerPCCPU * cpu)4559942f0eSCédric Le Goater static void pnv_core_cpu_reset(PnvCore *pc, PowerPCCPU *cpu)
46d2fd9612SCédric Le Goater {
47d2fd9612SCédric Le Goater CPUState *cs = CPU(cpu);
48d2fd9612SCédric Le Goater CPUPPCState *env = &cpu->env;
4959942f0eSCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(pc->chip);
50d2fd9612SCédric Le Goater
51d2fd9612SCédric Le Goater cpu_reset(cs);
52d2fd9612SCédric Le Goater
53d2fd9612SCédric Le Goater /*
54d2fd9612SCédric Le Goater * the skiboot firmware elects a primary thread to initialize the
55d2fd9612SCédric Le Goater * system and it can be any.
56d2fd9612SCédric Le Goater */
57d2fd9612SCédric Le Goater env->gpr[3] = PNV_FDT_ADDR;
58d2fd9612SCédric Le Goater env->nip = 0x10;
59d2fd9612SCédric Le Goater env->msr |= MSR_HVB; /* Hypervisor mode */
6008c3f3a7SCédric Le Goater env->spr[SPR_HRMOR] = pc->hrmor;
6127f61d1bSNicholas Piggin if (pc->big_core) {
6227f61d1bSNicholas Piggin /* Clear "small core" bit on Power9/10 (this is set in default PVR) */
6327f61d1bSNicholas Piggin env->spr[SPR_PVR] &= ~PPC_BIT(51);
6427f61d1bSNicholas Piggin }
65bd4160bcSRichard Henderson hreg_compute_hflags(env);
662fdedcbcSMatheus Ferst ppc_maybe_interrupt(env);
6708c3f3a7SCédric Le Goater
6830d0647bSNicholas Piggin cpu_ppc_tb_reset(env);
6930d0647bSNicholas Piggin
7059942f0eSCédric Le Goater pcc->intc_reset(pc->chip, cpu);
71d2fd9612SCédric Le Goater }
72d2fd9612SCédric Le Goater
7324ece072SCédric Le Goater /*
7424ece072SCédric Le Goater * These values are read by the PowerNV HW monitors under Linux
7524ece072SCédric Le Goater */
7624ece072SCédric Le Goater #define PNV_XSCOM_EX_DTS_RESULT0 0x50000
7724ece072SCédric Le Goater #define PNV_XSCOM_EX_DTS_RESULT1 0x50001
7824ece072SCédric Le Goater
pnv_core_power8_xscom_read(void * opaque,hwaddr addr,unsigned int width)7990ef386cSCédric Le Goater static uint64_t pnv_core_power8_xscom_read(void *opaque, hwaddr addr,
8024ece072SCédric Le Goater unsigned int width)
8124ece072SCédric Le Goater {
8224ece072SCédric Le Goater uint32_t offset = addr >> 3;
8324ece072SCédric Le Goater uint64_t val = 0;
8424ece072SCédric Le Goater
8524ece072SCédric Le Goater /* The result should be 38 C */
8624ece072SCédric Le Goater switch (offset) {
8724ece072SCédric Le Goater case PNV_XSCOM_EX_DTS_RESULT0:
8824ece072SCédric Le Goater val = 0x26f024f023f0000ull;
8924ece072SCédric Le Goater break;
9024ece072SCédric Le Goater case PNV_XSCOM_EX_DTS_RESULT1:
9124ece072SCédric Le Goater val = 0x24f000000000000ull;
9224ece072SCédric Le Goater break;
9324ece072SCédric Le Goater default:
94b0afb574SJoel Stanley qemu_log_mask(LOG_UNIMP, "%s: unimp read 0x%08x\n", __func__,
95b0afb574SJoel Stanley offset);
9624ece072SCédric Le Goater }
9724ece072SCédric Le Goater
9824ece072SCédric Le Goater return val;
9924ece072SCédric Le Goater }
10024ece072SCédric Le Goater
pnv_core_power8_xscom_write(void * opaque,hwaddr addr,uint64_t val,unsigned int width)10190ef386cSCédric Le Goater static void pnv_core_power8_xscom_write(void *opaque, hwaddr addr, uint64_t val,
10224ece072SCédric Le Goater unsigned int width)
10324ece072SCédric Le Goater {
104b0afb574SJoel Stanley uint32_t offset = addr >> 3;
105b0afb574SJoel Stanley
106b0afb574SJoel Stanley qemu_log_mask(LOG_UNIMP, "%s: unimp write 0x%08x\n", __func__,
107b0afb574SJoel Stanley offset);
10824ece072SCédric Le Goater }
10924ece072SCédric Le Goater
11090ef386cSCédric Le Goater static const MemoryRegionOps pnv_core_power8_xscom_ops = {
11190ef386cSCédric Le Goater .read = pnv_core_power8_xscom_read,
11290ef386cSCédric Le Goater .write = pnv_core_power8_xscom_write,
11390ef386cSCédric Le Goater .valid.min_access_size = 8,
11490ef386cSCédric Le Goater .valid.max_access_size = 8,
11590ef386cSCédric Le Goater .impl.min_access_size = 8,
11690ef386cSCédric Le Goater .impl.max_access_size = 8,
11790ef386cSCédric Le Goater .endianness = DEVICE_BIG_ENDIAN,
11890ef386cSCédric Le Goater };
11990ef386cSCédric Le Goater
12090ef386cSCédric Le Goater
12190ef386cSCédric Le Goater /*
12290ef386cSCédric Le Goater * POWER9 core controls
12390ef386cSCédric Le Goater */
12490ef386cSCédric Le Goater #define PNV9_XSCOM_EC_PPM_SPECIAL_WKUP_HYP 0xf010d
12590ef386cSCédric Le Goater #define PNV9_XSCOM_EC_PPM_SPECIAL_WKUP_OTR 0xf010a
12690ef386cSCédric Le Goater
12753658074SJoel Stanley #define PNV9_XSCOM_EC_CORE_THREAD_STATE 0x10ab3
12853658074SJoel Stanley
pnv_core_power9_xscom_read(void * opaque,hwaddr addr,unsigned int width)12990ef386cSCédric Le Goater static uint64_t pnv_core_power9_xscom_read(void *opaque, hwaddr addr,
13090ef386cSCédric Le Goater unsigned int width)
13190ef386cSCédric Le Goater {
13290ef386cSCédric Le Goater uint32_t offset = addr >> 3;
13390ef386cSCédric Le Goater uint64_t val = 0;
13490ef386cSCédric Le Goater
13590ef386cSCédric Le Goater /* The result should be 38 C */
13690ef386cSCédric Le Goater switch (offset) {
13790ef386cSCédric Le Goater case PNV_XSCOM_EX_DTS_RESULT0:
13890ef386cSCédric Le Goater val = 0x26f024f023f0000ull;
13990ef386cSCédric Le Goater break;
14090ef386cSCédric Le Goater case PNV_XSCOM_EX_DTS_RESULT1:
14190ef386cSCédric Le Goater val = 0x24f000000000000ull;
14290ef386cSCédric Le Goater break;
14390ef386cSCédric Le Goater case PNV9_XSCOM_EC_PPM_SPECIAL_WKUP_HYP:
14490ef386cSCédric Le Goater case PNV9_XSCOM_EC_PPM_SPECIAL_WKUP_OTR:
14590ef386cSCédric Le Goater val = 0x0;
14690ef386cSCédric Le Goater break;
14753658074SJoel Stanley case PNV9_XSCOM_EC_CORE_THREAD_STATE:
14853658074SJoel Stanley val = 0;
14953658074SJoel Stanley break;
15090ef386cSCédric Le Goater default:
151b0afb574SJoel Stanley qemu_log_mask(LOG_UNIMP, "%s: unimp read 0x%08x\n", __func__,
152b0afb574SJoel Stanley offset);
15390ef386cSCédric Le Goater }
15490ef386cSCédric Le Goater
15590ef386cSCédric Le Goater return val;
15690ef386cSCédric Le Goater }
15790ef386cSCédric Le Goater
pnv_core_power9_xscom_write(void * opaque,hwaddr addr,uint64_t val,unsigned int width)15890ef386cSCédric Le Goater static void pnv_core_power9_xscom_write(void *opaque, hwaddr addr, uint64_t val,
15990ef386cSCédric Le Goater unsigned int width)
16090ef386cSCédric Le Goater {
16190ef386cSCédric Le Goater uint32_t offset = addr >> 3;
16290ef386cSCédric Le Goater
16390ef386cSCédric Le Goater switch (offset) {
16490ef386cSCédric Le Goater case PNV9_XSCOM_EC_PPM_SPECIAL_WKUP_HYP:
16590ef386cSCédric Le Goater case PNV9_XSCOM_EC_PPM_SPECIAL_WKUP_OTR:
16690ef386cSCédric Le Goater break;
16790ef386cSCédric Le Goater default:
168b0afb574SJoel Stanley qemu_log_mask(LOG_UNIMP, "%s: unimp write 0x%08x\n", __func__,
169b0afb574SJoel Stanley offset);
17090ef386cSCédric Le Goater }
17190ef386cSCédric Le Goater }
17290ef386cSCédric Le Goater
17390ef386cSCédric Le Goater static const MemoryRegionOps pnv_core_power9_xscom_ops = {
17490ef386cSCédric Le Goater .read = pnv_core_power9_xscom_read,
17590ef386cSCédric Le Goater .write = pnv_core_power9_xscom_write,
17624ece072SCédric Le Goater .valid.min_access_size = 8,
17724ece072SCédric Le Goater .valid.max_access_size = 8,
17824ece072SCédric Le Goater .impl.min_access_size = 8,
17924ece072SCédric Le Goater .impl.max_access_size = 8,
18024ece072SCédric Le Goater .endianness = DEVICE_BIG_ENDIAN,
18124ece072SCédric Le Goater };
18224ece072SCédric Le Goater
1839a394217SJoel Stanley /*
1849a394217SJoel Stanley * POWER10 core controls
1859a394217SJoel Stanley */
1869a394217SJoel Stanley
18753658074SJoel Stanley #define PNV10_XSCOM_EC_CORE_THREAD_STATE 0x412
188c8891955SNicholas Piggin #define PNV10_XSCOM_EC_CORE_THREAD_INFO 0x413
189c8891955SNicholas Piggin #define PNV10_XSCOM_EC_CORE_DIRECT_CONTROLS 0x449
190c8891955SNicholas Piggin #define PNV10_XSCOM_EC_CORE_RAS_STATUS 0x454
19153658074SJoel Stanley
pnv_core_power10_xscom_read(void * opaque,hwaddr addr,unsigned int width)1929a394217SJoel Stanley static uint64_t pnv_core_power10_xscom_read(void *opaque, hwaddr addr,
1939a394217SJoel Stanley unsigned int width)
1949a394217SJoel Stanley {
195c8891955SNicholas Piggin PnvCore *pc = PNV_CORE(opaque);
196c8891955SNicholas Piggin int nr_threads = CPU_CORE(pc)->nr_threads;
197c8891955SNicholas Piggin int i;
1989a394217SJoel Stanley uint32_t offset = addr >> 3;
1999a394217SJoel Stanley uint64_t val = 0;
2009a394217SJoel Stanley
2019a394217SJoel Stanley switch (offset) {
20253658074SJoel Stanley case PNV10_XSCOM_EC_CORE_THREAD_STATE:
203c8891955SNicholas Piggin for (i = 0; i < nr_threads; i++) {
204c8891955SNicholas Piggin PowerPCCPU *cpu = pc->threads[i];
205c8891955SNicholas Piggin CPUState *cs = CPU(cpu);
206c8891955SNicholas Piggin
207c8891955SNicholas Piggin if (cs->halted) {
208c8891955SNicholas Piggin val |= PPC_BIT(56 + i);
209c8891955SNicholas Piggin }
210c8891955SNicholas Piggin }
2113b5ea01eSNicholas Piggin if (pc->lpar_per_core) {
2123b5ea01eSNicholas Piggin val |= PPC_BIT(62);
2133b5ea01eSNicholas Piggin }
214c8891955SNicholas Piggin break;
215c8891955SNicholas Piggin case PNV10_XSCOM_EC_CORE_THREAD_INFO:
216c8891955SNicholas Piggin break;
217c8891955SNicholas Piggin case PNV10_XSCOM_EC_CORE_RAS_STATUS:
218c8891955SNicholas Piggin for (i = 0; i < nr_threads; i++) {
219c8891955SNicholas Piggin PowerPCCPU *cpu = pc->threads[i];
22096746f7aSNicholas Piggin CPUPPCState *env = &cpu->env;
22196746f7aSNicholas Piggin if (env->quiesced) {
222c8891955SNicholas Piggin val |= PPC_BIT(0 + 8 * i) | PPC_BIT(1 + 8 * i);
223c8891955SNicholas Piggin }
224c8891955SNicholas Piggin }
22553658074SJoel Stanley break;
2269a394217SJoel Stanley default:
227b0afb574SJoel Stanley qemu_log_mask(LOG_UNIMP, "%s: unimp read 0x%08x\n", __func__,
228b0afb574SJoel Stanley offset);
2299a394217SJoel Stanley }
2309a394217SJoel Stanley
2319a394217SJoel Stanley return val;
2329a394217SJoel Stanley }
2339a394217SJoel Stanley
pnv_core_power10_xscom_write(void * opaque,hwaddr addr,uint64_t val,unsigned int width)2349a394217SJoel Stanley static void pnv_core_power10_xscom_write(void *opaque, hwaddr addr,
2359a394217SJoel Stanley uint64_t val, unsigned int width)
2369a394217SJoel Stanley {
237c8891955SNicholas Piggin PnvCore *pc = PNV_CORE(opaque);
238c8891955SNicholas Piggin int nr_threads = CPU_CORE(pc)->nr_threads;
239c8891955SNicholas Piggin int i;
2409a394217SJoel Stanley uint32_t offset = addr >> 3;
2419a394217SJoel Stanley
2429a394217SJoel Stanley switch (offset) {
243c8891955SNicholas Piggin case PNV10_XSCOM_EC_CORE_DIRECT_CONTROLS:
244c8891955SNicholas Piggin for (i = 0; i < nr_threads; i++) {
245c8891955SNicholas Piggin PowerPCCPU *cpu = pc->threads[i];
246c8891955SNicholas Piggin CPUState *cs = CPU(cpu);
24796746f7aSNicholas Piggin CPUPPCState *env = &cpu->env;
248c8891955SNicholas Piggin
249c8891955SNicholas Piggin if (val & PPC_BIT(7 + 8 * i)) { /* stop */
250c8891955SNicholas Piggin val &= ~PPC_BIT(7 + 8 * i);
251c8891955SNicholas Piggin cpu_pause(cs);
25296746f7aSNicholas Piggin env->quiesced = true;
253c8891955SNicholas Piggin }
254c8891955SNicholas Piggin if (val & PPC_BIT(6 + 8 * i)) { /* start */
255c8891955SNicholas Piggin val &= ~PPC_BIT(6 + 8 * i);
25696746f7aSNicholas Piggin env->quiesced = false;
257c8891955SNicholas Piggin cpu_resume(cs);
258c8891955SNicholas Piggin }
259c8891955SNicholas Piggin if (val & PPC_BIT(4 + 8 * i)) { /* sreset */
260c8891955SNicholas Piggin val &= ~PPC_BIT(4 + 8 * i);
26196746f7aSNicholas Piggin env->quiesced = false;
262c8891955SNicholas Piggin pnv_cpu_do_nmi_resume(cs);
263c8891955SNicholas Piggin }
264c8891955SNicholas Piggin if (val & PPC_BIT(3 + 8 * i)) { /* clear maint */
26596746f7aSNicholas Piggin env->quiesced = false;
266c8891955SNicholas Piggin /*
267c8891955SNicholas Piggin * Hardware has very particular cases for where clear maint
268c8891955SNicholas Piggin * must be used and where start must be used to resume a
269c8891955SNicholas Piggin * thread. These are not modelled exactly, just treat
270c8891955SNicholas Piggin * this and start the same.
271c8891955SNicholas Piggin */
272c8891955SNicholas Piggin val &= ~PPC_BIT(3 + 8 * i);
273c8891955SNicholas Piggin cpu_resume(cs);
274c8891955SNicholas Piggin }
275c8891955SNicholas Piggin }
276c8891955SNicholas Piggin if (val) {
277c8891955SNicholas Piggin qemu_log_mask(LOG_UNIMP, "%s: unimp bits in DIRECT_CONTROLS "
278c8891955SNicholas Piggin "0x%016" PRIx64 "\n", __func__, val);
279c8891955SNicholas Piggin }
280c8891955SNicholas Piggin break;
281c8891955SNicholas Piggin
2829a394217SJoel Stanley default:
283b0afb574SJoel Stanley qemu_log_mask(LOG_UNIMP, "%s: unimp write 0x%08x\n", __func__,
284b0afb574SJoel Stanley offset);
2859a394217SJoel Stanley }
2869a394217SJoel Stanley }
2879a394217SJoel Stanley
2889a394217SJoel Stanley static const MemoryRegionOps pnv_core_power10_xscom_ops = {
2899a394217SJoel Stanley .read = pnv_core_power10_xscom_read,
2909a394217SJoel Stanley .write = pnv_core_power10_xscom_write,
2919a394217SJoel Stanley .valid.min_access_size = 8,
2929a394217SJoel Stanley .valid.max_access_size = 8,
2939a394217SJoel Stanley .impl.min_access_size = 8,
2949a394217SJoel Stanley .impl.max_access_size = 8,
2959a394217SJoel Stanley .endianness = DEVICE_BIG_ENDIAN,
2969a394217SJoel Stanley };
2979a394217SJoel Stanley
pnv_core_cpu_realize(PnvCore * pc,PowerPCCPU * cpu,Error ** errp,int thread_index)298934676c7SNicholas Piggin static void pnv_core_cpu_realize(PnvCore *pc, PowerPCCPU *cpu, Error **errp,
299934676c7SNicholas Piggin int thread_index)
300d2fd9612SCédric Le Goater {
3013a247521SDavid Gibson CPUPPCState *env = &cpu->env;
3029940412aSCaleb Schlossin int core_hwid;
30325de2822SNicholas Piggin ppc_spr_t *pir_spr = &env->spr_cb[SPR_PIR];
30425de2822SNicholas Piggin ppc_spr_t *tir_spr = &env->spr_cb[SPR_TIR];
30525de2822SNicholas Piggin uint32_t pir, tir;
306d2fd9612SCédric Le Goater Error *local_err = NULL;
30759942f0eSCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(pc->chip);
308960fbd29SCédric Le Goater
309668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(cpu), NULL, errp)) {
310960fbd29SCédric Le Goater return;
311960fbd29SCédric Le Goater }
312d2fd9612SCédric Le Goater
31359942f0eSCédric Le Goater pcc->intc_create(pc->chip, cpu, &local_err);
314d2fd9612SCédric Le Goater if (local_err) {
315d2fd9612SCédric Le Goater error_propagate(errp, local_err);
316d2fd9612SCédric Le Goater return;
317d2fd9612SCédric Le Goater }
318d2fd9612SCédric Le Goater
3199940412aSCaleb Schlossin core_hwid = object_property_get_uint(OBJECT(pc), "hwid", &error_abort);
3203a247521SDavid Gibson
32125de2822SNicholas Piggin pcc->get_pir_tir(pc->chip, core_hwid, thread_index, &pir, &tir);
32225de2822SNicholas Piggin pir_spr->default_value = pir;
32325de2822SNicholas Piggin tir_spr->default_value = tir;
3243a247521SDavid Gibson
325*2fc0a78aSGlenn Miles env->chip_index = pc->chip->chip_id;
326*2fc0a78aSGlenn Miles
327c26504afSNicholas Piggin if (pc->big_core) {
328c26504afSNicholas Piggin /* 2 "small cores" get the same core index for SMT operations */
329c26504afSNicholas Piggin env->core_index = core_hwid >> 1;
330c26504afSNicholas Piggin } else {
331feb37fdcSNicholas Piggin env->core_index = core_hwid;
332c26504afSNicholas Piggin }
333feb37fdcSNicholas Piggin
3343b5ea01eSNicholas Piggin if (pc->lpar_per_core) {
3353b5ea01eSNicholas Piggin cpu_ppc_set_1lpar(cpu);
3363b5ea01eSNicholas Piggin }
3373b5ea01eSNicholas Piggin
3383a247521SDavid Gibson /* Set time-base frequency to 512 MHz */
3393a247521SDavid Gibson cpu_ppc_tb_init(env, PNV_TIMEBASE_FREQ);
340fa06541bSCédric Le Goater }
3413a247521SDavid Gibson
pnv_core_reset(void * dev)342fa06541bSCédric Le Goater static void pnv_core_reset(void *dev)
343fa06541bSCédric Le Goater {
344fa06541bSCédric Le Goater CPUCore *cc = CPU_CORE(dev);
345fa06541bSCédric Le Goater PnvCore *pc = PNV_CORE(dev);
346fa06541bSCédric Le Goater int i;
347fa06541bSCédric Le Goater
348fa06541bSCédric Le Goater for (i = 0; i < cc->nr_threads; i++) {
34959942f0eSCédric Le Goater pnv_core_cpu_reset(pc, pc->threads[i]);
350fa06541bSCédric Le Goater }
351d2fd9612SCédric Le Goater }
352d2fd9612SCédric Le Goater
pnv_core_realize(DeviceState * dev,Error ** errp)353d2fd9612SCédric Le Goater static void pnv_core_realize(DeviceState *dev, Error **errp)
354d2fd9612SCédric Le Goater {
355d2fd9612SCédric Le Goater PnvCore *pc = PNV_CORE(OBJECT(dev));
35690ef386cSCédric Le Goater PnvCoreClass *pcc = PNV_CORE_GET_CLASS(pc);
357d2fd9612SCédric Le Goater CPUCore *cc = CPU_CORE(OBJECT(dev));
35835bdb9deSIgor Mammedov const char *typename = pnv_core_cpu_typename(pc);
359d2fd9612SCédric Le Goater Error *local_err = NULL;
360d2fd9612SCédric Le Goater void *obj;
361d2fd9612SCédric Le Goater int i, j;
362d2fd9612SCédric Le Goater char name[32];
363960fbd29SCédric Le Goater
364158e17a6SGreg Kurz assert(pc->chip);
365d2fd9612SCédric Le Goater
36608304a86SDavid Gibson pc->threads = g_new(PowerPCCPU *, cc->nr_threads);
367d2fd9612SCédric Le Goater for (i = 0; i < cc->nr_threads; i++) {
3688907fc25SCédric Le Goater PowerPCCPU *cpu;
369060e6143SNicholas Piggin PnvCPUState *pnv_cpu;
3708907fc25SCédric Le Goater
37108304a86SDavid Gibson obj = object_new(typename);
3728907fc25SCédric Le Goater cpu = POWERPC_CPU(obj);
373d2fd9612SCédric Le Goater
37408304a86SDavid Gibson pc->threads[i] = POWERPC_CPU(obj);
37559c921f2SNicholas Piggin if (cc->nr_threads > 1) {
37659c921f2SNicholas Piggin cpu->env.has_smt_siblings = true;
37759c921f2SNicholas Piggin }
378d2fd9612SCédric Le Goater
379d2fd9612SCédric Le Goater snprintf(name, sizeof(name), "thread[%d]", i);
380d2623129SMarkus Armbruster object_property_add_child(OBJECT(pc), name, obj);
3818907fc25SCédric Le Goater
3828907fc25SCédric Le Goater cpu->machine_data = g_new0(PnvCPUState, 1);
383060e6143SNicholas Piggin pnv_cpu = pnv_cpu_state(cpu);
384060e6143SNicholas Piggin pnv_cpu->pnv_core = pc;
3858907fc25SCédric Le Goater
386d2fd9612SCédric Le Goater object_unref(obj);
387d2fd9612SCédric Le Goater }
388d2fd9612SCédric Le Goater
389d2fd9612SCédric Le Goater for (j = 0; j < cc->nr_threads; j++) {
390934676c7SNicholas Piggin pnv_core_cpu_realize(pc, pc->threads[j], &local_err, j);
391d2fd9612SCédric Le Goater if (local_err) {
392d2fd9612SCédric Le Goater goto err;
393d2fd9612SCédric Le Goater }
394d2fd9612SCédric Le Goater }
39524ece072SCédric Le Goater
39624ece072SCédric Le Goater snprintf(name, sizeof(name), "xscom-core.%d", cc->core_id);
39790ef386cSCédric Le Goater pnv_xscom_region_init(&pc->xscom_regs, OBJECT(dev), pcc->xscom_ops,
398aa2addf9SNicholas Piggin pc, name, pcc->xscom_size);
399fa06541bSCédric Le Goater
400fa06541bSCédric Le Goater qemu_register_reset(pnv_core_reset, pc);
401d2fd9612SCédric Le Goater return;
402d2fd9612SCédric Le Goater
403d2fd9612SCédric Le Goater err:
404d2fd9612SCédric Le Goater while (--i >= 0) {
40508304a86SDavid Gibson obj = OBJECT(pc->threads[i]);
406d2fd9612SCédric Le Goater object_unparent(obj);
407d2fd9612SCédric Le Goater }
408d2fd9612SCédric Le Goater g_free(pc->threads);
409d2fd9612SCédric Le Goater error_propagate(errp, local_err);
410d2fd9612SCédric Le Goater }
411d2fd9612SCédric Le Goater
pnv_core_cpu_unrealize(PnvCore * pc,PowerPCCPU * cpu)41259942f0eSCédric Le Goater static void pnv_core_cpu_unrealize(PnvCore *pc, PowerPCCPU *cpu)
4135e22e292SDavid Gibson {
4148907fc25SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
41559942f0eSCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(pc->chip);
4168907fc25SCédric Le Goater
41759942f0eSCédric Le Goater pcc->intc_destroy(pc->chip, cpu);
4185e22e292SDavid Gibson cpu_remove_sync(CPU(cpu));
4198907fc25SCédric Le Goater cpu->machine_data = NULL;
4208907fc25SCédric Le Goater g_free(pnv_cpu);
4215e22e292SDavid Gibson object_unparent(OBJECT(cpu));
4225e22e292SDavid Gibson }
4235e22e292SDavid Gibson
pnv_core_unrealize(DeviceState * dev)424b69c3c21SMarkus Armbruster static void pnv_core_unrealize(DeviceState *dev)
4255e22e292SDavid Gibson {
4265e22e292SDavid Gibson PnvCore *pc = PNV_CORE(dev);
4275e22e292SDavid Gibson CPUCore *cc = CPU_CORE(dev);
4285e22e292SDavid Gibson int i;
4295e22e292SDavid Gibson
430fa06541bSCédric Le Goater qemu_unregister_reset(pnv_core_reset, pc);
431fa06541bSCédric Le Goater
4325e22e292SDavid Gibson for (i = 0; i < cc->nr_threads; i++) {
43359942f0eSCédric Le Goater pnv_core_cpu_unrealize(pc, pc->threads[i]);
4345e22e292SDavid Gibson }
4355e22e292SDavid Gibson g_free(pc->threads);
4365e22e292SDavid Gibson }
4375e22e292SDavid Gibson
438d2fd9612SCédric Le Goater static Property pnv_core_properties[] = {
4399940412aSCaleb Schlossin DEFINE_PROP_UINT32("hwid", PnvCore, hwid, 0),
44008c3f3a7SCédric Le Goater DEFINE_PROP_UINT64("hrmor", PnvCore, hrmor, 0),
441c26504afSNicholas Piggin DEFINE_PROP_BOOL("big-core", PnvCore, big_core, false),
44278be3218SNicholas Piggin DEFINE_PROP_BOOL("quirk-tb-big-core", PnvCore, tod_state.big_core_quirk,
44378be3218SNicholas Piggin false),
4443b5ea01eSNicholas Piggin DEFINE_PROP_BOOL("lpar-per-core", PnvCore, lpar_per_core, false),
445158e17a6SGreg Kurz DEFINE_PROP_LINK("chip", PnvCore, chip, TYPE_PNV_CHIP, PnvChip *),
446d2fd9612SCédric Le Goater DEFINE_PROP_END_OF_LIST(),
447d2fd9612SCédric Le Goater };
448d2fd9612SCédric Le Goater
pnv_core_power8_class_init(ObjectClass * oc,void * data)44990ef386cSCédric Le Goater static void pnv_core_power8_class_init(ObjectClass *oc, void *data)
45090ef386cSCédric Le Goater {
45190ef386cSCédric Le Goater PnvCoreClass *pcc = PNV_CORE_CLASS(oc);
45290ef386cSCédric Le Goater
45390ef386cSCédric Le Goater pcc->xscom_ops = &pnv_core_power8_xscom_ops;
454aa2addf9SNicholas Piggin pcc->xscom_size = PNV_XSCOM_EX_SIZE;
45590ef386cSCédric Le Goater }
45690ef386cSCédric Le Goater
pnv_core_power9_class_init(ObjectClass * oc,void * data)45790ef386cSCédric Le Goater static void pnv_core_power9_class_init(ObjectClass *oc, void *data)
45890ef386cSCédric Le Goater {
45990ef386cSCédric Le Goater PnvCoreClass *pcc = PNV_CORE_CLASS(oc);
46090ef386cSCédric Le Goater
46190ef386cSCédric Le Goater pcc->xscom_ops = &pnv_core_power9_xscom_ops;
462aa2addf9SNicholas Piggin pcc->xscom_size = PNV_XSCOM_EX_SIZE;
46390ef386cSCédric Le Goater }
46490ef386cSCédric Le Goater
pnv_core_power10_class_init(ObjectClass * oc,void * data)4652b548a42SCédric Le Goater static void pnv_core_power10_class_init(ObjectClass *oc, void *data)
4662b548a42SCédric Le Goater {
4672b548a42SCédric Le Goater PnvCoreClass *pcc = PNV_CORE_CLASS(oc);
4682b548a42SCédric Le Goater
4699a394217SJoel Stanley pcc->xscom_ops = &pnv_core_power10_xscom_ops;
470aa2addf9SNicholas Piggin pcc->xscom_size = PNV10_XSCOM_EC_SIZE;
4712b548a42SCédric Le Goater }
4722b548a42SCédric Le Goater
pnv_core_class_init(ObjectClass * oc,void * data)473d2fd9612SCédric Le Goater static void pnv_core_class_init(ObjectClass *oc, void *data)
474d2fd9612SCédric Le Goater {
475d2fd9612SCédric Le Goater DeviceClass *dc = DEVICE_CLASS(oc);
476d2fd9612SCédric Le Goater
477d2fd9612SCédric Le Goater dc->realize = pnv_core_realize;
4785e22e292SDavid Gibson dc->unrealize = pnv_core_unrealize;
4794f67d30bSMarc-André Lureau device_class_set_props(dc, pnv_core_properties);
48023a782ebSCédric Le Goater dc->user_creatable = false;
481d2fd9612SCédric Le Goater }
482d2fd9612SCédric Le Goater
48390ef386cSCédric Le Goater #define DEFINE_PNV_CORE_TYPE(family, cpu_model) \
4847383af1eSIgor Mammedov { \
4857383af1eSIgor Mammedov .parent = TYPE_PNV_CORE, \
4867383af1eSIgor Mammedov .name = PNV_CORE_TYPE_NAME(cpu_model), \
48790ef386cSCédric Le Goater .class_init = pnv_core_##family##_class_init, \
4887383af1eSIgor Mammedov }
4897383af1eSIgor Mammedov
4907383af1eSIgor Mammedov static const TypeInfo pnv_core_infos[] = {
4917383af1eSIgor Mammedov {
492d2fd9612SCédric Le Goater .name = TYPE_PNV_CORE,
493d2fd9612SCédric Le Goater .parent = TYPE_CPU_CORE,
494d2fd9612SCédric Le Goater .instance_size = sizeof(PnvCore),
495d2fd9612SCédric Le Goater .class_size = sizeof(PnvCoreClass),
49635bdb9deSIgor Mammedov .class_init = pnv_core_class_init,
497d2fd9612SCédric Le Goater .abstract = true,
4987383af1eSIgor Mammedov },
49990ef386cSCédric Le Goater DEFINE_PNV_CORE_TYPE(power8, "power8e_v2.1"),
50090ef386cSCédric Le Goater DEFINE_PNV_CORE_TYPE(power8, "power8_v2.0"),
50190ef386cSCédric Le Goater DEFINE_PNV_CORE_TYPE(power8, "power8nvl_v1.0"),
502277ee172SNicholas Piggin DEFINE_PNV_CORE_TYPE(power9, "power9_v2.2"),
5036bc8c046SCédric Le Goater DEFINE_PNV_CORE_TYPE(power10, "power10_v2.0"),
504d2fd9612SCédric Le Goater };
505d2fd9612SCédric Le Goater
DEFINE_TYPES(pnv_core_infos)5067383af1eSIgor Mammedov DEFINE_TYPES(pnv_core_infos)
5075dad902cSCédric Le Goater
5085dad902cSCédric Le Goater /*
5095dad902cSCédric Le Goater * POWER9 Quads
5105dad902cSCédric Le Goater */
5115dad902cSCédric Le Goater
5125dad902cSCédric Le Goater #define P9X_EX_NCU_SPEC_BAR 0x11010
5135dad902cSCédric Le Goater
51419d197f5SJoel Stanley static uint64_t pnv_quad_power9_xscom_read(void *opaque, hwaddr addr,
5155dad902cSCédric Le Goater unsigned int width)
5165dad902cSCédric Le Goater {
5175dad902cSCédric Le Goater uint32_t offset = addr >> 3;
5185dad902cSCédric Le Goater uint64_t val = -1;
5195dad902cSCédric Le Goater
5205dad902cSCédric Le Goater switch (offset) {
5215dad902cSCédric Le Goater case P9X_EX_NCU_SPEC_BAR:
5225dad902cSCédric Le Goater case P9X_EX_NCU_SPEC_BAR + 0x400: /* Second EX */
5235dad902cSCédric Le Goater val = 0;
5245dad902cSCédric Le Goater break;
5255dad902cSCédric Le Goater default:
526b0afb574SJoel Stanley qemu_log_mask(LOG_UNIMP, "%s: unimp read 0x%08x\n", __func__,
5275dad902cSCédric Le Goater offset);
5285dad902cSCédric Le Goater }
5295dad902cSCédric Le Goater
5305dad902cSCédric Le Goater return val;
5315dad902cSCédric Le Goater }
5325dad902cSCédric Le Goater
pnv_quad_power9_xscom_write(void * opaque,hwaddr addr,uint64_t val,unsigned int width)53319d197f5SJoel Stanley static void pnv_quad_power9_xscom_write(void *opaque, hwaddr addr, uint64_t val,
5345dad902cSCédric Le Goater unsigned int width)
5355dad902cSCédric Le Goater {
5365dad902cSCédric Le Goater uint32_t offset = addr >> 3;
5375dad902cSCédric Le Goater
5385dad902cSCédric Le Goater switch (offset) {
5395dad902cSCédric Le Goater case P9X_EX_NCU_SPEC_BAR:
5405dad902cSCédric Le Goater case P9X_EX_NCU_SPEC_BAR + 0x400: /* Second EX */
5415dad902cSCédric Le Goater break;
5425dad902cSCédric Le Goater default:
543b0afb574SJoel Stanley qemu_log_mask(LOG_UNIMP, "%s: unimp write 0x%08x\n", __func__,
5445dad902cSCédric Le Goater offset);
5455dad902cSCédric Le Goater }
5465dad902cSCédric Le Goater }
5475dad902cSCédric Le Goater
54819d197f5SJoel Stanley static const MemoryRegionOps pnv_quad_power9_xscom_ops = {
54919d197f5SJoel Stanley .read = pnv_quad_power9_xscom_read,
55019d197f5SJoel Stanley .write = pnv_quad_power9_xscom_write,
5515dad902cSCédric Le Goater .valid.min_access_size = 8,
5525dad902cSCédric Le Goater .valid.max_access_size = 8,
5535dad902cSCédric Le Goater .impl.min_access_size = 8,
5545dad902cSCédric Le Goater .impl.max_access_size = 8,
5555dad902cSCédric Le Goater .endianness = DEVICE_BIG_ENDIAN,
5565dad902cSCédric Le Goater };
5575dad902cSCédric Le Goater
558a1d64b9eSJoel Stanley /*
559a1d64b9eSJoel Stanley * POWER10 Quads
560a1d64b9eSJoel Stanley */
561a1d64b9eSJoel Stanley
pnv_quad_power10_xscom_read(void * opaque,hwaddr addr,unsigned int width)562a1d64b9eSJoel Stanley static uint64_t pnv_quad_power10_xscom_read(void *opaque, hwaddr addr,
563a1d64b9eSJoel Stanley unsigned int width)
564a1d64b9eSJoel Stanley {
565a1d64b9eSJoel Stanley uint32_t offset = addr >> 3;
566a1d64b9eSJoel Stanley uint64_t val = -1;
567a1d64b9eSJoel Stanley
568a1d64b9eSJoel Stanley switch (offset) {
569a1d64b9eSJoel Stanley default:
570b0afb574SJoel Stanley qemu_log_mask(LOG_UNIMP, "%s: unimp read 0x%08x\n", __func__,
571a1d64b9eSJoel Stanley offset);
572a1d64b9eSJoel Stanley }
573a1d64b9eSJoel Stanley
574a1d64b9eSJoel Stanley return val;
575a1d64b9eSJoel Stanley }
576a1d64b9eSJoel Stanley
pnv_quad_power10_xscom_write(void * opaque,hwaddr addr,uint64_t val,unsigned int width)577a1d64b9eSJoel Stanley static void pnv_quad_power10_xscom_write(void *opaque, hwaddr addr,
578a1d64b9eSJoel Stanley uint64_t val, unsigned int width)
579a1d64b9eSJoel Stanley {
580a1d64b9eSJoel Stanley uint32_t offset = addr >> 3;
581a1d64b9eSJoel Stanley
582a1d64b9eSJoel Stanley switch (offset) {
583a1d64b9eSJoel Stanley default:
584b0afb574SJoel Stanley qemu_log_mask(LOG_UNIMP, "%s: unimp write 0x%08x\n", __func__,
585a1d64b9eSJoel Stanley offset);
586a1d64b9eSJoel Stanley }
587a1d64b9eSJoel Stanley }
588a1d64b9eSJoel Stanley
589a1d64b9eSJoel Stanley static const MemoryRegionOps pnv_quad_power10_xscom_ops = {
590a1d64b9eSJoel Stanley .read = pnv_quad_power10_xscom_read,
591a1d64b9eSJoel Stanley .write = pnv_quad_power10_xscom_write,
592a1d64b9eSJoel Stanley .valid.min_access_size = 8,
593a1d64b9eSJoel Stanley .valid.max_access_size = 8,
594a1d64b9eSJoel Stanley .impl.min_access_size = 8,
595a1d64b9eSJoel Stanley .impl.max_access_size = 8,
596a1d64b9eSJoel Stanley .endianness = DEVICE_BIG_ENDIAN,
597a1d64b9eSJoel Stanley };
598a1d64b9eSJoel Stanley
599bdb97596SJoel Stanley #define P10_QME_SPWU_HYP 0x83c
600bdb97596SJoel Stanley #define P10_QME_SSH_HYP 0x82c
601bdb97596SJoel Stanley
pnv_qme_power10_xscom_read(void * opaque,hwaddr addr,unsigned int width)602bdb97596SJoel Stanley static uint64_t pnv_qme_power10_xscom_read(void *opaque, hwaddr addr,
603bdb97596SJoel Stanley unsigned int width)
604bdb97596SJoel Stanley {
605c8891955SNicholas Piggin PnvQuad *eq = PNV_QUAD(opaque);
606bdb97596SJoel Stanley uint32_t offset = addr >> 3;
607bdb97596SJoel Stanley uint64_t val = -1;
608bdb97596SJoel Stanley
609bdb97596SJoel Stanley /*
610bdb97596SJoel Stanley * Forth nibble selects the core within a quad, mask it to process read
611bdb97596SJoel Stanley * for any core.
612bdb97596SJoel Stanley */
613c8891955SNicholas Piggin switch (offset & ~PPC_BITMASK32(16, 19)) {
614bdb97596SJoel Stanley case P10_QME_SSH_HYP:
615c8891955SNicholas Piggin val = 0;
616c8891955SNicholas Piggin if (eq->special_wakeup_done) {
617c8891955SNicholas Piggin val |= PPC_BIT(1); /* SPWU DONE */
618c8891955SNicholas Piggin val |= PPC_BIT(4); /* SSH SPWU DONE */
619c8891955SNicholas Piggin }
620c8891955SNicholas Piggin break;
621bdb97596SJoel Stanley default:
622bdb97596SJoel Stanley qemu_log_mask(LOG_UNIMP, "%s: unimp read 0x%08x\n", __func__,
623bdb97596SJoel Stanley offset);
624bdb97596SJoel Stanley }
625bdb97596SJoel Stanley
626bdb97596SJoel Stanley return val;
627bdb97596SJoel Stanley }
628bdb97596SJoel Stanley
pnv_qme_power10_xscom_write(void * opaque,hwaddr addr,uint64_t val,unsigned int width)629bdb97596SJoel Stanley static void pnv_qme_power10_xscom_write(void *opaque, hwaddr addr,
630bdb97596SJoel Stanley uint64_t val, unsigned int width)
631bdb97596SJoel Stanley {
632c8891955SNicholas Piggin PnvQuad *eq = PNV_QUAD(opaque);
633bdb97596SJoel Stanley uint32_t offset = addr >> 3;
634c8891955SNicholas Piggin bool set;
635c8891955SNicholas Piggin int i;
636bdb97596SJoel Stanley
637c8891955SNicholas Piggin switch (offset & ~PPC_BITMASK32(16, 19)) {
638c8891955SNicholas Piggin case P10_QME_SPWU_HYP:
639c8891955SNicholas Piggin set = !!(val & PPC_BIT(0));
640c8891955SNicholas Piggin eq->special_wakeup_done = set;
641c8891955SNicholas Piggin for (i = 0; i < 4; i++) {
642c8891955SNicholas Piggin /* These bits select cores in the quad */
643c8891955SNicholas Piggin if (offset & PPC_BIT32(16 + i)) {
644c8891955SNicholas Piggin eq->special_wakeup[i] = set;
645c8891955SNicholas Piggin }
646c8891955SNicholas Piggin }
647c8891955SNicholas Piggin break;
648bdb97596SJoel Stanley default:
649bdb97596SJoel Stanley qemu_log_mask(LOG_UNIMP, "%s: unimp write 0x%08x\n", __func__,
650bdb97596SJoel Stanley offset);
651bdb97596SJoel Stanley }
652bdb97596SJoel Stanley }
653bdb97596SJoel Stanley
654bdb97596SJoel Stanley static const MemoryRegionOps pnv_qme_power10_xscom_ops = {
655bdb97596SJoel Stanley .read = pnv_qme_power10_xscom_read,
656bdb97596SJoel Stanley .write = pnv_qme_power10_xscom_write,
657bdb97596SJoel Stanley .valid.min_access_size = 8,
658bdb97596SJoel Stanley .valid.max_access_size = 8,
659bdb97596SJoel Stanley .impl.min_access_size = 8,
660bdb97596SJoel Stanley .impl.max_access_size = 8,
661bdb97596SJoel Stanley .endianness = DEVICE_BIG_ENDIAN,
662bdb97596SJoel Stanley };
663bdb97596SJoel Stanley
pnv_quad_power9_realize(DeviceState * dev,Error ** errp)664bdb97596SJoel Stanley static void pnv_quad_power9_realize(DeviceState *dev, Error **errp)
6655dad902cSCédric Le Goater {
6665dad902cSCédric Le Goater PnvQuad *eq = PNV_QUAD(dev);
667fdc2b46aSJoel Stanley PnvQuadClass *pqc = PNV_QUAD_GET_CLASS(eq);
6685dad902cSCédric Le Goater char name[32];
6695dad902cSCédric Le Goater
67092612f15SCédric Le Goater snprintf(name, sizeof(name), "xscom-quad.%d", eq->quad_id);
67119d197f5SJoel Stanley pnv_xscom_region_init(&eq->xscom_regs, OBJECT(dev),
672fdc2b46aSJoel Stanley pqc->xscom_ops,
673fdc2b46aSJoel Stanley eq, name,
674fdc2b46aSJoel Stanley pqc->xscom_size);
6755dad902cSCédric Le Goater }
6765dad902cSCédric Le Goater
pnv_quad_power10_realize(DeviceState * dev,Error ** errp)677bdb97596SJoel Stanley static void pnv_quad_power10_realize(DeviceState *dev, Error **errp)
678bdb97596SJoel Stanley {
679bdb97596SJoel Stanley PnvQuad *eq = PNV_QUAD(dev);
680bdb97596SJoel Stanley PnvQuadClass *pqc = PNV_QUAD_GET_CLASS(eq);
681bdb97596SJoel Stanley char name[32];
682bdb97596SJoel Stanley
683bdb97596SJoel Stanley snprintf(name, sizeof(name), "xscom-quad.%d", eq->quad_id);
684bdb97596SJoel Stanley pnv_xscom_region_init(&eq->xscom_regs, OBJECT(dev),
685bdb97596SJoel Stanley pqc->xscom_ops,
686bdb97596SJoel Stanley eq, name,
687bdb97596SJoel Stanley pqc->xscom_size);
688bdb97596SJoel Stanley
689bdb97596SJoel Stanley snprintf(name, sizeof(name), "xscom-qme.%d", eq->quad_id);
690bdb97596SJoel Stanley pnv_xscom_region_init(&eq->xscom_qme_regs, OBJECT(dev),
691bdb97596SJoel Stanley pqc->xscom_qme_ops,
692bdb97596SJoel Stanley eq, name,
693bdb97596SJoel Stanley pqc->xscom_qme_size);
694bdb97596SJoel Stanley }
695bdb97596SJoel Stanley
6965dad902cSCédric Le Goater static Property pnv_quad_properties[] = {
69792612f15SCédric Le Goater DEFINE_PROP_UINT32("quad-id", PnvQuad, quad_id, 0),
6985dad902cSCédric Le Goater DEFINE_PROP_END_OF_LIST(),
6995dad902cSCédric Le Goater };
7005dad902cSCédric Le Goater
pnv_quad_power9_class_init(ObjectClass * oc,void * data)701fdc2b46aSJoel Stanley static void pnv_quad_power9_class_init(ObjectClass *oc, void *data)
702fdc2b46aSJoel Stanley {
703fdc2b46aSJoel Stanley PnvQuadClass *pqc = PNV_QUAD_CLASS(oc);
704bdb97596SJoel Stanley DeviceClass *dc = DEVICE_CLASS(oc);
705bdb97596SJoel Stanley
706bdb97596SJoel Stanley dc->realize = pnv_quad_power9_realize;
707fdc2b46aSJoel Stanley
708fdc2b46aSJoel Stanley pqc->xscom_ops = &pnv_quad_power9_xscom_ops;
709fdc2b46aSJoel Stanley pqc->xscom_size = PNV9_XSCOM_EQ_SIZE;
710fdc2b46aSJoel Stanley }
711fdc2b46aSJoel Stanley
pnv_quad_power10_class_init(ObjectClass * oc,void * data)712a1d64b9eSJoel Stanley static void pnv_quad_power10_class_init(ObjectClass *oc, void *data)
713a1d64b9eSJoel Stanley {
714a1d64b9eSJoel Stanley PnvQuadClass *pqc = PNV_QUAD_CLASS(oc);
715bdb97596SJoel Stanley DeviceClass *dc = DEVICE_CLASS(oc);
716bdb97596SJoel Stanley
717bdb97596SJoel Stanley dc->realize = pnv_quad_power10_realize;
718a1d64b9eSJoel Stanley
719a1d64b9eSJoel Stanley pqc->xscom_ops = &pnv_quad_power10_xscom_ops;
720a1d64b9eSJoel Stanley pqc->xscom_size = PNV10_XSCOM_EQ_SIZE;
721bdb97596SJoel Stanley
722bdb97596SJoel Stanley pqc->xscom_qme_ops = &pnv_qme_power10_xscom_ops;
723bdb97596SJoel Stanley pqc->xscom_qme_size = PNV10_XSCOM_QME_SIZE;
724a1d64b9eSJoel Stanley }
725a1d64b9eSJoel Stanley
pnv_quad_class_init(ObjectClass * oc,void * data)7265dad902cSCédric Le Goater static void pnv_quad_class_init(ObjectClass *oc, void *data)
7275dad902cSCédric Le Goater {
7285dad902cSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(oc);
7295dad902cSCédric Le Goater
7304f67d30bSMarc-André Lureau device_class_set_props(dc, pnv_quad_properties);
73123a782ebSCédric Le Goater dc->user_creatable = false;
7325dad902cSCédric Le Goater }
7335dad902cSCédric Le Goater
734fdc2b46aSJoel Stanley static const TypeInfo pnv_quad_infos[] = {
735fdc2b46aSJoel Stanley {
7365dad902cSCédric Le Goater .name = TYPE_PNV_QUAD,
7375dad902cSCédric Le Goater .parent = TYPE_DEVICE,
7385dad902cSCédric Le Goater .instance_size = sizeof(PnvQuad),
739fdc2b46aSJoel Stanley .class_size = sizeof(PnvQuadClass),
7405dad902cSCédric Le Goater .class_init = pnv_quad_class_init,
741fdc2b46aSJoel Stanley .abstract = true,
742fdc2b46aSJoel Stanley },
743fdc2b46aSJoel Stanley {
744fdc2b46aSJoel Stanley .parent = TYPE_PNV_QUAD,
745fdc2b46aSJoel Stanley .name = PNV_QUAD_TYPE_NAME("power9"),
746fdc2b46aSJoel Stanley .class_init = pnv_quad_power9_class_init,
747fdc2b46aSJoel Stanley },
748a1d64b9eSJoel Stanley {
749a1d64b9eSJoel Stanley .parent = TYPE_PNV_QUAD,
750a1d64b9eSJoel Stanley .name = PNV_QUAD_TYPE_NAME("power10"),
751a1d64b9eSJoel Stanley .class_init = pnv_quad_power10_class_init,
752a1d64b9eSJoel Stanley },
7535dad902cSCédric Le Goater };
7545dad902cSCédric Le Goater
755fdc2b46aSJoel Stanley DEFINE_TYPES(pnv_quad_infos);
756