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