Merge tag 'pull-loongarch-20241016' of https://gitlab.com/gaosong/qemu into staging
[qemu/armbru.git] / hw / ppc / pnv_core.c
bloba30693990b25643784102d6c65805bc12b536f3b
1 /*
2 * QEMU PowerPC PowerNV CPU Core model
4 * Copyright (c) 2016, IBM Corporation.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public License
8 * as published by the Free Software Foundation; either version 2.1 of
9 * the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
20 #include "qemu/osdep.h"
21 #include "sysemu/reset.h"
22 #include "qapi/error.h"
23 #include "qemu/log.h"
24 #include "qemu/module.h"
25 #include "target/ppc/cpu.h"
26 #include "hw/ppc/ppc.h"
27 #include "hw/ppc/pnv.h"
28 #include "hw/ppc/pnv_chip.h"
29 #include "hw/ppc/pnv_core.h"
30 #include "hw/ppc/pnv_xscom.h"
31 #include "hw/ppc/xics.h"
32 #include "hw/qdev-properties.h"
33 #include "helper_regs.h"
35 static const char *pnv_core_cpu_typename(PnvCore *pc)
37 const char *core_type = object_class_get_name(object_get_class(OBJECT(pc)));
38 int len = strlen(core_type) - strlen(PNV_CORE_TYPE_SUFFIX);
39 char *s = g_strdup_printf(POWERPC_CPU_TYPE_NAME("%.*s"), len, core_type);
40 const char *cpu_type = object_class_get_name(object_class_by_name(s));
41 g_free(s);
42 return cpu_type;
45 static void pnv_core_cpu_reset(PnvCore *pc, PowerPCCPU *cpu)
47 CPUState *cs = CPU(cpu);
48 CPUPPCState *env = &cpu->env;
49 PnvChipClass *pcc = PNV_CHIP_GET_CLASS(pc->chip);
51 cpu_reset(cs);
54 * the skiboot firmware elects a primary thread to initialize the
55 * system and it can be any.
57 env->gpr[3] = PNV_FDT_ADDR;
58 env->nip = 0x10;
59 env->msr |= MSR_HVB; /* Hypervisor mode */
60 env->spr[SPR_HRMOR] = pc->hrmor;
61 if (pc->big_core) {
62 /* Clear "small core" bit on Power9/10 (this is set in default PVR) */
63 env->spr[SPR_PVR] &= ~PPC_BIT(51);
65 hreg_compute_hflags(env);
66 ppc_maybe_interrupt(env);
68 cpu_ppc_tb_reset(env);
70 pcc->intc_reset(pc->chip, cpu);
74 * These values are read by the PowerNV HW monitors under Linux
76 #define PNV_XSCOM_EX_DTS_RESULT0 0x50000
77 #define PNV_XSCOM_EX_DTS_RESULT1 0x50001
79 static uint64_t pnv_core_power8_xscom_read(void *opaque, hwaddr addr,
80 unsigned int width)
82 uint32_t offset = addr >> 3;
83 uint64_t val = 0;
85 /* The result should be 38 C */
86 switch (offset) {
87 case PNV_XSCOM_EX_DTS_RESULT0:
88 val = 0x26f024f023f0000ull;
89 break;
90 case PNV_XSCOM_EX_DTS_RESULT1:
91 val = 0x24f000000000000ull;
92 break;
93 default:
94 qemu_log_mask(LOG_UNIMP, "%s: unimp read 0x%08x\n", __func__,
95 offset);
98 return val;
101 static void pnv_core_power8_xscom_write(void *opaque, hwaddr addr, uint64_t val,
102 unsigned int width)
104 uint32_t offset = addr >> 3;
106 qemu_log_mask(LOG_UNIMP, "%s: unimp write 0x%08x\n", __func__,
107 offset);
110 static const MemoryRegionOps pnv_core_power8_xscom_ops = {
111 .read = pnv_core_power8_xscom_read,
112 .write = pnv_core_power8_xscom_write,
113 .valid.min_access_size = 8,
114 .valid.max_access_size = 8,
115 .impl.min_access_size = 8,
116 .impl.max_access_size = 8,
117 .endianness = DEVICE_BIG_ENDIAN,
122 * POWER9 core controls
124 #define PNV9_XSCOM_EC_PPM_SPECIAL_WKUP_HYP 0xf010d
125 #define PNV9_XSCOM_EC_PPM_SPECIAL_WKUP_OTR 0xf010a
127 #define PNV9_XSCOM_EC_CORE_THREAD_STATE 0x10ab3
129 static uint64_t pnv_core_power9_xscom_read(void *opaque, hwaddr addr,
130 unsigned int width)
132 uint32_t offset = addr >> 3;
133 uint64_t val = 0;
135 /* The result should be 38 C */
136 switch (offset) {
137 case PNV_XSCOM_EX_DTS_RESULT0:
138 val = 0x26f024f023f0000ull;
139 break;
140 case PNV_XSCOM_EX_DTS_RESULT1:
141 val = 0x24f000000000000ull;
142 break;
143 case PNV9_XSCOM_EC_PPM_SPECIAL_WKUP_HYP:
144 case PNV9_XSCOM_EC_PPM_SPECIAL_WKUP_OTR:
145 val = 0x0;
146 break;
147 case PNV9_XSCOM_EC_CORE_THREAD_STATE:
148 val = 0;
149 break;
150 default:
151 qemu_log_mask(LOG_UNIMP, "%s: unimp read 0x%08x\n", __func__,
152 offset);
155 return val;
158 static void pnv_core_power9_xscom_write(void *opaque, hwaddr addr, uint64_t val,
159 unsigned int width)
161 uint32_t offset = addr >> 3;
163 switch (offset) {
164 case PNV9_XSCOM_EC_PPM_SPECIAL_WKUP_HYP:
165 case PNV9_XSCOM_EC_PPM_SPECIAL_WKUP_OTR:
166 break;
167 default:
168 qemu_log_mask(LOG_UNIMP, "%s: unimp write 0x%08x\n", __func__,
169 offset);
173 static const MemoryRegionOps pnv_core_power9_xscom_ops = {
174 .read = pnv_core_power9_xscom_read,
175 .write = pnv_core_power9_xscom_write,
176 .valid.min_access_size = 8,
177 .valid.max_access_size = 8,
178 .impl.min_access_size = 8,
179 .impl.max_access_size = 8,
180 .endianness = DEVICE_BIG_ENDIAN,
184 * POWER10 core controls
187 #define PNV10_XSCOM_EC_CORE_THREAD_STATE 0x412
188 #define PNV10_XSCOM_EC_CORE_THREAD_INFO 0x413
189 #define PNV10_XSCOM_EC_CORE_DIRECT_CONTROLS 0x449
190 #define PNV10_XSCOM_EC_CORE_RAS_STATUS 0x454
192 static uint64_t pnv_core_power10_xscom_read(void *opaque, hwaddr addr,
193 unsigned int width)
195 PnvCore *pc = PNV_CORE(opaque);
196 int nr_threads = CPU_CORE(pc)->nr_threads;
197 int i;
198 uint32_t offset = addr >> 3;
199 uint64_t val = 0;
201 switch (offset) {
202 case PNV10_XSCOM_EC_CORE_THREAD_STATE:
203 for (i = 0; i < nr_threads; i++) {
204 PowerPCCPU *cpu = pc->threads[i];
205 CPUState *cs = CPU(cpu);
207 if (cs->halted) {
208 val |= PPC_BIT(56 + i);
211 if (pc->lpar_per_core) {
212 val |= PPC_BIT(62);
214 break;
215 case PNV10_XSCOM_EC_CORE_THREAD_INFO:
216 break;
217 case PNV10_XSCOM_EC_CORE_RAS_STATUS:
218 for (i = 0; i < nr_threads; i++) {
219 PowerPCCPU *cpu = pc->threads[i];
220 CPUState *cs = CPU(cpu);
221 if (cs->stopped) {
222 val |= PPC_BIT(0 + 8 * i) | PPC_BIT(1 + 8 * i);
225 break;
226 default:
227 qemu_log_mask(LOG_UNIMP, "%s: unimp read 0x%08x\n", __func__,
228 offset);
231 return val;
234 static void pnv_core_power10_xscom_write(void *opaque, hwaddr addr,
235 uint64_t val, unsigned int width)
237 PnvCore *pc = PNV_CORE(opaque);
238 int nr_threads = CPU_CORE(pc)->nr_threads;
239 int i;
240 uint32_t offset = addr >> 3;
242 switch (offset) {
243 case PNV10_XSCOM_EC_CORE_DIRECT_CONTROLS:
244 for (i = 0; i < nr_threads; i++) {
245 PowerPCCPU *cpu = pc->threads[i];
246 CPUState *cs = CPU(cpu);
248 if (val & PPC_BIT(7 + 8 * i)) { /* stop */
249 val &= ~PPC_BIT(7 + 8 * i);
250 cpu_pause(cs);
252 if (val & PPC_BIT(6 + 8 * i)) { /* start */
253 val &= ~PPC_BIT(6 + 8 * i);
254 cpu_resume(cs);
256 if (val & PPC_BIT(4 + 8 * i)) { /* sreset */
257 val &= ~PPC_BIT(4 + 8 * i);
258 pnv_cpu_do_nmi_resume(cs);
260 if (val & PPC_BIT(3 + 8 * i)) { /* clear maint */
262 * Hardware has very particular cases for where clear maint
263 * must be used and where start must be used to resume a
264 * thread. These are not modelled exactly, just treat
265 * this and start the same.
267 val &= ~PPC_BIT(3 + 8 * i);
268 cpu_resume(cs);
271 if (val) {
272 qemu_log_mask(LOG_UNIMP, "%s: unimp bits in DIRECT_CONTROLS "
273 "0x%016" PRIx64 "\n", __func__, val);
275 break;
277 default:
278 qemu_log_mask(LOG_UNIMP, "%s: unimp write 0x%08x\n", __func__,
279 offset);
283 static const MemoryRegionOps pnv_core_power10_xscom_ops = {
284 .read = pnv_core_power10_xscom_read,
285 .write = pnv_core_power10_xscom_write,
286 .valid.min_access_size = 8,
287 .valid.max_access_size = 8,
288 .impl.min_access_size = 8,
289 .impl.max_access_size = 8,
290 .endianness = DEVICE_BIG_ENDIAN,
293 static void pnv_core_cpu_realize(PnvCore *pc, PowerPCCPU *cpu, Error **errp,
294 int thread_index)
296 CPUPPCState *env = &cpu->env;
297 int core_hwid;
298 ppc_spr_t *pir_spr = &env->spr_cb[SPR_PIR];
299 ppc_spr_t *tir_spr = &env->spr_cb[SPR_TIR];
300 uint32_t pir, tir;
301 Error *local_err = NULL;
302 PnvChipClass *pcc = PNV_CHIP_GET_CLASS(pc->chip);
304 if (!qdev_realize(DEVICE(cpu), NULL, errp)) {
305 return;
308 pcc->intc_create(pc->chip, cpu, &local_err);
309 if (local_err) {
310 error_propagate(errp, local_err);
311 return;
314 core_hwid = object_property_get_uint(OBJECT(pc), "hwid", &error_abort);
316 pcc->get_pir_tir(pc->chip, core_hwid, thread_index, &pir, &tir);
317 pir_spr->default_value = pir;
318 tir_spr->default_value = tir;
320 if (pc->big_core) {
321 /* 2 "small cores" get the same core index for SMT operations */
322 env->core_index = core_hwid >> 1;
323 } else {
324 env->core_index = core_hwid;
327 if (pc->lpar_per_core) {
328 cpu_ppc_set_1lpar(cpu);
331 /* Set time-base frequency to 512 MHz */
332 cpu_ppc_tb_init(env, PNV_TIMEBASE_FREQ);
335 static void pnv_core_reset(void *dev)
337 CPUCore *cc = CPU_CORE(dev);
338 PnvCore *pc = PNV_CORE(dev);
339 int i;
341 for (i = 0; i < cc->nr_threads; i++) {
342 pnv_core_cpu_reset(pc, pc->threads[i]);
346 static void pnv_core_realize(DeviceState *dev, Error **errp)
348 PnvCore *pc = PNV_CORE(OBJECT(dev));
349 PnvCoreClass *pcc = PNV_CORE_GET_CLASS(pc);
350 CPUCore *cc = CPU_CORE(OBJECT(dev));
351 const char *typename = pnv_core_cpu_typename(pc);
352 Error *local_err = NULL;
353 void *obj;
354 int i, j;
355 char name[32];
357 assert(pc->chip);
359 pc->threads = g_new(PowerPCCPU *, cc->nr_threads);
360 for (i = 0; i < cc->nr_threads; i++) {
361 PowerPCCPU *cpu;
362 PnvCPUState *pnv_cpu;
364 obj = object_new(typename);
365 cpu = POWERPC_CPU(obj);
367 pc->threads[i] = POWERPC_CPU(obj);
368 if (cc->nr_threads > 1) {
369 cpu->env.has_smt_siblings = true;
372 snprintf(name, sizeof(name), "thread[%d]", i);
373 object_property_add_child(OBJECT(pc), name, obj);
375 cpu->machine_data = g_new0(PnvCPUState, 1);
376 pnv_cpu = pnv_cpu_state(cpu);
377 pnv_cpu->pnv_core = pc;
379 object_unref(obj);
382 for (j = 0; j < cc->nr_threads; j++) {
383 pnv_core_cpu_realize(pc, pc->threads[j], &local_err, j);
384 if (local_err) {
385 goto err;
389 snprintf(name, sizeof(name), "xscom-core.%d", cc->core_id);
390 pnv_xscom_region_init(&pc->xscom_regs, OBJECT(dev), pcc->xscom_ops,
391 pc, name, pcc->xscom_size);
393 qemu_register_reset(pnv_core_reset, pc);
394 return;
396 err:
397 while (--i >= 0) {
398 obj = OBJECT(pc->threads[i]);
399 object_unparent(obj);
401 g_free(pc->threads);
402 error_propagate(errp, local_err);
405 static void pnv_core_cpu_unrealize(PnvCore *pc, PowerPCCPU *cpu)
407 PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
408 PnvChipClass *pcc = PNV_CHIP_GET_CLASS(pc->chip);
410 pcc->intc_destroy(pc->chip, cpu);
411 cpu_remove_sync(CPU(cpu));
412 cpu->machine_data = NULL;
413 g_free(pnv_cpu);
414 object_unparent(OBJECT(cpu));
417 static void pnv_core_unrealize(DeviceState *dev)
419 PnvCore *pc = PNV_CORE(dev);
420 CPUCore *cc = CPU_CORE(dev);
421 int i;
423 qemu_unregister_reset(pnv_core_reset, pc);
425 for (i = 0; i < cc->nr_threads; i++) {
426 pnv_core_cpu_unrealize(pc, pc->threads[i]);
428 g_free(pc->threads);
431 static Property pnv_core_properties[] = {
432 DEFINE_PROP_UINT32("hwid", PnvCore, hwid, 0),
433 DEFINE_PROP_UINT64("hrmor", PnvCore, hrmor, 0),
434 DEFINE_PROP_BOOL("big-core", PnvCore, big_core, false),
435 DEFINE_PROP_BOOL("quirk-tb-big-core", PnvCore, tod_state.big_core_quirk,
436 false),
437 DEFINE_PROP_BOOL("lpar-per-core", PnvCore, lpar_per_core, false),
438 DEFINE_PROP_LINK("chip", PnvCore, chip, TYPE_PNV_CHIP, PnvChip *),
439 DEFINE_PROP_END_OF_LIST(),
442 static void pnv_core_power8_class_init(ObjectClass *oc, void *data)
444 PnvCoreClass *pcc = PNV_CORE_CLASS(oc);
446 pcc->xscom_ops = &pnv_core_power8_xscom_ops;
447 pcc->xscom_size = PNV_XSCOM_EX_SIZE;
450 static void pnv_core_power9_class_init(ObjectClass *oc, void *data)
452 PnvCoreClass *pcc = PNV_CORE_CLASS(oc);
454 pcc->xscom_ops = &pnv_core_power9_xscom_ops;
455 pcc->xscom_size = PNV_XSCOM_EX_SIZE;
458 static void pnv_core_power10_class_init(ObjectClass *oc, void *data)
460 PnvCoreClass *pcc = PNV_CORE_CLASS(oc);
462 pcc->xscom_ops = &pnv_core_power10_xscom_ops;
463 pcc->xscom_size = PNV10_XSCOM_EC_SIZE;
466 static void pnv_core_class_init(ObjectClass *oc, void *data)
468 DeviceClass *dc = DEVICE_CLASS(oc);
470 dc->realize = pnv_core_realize;
471 dc->unrealize = pnv_core_unrealize;
472 device_class_set_props(dc, pnv_core_properties);
473 dc->user_creatable = false;
476 #define DEFINE_PNV_CORE_TYPE(family, cpu_model) \
478 .parent = TYPE_PNV_CORE, \
479 .name = PNV_CORE_TYPE_NAME(cpu_model), \
480 .class_init = pnv_core_##family##_class_init, \
483 static const TypeInfo pnv_core_infos[] = {
485 .name = TYPE_PNV_CORE,
486 .parent = TYPE_CPU_CORE,
487 .instance_size = sizeof(PnvCore),
488 .class_size = sizeof(PnvCoreClass),
489 .class_init = pnv_core_class_init,
490 .abstract = true,
492 DEFINE_PNV_CORE_TYPE(power8, "power8e_v2.1"),
493 DEFINE_PNV_CORE_TYPE(power8, "power8_v2.0"),
494 DEFINE_PNV_CORE_TYPE(power8, "power8nvl_v1.0"),
495 DEFINE_PNV_CORE_TYPE(power9, "power9_v2.2"),
496 DEFINE_PNV_CORE_TYPE(power10, "power10_v2.0"),
499 DEFINE_TYPES(pnv_core_infos)
502 * POWER9 Quads
505 #define P9X_EX_NCU_SPEC_BAR 0x11010
507 static uint64_t pnv_quad_power9_xscom_read(void *opaque, hwaddr addr,
508 unsigned int width)
510 uint32_t offset = addr >> 3;
511 uint64_t val = -1;
513 switch (offset) {
514 case P9X_EX_NCU_SPEC_BAR:
515 case P9X_EX_NCU_SPEC_BAR + 0x400: /* Second EX */
516 val = 0;
517 break;
518 default:
519 qemu_log_mask(LOG_UNIMP, "%s: unimp read 0x%08x\n", __func__,
520 offset);
523 return val;
526 static void pnv_quad_power9_xscom_write(void *opaque, hwaddr addr, uint64_t val,
527 unsigned int width)
529 uint32_t offset = addr >> 3;
531 switch (offset) {
532 case P9X_EX_NCU_SPEC_BAR:
533 case P9X_EX_NCU_SPEC_BAR + 0x400: /* Second EX */
534 break;
535 default:
536 qemu_log_mask(LOG_UNIMP, "%s: unimp write 0x%08x\n", __func__,
537 offset);
541 static const MemoryRegionOps pnv_quad_power9_xscom_ops = {
542 .read = pnv_quad_power9_xscom_read,
543 .write = pnv_quad_power9_xscom_write,
544 .valid.min_access_size = 8,
545 .valid.max_access_size = 8,
546 .impl.min_access_size = 8,
547 .impl.max_access_size = 8,
548 .endianness = DEVICE_BIG_ENDIAN,
552 * POWER10 Quads
555 static uint64_t pnv_quad_power10_xscom_read(void *opaque, hwaddr addr,
556 unsigned int width)
558 uint32_t offset = addr >> 3;
559 uint64_t val = -1;
561 switch (offset) {
562 default:
563 qemu_log_mask(LOG_UNIMP, "%s: unimp read 0x%08x\n", __func__,
564 offset);
567 return val;
570 static void pnv_quad_power10_xscom_write(void *opaque, hwaddr addr,
571 uint64_t val, unsigned int width)
573 uint32_t offset = addr >> 3;
575 switch (offset) {
576 default:
577 qemu_log_mask(LOG_UNIMP, "%s: unimp write 0x%08x\n", __func__,
578 offset);
582 static const MemoryRegionOps pnv_quad_power10_xscom_ops = {
583 .read = pnv_quad_power10_xscom_read,
584 .write = pnv_quad_power10_xscom_write,
585 .valid.min_access_size = 8,
586 .valid.max_access_size = 8,
587 .impl.min_access_size = 8,
588 .impl.max_access_size = 8,
589 .endianness = DEVICE_BIG_ENDIAN,
592 #define P10_QME_SPWU_HYP 0x83c
593 #define P10_QME_SSH_HYP 0x82c
595 static uint64_t pnv_qme_power10_xscom_read(void *opaque, hwaddr addr,
596 unsigned int width)
598 PnvQuad *eq = PNV_QUAD(opaque);
599 uint32_t offset = addr >> 3;
600 uint64_t val = -1;
603 * Forth nibble selects the core within a quad, mask it to process read
604 * for any core.
606 switch (offset & ~PPC_BITMASK32(16, 19)) {
607 case P10_QME_SSH_HYP:
608 val = 0;
609 if (eq->special_wakeup_done) {
610 val |= PPC_BIT(1); /* SPWU DONE */
611 val |= PPC_BIT(4); /* SSH SPWU DONE */
613 break;
614 default:
615 qemu_log_mask(LOG_UNIMP, "%s: unimp read 0x%08x\n", __func__,
616 offset);
619 return val;
622 static void pnv_qme_power10_xscom_write(void *opaque, hwaddr addr,
623 uint64_t val, unsigned int width)
625 PnvQuad *eq = PNV_QUAD(opaque);
626 uint32_t offset = addr >> 3;
627 bool set;
628 int i;
630 switch (offset & ~PPC_BITMASK32(16, 19)) {
631 case P10_QME_SPWU_HYP:
632 set = !!(val & PPC_BIT(0));
633 eq->special_wakeup_done = set;
634 for (i = 0; i < 4; i++) {
635 /* These bits select cores in the quad */
636 if (offset & PPC_BIT32(16 + i)) {
637 eq->special_wakeup[i] = set;
640 break;
641 default:
642 qemu_log_mask(LOG_UNIMP, "%s: unimp write 0x%08x\n", __func__,
643 offset);
647 static const MemoryRegionOps pnv_qme_power10_xscom_ops = {
648 .read = pnv_qme_power10_xscom_read,
649 .write = pnv_qme_power10_xscom_write,
650 .valid.min_access_size = 8,
651 .valid.max_access_size = 8,
652 .impl.min_access_size = 8,
653 .impl.max_access_size = 8,
654 .endianness = DEVICE_BIG_ENDIAN,
657 static void pnv_quad_power9_realize(DeviceState *dev, Error **errp)
659 PnvQuad *eq = PNV_QUAD(dev);
660 PnvQuadClass *pqc = PNV_QUAD_GET_CLASS(eq);
661 char name[32];
663 snprintf(name, sizeof(name), "xscom-quad.%d", eq->quad_id);
664 pnv_xscom_region_init(&eq->xscom_regs, OBJECT(dev),
665 pqc->xscom_ops,
666 eq, name,
667 pqc->xscom_size);
670 static void pnv_quad_power10_realize(DeviceState *dev, Error **errp)
672 PnvQuad *eq = PNV_QUAD(dev);
673 PnvQuadClass *pqc = PNV_QUAD_GET_CLASS(eq);
674 char name[32];
676 snprintf(name, sizeof(name), "xscom-quad.%d", eq->quad_id);
677 pnv_xscom_region_init(&eq->xscom_regs, OBJECT(dev),
678 pqc->xscom_ops,
679 eq, name,
680 pqc->xscom_size);
682 snprintf(name, sizeof(name), "xscom-qme.%d", eq->quad_id);
683 pnv_xscom_region_init(&eq->xscom_qme_regs, OBJECT(dev),
684 pqc->xscom_qme_ops,
685 eq, name,
686 pqc->xscom_qme_size);
689 static Property pnv_quad_properties[] = {
690 DEFINE_PROP_UINT32("quad-id", PnvQuad, quad_id, 0),
691 DEFINE_PROP_END_OF_LIST(),
694 static void pnv_quad_power9_class_init(ObjectClass *oc, void *data)
696 PnvQuadClass *pqc = PNV_QUAD_CLASS(oc);
697 DeviceClass *dc = DEVICE_CLASS(oc);
699 dc->realize = pnv_quad_power9_realize;
701 pqc->xscom_ops = &pnv_quad_power9_xscom_ops;
702 pqc->xscom_size = PNV9_XSCOM_EQ_SIZE;
705 static void pnv_quad_power10_class_init(ObjectClass *oc, void *data)
707 PnvQuadClass *pqc = PNV_QUAD_CLASS(oc);
708 DeviceClass *dc = DEVICE_CLASS(oc);
710 dc->realize = pnv_quad_power10_realize;
712 pqc->xscom_ops = &pnv_quad_power10_xscom_ops;
713 pqc->xscom_size = PNV10_XSCOM_EQ_SIZE;
715 pqc->xscom_qme_ops = &pnv_qme_power10_xscom_ops;
716 pqc->xscom_qme_size = PNV10_XSCOM_QME_SIZE;
719 static void pnv_quad_class_init(ObjectClass *oc, void *data)
721 DeviceClass *dc = DEVICE_CLASS(oc);
723 device_class_set_props(dc, pnv_quad_properties);
724 dc->user_creatable = false;
727 static const TypeInfo pnv_quad_infos[] = {
729 .name = TYPE_PNV_QUAD,
730 .parent = TYPE_DEVICE,
731 .instance_size = sizeof(PnvQuad),
732 .class_size = sizeof(PnvQuadClass),
733 .class_init = pnv_quad_class_init,
734 .abstract = true,
737 .parent = TYPE_PNV_QUAD,
738 .name = PNV_QUAD_TYPE_NAME("power9"),
739 .class_init = pnv_quad_power9_class_init,
742 .parent = TYPE_PNV_QUAD,
743 .name = PNV_QUAD_TYPE_NAME("power10"),
744 .class_init = pnv_quad_power10_class_init,
748 DEFINE_TYPES(pnv_quad_infos);