2 * QEMU PowerPC nest pervasive common chiplet model
4 * Copyright (c) 2023, IBM Corporation.
6 * SPDX-License-Identifier: GPL-2.0-or-later
9 #include "qemu/osdep.h"
11 #include "hw/qdev-properties.h"
12 #include "hw/ppc/pnv.h"
13 #include "hw/ppc/pnv_xscom.h"
14 #include "hw/ppc/pnv_nest_pervasive.h"
17 * Status, configuration, and control units in POWER chips is provided
18 * by the pervasive subsystem, which connects registers to the SCOM bus,
19 * which can be programmed by processor cores, other units on the chip,
20 * BMCs, or other POWER chips.
22 * A POWER10 chip is divided into logical units called chiplets. Chiplets
23 * are broadly divided into "core chiplets" (with the processor cores) and
24 * "nest chiplets" (with everything else). Each chiplet has an attachment
25 * to the pervasive bus (PIB) and with chiplet-specific registers.
26 * All nest chiplets have a common basic set of registers.
28 * This model will provide the registers functionality for common registers of
29 * nest unit (PB Chiplet, PCI Chiplets, MC Chiplet, PAU Chiplets)
31 * Currently this model provide the read/write functionality of chiplet control
35 #define CPLT_CONF0 0x08
36 #define CPLT_CONF0_OR 0x18
37 #define CPLT_CONF0_CLEAR 0x28
38 #define CPLT_CONF1 0x09
39 #define CPLT_CONF1_OR 0x19
40 #define CPLT_CONF1_CLEAR 0x29
41 #define CPLT_STAT0 0x100
42 #define CPLT_MASK0 0x101
43 #define CPLT_PROTECT_MODE 0x3FE
44 #define CPLT_ATOMIC_CLOCK 0x3FF
46 static uint64_t pnv_chiplet_ctrl_read(void *opaque
, hwaddr addr
, unsigned size
)
48 PnvNestChipletPervasive
*nest_pervasive
= PNV_NEST_CHIPLET_PERVASIVE(
50 uint32_t reg
= addr
>> 3;
53 /* CPLT_CTRL0 to CPLT_CTRL5 */
54 for (int i
= 0; i
< PNV_CPLT_CTRL_SIZE
; i
++) {
56 return nest_pervasive
->control_regs
.cplt_ctrl
[i
];
57 } else if ((reg
== (i
+ 0x10)) || (reg
== (i
+ 0x20))) {
58 qemu_log_mask(LOG_GUEST_ERROR
, "%s: Write only register, ignoring "
59 "xscom read at 0x%" PRIx32
"\n",
67 val
= nest_pervasive
->control_regs
.cplt_cfg0
;
70 case CPLT_CONF0_CLEAR
:
71 qemu_log_mask(LOG_GUEST_ERROR
, "%s: Write only register, ignoring "
72 "xscom read at 0x%" PRIx32
"\n",
76 val
= nest_pervasive
->control_regs
.cplt_cfg1
;
79 case CPLT_CONF1_CLEAR
:
80 qemu_log_mask(LOG_GUEST_ERROR
, "%s: Write only register, ignoring "
81 "xscom read at 0x%" PRIx32
"\n",
85 val
= nest_pervasive
->control_regs
.cplt_stat0
;
88 val
= nest_pervasive
->control_regs
.cplt_mask0
;
90 case CPLT_PROTECT_MODE
:
91 val
= nest_pervasive
->control_regs
.ctrl_protect_mode
;
93 case CPLT_ATOMIC_CLOCK
:
94 val
= nest_pervasive
->control_regs
.ctrl_atomic_lock
;
97 qemu_log_mask(LOG_UNIMP
, "%s: Chiplet_control_regs: Invalid xscom "
98 "read at 0x%" PRIx32
"\n", __func__
, reg
);
103 static void pnv_chiplet_ctrl_write(void *opaque
, hwaddr addr
,
104 uint64_t val
, unsigned size
)
106 PnvNestChipletPervasive
*nest_pervasive
= PNV_NEST_CHIPLET_PERVASIVE(
108 uint32_t reg
= addr
>> 3;
110 /* CPLT_CTRL0 to CPLT_CTRL5 */
111 for (int i
= 0; i
< PNV_CPLT_CTRL_SIZE
; i
++) {
113 nest_pervasive
->control_regs
.cplt_ctrl
[i
] = val
;
115 } else if (reg
== (i
+ 0x10)) {
116 nest_pervasive
->control_regs
.cplt_ctrl
[i
] |= val
;
118 } else if (reg
== (i
+ 0x20)) {
119 nest_pervasive
->control_regs
.cplt_ctrl
[i
] &= ~val
;
126 nest_pervasive
->control_regs
.cplt_cfg0
= val
;
129 nest_pervasive
->control_regs
.cplt_cfg0
|= val
;
131 case CPLT_CONF0_CLEAR
:
132 nest_pervasive
->control_regs
.cplt_cfg0
&= ~val
;
135 nest_pervasive
->control_regs
.cplt_cfg1
= val
;
138 nest_pervasive
->control_regs
.cplt_cfg1
|= val
;
140 case CPLT_CONF1_CLEAR
:
141 nest_pervasive
->control_regs
.cplt_cfg1
&= ~val
;
144 nest_pervasive
->control_regs
.cplt_stat0
= val
;
147 nest_pervasive
->control_regs
.cplt_mask0
= val
;
149 case CPLT_PROTECT_MODE
:
150 nest_pervasive
->control_regs
.ctrl_protect_mode
= val
;
152 case CPLT_ATOMIC_CLOCK
:
153 nest_pervasive
->control_regs
.ctrl_atomic_lock
= val
;
156 qemu_log_mask(LOG_UNIMP
, "%s: Chiplet_control_regs: Invalid xscom "
157 "write at 0x%" PRIx32
"\n",
162 static const MemoryRegionOps pnv_nest_pervasive_control_xscom_ops
= {
163 .read
= pnv_chiplet_ctrl_read
,
164 .write
= pnv_chiplet_ctrl_write
,
165 .valid
.min_access_size
= 8,
166 .valid
.max_access_size
= 8,
167 .impl
.min_access_size
= 8,
168 .impl
.max_access_size
= 8,
169 .endianness
= DEVICE_BIG_ENDIAN
,
172 static void pnv_nest_pervasive_realize(DeviceState
*dev
, Error
**errp
)
174 PnvNestChipletPervasive
*nest_pervasive
= PNV_NEST_CHIPLET_PERVASIVE(dev
);
176 /* Chiplet control scoms */
177 pnv_xscom_region_init(&nest_pervasive
->xscom_ctrl_regs_mr
,
178 OBJECT(nest_pervasive
),
179 &pnv_nest_pervasive_control_xscom_ops
,
180 nest_pervasive
, "pervasive-control",
181 PNV10_XSCOM_CHIPLET_CTRL_REGS_SIZE
);
184 static void pnv_nest_pervasive_class_init(ObjectClass
*klass
, void *data
)
186 DeviceClass
*dc
= DEVICE_CLASS(klass
);
188 dc
->desc
= "PowerNV nest pervasive chiplet";
189 dc
->realize
= pnv_nest_pervasive_realize
;
192 static const TypeInfo pnv_nest_pervasive_info
= {
193 .name
= TYPE_PNV_NEST_CHIPLET_PERVASIVE
,
194 .parent
= TYPE_DEVICE
,
195 .instance_size
= sizeof(PnvNestChipletPervasive
),
196 .class_init
= pnv_nest_pervasive_class_init
,
197 .interfaces
= (InterfaceInfo
[]) {
198 { TYPE_PNV_XSCOM_INTERFACE
},
203 static void pnv_nest_pervasive_register_types(void)
205 type_register_static(&pnv_nest_pervasive_info
);
208 type_init(pnv_nest_pervasive_register_types
);