2 * QEMU PowerPC PowerNV Emulation of a few HOMER related registers
4 * Copyright (c) 2019, IBM Corporation.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License, version 2, as
8 * published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, see <http://www.gnu.org/licenses/>.
19 #include "qemu/osdep.h"
21 #include "qapi/error.h"
22 #include "exec/hwaddr.h"
23 #include "exec/memory.h"
24 #include "sysemu/cpus.h"
25 #include "hw/qdev-core.h"
26 #include "hw/qdev-properties.h"
27 #include "hw/ppc/pnv.h"
28 #include "hw/ppc/pnv_homer.h"
29 #include "hw/ppc/pnv_xscom.h"
32 static bool core_max_array(PnvHomer
*homer
, hwaddr addr
)
35 PnvHomerClass
*hmrc
= PNV_HOMER_GET_CLASS(homer
);
37 for (i
= 0; i
<= homer
->chip
->nr_cores
; i
++) {
38 if (addr
== (hmrc
->core_max_base
+ i
)) {
47 #define PNV8_OCC_PSTATE_VERSION 0x1f8001
48 #define PNV8_OCC_PSTATE_MIN 0x1f8003
49 #define PNV8_OCC_PSTATE_VALID 0x1f8000
50 #define PNV8_OCC_PSTATE_THROTTLE 0x1f8002
51 #define PNV8_OCC_PSTATE_NOM 0x1f8004
52 #define PNV8_OCC_PSTATE_TURBO 0x1f8005
53 #define PNV8_OCC_PSTATE_ULTRA_TURBO 0x1f8006
54 #define PNV8_OCC_PSTATE_DATA 0x1f8008
55 #define PNV8_OCC_PSTATE_ID_ZERO 0x1f8010
56 #define PNV8_OCC_PSTATE_ID_ONE 0x1f8018
57 #define PNV8_OCC_PSTATE_ID_TWO 0x1f8020
58 #define PNV8_OCC_VDD_VOLTAGE_IDENTIFIER 0x1f8012
59 #define PNV8_OCC_VCS_VOLTAGE_IDENTIFIER 0x1f8013
60 #define PNV8_OCC_PSTATE_ZERO_FREQUENCY 0x1f8014
61 #define PNV8_OCC_PSTATE_ONE_FREQUENCY 0x1f801c
62 #define PNV8_OCC_PSTATE_TWO_FREQUENCY 0x1f8024
63 #define PNV8_CORE_MAX_BASE 0x1f8810
66 static uint64_t pnv_power8_homer_read(void *opaque
, hwaddr addr
,
69 PnvHomer
*homer
= PNV_HOMER(opaque
);
72 case PNV8_OCC_PSTATE_VERSION
:
73 case PNV8_OCC_PSTATE_MIN
:
74 case PNV8_OCC_PSTATE_ID_ZERO
:
76 case PNV8_OCC_PSTATE_VALID
:
77 case PNV8_OCC_PSTATE_THROTTLE
:
78 case PNV8_OCC_PSTATE_NOM
:
79 case PNV8_OCC_PSTATE_TURBO
:
80 case PNV8_OCC_PSTATE_ID_ONE
:
81 case PNV8_OCC_VDD_VOLTAGE_IDENTIFIER
:
82 case PNV8_OCC_VCS_VOLTAGE_IDENTIFIER
:
84 case PNV8_OCC_PSTATE_ULTRA_TURBO
:
85 case PNV8_OCC_PSTATE_ID_TWO
:
87 case PNV8_OCC_PSTATE_DATA
:
88 return 0x1000000000000000;
89 /* P8 frequency for 0, 1, and 2 pstates */
90 case PNV8_OCC_PSTATE_ZERO_FREQUENCY
:
91 case PNV8_OCC_PSTATE_ONE_FREQUENCY
:
92 case PNV8_OCC_PSTATE_TWO_FREQUENCY
:
95 /* pstate table core max array */
96 if (core_max_array(homer
, addr
)) {
102 static void pnv_power8_homer_write(void *opaque
, hwaddr addr
,
103 uint64_t val
, unsigned size
)
105 /* callback function defined to homer write */
109 static const MemoryRegionOps pnv_power8_homer_ops
= {
110 .read
= pnv_power8_homer_read
,
111 .write
= pnv_power8_homer_write
,
112 .valid
.min_access_size
= 1,
113 .valid
.max_access_size
= 8,
114 .impl
.min_access_size
= 1,
115 .impl
.max_access_size
= 8,
116 .endianness
= DEVICE_BIG_ENDIAN
,
120 #define PBA_BAR0 0x00
121 #define PBA_BAR1 0x01
122 #define PBA_BAR2 0x02
123 #define PBA_BAR3 0x03
124 #define PBA_BARMASK0 0x04
125 #define PBA_BARMASK1 0x05
126 #define PBA_BARMASK2 0x06
127 #define PBA_BARMASK3 0x07
129 static uint64_t pnv_homer_power8_pba_read(void *opaque
, hwaddr addr
,
132 PnvHomer
*homer
= PNV_HOMER(opaque
);
133 PnvChip
*chip
= homer
->chip
;
134 uint32_t reg
= addr
>> 3;
139 val
= PNV_HOMER_BASE(chip
);
141 case PBA_BARMASK0
: /* P8 homer region mask */
142 val
= (PNV_HOMER_SIZE
- 1) & 0x300000;
144 case PBA_BAR3
: /* P8 occ common area */
145 val
= PNV_OCC_COMMON_AREA_BASE
;
147 case PBA_BARMASK3
: /* P8 occ common area mask */
148 val
= (PNV_OCC_COMMON_AREA_SIZE
- 1) & 0x700000;
151 qemu_log_mask(LOG_UNIMP
, "PBA: read to unimplemented register: Ox%"
152 HWADDR_PRIx
"\n", addr
>> 3);
157 static void pnv_homer_power8_pba_write(void *opaque
, hwaddr addr
,
158 uint64_t val
, unsigned size
)
160 qemu_log_mask(LOG_UNIMP
, "PBA: write to unimplemented register: Ox%"
161 HWADDR_PRIx
"\n", addr
>> 3);
164 static const MemoryRegionOps pnv_homer_power8_pba_ops
= {
165 .read
= pnv_homer_power8_pba_read
,
166 .write
= pnv_homer_power8_pba_write
,
167 .valid
.min_access_size
= 8,
168 .valid
.max_access_size
= 8,
169 .impl
.min_access_size
= 8,
170 .impl
.max_access_size
= 8,
171 .endianness
= DEVICE_BIG_ENDIAN
,
174 static void pnv_homer_power8_class_init(ObjectClass
*klass
, void *data
)
176 PnvHomerClass
*homer
= PNV_HOMER_CLASS(klass
);
178 homer
->pba_size
= PNV_XSCOM_PBA_SIZE
;
179 homer
->pba_ops
= &pnv_homer_power8_pba_ops
;
180 homer
->homer_size
= PNV_HOMER_SIZE
;
181 homer
->homer_ops
= &pnv_power8_homer_ops
;
182 homer
->core_max_base
= PNV8_CORE_MAX_BASE
;
185 static const TypeInfo pnv_homer_power8_type_info
= {
186 .name
= TYPE_PNV8_HOMER
,
187 .parent
= TYPE_PNV_HOMER
,
188 .instance_size
= sizeof(PnvHomer
),
189 .class_init
= pnv_homer_power8_class_init
,
192 /* P9 Pstate table */
194 #define PNV9_OCC_PSTATE_ID_ZERO 0xe2018
195 #define PNV9_OCC_PSTATE_ID_ONE 0xe2020
196 #define PNV9_OCC_PSTATE_ID_TWO 0xe2028
197 #define PNV9_OCC_PSTATE_DATA 0xe2000
198 #define PNV9_OCC_PSTATE_DATA_AREA 0xe2008
199 #define PNV9_OCC_PSTATE_MIN 0xe2003
200 #define PNV9_OCC_PSTATE_NOM 0xe2004
201 #define PNV9_OCC_PSTATE_TURBO 0xe2005
202 #define PNV9_OCC_PSTATE_ULTRA_TURBO 0xe2818
203 #define PNV9_OCC_MAX_PSTATE_ULTRA_TURBO 0xe2006
204 #define PNV9_OCC_PSTATE_MAJOR_VERSION 0xe2001
205 #define PNV9_OCC_OPAL_RUNTIME_DATA 0xe2b85
206 #define PNV9_CHIP_HOMER_IMAGE_POINTER 0x200008
207 #define PNV9_CHIP_HOMER_BASE 0x0
208 #define PNV9_OCC_PSTATE_ZERO_FREQUENCY 0xe201c
209 #define PNV9_OCC_PSTATE_ONE_FREQUENCY 0xe2024
210 #define PNV9_OCC_PSTATE_TWO_FREQUENCY 0xe202c
211 #define PNV9_OCC_ROLE_MASTER_OR_SLAVE 0xe2002
212 #define PNV9_CORE_MAX_BASE 0xe2819
215 static uint64_t pnv_power9_homer_read(void *opaque
, hwaddr addr
,
218 PnvHomer
*homer
= PNV_HOMER(opaque
);
221 case PNV9_OCC_MAX_PSTATE_ULTRA_TURBO
:
222 case PNV9_OCC_PSTATE_ID_ZERO
:
224 case PNV9_OCC_PSTATE_DATA
:
225 case PNV9_OCC_ROLE_MASTER_OR_SLAVE
:
226 case PNV9_OCC_PSTATE_NOM
:
227 case PNV9_OCC_PSTATE_TURBO
:
228 case PNV9_OCC_PSTATE_ID_ONE
:
229 case PNV9_OCC_PSTATE_ULTRA_TURBO
:
230 case PNV9_OCC_OPAL_RUNTIME_DATA
:
232 case PNV9_OCC_PSTATE_MIN
:
233 case PNV9_OCC_PSTATE_ID_TWO
:
236 /* 3000 khz frequency for 0, 1, and 2 pstates */
237 case PNV9_OCC_PSTATE_ZERO_FREQUENCY
:
238 case PNV9_OCC_PSTATE_ONE_FREQUENCY
:
239 case PNV9_OCC_PSTATE_TWO_FREQUENCY
:
241 case PNV9_OCC_PSTATE_MAJOR_VERSION
:
243 case PNV9_CHIP_HOMER_BASE
:
244 case PNV9_OCC_PSTATE_DATA_AREA
:
245 case PNV9_CHIP_HOMER_IMAGE_POINTER
:
246 return 0x1000000000000000;
248 /* pstate table core max array */
249 if (core_max_array(homer
, addr
)) {
255 static void pnv_power9_homer_write(void *opaque
, hwaddr addr
,
256 uint64_t val
, unsigned size
)
258 /* callback function defined to homer write */
262 static const MemoryRegionOps pnv_power9_homer_ops
= {
263 .read
= pnv_power9_homer_read
,
264 .write
= pnv_power9_homer_write
,
265 .valid
.min_access_size
= 1,
266 .valid
.max_access_size
= 8,
267 .impl
.min_access_size
= 1,
268 .impl
.max_access_size
= 8,
269 .endianness
= DEVICE_BIG_ENDIAN
,
272 static uint64_t pnv_homer_power9_pba_read(void *opaque
, hwaddr addr
,
275 PnvHomer
*homer
= PNV_HOMER(opaque
);
276 PnvChip
*chip
= homer
->chip
;
277 uint32_t reg
= addr
>> 3;
282 val
= PNV9_HOMER_BASE(chip
);
284 case PBA_BARMASK0
: /* P9 homer region mask */
285 val
= (PNV9_HOMER_SIZE
- 1) & 0x300000;
287 case PBA_BAR2
: /* P9 occ common area */
288 val
= PNV9_OCC_COMMON_AREA_BASE
;
290 case PBA_BARMASK2
: /* P9 occ common area size */
291 val
= (PNV9_OCC_COMMON_AREA_SIZE
- 1) & 0x700000;
294 qemu_log_mask(LOG_UNIMP
, "PBA: read to unimplemented register: Ox%"
295 HWADDR_PRIx
"\n", addr
>> 3);
300 static void pnv_homer_power9_pba_write(void *opaque
, hwaddr addr
,
301 uint64_t val
, unsigned size
)
303 qemu_log_mask(LOG_UNIMP
, "PBA: write to unimplemented register: Ox%"
304 HWADDR_PRIx
"\n", addr
>> 3);
307 static const MemoryRegionOps pnv_homer_power9_pba_ops
= {
308 .read
= pnv_homer_power9_pba_read
,
309 .write
= pnv_homer_power9_pba_write
,
310 .valid
.min_access_size
= 8,
311 .valid
.max_access_size
= 8,
312 .impl
.min_access_size
= 8,
313 .impl
.max_access_size
= 8,
314 .endianness
= DEVICE_BIG_ENDIAN
,
317 static void pnv_homer_power9_class_init(ObjectClass
*klass
, void *data
)
319 PnvHomerClass
*homer
= PNV_HOMER_CLASS(klass
);
321 homer
->pba_size
= PNV9_XSCOM_PBA_SIZE
;
322 homer
->pba_ops
= &pnv_homer_power9_pba_ops
;
323 homer
->homer_size
= PNV9_HOMER_SIZE
;
324 homer
->homer_ops
= &pnv_power9_homer_ops
;
325 homer
->core_max_base
= PNV9_CORE_MAX_BASE
;
328 static const TypeInfo pnv_homer_power9_type_info
= {
329 .name
= TYPE_PNV9_HOMER
,
330 .parent
= TYPE_PNV_HOMER
,
331 .instance_size
= sizeof(PnvHomer
),
332 .class_init
= pnv_homer_power9_class_init
,
335 static void pnv_homer_realize(DeviceState
*dev
, Error
**errp
)
337 PnvHomer
*homer
= PNV_HOMER(dev
);
338 PnvHomerClass
*hmrc
= PNV_HOMER_GET_CLASS(homer
);
342 pnv_xscom_region_init(&homer
->pba_regs
, OBJECT(dev
), hmrc
->pba_ops
,
343 homer
, "xscom-pba", hmrc
->pba_size
);
346 memory_region_init_io(&homer
->regs
, OBJECT(dev
),
347 hmrc
->homer_ops
, homer
, "homer-main-memory",
351 static Property pnv_homer_properties
[] = {
352 DEFINE_PROP_LINK("chip", PnvHomer
, chip
, TYPE_PNV_CHIP
, PnvChip
*),
353 DEFINE_PROP_END_OF_LIST(),
356 static void pnv_homer_class_init(ObjectClass
*klass
, void *data
)
358 DeviceClass
*dc
= DEVICE_CLASS(klass
);
360 dc
->realize
= pnv_homer_realize
;
361 dc
->desc
= "PowerNV HOMER Memory";
362 device_class_set_props(dc
, pnv_homer_properties
);
363 dc
->user_creatable
= false;
366 static const TypeInfo pnv_homer_type_info
= {
367 .name
= TYPE_PNV_HOMER
,
368 .parent
= TYPE_DEVICE
,
369 .instance_size
= sizeof(PnvHomer
),
370 .class_init
= pnv_homer_class_init
,
371 .class_size
= sizeof(PnvHomerClass
),
375 static void pnv_homer_register_types(void)
377 type_register_static(&pnv_homer_type_info
);
378 type_register_static(&pnv_homer_power8_type_info
);
379 type_register_static(&pnv_homer_power9_type_info
);
382 type_init(pnv_homer_register_types
);