xref: /openbmc/qemu/hw/ppc/pnv_core.c (revision 10bfa161fbcf40d74db4103a0f2402779e98d0f7)
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