xref: /openbmc/qemu/hw/ppc/pnv_homer.c (revision b91a0fa7)
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_homer.h"
29 #include "hw/ppc/pnv_xscom.h"
30 
31 
32 static bool core_max_array(PnvHomer *homer, hwaddr addr)
33 {
34     int i;
35     PnvHomerClass *hmrc = PNV_HOMER_GET_CLASS(homer);
36 
37     for (i = 0; i <= homer->chip->nr_cores; i++) {
38         if (addr == (hmrc->core_max_base + i)) {
39             return true;
40        }
41     }
42     return false;
43 }
44 
45 /* P8 Pstate table */
46 
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
64 
65 
66 static uint64_t pnv_power8_homer_read(void *opaque, hwaddr addr,
67                                       unsigned size)
68 {
69     PnvHomer *homer = PNV_HOMER(opaque);
70 
71     switch (addr) {
72     case PNV8_OCC_PSTATE_VERSION:
73     case PNV8_OCC_PSTATE_MIN:
74     case PNV8_OCC_PSTATE_ID_ZERO:
75         return 0;
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:
83         return 1;
84     case PNV8_OCC_PSTATE_ULTRA_TURBO:
85     case PNV8_OCC_PSTATE_ID_TWO:
86         return 2;
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:
93         return 3000;
94     }
95     /* pstate table core max array */
96     if (core_max_array(homer, addr)) {
97         return 1;
98     }
99     return 0;
100 }
101 
102 static void pnv_power8_homer_write(void *opaque, hwaddr addr,
103                                    uint64_t val, unsigned size)
104 {
105     /* callback function defined to homer write */
106     return;
107 }
108 
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,
117 };
118 
119 /* P8 PBA BARs */
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
128 
129 static uint64_t pnv_homer_power8_pba_read(void *opaque, hwaddr addr,
130                                           unsigned size)
131 {
132     PnvHomer *homer = PNV_HOMER(opaque);
133     PnvChip *chip = homer->chip;
134     uint32_t reg = addr >> 3;
135     uint64_t val = 0;
136 
137     switch (reg) {
138     case PBA_BAR0:
139         val = PNV_HOMER_BASE(chip);
140         break;
141     case PBA_BARMASK0: /* P8 homer region mask */
142         val = (PNV_HOMER_SIZE - 1) & 0x300000;
143         break;
144     case PBA_BAR3: /* P8 occ common area */
145         val = PNV_OCC_COMMON_AREA_BASE;
146         break;
147     case PBA_BARMASK3: /* P8 occ common area mask */
148         val = (PNV_OCC_COMMON_AREA_SIZE - 1) & 0x700000;
149         break;
150     default:
151         qemu_log_mask(LOG_UNIMP, "PBA: read to unimplemented register: Ox%"
152                       HWADDR_PRIx "\n", addr >> 3);
153     }
154     return val;
155 }
156 
157 static void pnv_homer_power8_pba_write(void *opaque, hwaddr addr,
158                                          uint64_t val, unsigned size)
159 {
160     qemu_log_mask(LOG_UNIMP, "PBA: write to unimplemented register: Ox%"
161                   HWADDR_PRIx "\n", addr >> 3);
162 }
163 
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,
172 };
173 
174 static void pnv_homer_power8_class_init(ObjectClass *klass, void *data)
175 {
176     PnvHomerClass *homer = PNV_HOMER_CLASS(klass);
177 
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;
183 }
184 
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,
190 };
191 
192 /* P9 Pstate table */
193 
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
213 
214 
215 static uint64_t pnv_power9_homer_read(void *opaque, hwaddr addr,
216                                       unsigned size)
217 {
218     PnvHomer *homer = PNV_HOMER(opaque);
219 
220     switch (addr) {
221     case PNV9_OCC_MAX_PSTATE_ULTRA_TURBO:
222     case PNV9_OCC_PSTATE_ID_ZERO:
223         return 0;
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:
231         return 1;
232     case PNV9_OCC_PSTATE_MIN:
233     case PNV9_OCC_PSTATE_ID_TWO:
234         return 2;
235 
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:
240         return 3000;
241     case PNV9_OCC_PSTATE_MAJOR_VERSION:
242         return 0x90;
243     case PNV9_CHIP_HOMER_BASE:
244     case PNV9_OCC_PSTATE_DATA_AREA:
245     case PNV9_CHIP_HOMER_IMAGE_POINTER:
246         return 0x1000000000000000;
247     }
248     /* pstate table core max array */
249     if (core_max_array(homer, addr)) {
250         return 1;
251     }
252     return 0;
253 }
254 
255 static void pnv_power9_homer_write(void *opaque, hwaddr addr,
256                                    uint64_t val, unsigned size)
257 {
258     /* callback function defined to homer write */
259     return;
260 }
261 
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,
270 };
271 
272 static uint64_t pnv_homer_power9_pba_read(void *opaque, hwaddr addr,
273                                           unsigned size)
274 {
275     PnvHomer *homer = PNV_HOMER(opaque);
276     PnvChip *chip = homer->chip;
277     uint32_t reg = addr >> 3;
278     uint64_t val = 0;
279 
280     switch (reg) {
281     case PBA_BAR0:
282         val = PNV9_HOMER_BASE(chip);
283         break;
284     case PBA_BARMASK0: /* P9 homer region mask */
285         val = (PNV9_HOMER_SIZE - 1) & 0x300000;
286         break;
287     case PBA_BAR2: /* P9 occ common area */
288         val = PNV9_OCC_COMMON_AREA_BASE;
289         break;
290     case PBA_BARMASK2: /* P9 occ common area size */
291         val = (PNV9_OCC_COMMON_AREA_SIZE - 1) & 0x700000;
292         break;
293     default:
294         qemu_log_mask(LOG_UNIMP, "PBA: read to unimplemented register: Ox%"
295                       HWADDR_PRIx "\n", addr >> 3);
296     }
297     return val;
298 }
299 
300 static void pnv_homer_power9_pba_write(void *opaque, hwaddr addr,
301                                          uint64_t val, unsigned size)
302 {
303     qemu_log_mask(LOG_UNIMP, "PBA: write to unimplemented register: Ox%"
304                   HWADDR_PRIx "\n", addr >> 3);
305 }
306 
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,
315 };
316 
317 static void pnv_homer_power9_class_init(ObjectClass *klass, void *data)
318 {
319     PnvHomerClass *homer = PNV_HOMER_CLASS(klass);
320 
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;
326 }
327 
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,
333 };
334 
335 static void pnv_homer_realize(DeviceState *dev, Error **errp)
336 {
337     PnvHomer *homer = PNV_HOMER(dev);
338     PnvHomerClass *hmrc = PNV_HOMER_GET_CLASS(homer);
339 
340     assert(homer->chip);
341 
342     pnv_xscom_region_init(&homer->pba_regs, OBJECT(dev), hmrc->pba_ops,
343                           homer, "xscom-pba", hmrc->pba_size);
344 
345     /* homer region */
346     memory_region_init_io(&homer->regs, OBJECT(dev),
347                           hmrc->homer_ops, homer, "homer-main-memory",
348                           hmrc->homer_size);
349 }
350 
351 static Property pnv_homer_properties[] = {
352     DEFINE_PROP_LINK("chip", PnvHomer, chip, TYPE_PNV_CHIP, PnvChip *),
353     DEFINE_PROP_END_OF_LIST(),
354 };
355 
356 static void pnv_homer_class_init(ObjectClass *klass, void *data)
357 {
358     DeviceClass *dc = DEVICE_CLASS(klass);
359 
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;
364 }
365 
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),
372     .abstract      = true,
373 };
374 
375 static void pnv_homer_register_types(void)
376 {
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);
380 }
381 
382 type_init(pnv_homer_register_types);
383