xref: /openbmc/qemu/hw/ppc/pnv_homer.c (revision 2df1eb27)
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 "qemu/log.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_chip.h"
29 #include "hw/ppc/pnv_homer.h"
30 #include "hw/ppc/pnv_xscom.h"
31 
32 
33 static bool core_max_array(PnvHomer *homer, hwaddr addr)
34 {
35     int i;
36     PnvHomerClass *hmrc = PNV_HOMER_GET_CLASS(homer);
37 
38     for (i = 0; i <= homer->chip->nr_cores; i++) {
39         if (addr == (hmrc->core_max_base + i)) {
40             return true;
41        }
42     }
43     return false;
44 }
45 
46 /* P8 Pstate table */
47 
48 #define PNV8_OCC_PSTATE_VERSION          0x1f8001
49 #define PNV8_OCC_PSTATE_MIN              0x1f8003
50 #define PNV8_OCC_PSTATE_VALID            0x1f8000
51 #define PNV8_OCC_PSTATE_THROTTLE         0x1f8002
52 #define PNV8_OCC_PSTATE_NOM              0x1f8004
53 #define PNV8_OCC_PSTATE_TURBO            0x1f8005
54 #define PNV8_OCC_PSTATE_ULTRA_TURBO      0x1f8006
55 #define PNV8_OCC_PSTATE_DATA             0x1f8008
56 #define PNV8_OCC_PSTATE_ID_ZERO          0x1f8010
57 #define PNV8_OCC_PSTATE_ID_ONE           0x1f8018
58 #define PNV8_OCC_PSTATE_ID_TWO           0x1f8020
59 #define PNV8_OCC_VDD_VOLTAGE_IDENTIFIER  0x1f8012
60 #define PNV8_OCC_VCS_VOLTAGE_IDENTIFIER  0x1f8013
61 #define PNV8_OCC_PSTATE_ZERO_FREQUENCY   0x1f8014
62 #define PNV8_OCC_PSTATE_ONE_FREQUENCY    0x1f801c
63 #define PNV8_OCC_PSTATE_TWO_FREQUENCY    0x1f8024
64 #define PNV8_CORE_MAX_BASE               0x1f8810
65 
66 
67 static uint64_t pnv_power8_homer_read(void *opaque, hwaddr addr,
68                                       unsigned size)
69 {
70     PnvHomer *homer = PNV_HOMER(opaque);
71 
72     switch (addr) {
73     case PNV8_OCC_PSTATE_VERSION:
74     case PNV8_OCC_PSTATE_MIN:
75     case PNV8_OCC_PSTATE_ID_ZERO:
76         return 0;
77     case PNV8_OCC_PSTATE_VALID:
78     case PNV8_OCC_PSTATE_THROTTLE:
79     case PNV8_OCC_PSTATE_NOM:
80     case PNV8_OCC_PSTATE_TURBO:
81     case PNV8_OCC_PSTATE_ID_ONE:
82     case PNV8_OCC_VDD_VOLTAGE_IDENTIFIER:
83     case PNV8_OCC_VCS_VOLTAGE_IDENTIFIER:
84         return 1;
85     case PNV8_OCC_PSTATE_ULTRA_TURBO:
86     case PNV8_OCC_PSTATE_ID_TWO:
87         return 2;
88     case PNV8_OCC_PSTATE_DATA:
89         return 0x1000000000000000;
90     /* P8 frequency for 0, 1, and 2 pstates */
91     case PNV8_OCC_PSTATE_ZERO_FREQUENCY:
92     case PNV8_OCC_PSTATE_ONE_FREQUENCY:
93     case PNV8_OCC_PSTATE_TWO_FREQUENCY:
94         return 3000;
95     }
96     /* pstate table core max array */
97     if (core_max_array(homer, addr)) {
98         return 1;
99     }
100     return 0;
101 }
102 
103 static void pnv_power8_homer_write(void *opaque, hwaddr addr,
104                                    uint64_t val, unsigned size)
105 {
106     /* callback function defined to homer write */
107     return;
108 }
109 
110 static const MemoryRegionOps pnv_power8_homer_ops = {
111     .read = pnv_power8_homer_read,
112     .write = pnv_power8_homer_write,
113     .valid.min_access_size = 1,
114     .valid.max_access_size = 8,
115     .impl.min_access_size = 1,
116     .impl.max_access_size = 8,
117     .endianness = DEVICE_BIG_ENDIAN,
118 };
119 
120 /* P8 PBA BARs */
121 #define PBA_BAR0                     0x00
122 #define PBA_BAR1                     0x01
123 #define PBA_BAR2                     0x02
124 #define PBA_BAR3                     0x03
125 #define PBA_BARMASK0                 0x04
126 #define PBA_BARMASK1                 0x05
127 #define PBA_BARMASK2                 0x06
128 #define PBA_BARMASK3                 0x07
129 
130 static uint64_t pnv_homer_power8_pba_read(void *opaque, hwaddr addr,
131                                           unsigned size)
132 {
133     PnvHomer *homer = PNV_HOMER(opaque);
134     PnvChip *chip = homer->chip;
135     uint32_t reg = addr >> 3;
136     uint64_t val = 0;
137 
138     switch (reg) {
139     case PBA_BAR0:
140         val = PNV_HOMER_BASE(chip);
141         break;
142     case PBA_BARMASK0: /* P8 homer region mask */
143         val = (PNV_HOMER_SIZE - 1) & 0x300000;
144         break;
145     case PBA_BAR3: /* P8 occ common area */
146         val = PNV_OCC_COMMON_AREA_BASE;
147         break;
148     case PBA_BARMASK3: /* P8 occ common area mask */
149         val = (PNV_OCC_COMMON_AREA_SIZE - 1) & 0x700000;
150         break;
151     default:
152         qemu_log_mask(LOG_UNIMP, "PBA: read to unimplemented register: Ox%"
153                       HWADDR_PRIx "\n", addr >> 3);
154     }
155     return val;
156 }
157 
158 static void pnv_homer_power8_pba_write(void *opaque, hwaddr addr,
159                                          uint64_t val, unsigned size)
160 {
161     qemu_log_mask(LOG_UNIMP, "PBA: write to unimplemented register: Ox%"
162                   HWADDR_PRIx "\n", addr >> 3);
163 }
164 
165 static const MemoryRegionOps pnv_homer_power8_pba_ops = {
166     .read = pnv_homer_power8_pba_read,
167     .write = pnv_homer_power8_pba_write,
168     .valid.min_access_size = 8,
169     .valid.max_access_size = 8,
170     .impl.min_access_size = 8,
171     .impl.max_access_size = 8,
172     .endianness = DEVICE_BIG_ENDIAN,
173 };
174 
175 static void pnv_homer_power8_class_init(ObjectClass *klass, void *data)
176 {
177     PnvHomerClass *homer = PNV_HOMER_CLASS(klass);
178 
179     homer->pba_size = PNV_XSCOM_PBA_SIZE;
180     homer->pba_ops = &pnv_homer_power8_pba_ops;
181     homer->homer_size = PNV_HOMER_SIZE;
182     homer->homer_ops = &pnv_power8_homer_ops;
183     homer->core_max_base = PNV8_CORE_MAX_BASE;
184 }
185 
186 static const TypeInfo pnv_homer_power8_type_info = {
187     .name          = TYPE_PNV8_HOMER,
188     .parent        = TYPE_PNV_HOMER,
189     .instance_size = sizeof(PnvHomer),
190     .class_init    = pnv_homer_power8_class_init,
191 };
192 
193 /* P9 Pstate table */
194 
195 #define PNV9_OCC_PSTATE_ID_ZERO          0xe2018
196 #define PNV9_OCC_PSTATE_ID_ONE           0xe2020
197 #define PNV9_OCC_PSTATE_ID_TWO           0xe2028
198 #define PNV9_OCC_PSTATE_DATA             0xe2000
199 #define PNV9_OCC_PSTATE_DATA_AREA        0xe2008
200 #define PNV9_OCC_PSTATE_MIN              0xe2003
201 #define PNV9_OCC_PSTATE_NOM              0xe2004
202 #define PNV9_OCC_PSTATE_TURBO            0xe2005
203 #define PNV9_OCC_PSTATE_ULTRA_TURBO      0xe2818
204 #define PNV9_OCC_MAX_PSTATE_ULTRA_TURBO  0xe2006
205 #define PNV9_OCC_PSTATE_MAJOR_VERSION    0xe2001
206 #define PNV9_OCC_OPAL_RUNTIME_DATA       0xe2b85
207 #define PNV9_CHIP_HOMER_IMAGE_POINTER    0x200008
208 #define PNV9_CHIP_HOMER_BASE             0x0
209 #define PNV9_OCC_PSTATE_ZERO_FREQUENCY   0xe201c
210 #define PNV9_OCC_PSTATE_ONE_FREQUENCY    0xe2024
211 #define PNV9_OCC_PSTATE_TWO_FREQUENCY    0xe202c
212 #define PNV9_OCC_ROLE_MASTER_OR_SLAVE    0xe2002
213 #define PNV9_CORE_MAX_BASE               0xe2819
214 
215 
216 static uint64_t pnv_power9_homer_read(void *opaque, hwaddr addr,
217                                       unsigned size)
218 {
219     PnvHomer *homer = PNV_HOMER(opaque);
220 
221     switch (addr) {
222     case PNV9_OCC_MAX_PSTATE_ULTRA_TURBO:
223     case PNV9_OCC_PSTATE_ID_ZERO:
224         return 0;
225     case PNV9_OCC_PSTATE_DATA:
226     case PNV9_OCC_ROLE_MASTER_OR_SLAVE:
227     case PNV9_OCC_PSTATE_NOM:
228     case PNV9_OCC_PSTATE_TURBO:
229     case PNV9_OCC_PSTATE_ID_ONE:
230     case PNV9_OCC_PSTATE_ULTRA_TURBO:
231     case PNV9_OCC_OPAL_RUNTIME_DATA:
232         return 1;
233     case PNV9_OCC_PSTATE_MIN:
234     case PNV9_OCC_PSTATE_ID_TWO:
235         return 2;
236 
237     /* 3000 khz frequency for 0, 1, and 2 pstates */
238     case PNV9_OCC_PSTATE_ZERO_FREQUENCY:
239     case PNV9_OCC_PSTATE_ONE_FREQUENCY:
240     case PNV9_OCC_PSTATE_TWO_FREQUENCY:
241         return 3000;
242     case PNV9_OCC_PSTATE_MAJOR_VERSION:
243         return 0x90;
244     case PNV9_CHIP_HOMER_BASE:
245     case PNV9_OCC_PSTATE_DATA_AREA:
246     case PNV9_CHIP_HOMER_IMAGE_POINTER:
247         return 0x1000000000000000;
248     }
249     /* pstate table core max array */
250     if (core_max_array(homer, addr)) {
251         return 1;
252     }
253     return 0;
254 }
255 
256 static void pnv_power9_homer_write(void *opaque, hwaddr addr,
257                                    uint64_t val, unsigned size)
258 {
259     /* callback function defined to homer write */
260     return;
261 }
262 
263 static const MemoryRegionOps pnv_power9_homer_ops = {
264     .read = pnv_power9_homer_read,
265     .write = pnv_power9_homer_write,
266     .valid.min_access_size = 1,
267     .valid.max_access_size = 8,
268     .impl.min_access_size = 1,
269     .impl.max_access_size = 8,
270     .endianness = DEVICE_BIG_ENDIAN,
271 };
272 
273 static uint64_t pnv_homer_power9_pba_read(void *opaque, hwaddr addr,
274                                           unsigned size)
275 {
276     PnvHomer *homer = PNV_HOMER(opaque);
277     PnvChip *chip = homer->chip;
278     uint32_t reg = addr >> 3;
279     uint64_t val = 0;
280 
281     switch (reg) {
282     case PBA_BAR0:
283         val = PNV9_HOMER_BASE(chip);
284         break;
285     case PBA_BARMASK0: /* P9 homer region mask */
286         val = (PNV9_HOMER_SIZE - 1) & 0x300000;
287         break;
288     case PBA_BAR2: /* P9 occ common area */
289         val = PNV9_OCC_COMMON_AREA_BASE;
290         break;
291     case PBA_BARMASK2: /* P9 occ common area size */
292         val = (PNV9_OCC_COMMON_AREA_SIZE - 1) & 0x700000;
293         break;
294     default:
295         qemu_log_mask(LOG_UNIMP, "PBA: read to unimplemented register: Ox%"
296                       HWADDR_PRIx "\n", addr >> 3);
297     }
298     return val;
299 }
300 
301 static void pnv_homer_power9_pba_write(void *opaque, hwaddr addr,
302                                          uint64_t val, unsigned size)
303 {
304     qemu_log_mask(LOG_UNIMP, "PBA: write to unimplemented register: Ox%"
305                   HWADDR_PRIx "\n", addr >> 3);
306 }
307 
308 static const MemoryRegionOps pnv_homer_power9_pba_ops = {
309     .read = pnv_homer_power9_pba_read,
310     .write = pnv_homer_power9_pba_write,
311     .valid.min_access_size = 8,
312     .valid.max_access_size = 8,
313     .impl.min_access_size = 8,
314     .impl.max_access_size = 8,
315     .endianness = DEVICE_BIG_ENDIAN,
316 };
317 
318 static void pnv_homer_power9_class_init(ObjectClass *klass, void *data)
319 {
320     PnvHomerClass *homer = PNV_HOMER_CLASS(klass);
321 
322     homer->pba_size = PNV9_XSCOM_PBA_SIZE;
323     homer->pba_ops = &pnv_homer_power9_pba_ops;
324     homer->homer_size = PNV9_HOMER_SIZE;
325     homer->homer_ops = &pnv_power9_homer_ops;
326     homer->core_max_base = PNV9_CORE_MAX_BASE;
327 }
328 
329 static const TypeInfo pnv_homer_power9_type_info = {
330     .name          = TYPE_PNV9_HOMER,
331     .parent        = TYPE_PNV_HOMER,
332     .instance_size = sizeof(PnvHomer),
333     .class_init    = pnv_homer_power9_class_init,
334 };
335 
336 static uint64_t pnv_homer_power10_pba_read(void *opaque, hwaddr addr,
337                                           unsigned size)
338 {
339     PnvHomer *homer = PNV_HOMER(opaque);
340     PnvChip *chip = homer->chip;
341     uint32_t reg = addr >> 3;
342     uint64_t val = 0;
343 
344     switch (reg) {
345     case PBA_BAR0:
346         val = PNV10_HOMER_BASE(chip);
347         break;
348     case PBA_BARMASK0: /* P10 homer region mask */
349         val = (PNV10_HOMER_SIZE - 1) & 0x300000;
350         break;
351     case PBA_BAR2: /* P10 occ common area */
352         val = PNV10_OCC_COMMON_AREA_BASE;
353         break;
354     case PBA_BARMASK2: /* P10 occ common area size */
355         val = (PNV10_OCC_COMMON_AREA_SIZE - 1) & 0x700000;
356         break;
357     default:
358         qemu_log_mask(LOG_UNIMP, "PBA: read to unimplemented register: Ox%"
359                       HWADDR_PRIx "\n", addr >> 3);
360     }
361     return val;
362 }
363 
364 static void pnv_homer_power10_pba_write(void *opaque, hwaddr addr,
365                                          uint64_t val, unsigned size)
366 {
367     qemu_log_mask(LOG_UNIMP, "PBA: write to unimplemented register: Ox%"
368                   HWADDR_PRIx "\n", addr >> 3);
369 }
370 
371 static const MemoryRegionOps pnv_homer_power10_pba_ops = {
372     .read = pnv_homer_power10_pba_read,
373     .write = pnv_homer_power10_pba_write,
374     .valid.min_access_size = 8,
375     .valid.max_access_size = 8,
376     .impl.min_access_size = 8,
377     .impl.max_access_size = 8,
378     .endianness = DEVICE_BIG_ENDIAN,
379 };
380 
381 static void pnv_homer_power10_class_init(ObjectClass *klass, void *data)
382 {
383     PnvHomerClass *homer = PNV_HOMER_CLASS(klass);
384 
385     homer->pba_size = PNV10_XSCOM_PBA_SIZE;
386     homer->pba_ops = &pnv_homer_power10_pba_ops;
387     homer->homer_size = PNV10_HOMER_SIZE;
388     homer->homer_ops = &pnv_power9_homer_ops; /* TODO */
389     homer->core_max_base = PNV9_CORE_MAX_BASE;
390 }
391 
392 static const TypeInfo pnv_homer_power10_type_info = {
393     .name          = TYPE_PNV10_HOMER,
394     .parent        = TYPE_PNV_HOMER,
395     .instance_size = sizeof(PnvHomer),
396     .class_init    = pnv_homer_power10_class_init,
397 };
398 
399 static void pnv_homer_realize(DeviceState *dev, Error **errp)
400 {
401     PnvHomer *homer = PNV_HOMER(dev);
402     PnvHomerClass *hmrc = PNV_HOMER_GET_CLASS(homer);
403 
404     assert(homer->chip);
405 
406     pnv_xscom_region_init(&homer->pba_regs, OBJECT(dev), hmrc->pba_ops,
407                           homer, "xscom-pba", hmrc->pba_size);
408 
409     /* homer region */
410     memory_region_init_io(&homer->regs, OBJECT(dev),
411                           hmrc->homer_ops, homer, "homer-main-memory",
412                           hmrc->homer_size);
413 }
414 
415 static Property pnv_homer_properties[] = {
416     DEFINE_PROP_LINK("chip", PnvHomer, chip, TYPE_PNV_CHIP, PnvChip *),
417     DEFINE_PROP_END_OF_LIST(),
418 };
419 
420 static void pnv_homer_class_init(ObjectClass *klass, void *data)
421 {
422     DeviceClass *dc = DEVICE_CLASS(klass);
423 
424     dc->realize = pnv_homer_realize;
425     dc->desc = "PowerNV HOMER Memory";
426     device_class_set_props(dc, pnv_homer_properties);
427     dc->user_creatable = false;
428 }
429 
430 static const TypeInfo pnv_homer_type_info = {
431     .name          = TYPE_PNV_HOMER,
432     .parent        = TYPE_DEVICE,
433     .instance_size = sizeof(PnvHomer),
434     .class_init    = pnv_homer_class_init,
435     .class_size    = sizeof(PnvHomerClass),
436     .abstract      = true,
437 };
438 
439 static void pnv_homer_register_types(void)
440 {
441     type_register_static(&pnv_homer_type_info);
442     type_register_static(&pnv_homer_power8_type_info);
443     type_register_static(&pnv_homer_power9_type_info);
444     type_register_static(&pnv_homer_power10_type_info);
445 }
446 
447 type_init(pnv_homer_register_types);
448