xref: /openbmc/qemu/hw/ppc/pnv_homer.c (revision 2a886794)
1 /*
2  * QEMU PowerPC PowerNV Emulation of a few HOMER related registers
3  *
4  * Copyright (c) 2019, IBM Corporation.
5  *
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.
9  *
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.
14  *
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/>.
17  */
18 
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/qdev-properties.h"
26 #include "hw/ppc/pnv.h"
27 #include "hw/ppc/pnv_homer.h"
28 
29 
30 static bool core_max_array(PnvHomer *homer, hwaddr addr)
31 {
32     int i;
33     PnvHomerClass *hmrc = PNV_HOMER_GET_CLASS(homer);
34 
35     for (i = 0; i <= homer->chip->nr_cores; i++) {
36         if (addr == (hmrc->core_max_base + i)) {
37             return true;
38        }
39     }
40     return false;
41 }
42 
43 /* P8 Pstate table */
44 
45 #define PNV8_OCC_PSTATE_VERSION          0x1f8001
46 #define PNV8_OCC_PSTATE_MIN              0x1f8003
47 #define PNV8_OCC_PSTATE_VALID            0x1f8000
48 #define PNV8_OCC_PSTATE_THROTTLE         0x1f8002
49 #define PNV8_OCC_PSTATE_NOM              0x1f8004
50 #define PNV8_OCC_PSTATE_TURBO            0x1f8005
51 #define PNV8_OCC_PSTATE_ULTRA_TURBO      0x1f8006
52 #define PNV8_OCC_PSTATE_DATA             0x1f8008
53 #define PNV8_OCC_PSTATE_ID_ZERO          0x1f8010
54 #define PNV8_OCC_PSTATE_ID_ONE           0x1f8018
55 #define PNV8_OCC_PSTATE_ID_TWO           0x1f8020
56 #define PNV8_OCC_VDD_VOLTAGE_IDENTIFIER  0x1f8012
57 #define PNV8_OCC_VCS_VOLTAGE_IDENTIFIER  0x1f8013
58 #define PNV8_OCC_PSTATE_ZERO_FREQUENCY   0x1f8014
59 #define PNV8_OCC_PSTATE_ONE_FREQUENCY    0x1f801c
60 #define PNV8_OCC_PSTATE_TWO_FREQUENCY    0x1f8024
61 #define PNV8_CORE_MAX_BASE               0x1f8810
62 
63 
64 static uint64_t pnv_power8_homer_read(void *opaque, hwaddr addr,
65                                       unsigned size)
66 {
67     PnvHomer *homer = PNV_HOMER(opaque);
68 
69     switch (addr) {
70     case PNV8_OCC_PSTATE_VERSION:
71     case PNV8_OCC_PSTATE_MIN:
72     case PNV8_OCC_PSTATE_ID_ZERO:
73         return 0;
74     case PNV8_OCC_PSTATE_VALID:
75     case PNV8_OCC_PSTATE_THROTTLE:
76     case PNV8_OCC_PSTATE_NOM:
77     case PNV8_OCC_PSTATE_TURBO:
78     case PNV8_OCC_PSTATE_ID_ONE:
79     case PNV8_OCC_VDD_VOLTAGE_IDENTIFIER:
80     case PNV8_OCC_VCS_VOLTAGE_IDENTIFIER:
81         return 1;
82     case PNV8_OCC_PSTATE_ULTRA_TURBO:
83     case PNV8_OCC_PSTATE_ID_TWO:
84         return 2;
85     case PNV8_OCC_PSTATE_DATA:
86         return 0x1000000000000000;
87     /* P8 frequency for 0, 1, and 2 pstates */
88     case PNV8_OCC_PSTATE_ZERO_FREQUENCY:
89     case PNV8_OCC_PSTATE_ONE_FREQUENCY:
90     case PNV8_OCC_PSTATE_TWO_FREQUENCY:
91         return 3000;
92     }
93     /* pstate table core max array */
94     if (core_max_array(homer, addr)) {
95         return 1;
96     }
97     return 0;
98 }
99 
100 static void pnv_power8_homer_write(void *opaque, hwaddr addr,
101                                    uint64_t val, unsigned size)
102 {
103     /* callback function defined to homer write */
104     return;
105 }
106 
107 static const MemoryRegionOps pnv_power8_homer_ops = {
108     .read = pnv_power8_homer_read,
109     .write = pnv_power8_homer_write,
110     .valid.min_access_size = 1,
111     .valid.max_access_size = 8,
112     .impl.min_access_size = 1,
113     .impl.max_access_size = 8,
114     .endianness = DEVICE_BIG_ENDIAN,
115 };
116 
117 static void pnv_homer_power8_class_init(ObjectClass *klass, void *data)
118 {
119     PnvHomerClass *homer = PNV_HOMER_CLASS(klass);
120 
121     homer->homer_size = PNV_HOMER_SIZE;
122     homer->homer_ops = &pnv_power8_homer_ops;
123     homer->core_max_base = PNV8_CORE_MAX_BASE;
124 }
125 
126 static const TypeInfo pnv_homer_power8_type_info = {
127     .name          = TYPE_PNV8_HOMER,
128     .parent        = TYPE_PNV_HOMER,
129     .instance_size = sizeof(PnvHomer),
130     .class_init    = pnv_homer_power8_class_init,
131 };
132 
133 /* P9 Pstate table */
134 
135 #define PNV9_OCC_PSTATE_ID_ZERO          0xe2018
136 #define PNV9_OCC_PSTATE_ID_ONE           0xe2020
137 #define PNV9_OCC_PSTATE_ID_TWO           0xe2028
138 #define PNV9_OCC_PSTATE_DATA             0xe2000
139 #define PNV9_OCC_PSTATE_DATA_AREA        0xe2008
140 #define PNV9_OCC_PSTATE_MIN              0xe2003
141 #define PNV9_OCC_PSTATE_NOM              0xe2004
142 #define PNV9_OCC_PSTATE_TURBO            0xe2005
143 #define PNV9_OCC_PSTATE_ULTRA_TURBO      0xe2818
144 #define PNV9_OCC_MAX_PSTATE_ULTRA_TURBO  0xe2006
145 #define PNV9_OCC_PSTATE_MAJOR_VERSION    0xe2001
146 #define PNV9_OCC_OPAL_RUNTIME_DATA       0xe2b85
147 #define PNV9_CHIP_HOMER_IMAGE_POINTER    0x200008
148 #define PNV9_CHIP_HOMER_BASE             0x0
149 #define PNV9_OCC_PSTATE_ZERO_FREQUENCY   0xe201c
150 #define PNV9_OCC_PSTATE_ONE_FREQUENCY    0xe2024
151 #define PNV9_OCC_PSTATE_TWO_FREQUENCY    0xe202c
152 #define PNV9_OCC_ROLE_MASTER_OR_SLAVE    0xe2002
153 #define PNV9_CORE_MAX_BASE               0xe2819
154 
155 
156 static uint64_t pnv_power9_homer_read(void *opaque, hwaddr addr,
157                                       unsigned size)
158 {
159     PnvHomer *homer = PNV_HOMER(opaque);
160 
161     switch (addr) {
162     case PNV9_OCC_MAX_PSTATE_ULTRA_TURBO:
163     case PNV9_OCC_PSTATE_ID_ZERO:
164         return 0;
165     case PNV9_OCC_PSTATE_DATA:
166     case PNV9_OCC_ROLE_MASTER_OR_SLAVE:
167     case PNV9_OCC_PSTATE_NOM:
168     case PNV9_OCC_PSTATE_TURBO:
169     case PNV9_OCC_PSTATE_ID_ONE:
170     case PNV9_OCC_PSTATE_ULTRA_TURBO:
171     case PNV9_OCC_OPAL_RUNTIME_DATA:
172         return 1;
173     case PNV9_OCC_PSTATE_MIN:
174     case PNV9_OCC_PSTATE_ID_TWO:
175         return 2;
176 
177     /* 3000 khz frequency for 0, 1, and 2 pstates */
178     case PNV9_OCC_PSTATE_ZERO_FREQUENCY:
179     case PNV9_OCC_PSTATE_ONE_FREQUENCY:
180     case PNV9_OCC_PSTATE_TWO_FREQUENCY:
181         return 3000;
182     case PNV9_OCC_PSTATE_MAJOR_VERSION:
183         return 0x90;
184     case PNV9_CHIP_HOMER_BASE:
185     case PNV9_OCC_PSTATE_DATA_AREA:
186     case PNV9_CHIP_HOMER_IMAGE_POINTER:
187         return 0x1000000000000000;
188     }
189     /* pstate table core max array */
190     if (core_max_array(homer, addr)) {
191         return 1;
192     }
193     return 0;
194 }
195 
196 static void pnv_power9_homer_write(void *opaque, hwaddr addr,
197                                    uint64_t val, unsigned size)
198 {
199     /* callback function defined to homer write */
200     return;
201 }
202 
203 static const MemoryRegionOps pnv_power9_homer_ops = {
204     .read = pnv_power9_homer_read,
205     .write = pnv_power9_homer_write,
206     .valid.min_access_size = 1,
207     .valid.max_access_size = 8,
208     .impl.min_access_size = 1,
209     .impl.max_access_size = 8,
210     .endianness = DEVICE_BIG_ENDIAN,
211 };
212 
213 static void pnv_homer_power9_class_init(ObjectClass *klass, void *data)
214 {
215     PnvHomerClass *homer = PNV_HOMER_CLASS(klass);
216 
217     homer->homer_size = PNV9_HOMER_SIZE;
218     homer->homer_ops = &pnv_power9_homer_ops;
219     homer->core_max_base = PNV9_CORE_MAX_BASE;
220 }
221 
222 static const TypeInfo pnv_homer_power9_type_info = {
223     .name          = TYPE_PNV9_HOMER,
224     .parent        = TYPE_PNV_HOMER,
225     .instance_size = sizeof(PnvHomer),
226     .class_init    = pnv_homer_power9_class_init,
227 };
228 
229 static void pnv_homer_realize(DeviceState *dev, Error **errp)
230 {
231     PnvHomer *homer = PNV_HOMER(dev);
232     PnvHomerClass *hmrc = PNV_HOMER_GET_CLASS(homer);
233 
234     assert(homer->chip);
235 
236     /* homer region */
237     memory_region_init_io(&homer->regs, OBJECT(dev),
238                           hmrc->homer_ops, homer, "homer-main-memory",
239                           hmrc->homer_size);
240 }
241 
242 static Property pnv_homer_properties[] = {
243     DEFINE_PROP_LINK("chip", PnvHomer, chip, TYPE_PNV_CHIP, PnvChip *),
244     DEFINE_PROP_END_OF_LIST(),
245 };
246 
247 static void pnv_homer_class_init(ObjectClass *klass, void *data)
248 {
249     DeviceClass *dc = DEVICE_CLASS(klass);
250 
251     dc->realize = pnv_homer_realize;
252     dc->desc = "PowerNV HOMER Memory";
253     dc->props = pnv_homer_properties;
254 }
255 
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),
262     .abstract      = true,
263 };
264 
265 static void pnv_homer_register_types(void)
266 {
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);
270 }
271 
272 type_init(pnv_homer_register_types);
273