xref: /qemu/hw/ppc/pnv_homer.c (revision f64766976d39fbf2b81a25b5c5f043180383d408)
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