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"
20 #include "qapi/error.h"
21 #include "exec/hwaddr.h"
22 #include "exec/memory.h"
23 #include "sysemu/cpus.h"
24 #include "hw/qdev-core.h"
25 #include "hw/ppc/pnv.h"
26 #include "hw/ppc/pnv_homer.h"
29 static bool core_max_array(PnvHomer
*homer
, hwaddr addr
)
32 PnvHomerClass
*hmrc
= PNV_HOMER_GET_CLASS(homer
);
34 for (i
= 0; i
<= homer
->chip
->nr_cores
; i
++) {
35 if (addr
== (hmrc
->core_max_base
+ i
)) {
44 #define PNV8_OCC_PSTATE_VERSION 0x1f8001
45 #define PNV8_OCC_PSTATE_MIN 0x1f8003
46 #define PNV8_OCC_PSTATE_VALID 0x1f8000
47 #define PNV8_OCC_PSTATE_THROTTLE 0x1f8002
48 #define PNV8_OCC_PSTATE_NOM 0x1f8004
49 #define PNV8_OCC_PSTATE_TURBO 0x1f8005
50 #define PNV8_OCC_PSTATE_ULTRA_TURBO 0x1f8006
51 #define PNV8_OCC_PSTATE_DATA 0x1f8008
52 #define PNV8_OCC_PSTATE_ID_ZERO 0x1f8010
53 #define PNV8_OCC_PSTATE_ID_ONE 0x1f8018
54 #define PNV8_OCC_PSTATE_ID_TWO 0x1f8020
55 #define PNV8_OCC_VDD_VOLTAGE_IDENTIFIER 0x1f8012
56 #define PNV8_OCC_VCS_VOLTAGE_IDENTIFIER 0x1f8013
57 #define PNV8_OCC_PSTATE_ZERO_FREQUENCY 0x1f8014
58 #define PNV8_OCC_PSTATE_ONE_FREQUENCY 0x1f801c
59 #define PNV8_OCC_PSTATE_TWO_FREQUENCY 0x1f8024
60 #define PNV8_CORE_MAX_BASE 0x1f8810
63 static uint64_t pnv_power8_homer_read(void *opaque
, hwaddr addr
,
66 PnvHomer
*homer
= PNV_HOMER(opaque
);
69 case PNV8_OCC_PSTATE_VERSION
:
70 case PNV8_OCC_PSTATE_MIN
:
71 case PNV8_OCC_PSTATE_ID_ZERO
:
73 case PNV8_OCC_PSTATE_VALID
:
74 case PNV8_OCC_PSTATE_THROTTLE
:
75 case PNV8_OCC_PSTATE_NOM
:
76 case PNV8_OCC_PSTATE_TURBO
:
77 case PNV8_OCC_PSTATE_ID_ONE
:
78 case PNV8_OCC_VDD_VOLTAGE_IDENTIFIER
:
79 case PNV8_OCC_VCS_VOLTAGE_IDENTIFIER
:
81 case PNV8_OCC_PSTATE_ULTRA_TURBO
:
82 case PNV8_OCC_PSTATE_ID_TWO
:
84 case PNV8_OCC_PSTATE_DATA
:
85 return 0x1000000000000000;
86 /* P8 frequency for 0, 1, and 2 pstates */
87 case PNV8_OCC_PSTATE_ZERO_FREQUENCY
:
88 case PNV8_OCC_PSTATE_ONE_FREQUENCY
:
89 case PNV8_OCC_PSTATE_TWO_FREQUENCY
:
92 /* pstate table core max array */
93 if (core_max_array(homer
, addr
)) {
99 static void pnv_power8_homer_write(void *opaque
, hwaddr addr
,
100 uint64_t val
, unsigned size
)
102 /* callback function defined to homer write */
106 static const MemoryRegionOps pnv_power8_homer_ops
= {
107 .read
= pnv_power8_homer_read
,
108 .write
= pnv_power8_homer_write
,
109 .valid
.min_access_size
= 1,
110 .valid
.max_access_size
= 8,
111 .impl
.min_access_size
= 1,
112 .impl
.max_access_size
= 8,
113 .endianness
= DEVICE_BIG_ENDIAN
,
116 static void pnv_homer_power8_class_init(ObjectClass
*klass
, void *data
)
118 PnvHomerClass
*homer
= PNV_HOMER_CLASS(klass
);
120 homer
->homer_size
= PNV_HOMER_SIZE
;
121 homer
->homer_ops
= &pnv_power8_homer_ops
;
122 homer
->core_max_base
= PNV8_CORE_MAX_BASE
;
125 static const TypeInfo pnv_homer_power8_type_info
= {
126 .name
= TYPE_PNV8_HOMER
,
127 .parent
= TYPE_PNV_HOMER
,
128 .instance_size
= sizeof(PnvHomer
),
129 .class_init
= pnv_homer_power8_class_init
,
132 /* P9 Pstate table */
134 #define PNV9_OCC_PSTATE_ID_ZERO 0xe2018
135 #define PNV9_OCC_PSTATE_ID_ONE 0xe2020
136 #define PNV9_OCC_PSTATE_ID_TWO 0xe2028
137 #define PNV9_OCC_PSTATE_DATA 0xe2000
138 #define PNV9_OCC_PSTATE_DATA_AREA 0xe2008
139 #define PNV9_OCC_PSTATE_MIN 0xe2003
140 #define PNV9_OCC_PSTATE_NOM 0xe2004
141 #define PNV9_OCC_PSTATE_TURBO 0xe2005
142 #define PNV9_OCC_PSTATE_ULTRA_TURBO 0xe2818
143 #define PNV9_OCC_MAX_PSTATE_ULTRA_TURBO 0xe2006
144 #define PNV9_OCC_PSTATE_MAJOR_VERSION 0xe2001
145 #define PNV9_OCC_OPAL_RUNTIME_DATA 0xe2b85
146 #define PNV9_CHIP_HOMER_IMAGE_POINTER 0x200008
147 #define PNV9_CHIP_HOMER_BASE 0x0
148 #define PNV9_OCC_PSTATE_ZERO_FREQUENCY 0xe201c
149 #define PNV9_OCC_PSTATE_ONE_FREQUENCY 0xe2024
150 #define PNV9_OCC_PSTATE_TWO_FREQUENCY 0xe202c
151 #define PNV9_OCC_ROLE_MASTER_OR_SLAVE 0xe2002
152 #define PNV9_CORE_MAX_BASE 0xe2819
155 static uint64_t pnv_power9_homer_read(void *opaque
, hwaddr addr
,
158 PnvHomer
*homer
= PNV_HOMER(opaque
);
161 case PNV9_OCC_MAX_PSTATE_ULTRA_TURBO
:
162 case PNV9_OCC_PSTATE_ID_ZERO
:
164 case PNV9_OCC_PSTATE_DATA
:
165 case PNV9_OCC_ROLE_MASTER_OR_SLAVE
:
166 case PNV9_OCC_PSTATE_NOM
:
167 case PNV9_OCC_PSTATE_TURBO
:
168 case PNV9_OCC_PSTATE_ID_ONE
:
169 case PNV9_OCC_PSTATE_ULTRA_TURBO
:
170 case PNV9_OCC_OPAL_RUNTIME_DATA
:
172 case PNV9_OCC_PSTATE_MIN
:
173 case PNV9_OCC_PSTATE_ID_TWO
:
176 /* 3000 khz frequency for 0, 1, and 2 pstates */
177 case PNV9_OCC_PSTATE_ZERO_FREQUENCY
:
178 case PNV9_OCC_PSTATE_ONE_FREQUENCY
:
179 case PNV9_OCC_PSTATE_TWO_FREQUENCY
:
181 case PNV9_OCC_PSTATE_MAJOR_VERSION
:
183 case PNV9_CHIP_HOMER_BASE
:
184 case PNV9_OCC_PSTATE_DATA_AREA
:
185 case PNV9_CHIP_HOMER_IMAGE_POINTER
:
186 return 0x1000000000000000;
188 /* pstate table core max array */
189 if (core_max_array(homer
, addr
)) {
195 static void pnv_power9_homer_write(void *opaque
, hwaddr addr
,
196 uint64_t val
, unsigned size
)
198 /* callback function defined to homer write */
202 static const MemoryRegionOps pnv_power9_homer_ops
= {
203 .read
= pnv_power9_homer_read
,
204 .write
= pnv_power9_homer_write
,
205 .valid
.min_access_size
= 1,
206 .valid
.max_access_size
= 8,
207 .impl
.min_access_size
= 1,
208 .impl
.max_access_size
= 8,
209 .endianness
= DEVICE_BIG_ENDIAN
,
212 static void pnv_homer_power9_class_init(ObjectClass
*klass
, void *data
)
214 PnvHomerClass
*homer
= PNV_HOMER_CLASS(klass
);
216 homer
->homer_size
= PNV9_HOMER_SIZE
;
217 homer
->homer_ops
= &pnv_power9_homer_ops
;
218 homer
->core_max_base
= PNV9_CORE_MAX_BASE
;
221 static const TypeInfo pnv_homer_power9_type_info
= {
222 .name
= TYPE_PNV9_HOMER
,
223 .parent
= TYPE_PNV_HOMER
,
224 .instance_size
= sizeof(PnvHomer
),
225 .class_init
= pnv_homer_power9_class_init
,
228 static void pnv_homer_realize(DeviceState
*dev
, Error
**errp
)
230 PnvHomer
*homer
= PNV_HOMER(dev
);
231 PnvHomerClass
*hmrc
= PNV_HOMER_GET_CLASS(homer
);
233 Error
*local_err
= NULL
;
235 obj
= object_property_get_link(OBJECT(dev
), "chip", &local_err
);
237 error_propagate(errp
, local_err
);
238 error_prepend(errp
, "required link 'chip' not found: ");
241 homer
->chip
= PNV_CHIP(obj
);
243 memory_region_init_io(&homer
->regs
, OBJECT(dev
),
244 hmrc
->homer_ops
, homer
, "homer-main-memory",
248 static void pnv_homer_class_init(ObjectClass
*klass
, void *data
)
250 DeviceClass
*dc
= DEVICE_CLASS(klass
);
252 dc
->realize
= pnv_homer_realize
;
253 dc
->desc
= "PowerNV HOMER Memory";
256 static const TypeInfo pnv_homer_type_info
= {
257 .name
= TYPE_PNV_HOMER
,
258 .parent
= TYPE_DEVICE
,
259 .instance_size
= sizeof(PnvHomer
),
260 .class_init
= pnv_homer_class_init
,
261 .class_size
= sizeof(PnvHomerClass
),
265 static void pnv_homer_register_types(void)
267 type_register_static(&pnv_homer_type_info
);
268 type_register_static(&pnv_homer_power8_type_info
);
269 type_register_static(&pnv_homer_power9_type_info
);
272 type_init(pnv_homer_register_types
);