xref: /qemu/hw/ppc/pnv.c (revision 8f06e370)
19e933f4aSBenjamin Herrenschmidt /*
29e933f4aSBenjamin Herrenschmidt  * QEMU PowerPC PowerNV machine model
39e933f4aSBenjamin Herrenschmidt  *
49e933f4aSBenjamin Herrenschmidt  * Copyright (c) 2016, IBM Corporation.
59e933f4aSBenjamin Herrenschmidt  *
69e933f4aSBenjamin Herrenschmidt  * This library is free software; you can redistribute it and/or
79e933f4aSBenjamin Herrenschmidt  * modify it under the terms of the GNU Lesser General Public
89e933f4aSBenjamin Herrenschmidt  * License as published by the Free Software Foundation; either
99e933f4aSBenjamin Herrenschmidt  * version 2 of the License, or (at your option) any later version.
109e933f4aSBenjamin Herrenschmidt  *
119e933f4aSBenjamin Herrenschmidt  * This library is distributed in the hope that it will be useful,
129e933f4aSBenjamin Herrenschmidt  * but WITHOUT ANY WARRANTY; without even the implied warranty of
139e933f4aSBenjamin Herrenschmidt  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
149e933f4aSBenjamin Herrenschmidt  * Lesser General Public License for more details.
159e933f4aSBenjamin Herrenschmidt  *
169e933f4aSBenjamin Herrenschmidt  * You should have received a copy of the GNU Lesser General Public
179e933f4aSBenjamin Herrenschmidt  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
189e933f4aSBenjamin Herrenschmidt  */
199e933f4aSBenjamin Herrenschmidt 
209e933f4aSBenjamin Herrenschmidt #include "qemu/osdep.h"
21a8d25326SMarkus Armbruster #include "qemu-common.h"
22fc6b3cf9SPhilippe Mathieu-Daudé #include "qemu/units.h"
239e933f4aSBenjamin Herrenschmidt #include "qapi/error.h"
249e933f4aSBenjamin Herrenschmidt #include "sysemu/sysemu.h"
259e933f4aSBenjamin Herrenschmidt #include "sysemu/numa.h"
2671e8a915SMarkus Armbruster #include "sysemu/reset.h"
2754d31236SMarkus Armbruster #include "sysemu/runstate.h"
28d2528bdcSPaolo Bonzini #include "sysemu/cpus.h"
298d409261SCédric Le Goater #include "sysemu/device_tree.h"
30fcf5ef2aSThomas Huth #include "target/ppc/cpu.h"
319e933f4aSBenjamin Herrenschmidt #include "qemu/log.h"
329e933f4aSBenjamin Herrenschmidt #include "hw/ppc/fdt.h"
339e933f4aSBenjamin Herrenschmidt #include "hw/ppc/ppc.h"
349e933f4aSBenjamin Herrenschmidt #include "hw/ppc/pnv.h"
35d2fd9612SCédric Le Goater #include "hw/ppc/pnv_core.h"
369e933f4aSBenjamin Herrenschmidt #include "hw/loader.h"
379e933f4aSBenjamin Herrenschmidt #include "exec/address-spaces.h"
38e997040eSCédric Le Goater #include "qapi/visitor.h"
3947fea43aSCédric Le Goater #include "monitor/monitor.h"
4047fea43aSCédric Le Goater #include "hw/intc/intc.h"
41aeaef83dSCédric Le Goater #include "hw/ipmi/ipmi.h"
4258969eeeSDavid Gibson #include "target/ppc/mmu-hash64.h"
439e933f4aSBenjamin Herrenschmidt 
4436fc6f08SCédric Le Goater #include "hw/ppc/xics.h"
45a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h"
46967b7523SCédric Le Goater #include "hw/ppc/pnv_xscom.h"
4735dde576SCédric Le Goater #include "hw/ppc/pnv_pnor.h"
48967b7523SCédric Le Goater 
493495b6b6SCédric Le Goater #include "hw/isa/isa.h"
5012e9493dSMarkus Armbruster #include "hw/boards.h"
513495b6b6SCédric Le Goater #include "hw/char/serial.h"
52bcdb9064SPhilippe Mathieu-Daudé #include "hw/rtc/mc146818rtc.h"
533495b6b6SCédric Le Goater 
549e933f4aSBenjamin Herrenschmidt #include <libfdt.h>
559e933f4aSBenjamin Herrenschmidt 
56b268a616SMurilo Opsfelder Araujo #define FDT_MAX_SIZE            (1 * MiB)
579e933f4aSBenjamin Herrenschmidt 
589e933f4aSBenjamin Herrenschmidt #define FW_FILE_NAME            "skiboot.lid"
599e933f4aSBenjamin Herrenschmidt #define FW_LOAD_ADDR            0x0
60b268a616SMurilo Opsfelder Araujo #define FW_MAX_SIZE             (4 * MiB)
619e933f4aSBenjamin Herrenschmidt 
629e933f4aSBenjamin Herrenschmidt #define KERNEL_LOAD_ADDR        0x20000000
63b45b56baSMurilo Opsfelder Araujo #define KERNEL_MAX_SIZE         (256 * MiB)
64fef592f9SCédric Le Goater #define INITRD_LOAD_ADDR        0x60000000
65584ea7e7SMurilo Opsfelder Araujo #define INITRD_MAX_SIZE         (256 * MiB)
669e933f4aSBenjamin Herrenschmidt 
6740abf43fSIgor Mammedov static const char *pnv_chip_core_typename(const PnvChip *o)
6840abf43fSIgor Mammedov {
6940abf43fSIgor Mammedov     const char *chip_type = object_class_get_name(object_get_class(OBJECT(o)));
7040abf43fSIgor Mammedov     int len = strlen(chip_type) - strlen(PNV_CHIP_TYPE_SUFFIX);
7140abf43fSIgor Mammedov     char *s = g_strdup_printf(PNV_CORE_TYPE_NAME("%.*s"), len, chip_type);
7240abf43fSIgor Mammedov     const char *core_type = object_class_get_name(object_class_by_name(s));
7340abf43fSIgor Mammedov     g_free(s);
7440abf43fSIgor Mammedov     return core_type;
7540abf43fSIgor Mammedov }
7640abf43fSIgor Mammedov 
779e933f4aSBenjamin Herrenschmidt /*
789e933f4aSBenjamin Herrenschmidt  * On Power Systems E880 (POWER8), the max cpus (threads) should be :
799e933f4aSBenjamin Herrenschmidt  *     4 * 4 sockets * 12 cores * 8 threads = 1536
809e933f4aSBenjamin Herrenschmidt  * Let's make it 2^11
819e933f4aSBenjamin Herrenschmidt  */
829e933f4aSBenjamin Herrenschmidt #define MAX_CPUS                2048
839e933f4aSBenjamin Herrenschmidt 
849e933f4aSBenjamin Herrenschmidt /*
859e933f4aSBenjamin Herrenschmidt  * Memory nodes are created by hostboot, one for each range of memory
869e933f4aSBenjamin Herrenschmidt  * that has a different "affinity". In practice, it means one range
879e933f4aSBenjamin Herrenschmidt  * per chip.
889e933f4aSBenjamin Herrenschmidt  */
89b168a138SCédric Le Goater static void pnv_dt_memory(void *fdt, int chip_id, hwaddr start, hwaddr size)
909e933f4aSBenjamin Herrenschmidt {
919e933f4aSBenjamin Herrenschmidt     char *mem_name;
929e933f4aSBenjamin Herrenschmidt     uint64_t mem_reg_property[2];
939e933f4aSBenjamin Herrenschmidt     int off;
949e933f4aSBenjamin Herrenschmidt 
959e933f4aSBenjamin Herrenschmidt     mem_reg_property[0] = cpu_to_be64(start);
969e933f4aSBenjamin Herrenschmidt     mem_reg_property[1] = cpu_to_be64(size);
979e933f4aSBenjamin Herrenschmidt 
989e933f4aSBenjamin Herrenschmidt     mem_name = g_strdup_printf("memory@%"HWADDR_PRIx, start);
999e933f4aSBenjamin Herrenschmidt     off = fdt_add_subnode(fdt, 0, mem_name);
1009e933f4aSBenjamin Herrenschmidt     g_free(mem_name);
1019e933f4aSBenjamin Herrenschmidt 
1029e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_string(fdt, off, "device_type", "memory")));
1039e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property,
1049e933f4aSBenjamin Herrenschmidt                        sizeof(mem_reg_property))));
1059e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_cell(fdt, off, "ibm,chip-id", chip_id)));
1069e933f4aSBenjamin Herrenschmidt }
1079e933f4aSBenjamin Herrenschmidt 
108d2fd9612SCédric Le Goater static int get_cpus_node(void *fdt)
109d2fd9612SCédric Le Goater {
110d2fd9612SCédric Le Goater     int cpus_offset = fdt_path_offset(fdt, "/cpus");
111d2fd9612SCédric Le Goater 
112d2fd9612SCédric Le Goater     if (cpus_offset < 0) {
113a4f3885cSGreg Kurz         cpus_offset = fdt_add_subnode(fdt, 0, "cpus");
114d2fd9612SCédric Le Goater         if (cpus_offset) {
115d2fd9612SCédric Le Goater             _FDT((fdt_setprop_cell(fdt, cpus_offset, "#address-cells", 0x1)));
116d2fd9612SCédric Le Goater             _FDT((fdt_setprop_cell(fdt, cpus_offset, "#size-cells", 0x0)));
117d2fd9612SCédric Le Goater         }
118d2fd9612SCédric Le Goater     }
119d2fd9612SCédric Le Goater     _FDT(cpus_offset);
120d2fd9612SCédric Le Goater     return cpus_offset;
121d2fd9612SCédric Le Goater }
122d2fd9612SCédric Le Goater 
123d2fd9612SCédric Le Goater /*
124d2fd9612SCédric Le Goater  * The PowerNV cores (and threads) need to use real HW ids and not an
125d2fd9612SCédric Le Goater  * incremental index like it has been done on other platforms. This HW
126d2fd9612SCédric Le Goater  * id is stored in the CPU PIR, it is used to create cpu nodes in the
127d2fd9612SCédric Le Goater  * device tree, used in XSCOM to address cores and in interrupt
128d2fd9612SCédric Le Goater  * servers.
129d2fd9612SCédric Le Goater  */
130b168a138SCédric Le Goater static void pnv_dt_core(PnvChip *chip, PnvCore *pc, void *fdt)
131d2fd9612SCédric Le Goater {
13208304a86SDavid Gibson     PowerPCCPU *cpu = pc->threads[0];
13308304a86SDavid Gibson     CPUState *cs = CPU(cpu);
134d2fd9612SCédric Le Goater     DeviceClass *dc = DEVICE_GET_CLASS(cs);
1358bd9530eSDavid Gibson     int smt_threads = CPU_CORE(pc)->nr_threads;
136d2fd9612SCédric Le Goater     CPUPPCState *env = &cpu->env;
137d2fd9612SCédric Le Goater     PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs);
138d2fd9612SCédric Le Goater     uint32_t servers_prop[smt_threads];
139d2fd9612SCédric Le Goater     int i;
140d2fd9612SCédric Le Goater     uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40),
141d2fd9612SCédric Le Goater                        0xffffffff, 0xffffffff};
142d2fd9612SCédric Le Goater     uint32_t tbfreq = PNV_TIMEBASE_FREQ;
143d2fd9612SCédric Le Goater     uint32_t cpufreq = 1000000000;
144d2fd9612SCédric Le Goater     uint32_t page_sizes_prop[64];
145d2fd9612SCédric Le Goater     size_t page_sizes_prop_size;
146d2fd9612SCédric Le Goater     const uint8_t pa_features[] = { 24, 0,
147d2fd9612SCédric Le Goater                                     0xf6, 0x3f, 0xc7, 0xc0, 0x80, 0xf0,
148d2fd9612SCédric Le Goater                                     0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
149d2fd9612SCédric Le Goater                                     0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
150d2fd9612SCédric Le Goater                                     0x80, 0x00, 0x80, 0x00, 0x80, 0x00 };
151d2fd9612SCédric Le Goater     int offset;
152d2fd9612SCédric Le Goater     char *nodename;
153d2fd9612SCédric Le Goater     int cpus_offset = get_cpus_node(fdt);
154d2fd9612SCédric Le Goater 
155d2fd9612SCédric Le Goater     nodename = g_strdup_printf("%s@%x", dc->fw_name, pc->pir);
156d2fd9612SCédric Le Goater     offset = fdt_add_subnode(fdt, cpus_offset, nodename);
157d2fd9612SCédric Le Goater     _FDT(offset);
158d2fd9612SCédric Le Goater     g_free(nodename);
159d2fd9612SCédric Le Goater 
160d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id", chip->chip_id)));
161d2fd9612SCédric Le Goater 
162d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "reg", pc->pir)));
163d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "ibm,pir", pc->pir)));
164d2fd9612SCédric Le Goater     _FDT((fdt_setprop_string(fdt, offset, "device_type", "cpu")));
165d2fd9612SCédric Le Goater 
166d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "cpu-version", env->spr[SPR_PVR])));
167d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "d-cache-block-size",
168d2fd9612SCédric Le Goater                             env->dcache_line_size)));
169d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "d-cache-line-size",
170d2fd9612SCédric Le Goater                             env->dcache_line_size)));
171d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "i-cache-block-size",
172d2fd9612SCédric Le Goater                             env->icache_line_size)));
173d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "i-cache-line-size",
174d2fd9612SCédric Le Goater                             env->icache_line_size)));
175d2fd9612SCédric Le Goater 
176d2fd9612SCédric Le Goater     if (pcc->l1_dcache_size) {
177d2fd9612SCédric Le Goater         _FDT((fdt_setprop_cell(fdt, offset, "d-cache-size",
178d2fd9612SCédric Le Goater                                pcc->l1_dcache_size)));
179d2fd9612SCédric Le Goater     } else {
1803dc6f869SAlistair Francis         warn_report("Unknown L1 dcache size for cpu");
181d2fd9612SCédric Le Goater     }
182d2fd9612SCédric Le Goater     if (pcc->l1_icache_size) {
183d2fd9612SCédric Le Goater         _FDT((fdt_setprop_cell(fdt, offset, "i-cache-size",
184d2fd9612SCédric Le Goater                                pcc->l1_icache_size)));
185d2fd9612SCédric Le Goater     } else {
1863dc6f869SAlistair Francis         warn_report("Unknown L1 icache size for cpu");
187d2fd9612SCédric Le Goater     }
188d2fd9612SCédric Le Goater 
189d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "timebase-frequency", tbfreq)));
190d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "clock-frequency", cpufreq)));
19159b7c1c2SBalamuruhan S     _FDT((fdt_setprop_cell(fdt, offset, "ibm,slb-size",
19259b7c1c2SBalamuruhan S                            cpu->hash64_opts->slb_size)));
193d2fd9612SCédric Le Goater     _FDT((fdt_setprop_string(fdt, offset, "status", "okay")));
194d2fd9612SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "64-bit", NULL, 0)));
195d2fd9612SCédric Le Goater 
196d2fd9612SCédric Le Goater     if (env->spr_cb[SPR_PURR].oea_read) {
197d2fd9612SCédric Le Goater         _FDT((fdt_setprop(fdt, offset, "ibm,purr", NULL, 0)));
198d2fd9612SCédric Le Goater     }
199d2fd9612SCédric Le Goater 
20058969eeeSDavid Gibson     if (ppc_hash64_has(cpu, PPC_HASH64_1TSEG)) {
201d2fd9612SCédric Le Goater         _FDT((fdt_setprop(fdt, offset, "ibm,processor-segment-sizes",
202d2fd9612SCédric Le Goater                            segs, sizeof(segs))));
203d2fd9612SCédric Le Goater     }
204d2fd9612SCédric Le Goater 
20559b7c1c2SBalamuruhan S     /*
20659b7c1c2SBalamuruhan S      * Advertise VMX/VSX (vector extensions) if available
207d2fd9612SCédric Le Goater      *   0 / no property == no vector extensions
208d2fd9612SCédric Le Goater      *   1               == VMX / Altivec available
20959b7c1c2SBalamuruhan S      *   2               == VSX available
21059b7c1c2SBalamuruhan S      */
211d2fd9612SCédric Le Goater     if (env->insns_flags & PPC_ALTIVEC) {
212d2fd9612SCédric Le Goater         uint32_t vmx = (env->insns_flags2 & PPC2_VSX) ? 2 : 1;
213d2fd9612SCédric Le Goater 
214d2fd9612SCédric Le Goater         _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", vmx)));
215d2fd9612SCédric Le Goater     }
216d2fd9612SCédric Le Goater 
21759b7c1c2SBalamuruhan S     /*
21859b7c1c2SBalamuruhan S      * Advertise DFP (Decimal Floating Point) if available
219d2fd9612SCédric Le Goater      *   0 / no property == no DFP
22059b7c1c2SBalamuruhan S      *   1               == DFP available
22159b7c1c2SBalamuruhan S      */
222d2fd9612SCédric Le Goater     if (env->insns_flags2 & PPC2_DFP) {
223d2fd9612SCédric Le Goater         _FDT((fdt_setprop_cell(fdt, offset, "ibm,dfp", 1)));
224d2fd9612SCédric Le Goater     }
225d2fd9612SCédric Le Goater 
226644a2c99SDavid Gibson     page_sizes_prop_size = ppc_create_page_sizes_prop(cpu, page_sizes_prop,
227d2fd9612SCédric Le Goater                                                       sizeof(page_sizes_prop));
228d2fd9612SCédric Le Goater     if (page_sizes_prop_size) {
229d2fd9612SCédric Le Goater         _FDT((fdt_setprop(fdt, offset, "ibm,segment-page-sizes",
230d2fd9612SCédric Le Goater                            page_sizes_prop, page_sizes_prop_size)));
231d2fd9612SCédric Le Goater     }
232d2fd9612SCédric Le Goater 
233d2fd9612SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "ibm,pa-features",
234d2fd9612SCédric Le Goater                        pa_features, sizeof(pa_features))));
235d2fd9612SCédric Le Goater 
236d2fd9612SCédric Le Goater     /* Build interrupt servers properties */
237d2fd9612SCédric Le Goater     for (i = 0; i < smt_threads; i++) {
238d2fd9612SCédric Le Goater         servers_prop[i] = cpu_to_be32(pc->pir + i);
239d2fd9612SCédric Le Goater     }
240d2fd9612SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "ibm,ppc-interrupt-server#s",
241d2fd9612SCédric Le Goater                        servers_prop, sizeof(servers_prop))));
242d2fd9612SCédric Le Goater }
243d2fd9612SCédric Le Goater 
244b168a138SCédric Le Goater static void pnv_dt_icp(PnvChip *chip, void *fdt, uint32_t pir,
245bf5615e7SCédric Le Goater                        uint32_t nr_threads)
246bf5615e7SCédric Le Goater {
247bf5615e7SCédric Le Goater     uint64_t addr = PNV_ICP_BASE(chip) | (pir << 12);
248bf5615e7SCédric Le Goater     char *name;
249bf5615e7SCédric Le Goater     const char compat[] = "IBM,power8-icp\0IBM,ppc-xicp";
250bf5615e7SCédric Le Goater     uint32_t irange[2], i, rsize;
251bf5615e7SCédric Le Goater     uint64_t *reg;
252bf5615e7SCédric Le Goater     int offset;
253bf5615e7SCédric Le Goater 
254bf5615e7SCédric Le Goater     irange[0] = cpu_to_be32(pir);
255bf5615e7SCédric Le Goater     irange[1] = cpu_to_be32(nr_threads);
256bf5615e7SCédric Le Goater 
257bf5615e7SCédric Le Goater     rsize = sizeof(uint64_t) * 2 * nr_threads;
258bf5615e7SCédric Le Goater     reg = g_malloc(rsize);
259bf5615e7SCédric Le Goater     for (i = 0; i < nr_threads; i++) {
260bf5615e7SCédric Le Goater         reg[i * 2] = cpu_to_be64(addr | ((pir + i) * 0x1000));
261bf5615e7SCédric Le Goater         reg[i * 2 + 1] = cpu_to_be64(0x1000);
262bf5615e7SCédric Le Goater     }
263bf5615e7SCédric Le Goater 
264bf5615e7SCédric Le Goater     name = g_strdup_printf("interrupt-controller@%"PRIX64, addr);
265bf5615e7SCédric Le Goater     offset = fdt_add_subnode(fdt, 0, name);
266bf5615e7SCédric Le Goater     _FDT(offset);
267bf5615e7SCédric Le Goater     g_free(name);
268bf5615e7SCédric Le Goater 
269bf5615e7SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "compatible", compat, sizeof(compat))));
270bf5615e7SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "reg", reg, rsize)));
271bf5615e7SCédric Le Goater     _FDT((fdt_setprop_string(fdt, offset, "device_type",
272bf5615e7SCédric Le Goater                               "PowerPC-External-Interrupt-Presentation")));
273bf5615e7SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "interrupt-controller", NULL, 0)));
274bf5615e7SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "ibm,interrupt-server-ranges",
275bf5615e7SCédric Le Goater                        irange, sizeof(irange))));
276bf5615e7SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "#interrupt-cells", 1)));
277bf5615e7SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "#address-cells", 0)));
278bf5615e7SCédric Le Goater     g_free(reg);
279bf5615e7SCédric Le Goater }
280bf5615e7SCédric Le Goater 
281eb859a27SCédric Le Goater static void pnv_chip_power8_dt_populate(PnvChip *chip, void *fdt)
282e997040eSCédric Le Goater {
283c396c58aSGreg Kurz     static const char compat[] = "ibm,power8-xscom\0ibm,xscom";
284d2fd9612SCédric Le Goater     int i;
285d2fd9612SCédric Le Goater 
2863f5b45caSGreg Kurz     pnv_dt_xscom(chip, fdt, 0,
2873f5b45caSGreg Kurz                  cpu_to_be64(PNV_XSCOM_BASE(chip)),
288c396c58aSGreg Kurz                  cpu_to_be64(PNV_XSCOM_SIZE),
289c396c58aSGreg Kurz                  compat, sizeof(compat));
290967b7523SCédric Le Goater 
291d2fd9612SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
2924fa28f23SGreg Kurz         PnvCore *pnv_core = chip->cores[i];
293d2fd9612SCédric Le Goater 
294b168a138SCédric Le Goater         pnv_dt_core(chip, pnv_core, fdt);
295bf5615e7SCédric Le Goater 
296bf5615e7SCédric Le Goater         /* Interrupt Control Presenters (ICP). One per core. */
297b168a138SCédric Le Goater         pnv_dt_icp(chip, fdt, pnv_core->pir, CPU_CORE(pnv_core)->nr_threads);
298d2fd9612SCédric Le Goater     }
299d2fd9612SCédric Le Goater 
300e997040eSCédric Le Goater     if (chip->ram_size) {
301b168a138SCédric Le Goater         pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size);
302e997040eSCédric Le Goater     }
303e997040eSCédric Le Goater }
304e997040eSCédric Le Goater 
305eb859a27SCédric Le Goater static void pnv_chip_power9_dt_populate(PnvChip *chip, void *fdt)
306eb859a27SCédric Le Goater {
307c396c58aSGreg Kurz     static const char compat[] = "ibm,power9-xscom\0ibm,xscom";
308eb859a27SCédric Le Goater     int i;
309eb859a27SCédric Le Goater 
3103f5b45caSGreg Kurz     pnv_dt_xscom(chip, fdt, 0,
3113f5b45caSGreg Kurz                  cpu_to_be64(PNV9_XSCOM_BASE(chip)),
312c396c58aSGreg Kurz                  cpu_to_be64(PNV9_XSCOM_SIZE),
313c396c58aSGreg Kurz                  compat, sizeof(compat));
314eb859a27SCédric Le Goater 
315eb859a27SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
3164fa28f23SGreg Kurz         PnvCore *pnv_core = chip->cores[i];
317eb859a27SCédric Le Goater 
318eb859a27SCédric Le Goater         pnv_dt_core(chip, pnv_core, fdt);
319eb859a27SCédric Le Goater     }
320eb859a27SCédric Le Goater 
321eb859a27SCédric Le Goater     if (chip->ram_size) {
322eb859a27SCédric Le Goater         pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size);
323eb859a27SCédric Le Goater     }
32415376c66SCédric Le Goater 
3252661f6abSCédric Le Goater     pnv_dt_lpc(chip, fdt, 0, PNV9_LPCM_BASE(chip), PNV9_LPCM_SIZE);
326eb859a27SCédric Le Goater }
327eb859a27SCédric Le Goater 
3282b548a42SCédric Le Goater static void pnv_chip_power10_dt_populate(PnvChip *chip, void *fdt)
3292b548a42SCédric Le Goater {
330c396c58aSGreg Kurz     static const char compat[] = "ibm,power10-xscom\0ibm,xscom";
3312b548a42SCédric Le Goater     int i;
3322b548a42SCédric Le Goater 
3333f5b45caSGreg Kurz     pnv_dt_xscom(chip, fdt, 0,
3343f5b45caSGreg Kurz                  cpu_to_be64(PNV10_XSCOM_BASE(chip)),
335c396c58aSGreg Kurz                  cpu_to_be64(PNV10_XSCOM_SIZE),
336c396c58aSGreg Kurz                  compat, sizeof(compat));
3372b548a42SCédric Le Goater 
3382b548a42SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
3392b548a42SCédric Le Goater         PnvCore *pnv_core = chip->cores[i];
3402b548a42SCédric Le Goater 
3412b548a42SCédric Le Goater         pnv_dt_core(chip, pnv_core, fdt);
3422b548a42SCédric Le Goater     }
3432b548a42SCédric Le Goater 
3442b548a42SCédric Le Goater     if (chip->ram_size) {
3452b548a42SCédric Le Goater         pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size);
3462b548a42SCédric Le Goater     }
3472661f6abSCédric Le Goater 
3482661f6abSCédric Le Goater     pnv_dt_lpc(chip, fdt, 0, PNV10_LPCM_BASE(chip), PNV10_LPCM_SIZE);
3492b548a42SCédric Le Goater }
3502b548a42SCédric Le Goater 
351b168a138SCédric Le Goater static void pnv_dt_rtc(ISADevice *d, void *fdt, int lpc_off)
352c5ffdcaeSCédric Le Goater {
353c5ffdcaeSCédric Le Goater     uint32_t io_base = d->ioport_id;
354c5ffdcaeSCédric Le Goater     uint32_t io_regs[] = {
355c5ffdcaeSCédric Le Goater         cpu_to_be32(1),
356c5ffdcaeSCédric Le Goater         cpu_to_be32(io_base),
357c5ffdcaeSCédric Le Goater         cpu_to_be32(2)
358c5ffdcaeSCédric Le Goater     };
359c5ffdcaeSCédric Le Goater     char *name;
360c5ffdcaeSCédric Le Goater     int node;
361c5ffdcaeSCédric Le Goater 
362c5ffdcaeSCédric Le Goater     name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base);
363c5ffdcaeSCédric Le Goater     node = fdt_add_subnode(fdt, lpc_off, name);
364c5ffdcaeSCédric Le Goater     _FDT(node);
365c5ffdcaeSCédric Le Goater     g_free(name);
366c5ffdcaeSCédric Le Goater 
367c5ffdcaeSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs))));
368c5ffdcaeSCédric Le Goater     _FDT((fdt_setprop_string(fdt, node, "compatible", "pnpPNP,b00")));
369c5ffdcaeSCédric Le Goater }
370c5ffdcaeSCédric Le Goater 
371b168a138SCédric Le Goater static void pnv_dt_serial(ISADevice *d, void *fdt, int lpc_off)
372cb228f5aSCédric Le Goater {
373cb228f5aSCédric Le Goater     const char compatible[] = "ns16550\0pnpPNP,501";
374cb228f5aSCédric Le Goater     uint32_t io_base = d->ioport_id;
375cb228f5aSCédric Le Goater     uint32_t io_regs[] = {
376cb228f5aSCédric Le Goater         cpu_to_be32(1),
377cb228f5aSCédric Le Goater         cpu_to_be32(io_base),
378cb228f5aSCédric Le Goater         cpu_to_be32(8)
379cb228f5aSCédric Le Goater     };
380cb228f5aSCédric Le Goater     char *name;
381cb228f5aSCédric Le Goater     int node;
382cb228f5aSCédric Le Goater 
383cb228f5aSCédric Le Goater     name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base);
384cb228f5aSCédric Le Goater     node = fdt_add_subnode(fdt, lpc_off, name);
385cb228f5aSCédric Le Goater     _FDT(node);
386cb228f5aSCédric Le Goater     g_free(name);
387cb228f5aSCédric Le Goater 
388cb228f5aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs))));
389cb228f5aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "compatible", compatible,
390cb228f5aSCédric Le Goater                       sizeof(compatible))));
391cb228f5aSCédric Le Goater 
392cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "clock-frequency", 1843200)));
393cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "current-speed", 115200)));
394cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupts", d->isairq[0])));
395cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent",
396cb228f5aSCédric Le Goater                            fdt_get_phandle(fdt, lpc_off))));
397cb228f5aSCédric Le Goater 
398cb228f5aSCédric Le Goater     /* This is needed by Linux */
399cb228f5aSCédric Le Goater     _FDT((fdt_setprop_string(fdt, node, "device_type", "serial")));
400cb228f5aSCédric Le Goater }
401cb228f5aSCédric Le Goater 
402b168a138SCédric Le Goater static void pnv_dt_ipmi_bt(ISADevice *d, void *fdt, int lpc_off)
40304f6c8b2SCédric Le Goater {
40404f6c8b2SCédric Le Goater     const char compatible[] = "bt\0ipmi-bt";
40504f6c8b2SCédric Le Goater     uint32_t io_base;
40604f6c8b2SCédric Le Goater     uint32_t io_regs[] = {
40704f6c8b2SCédric Le Goater         cpu_to_be32(1),
40804f6c8b2SCédric Le Goater         0, /* 'io_base' retrieved from the 'ioport' property of 'isa-ipmi-bt' */
40904f6c8b2SCédric Le Goater         cpu_to_be32(3)
41004f6c8b2SCédric Le Goater     };
41104f6c8b2SCédric Le Goater     uint32_t irq;
41204f6c8b2SCédric Le Goater     char *name;
41304f6c8b2SCédric Le Goater     int node;
41404f6c8b2SCédric Le Goater 
41504f6c8b2SCédric Le Goater     io_base = object_property_get_int(OBJECT(d), "ioport", &error_fatal);
41604f6c8b2SCédric Le Goater     io_regs[1] = cpu_to_be32(io_base);
41704f6c8b2SCédric Le Goater 
41804f6c8b2SCédric Le Goater     irq = object_property_get_int(OBJECT(d), "irq", &error_fatal);
41904f6c8b2SCédric Le Goater 
42004f6c8b2SCédric Le Goater     name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base);
42104f6c8b2SCédric Le Goater     node = fdt_add_subnode(fdt, lpc_off, name);
42204f6c8b2SCédric Le Goater     _FDT(node);
42304f6c8b2SCédric Le Goater     g_free(name);
42404f6c8b2SCédric Le Goater 
4257032d92aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs))));
4267032d92aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "compatible", compatible,
4277032d92aSCédric Le Goater                       sizeof(compatible))));
42804f6c8b2SCédric Le Goater 
42904f6c8b2SCédric Le Goater     /* Mark it as reserved to avoid Linux trying to claim it */
43004f6c8b2SCédric Le Goater     _FDT((fdt_setprop_string(fdt, node, "status", "reserved")));
43104f6c8b2SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupts", irq)));
43204f6c8b2SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent",
43304f6c8b2SCédric Le Goater                            fdt_get_phandle(fdt, lpc_off))));
43404f6c8b2SCédric Le Goater }
43504f6c8b2SCédric Le Goater 
436e7a3fee3SCédric Le Goater typedef struct ForeachPopulateArgs {
437e7a3fee3SCédric Le Goater     void *fdt;
438e7a3fee3SCédric Le Goater     int offset;
439e7a3fee3SCédric Le Goater } ForeachPopulateArgs;
440e7a3fee3SCédric Le Goater 
441b168a138SCédric Le Goater static int pnv_dt_isa_device(DeviceState *dev, void *opaque)
442e7a3fee3SCédric Le Goater {
443c5ffdcaeSCédric Le Goater     ForeachPopulateArgs *args = opaque;
444c5ffdcaeSCédric Le Goater     ISADevice *d = ISA_DEVICE(dev);
445c5ffdcaeSCédric Le Goater 
446c5ffdcaeSCédric Le Goater     if (object_dynamic_cast(OBJECT(dev), TYPE_MC146818_RTC)) {
447b168a138SCédric Le Goater         pnv_dt_rtc(d, args->fdt, args->offset);
448cb228f5aSCédric Le Goater     } else if (object_dynamic_cast(OBJECT(dev), TYPE_ISA_SERIAL)) {
449b168a138SCédric Le Goater         pnv_dt_serial(d, args->fdt, args->offset);
45004f6c8b2SCédric Le Goater     } else if (object_dynamic_cast(OBJECT(dev), "isa-ipmi-bt")) {
451b168a138SCédric Le Goater         pnv_dt_ipmi_bt(d, args->fdt, args->offset);
452c5ffdcaeSCédric Le Goater     } else {
453c5ffdcaeSCédric Le Goater         error_report("unknown isa device %s@i%x", qdev_fw_name(dev),
454c5ffdcaeSCédric Le Goater                      d->ioport_id);
455c5ffdcaeSCédric Le Goater     }
456c5ffdcaeSCédric Le Goater 
457e7a3fee3SCédric Le Goater     return 0;
458e7a3fee3SCédric Le Goater }
459e7a3fee3SCédric Le Goater 
46059b7c1c2SBalamuruhan S /*
46159b7c1c2SBalamuruhan S  * The default LPC bus of a multichip system is on chip 0. It's
462bb7ab95cSCédric Le Goater  * recognized by the firmware (skiboot) using a "primary" property.
463bb7ab95cSCédric Le Goater  */
464bb7ab95cSCédric Le Goater static void pnv_dt_isa(PnvMachineState *pnv, void *fdt)
465bb7ab95cSCédric Le Goater {
46664d011d5SCédric Le Goater     int isa_offset = fdt_path_offset(fdt, pnv->chips[0]->dt_isa_nodename);
467e7a3fee3SCédric Le Goater     ForeachPopulateArgs args = {
468e7a3fee3SCédric Le Goater         .fdt = fdt,
469bb7ab95cSCédric Le Goater         .offset = isa_offset,
470e7a3fee3SCédric Le Goater     };
471f47a08d1SCédric Le Goater     uint32_t phandle;
472e7a3fee3SCédric Le Goater 
473bb7ab95cSCédric Le Goater     _FDT((fdt_setprop(fdt, isa_offset, "primary", NULL, 0)));
474bb7ab95cSCédric Le Goater 
475f47a08d1SCédric Le Goater     phandle = qemu_fdt_alloc_phandle(fdt);
476f47a08d1SCédric Le Goater     assert(phandle > 0);
477f47a08d1SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, isa_offset, "phandle", phandle)));
478f47a08d1SCédric Le Goater 
47959b7c1c2SBalamuruhan S     /*
48059b7c1c2SBalamuruhan S      * ISA devices are not necessarily parented to the ISA bus so we
48159b7c1c2SBalamuruhan S      * can not use object_child_foreach()
48259b7c1c2SBalamuruhan S      */
483bb7ab95cSCédric Le Goater     qbus_walk_children(BUS(pnv->isa_bus), pnv_dt_isa_device, NULL, NULL, NULL,
484bb7ab95cSCédric Le Goater                        &args);
485e7a3fee3SCédric Le Goater }
486e7a3fee3SCédric Le Goater 
4877a90c6a1SGreg Kurz static void pnv_dt_power_mgt(PnvMachineState *pnv, void *fdt)
488e5694793SCédric Le Goater {
489e5694793SCédric Le Goater     int off;
490e5694793SCédric Le Goater 
491e5694793SCédric Le Goater     off = fdt_add_subnode(fdt, 0, "ibm,opal");
492e5694793SCédric Le Goater     off = fdt_add_subnode(fdt, off, "power-mgt");
493e5694793SCédric Le Goater 
494e5694793SCédric Le Goater     _FDT(fdt_setprop_cell(fdt, off, "ibm,enabled-stop-levels", 0xc0000000));
495e5694793SCédric Le Goater }
496e5694793SCédric Le Goater 
497b168a138SCédric Le Goater static void *pnv_dt_create(MachineState *machine)
4989e933f4aSBenjamin Herrenschmidt {
499d76f2da7SGreg Kurz     PnvMachineClass *pmc = PNV_MACHINE_GET_CLASS(machine);
500b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(machine);
5019e933f4aSBenjamin Herrenschmidt     void *fdt;
5029e933f4aSBenjamin Herrenschmidt     char *buf;
5039e933f4aSBenjamin Herrenschmidt     int off;
504e997040eSCédric Le Goater     int i;
5059e933f4aSBenjamin Herrenschmidt 
5069e933f4aSBenjamin Herrenschmidt     fdt = g_malloc0(FDT_MAX_SIZE);
5079e933f4aSBenjamin Herrenschmidt     _FDT((fdt_create_empty_tree(fdt, FDT_MAX_SIZE)));
5089e933f4aSBenjamin Herrenschmidt 
509ccb099b3SCédric Le Goater     /* /qemu node */
510ccb099b3SCédric Le Goater     _FDT((fdt_add_subnode(fdt, 0, "qemu")));
511ccb099b3SCédric Le Goater 
5129e933f4aSBenjamin Herrenschmidt     /* Root node */
5139e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_cell(fdt, 0, "#address-cells", 0x2)));
5149e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_cell(fdt, 0, "#size-cells", 0x2)));
5159e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_string(fdt, 0, "model",
5169e933f4aSBenjamin Herrenschmidt                              "IBM PowerNV (emulated by qemu)")));
517d76f2da7SGreg Kurz     _FDT((fdt_setprop(fdt, 0, "compatible", pmc->compat, pmc->compat_size)));
5189e933f4aSBenjamin Herrenschmidt 
5199e933f4aSBenjamin Herrenschmidt     buf =  qemu_uuid_unparse_strdup(&qemu_uuid);
5209e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_string(fdt, 0, "vm,uuid", buf)));
5219e933f4aSBenjamin Herrenschmidt     if (qemu_uuid_set) {
5229e933f4aSBenjamin Herrenschmidt         _FDT((fdt_property_string(fdt, "system-id", buf)));
5239e933f4aSBenjamin Herrenschmidt     }
5249e933f4aSBenjamin Herrenschmidt     g_free(buf);
5259e933f4aSBenjamin Herrenschmidt 
5269e933f4aSBenjamin Herrenschmidt     off = fdt_add_subnode(fdt, 0, "chosen");
5279e933f4aSBenjamin Herrenschmidt     if (machine->kernel_cmdline) {
5289e933f4aSBenjamin Herrenschmidt         _FDT((fdt_setprop_string(fdt, off, "bootargs",
5299e933f4aSBenjamin Herrenschmidt                                  machine->kernel_cmdline)));
5309e933f4aSBenjamin Herrenschmidt     }
5319e933f4aSBenjamin Herrenschmidt 
5329e933f4aSBenjamin Herrenschmidt     if (pnv->initrd_size) {
5339e933f4aSBenjamin Herrenschmidt         uint32_t start_prop = cpu_to_be32(pnv->initrd_base);
5349e933f4aSBenjamin Herrenschmidt         uint32_t end_prop = cpu_to_be32(pnv->initrd_base + pnv->initrd_size);
5359e933f4aSBenjamin Herrenschmidt 
5369e933f4aSBenjamin Herrenschmidt         _FDT((fdt_setprop(fdt, off, "linux,initrd-start",
5379e933f4aSBenjamin Herrenschmidt                                &start_prop, sizeof(start_prop))));
5389e933f4aSBenjamin Herrenschmidt         _FDT((fdt_setprop(fdt, off, "linux,initrd-end",
5399e933f4aSBenjamin Herrenschmidt                                &end_prop, sizeof(end_prop))));
5409e933f4aSBenjamin Herrenschmidt     }
5419e933f4aSBenjamin Herrenschmidt 
542e997040eSCédric Le Goater     /* Populate device tree for each chip */
543e997040eSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
544eb859a27SCédric Le Goater         PNV_CHIP_GET_CLASS(pnv->chips[i])->dt_populate(pnv->chips[i], fdt);
545e997040eSCédric Le Goater     }
546e7a3fee3SCédric Le Goater 
547e7a3fee3SCédric Le Goater     /* Populate ISA devices on chip 0 */
548bb7ab95cSCédric Le Goater     pnv_dt_isa(pnv, fdt);
549aeaef83dSCédric Le Goater 
550aeaef83dSCédric Le Goater     if (pnv->bmc) {
551b168a138SCédric Le Goater         pnv_dt_bmc_sensors(pnv->bmc, fdt);
552aeaef83dSCédric Le Goater     }
553aeaef83dSCédric Le Goater 
5547a90c6a1SGreg Kurz     /* Create an extra node for power management on machines that support it */
5557a90c6a1SGreg Kurz     if (pmc->dt_power_mgt) {
5567a90c6a1SGreg Kurz         pmc->dt_power_mgt(pnv, fdt);
557e5694793SCédric Le Goater     }
558e5694793SCédric Le Goater 
5599e933f4aSBenjamin Herrenschmidt     return fdt;
5609e933f4aSBenjamin Herrenschmidt }
5619e933f4aSBenjamin Herrenschmidt 
562bce0b691SCédric Le Goater static void pnv_powerdown_notify(Notifier *n, void *opaque)
563bce0b691SCédric Le Goater {
564*8f06e370SCédric Le Goater     PnvMachineState *pnv = container_of(n, PnvMachineState, powerdown_notifier);
565bce0b691SCédric Le Goater 
566bce0b691SCédric Le Goater     if (pnv->bmc) {
567bce0b691SCédric Le Goater         pnv_bmc_powerdown(pnv->bmc);
568bce0b691SCédric Le Goater     }
569bce0b691SCédric Le Goater }
570bce0b691SCédric Le Goater 
571a0628599SLike Xu static void pnv_reset(MachineState *machine)
5729e933f4aSBenjamin Herrenschmidt {
5739e933f4aSBenjamin Herrenschmidt     void *fdt;
5749e933f4aSBenjamin Herrenschmidt 
5759e933f4aSBenjamin Herrenschmidt     qemu_devices_reset();
5769e933f4aSBenjamin Herrenschmidt 
577b168a138SCédric Le Goater     fdt = pnv_dt_create(machine);
5789e933f4aSBenjamin Herrenschmidt 
5799e933f4aSBenjamin Herrenschmidt     /* Pack resulting tree */
5809e933f4aSBenjamin Herrenschmidt     _FDT((fdt_pack(fdt)));
5819e933f4aSBenjamin Herrenschmidt 
5828d409261SCédric Le Goater     qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt));
5839e933f4aSBenjamin Herrenschmidt     cpu_physical_memory_write(PNV_FDT_ADDR, fdt, fdt_totalsize(fdt));
5849e933f4aSBenjamin Herrenschmidt }
5859e933f4aSBenjamin Herrenschmidt 
58604026890SCédric Le Goater static ISABus *pnv_chip_power8_isa_create(PnvChip *chip, Error **errp)
5873495b6b6SCédric Le Goater {
58877864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
58977864267SCédric Le Goater     return pnv_lpc_isa_create(&chip8->lpc, true, errp);
59004026890SCédric Le Goater }
5913495b6b6SCédric Le Goater 
59204026890SCédric Le Goater static ISABus *pnv_chip_power8nvl_isa_create(PnvChip *chip, Error **errp)
59304026890SCédric Le Goater {
59477864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
59577864267SCédric Le Goater     return pnv_lpc_isa_create(&chip8->lpc, false, errp);
59604026890SCédric Le Goater }
5973495b6b6SCédric Le Goater 
59804026890SCédric Le Goater static ISABus *pnv_chip_power9_isa_create(PnvChip *chip, Error **errp)
59904026890SCédric Le Goater {
60015376c66SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(chip);
60115376c66SCédric Le Goater     return pnv_lpc_isa_create(&chip9->lpc, false, errp);
60204026890SCédric Le Goater }
6033495b6b6SCédric Le Goater 
6042b548a42SCédric Le Goater static ISABus *pnv_chip_power10_isa_create(PnvChip *chip, Error **errp)
6052b548a42SCédric Le Goater {
6062661f6abSCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(chip);
6072661f6abSCédric Le Goater     return pnv_lpc_isa_create(&chip10->lpc, false, errp);
6082b548a42SCédric Le Goater }
6092b548a42SCédric Le Goater 
61004026890SCédric Le Goater static ISABus *pnv_isa_create(PnvChip *chip, Error **errp)
61104026890SCédric Le Goater {
61204026890SCédric Le Goater     return PNV_CHIP_GET_CLASS(chip)->isa_create(chip, errp);
6133495b6b6SCédric Le Goater }
6143495b6b6SCédric Le Goater 
615d8e4aad5SCédric Le Goater static void pnv_chip_power8_pic_print_info(PnvChip *chip, Monitor *mon)
616d8e4aad5SCédric Le Goater {
617d8e4aad5SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
618d8e4aad5SCédric Le Goater 
619d8e4aad5SCédric Le Goater     ics_pic_print_info(&chip8->psi.ics, mon);
620d8e4aad5SCédric Le Goater }
621d8e4aad5SCédric Le Goater 
622d8e4aad5SCédric Le Goater static void pnv_chip_power9_pic_print_info(PnvChip *chip, Monitor *mon)
623d8e4aad5SCédric Le Goater {
624d8e4aad5SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(chip);
625d8e4aad5SCédric Le Goater 
626d8e4aad5SCédric Le Goater     pnv_xive_pic_print_info(&chip9->xive, mon);
627c38536bcSCédric Le Goater     pnv_psi_pic_print_info(&chip9->psi, mon);
628d8e4aad5SCédric Le Goater }
629d8e4aad5SCédric Le Goater 
630c4b2c40cSGreg Kurz static uint64_t pnv_chip_power8_xscom_core_base(PnvChip *chip,
631c4b2c40cSGreg Kurz                                                 uint32_t core_id)
632c4b2c40cSGreg Kurz {
633c4b2c40cSGreg Kurz     return PNV_XSCOM_EX_BASE(core_id);
634c4b2c40cSGreg Kurz }
635c4b2c40cSGreg Kurz 
636c4b2c40cSGreg Kurz static uint64_t pnv_chip_power9_xscom_core_base(PnvChip *chip,
637c4b2c40cSGreg Kurz                                                 uint32_t core_id)
638c4b2c40cSGreg Kurz {
639c4b2c40cSGreg Kurz     return PNV9_XSCOM_EC_BASE(core_id);
640c4b2c40cSGreg Kurz }
641c4b2c40cSGreg Kurz 
642c4b2c40cSGreg Kurz static uint64_t pnv_chip_power10_xscom_core_base(PnvChip *chip,
643c4b2c40cSGreg Kurz                                                  uint32_t core_id)
644c4b2c40cSGreg Kurz {
645c4b2c40cSGreg Kurz     return PNV10_XSCOM_EC_BASE(core_id);
646c4b2c40cSGreg Kurz }
647c4b2c40cSGreg Kurz 
648f30c843cSCédric Le Goater static bool pnv_match_cpu(const char *default_type, const char *cpu_type)
649f30c843cSCédric Le Goater {
650f30c843cSCédric Le Goater     PowerPCCPUClass *ppc_default =
651f30c843cSCédric Le Goater         POWERPC_CPU_CLASS(object_class_by_name(default_type));
652f30c843cSCédric Le Goater     PowerPCCPUClass *ppc =
653f30c843cSCédric Le Goater         POWERPC_CPU_CLASS(object_class_by_name(cpu_type));
654f30c843cSCédric Le Goater 
655f30c843cSCédric Le Goater     return ppc_default->pvr_match(ppc_default, ppc->pvr);
656f30c843cSCédric Le Goater }
657f30c843cSCédric Le Goater 
658e2392d43SCédric Le Goater static void pnv_ipmi_bt_init(ISABus *bus, IPMIBmc *bmc, uint32_t irq)
659e2392d43SCédric Le Goater {
660e2392d43SCédric Le Goater     Object *obj;
661e2392d43SCédric Le Goater 
662e2392d43SCédric Le Goater     obj = OBJECT(isa_create(bus, "isa-ipmi-bt"));
663e2392d43SCédric Le Goater     object_property_set_link(obj, OBJECT(bmc), "bmc", &error_fatal);
664e2392d43SCédric Le Goater     object_property_set_int(obj, irq, "irq", &error_fatal);
665e2392d43SCédric Le Goater     object_property_set_bool(obj, true, "realized", &error_fatal);
666e2392d43SCédric Le Goater }
667e2392d43SCédric Le Goater 
6682b548a42SCédric Le Goater static void pnv_chip_power10_pic_print_info(PnvChip *chip, Monitor *mon)
6692b548a42SCédric Le Goater {
6708b50ce85SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(chip);
6718b50ce85SCédric Le Goater 
6728b50ce85SCédric Le Goater     pnv_psi_pic_print_info(&chip10->psi, mon);
6732b548a42SCédric Le Goater }
6742b548a42SCédric Le Goater 
675b168a138SCédric Le Goater static void pnv_init(MachineState *machine)
6769e933f4aSBenjamin Herrenschmidt {
677b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(machine);
678f30c843cSCédric Le Goater     MachineClass *mc = MACHINE_GET_CLASS(machine);
6799e933f4aSBenjamin Herrenschmidt     MemoryRegion *ram;
6809e933f4aSBenjamin Herrenschmidt     char *fw_filename;
6819e933f4aSBenjamin Herrenschmidt     long fw_size;
682e997040eSCédric Le Goater     int i;
683e997040eSCédric Le Goater     char *chip_typename;
68435dde576SCédric Le Goater     DriveInfo *pnor = drive_get(IF_MTD, 0, 0);
68535dde576SCédric Le Goater     DeviceState *dev;
6869e933f4aSBenjamin Herrenschmidt 
6879e933f4aSBenjamin Herrenschmidt     /* allocate RAM */
688d23b6caaSPhilippe Mathieu-Daudé     if (machine->ram_size < (1 * GiB)) {
6893dc6f869SAlistair Francis         warn_report("skiboot may not work with < 1GB of RAM");
6909e933f4aSBenjamin Herrenschmidt     }
6919e933f4aSBenjamin Herrenschmidt 
6929e933f4aSBenjamin Herrenschmidt     ram = g_new(MemoryRegion, 1);
693b168a138SCédric Le Goater     memory_region_allocate_system_memory(ram, NULL, "pnv.ram",
6949e933f4aSBenjamin Herrenschmidt                                          machine->ram_size);
6959e933f4aSBenjamin Herrenschmidt     memory_region_add_subregion(get_system_memory(), 0, ram);
6969e933f4aSBenjamin Herrenschmidt 
69735dde576SCédric Le Goater     /*
69835dde576SCédric Le Goater      * Create our simple PNOR device
69935dde576SCédric Le Goater      */
70035dde576SCédric Le Goater     dev = qdev_create(NULL, TYPE_PNV_PNOR);
70135dde576SCédric Le Goater     if (pnor) {
70235dde576SCédric Le Goater         qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(pnor),
70335dde576SCédric Le Goater                             &error_abort);
70435dde576SCédric Le Goater     }
70535dde576SCédric Le Goater     qdev_init_nofail(dev);
70635dde576SCédric Le Goater     pnv->pnor = PNV_PNOR(dev);
70735dde576SCédric Le Goater 
7089e933f4aSBenjamin Herrenschmidt     /* load skiboot firmware  */
7099e933f4aSBenjamin Herrenschmidt     if (bios_name == NULL) {
7109e933f4aSBenjamin Herrenschmidt         bios_name = FW_FILE_NAME;
7119e933f4aSBenjamin Herrenschmidt     }
7129e933f4aSBenjamin Herrenschmidt 
7139e933f4aSBenjamin Herrenschmidt     fw_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
71415fcedb2SCédric Le Goater     if (!fw_filename) {
71515fcedb2SCédric Le Goater         error_report("Could not find OPAL firmware '%s'", bios_name);
71615fcedb2SCédric Le Goater         exit(1);
71715fcedb2SCédric Le Goater     }
7189e933f4aSBenjamin Herrenschmidt 
7199e933f4aSBenjamin Herrenschmidt     fw_size = load_image_targphys(fw_filename, FW_LOAD_ADDR, FW_MAX_SIZE);
7209e933f4aSBenjamin Herrenschmidt     if (fw_size < 0) {
72115fcedb2SCédric Le Goater         error_report("Could not load OPAL firmware '%s'", fw_filename);
7229e933f4aSBenjamin Herrenschmidt         exit(1);
7239e933f4aSBenjamin Herrenschmidt     }
7249e933f4aSBenjamin Herrenschmidt     g_free(fw_filename);
7259e933f4aSBenjamin Herrenschmidt 
7269e933f4aSBenjamin Herrenschmidt     /* load kernel */
7279e933f4aSBenjamin Herrenschmidt     if (machine->kernel_filename) {
7289e933f4aSBenjamin Herrenschmidt         long kernel_size;
7299e933f4aSBenjamin Herrenschmidt 
7309e933f4aSBenjamin Herrenschmidt         kernel_size = load_image_targphys(machine->kernel_filename,
731b45b56baSMurilo Opsfelder Araujo                                           KERNEL_LOAD_ADDR, KERNEL_MAX_SIZE);
7329e933f4aSBenjamin Herrenschmidt         if (kernel_size < 0) {
733802fc7abSThomas Huth             error_report("Could not load kernel '%s'",
7349e933f4aSBenjamin Herrenschmidt                          machine->kernel_filename);
7359e933f4aSBenjamin Herrenschmidt             exit(1);
7369e933f4aSBenjamin Herrenschmidt         }
7379e933f4aSBenjamin Herrenschmidt     }
7389e933f4aSBenjamin Herrenschmidt 
7399e933f4aSBenjamin Herrenschmidt     /* load initrd */
7409e933f4aSBenjamin Herrenschmidt     if (machine->initrd_filename) {
7419e933f4aSBenjamin Herrenschmidt         pnv->initrd_base = INITRD_LOAD_ADDR;
7429e933f4aSBenjamin Herrenschmidt         pnv->initrd_size = load_image_targphys(machine->initrd_filename,
743584ea7e7SMurilo Opsfelder Araujo                                   pnv->initrd_base, INITRD_MAX_SIZE);
7449e933f4aSBenjamin Herrenschmidt         if (pnv->initrd_size < 0) {
745802fc7abSThomas Huth             error_report("Could not load initial ram disk '%s'",
7469e933f4aSBenjamin Herrenschmidt                          machine->initrd_filename);
7479e933f4aSBenjamin Herrenschmidt             exit(1);
7489e933f4aSBenjamin Herrenschmidt         }
7499e933f4aSBenjamin Herrenschmidt     }
750e997040eSCédric Le Goater 
751f30c843cSCédric Le Goater     /*
752f30c843cSCédric Le Goater      * Check compatibility of the specified CPU with the machine
753f30c843cSCédric Le Goater      * default.
754f30c843cSCédric Le Goater      */
755f30c843cSCédric Le Goater     if (!pnv_match_cpu(mc->default_cpu_type, machine->cpu_type)) {
756f30c843cSCédric Le Goater         error_report("invalid CPU model '%s' for %s machine",
757f30c843cSCédric Le Goater                      machine->cpu_type, mc->name);
758f30c843cSCédric Le Goater         exit(1);
759f30c843cSCédric Le Goater     }
760f30c843cSCédric Le Goater 
761e997040eSCédric Le Goater     /* Create the processor chips */
7624a12c699SIgor Mammedov     i = strlen(machine->cpu_type) - strlen(POWERPC_CPU_TYPE_SUFFIX);
7637fd544d8SIgor Mammedov     chip_typename = g_strdup_printf(PNV_CHIP_TYPE_NAME("%.*s"),
7644a12c699SIgor Mammedov                                     i, machine->cpu_type);
765e997040eSCédric Le Goater     if (!object_class_by_name(chip_typename)) {
766f30c843cSCédric Le Goater         error_report("invalid chip model '%.*s' for %s machine",
767f30c843cSCédric Le Goater                      i, machine->cpu_type, mc->name);
768e997040eSCédric Le Goater         exit(1);
769e997040eSCédric Le Goater     }
770e997040eSCédric Le Goater 
771e997040eSCédric Le Goater     pnv->chips = g_new0(PnvChip *, pnv->num_chips);
772e997040eSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
773e997040eSCédric Le Goater         char chip_name[32];
774e997040eSCédric Le Goater         Object *chip = object_new(chip_typename);
775e997040eSCédric Le Goater 
776e997040eSCédric Le Goater         pnv->chips[i] = PNV_CHIP(chip);
777e997040eSCédric Le Goater 
77859b7c1c2SBalamuruhan S         /*
77959b7c1c2SBalamuruhan S          * TODO: put all the memory in one node on chip 0 until we find a
780e997040eSCédric Le Goater          * way to specify different ranges for each chip
781e997040eSCédric Le Goater          */
782e997040eSCédric Le Goater         if (i == 0) {
783e997040eSCédric Le Goater             object_property_set_int(chip, machine->ram_size, "ram-size",
784e997040eSCédric Le Goater                                     &error_fatal);
785e997040eSCédric Le Goater         }
786e997040eSCédric Le Goater 
787e997040eSCédric Le Goater         snprintf(chip_name, sizeof(chip_name), "chip[%d]", PNV_CHIP_HWID(i));
788e997040eSCédric Le Goater         object_property_add_child(OBJECT(pnv), chip_name, chip, &error_fatal);
789e997040eSCédric Le Goater         object_property_set_int(chip, PNV_CHIP_HWID(i), "chip-id",
790e997040eSCédric Le Goater                                 &error_fatal);
791fe6b6346SLike Xu         object_property_set_int(chip, machine->smp.cores,
792fe6b6346SLike Xu                                 "nr-cores", &error_fatal);
793e997040eSCédric Le Goater         object_property_set_bool(chip, true, "realized", &error_fatal);
794e997040eSCédric Le Goater     }
795e997040eSCédric Le Goater     g_free(chip_typename);
7963495b6b6SCédric Le Goater 
797e2392d43SCédric Le Goater     /* Create the machine BMC simulator */
798e2392d43SCédric Le Goater     pnv->bmc = pnv_bmc_create();
799e2392d43SCédric Le Goater 
8003495b6b6SCédric Le Goater     /* Instantiate ISA bus on chip 0 */
80104026890SCédric Le Goater     pnv->isa_bus = pnv_isa_create(pnv->chips[0], &error_fatal);
8023495b6b6SCédric Le Goater 
8033495b6b6SCédric Le Goater     /* Create serial port */
804def337ffSPeter Maydell     serial_hds_isa_init(pnv->isa_bus, 0, MAX_ISA_SERIAL_PORTS);
8053495b6b6SCédric Le Goater 
8063495b6b6SCédric Le Goater     /* Create an RTC ISA device too */
8076c646a11SPhilippe Mathieu-Daudé     mc146818_rtc_init(pnv->isa_bus, 2000, NULL);
808bce0b691SCédric Le Goater 
809e2392d43SCédric Le Goater     /* Create the IPMI BT device for communication with the BMC */
810e2392d43SCédric Le Goater     pnv_ipmi_bt_init(pnv->isa_bus, pnv->bmc, 10);
811e2392d43SCédric Le Goater 
81259b7c1c2SBalamuruhan S     /*
81359b7c1c2SBalamuruhan S      * OpenPOWER systems use a IPMI SEL Event message to notify the
81459b7c1c2SBalamuruhan S      * host to powerdown
81559b7c1c2SBalamuruhan S      */
816bce0b691SCédric Le Goater     pnv->powerdown_notifier.notify = pnv_powerdown_notify;
817bce0b691SCédric Le Goater     qemu_register_powerdown_notifier(&pnv->powerdown_notifier);
818e997040eSCédric Le Goater }
819e997040eSCédric Le Goater 
820631adaffSCédric Le Goater /*
821631adaffSCédric Le Goater  *    0:21  Reserved - Read as zeros
822631adaffSCédric Le Goater  *   22:24  Chip ID
823631adaffSCédric Le Goater  *   25:28  Core number
824631adaffSCédric Le Goater  *   29:31  Thread ID
825631adaffSCédric Le Goater  */
826631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p8(PnvChip *chip, uint32_t core_id)
827631adaffSCédric Le Goater {
828631adaffSCédric Le Goater     return (chip->chip_id << 7) | (core_id << 3);
829631adaffSCédric Le Goater }
830631adaffSCédric Le Goater 
8318fa1f4efSCédric Le Goater static void pnv_chip_power8_intc_create(PnvChip *chip, PowerPCCPU *cpu,
832d35aefa9SCédric Le Goater                                         Error **errp)
833d35aefa9SCédric Le Goater {
8348fa1f4efSCédric Le Goater     Error *local_err = NULL;
8358fa1f4efSCédric Le Goater     Object *obj;
8368907fc25SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
8378fa1f4efSCédric Le Goater 
8388fa1f4efSCédric Le Goater     obj = icp_create(OBJECT(cpu), TYPE_PNV_ICP, XICS_FABRIC(qdev_get_machine()),
8398fa1f4efSCédric Le Goater                      &local_err);
8408fa1f4efSCédric Le Goater     if (local_err) {
8418fa1f4efSCédric Le Goater         error_propagate(errp, local_err);
8428fa1f4efSCédric Le Goater         return;
8438fa1f4efSCédric Le Goater     }
8448fa1f4efSCédric Le Goater 
845956b8f46SCédric Le Goater     pnv_cpu->intc = obj;
846d35aefa9SCédric Le Goater }
847d35aefa9SCédric Le Goater 
8480990ce6aSGreg Kurz 
849d49e8a9bSCédric Le Goater static void pnv_chip_power8_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
850d49e8a9bSCédric Le Goater {
851d49e8a9bSCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
852d49e8a9bSCédric Le Goater 
853d49e8a9bSCédric Le Goater     icp_reset(ICP(pnv_cpu->intc));
854d49e8a9bSCédric Le Goater }
855d49e8a9bSCédric Le Goater 
8560990ce6aSGreg Kurz static void pnv_chip_power8_intc_destroy(PnvChip *chip, PowerPCCPU *cpu)
8570990ce6aSGreg Kurz {
8580990ce6aSGreg Kurz     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
8590990ce6aSGreg Kurz 
8600990ce6aSGreg Kurz     icp_destroy(ICP(pnv_cpu->intc));
8610990ce6aSGreg Kurz     pnv_cpu->intc = NULL;
8620990ce6aSGreg Kurz }
8630990ce6aSGreg Kurz 
86485913070SGreg Kurz static void pnv_chip_power8_intc_print_info(PnvChip *chip, PowerPCCPU *cpu,
86585913070SGreg Kurz                                             Monitor *mon)
86685913070SGreg Kurz {
86785913070SGreg Kurz     icp_pic_print_info(ICP(pnv_cpu_state(cpu)->intc), mon);
86885913070SGreg Kurz }
86985913070SGreg Kurz 
870631adaffSCédric Le Goater /*
871631adaffSCédric Le Goater  *    0:48  Reserved - Read as zeroes
872631adaffSCédric Le Goater  *   49:52  Node ID
873631adaffSCédric Le Goater  *   53:55  Chip ID
874631adaffSCédric Le Goater  *   56     Reserved - Read as zero
875631adaffSCédric Le Goater  *   57:61  Core number
876631adaffSCédric Le Goater  *   62:63  Thread ID
877631adaffSCédric Le Goater  *
878631adaffSCédric Le Goater  * We only care about the lower bits. uint32_t is fine for the moment.
879631adaffSCédric Le Goater  */
880631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p9(PnvChip *chip, uint32_t core_id)
881631adaffSCédric Le Goater {
882631adaffSCédric Le Goater     return (chip->chip_id << 8) | (core_id << 2);
883631adaffSCédric Le Goater }
884631adaffSCédric Le Goater 
8852b548a42SCédric Le Goater static uint32_t pnv_chip_core_pir_p10(PnvChip *chip, uint32_t core_id)
8862b548a42SCédric Le Goater {
8872b548a42SCédric Le Goater     return (chip->chip_id << 8) | (core_id << 2);
8882b548a42SCédric Le Goater }
8892b548a42SCédric Le Goater 
8908fa1f4efSCédric Le Goater static void pnv_chip_power9_intc_create(PnvChip *chip, PowerPCCPU *cpu,
891d35aefa9SCédric Le Goater                                         Error **errp)
892d35aefa9SCédric Le Goater {
8932dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(chip);
8942dfa91a2SCédric Le Goater     Error *local_err = NULL;
8952dfa91a2SCédric Le Goater     Object *obj;
8962dfa91a2SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
8972dfa91a2SCédric Le Goater 
8982dfa91a2SCédric Le Goater     /*
8992dfa91a2SCédric Le Goater      * The core creates its interrupt presenter but the XIVE interrupt
9002dfa91a2SCédric Le Goater      * controller object is initialized afterwards. Hopefully, it's
9012dfa91a2SCédric Le Goater      * only used at runtime.
9022dfa91a2SCédric Le Goater      */
90326aa5b1eSGreg Kurz     obj = xive_tctx_create(OBJECT(cpu), XIVE_ROUTER(&chip9->xive), &local_err);
9042dfa91a2SCédric Le Goater     if (local_err) {
9052dfa91a2SCédric Le Goater         error_propagate(errp, local_err);
9068fa1f4efSCédric Le Goater         return;
907d35aefa9SCédric Le Goater     }
908d35aefa9SCédric Le Goater 
9092dfa91a2SCédric Le Goater     pnv_cpu->intc = obj;
9102dfa91a2SCédric Le Goater }
9112dfa91a2SCédric Le Goater 
912d49e8a9bSCédric Le Goater static void pnv_chip_power9_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
913d49e8a9bSCédric Le Goater {
914d49e8a9bSCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
915d49e8a9bSCédric Le Goater 
916d49e8a9bSCédric Le Goater     xive_tctx_reset(XIVE_TCTX(pnv_cpu->intc));
917d49e8a9bSCédric Le Goater }
918d49e8a9bSCédric Le Goater 
9190990ce6aSGreg Kurz static void pnv_chip_power9_intc_destroy(PnvChip *chip, PowerPCCPU *cpu)
9200990ce6aSGreg Kurz {
9210990ce6aSGreg Kurz     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
9220990ce6aSGreg Kurz 
9230990ce6aSGreg Kurz     xive_tctx_destroy(XIVE_TCTX(pnv_cpu->intc));
9240990ce6aSGreg Kurz     pnv_cpu->intc = NULL;
9250990ce6aSGreg Kurz }
9260990ce6aSGreg Kurz 
92785913070SGreg Kurz static void pnv_chip_power9_intc_print_info(PnvChip *chip, PowerPCCPU *cpu,
92885913070SGreg Kurz                                             Monitor *mon)
92985913070SGreg Kurz {
93085913070SGreg Kurz     xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), mon);
93185913070SGreg Kurz }
93285913070SGreg Kurz 
9332b548a42SCédric Le Goater static void pnv_chip_power10_intc_create(PnvChip *chip, PowerPCCPU *cpu,
9342b548a42SCédric Le Goater                                         Error **errp)
9352b548a42SCédric Le Goater {
9362b548a42SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
9372b548a42SCédric Le Goater 
9382b548a42SCédric Le Goater     /* Will be defined when the interrupt controller is */
9392b548a42SCédric Le Goater     pnv_cpu->intc = NULL;
9402b548a42SCédric Le Goater }
9412b548a42SCédric Le Goater 
9422b548a42SCédric Le Goater static void pnv_chip_power10_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
9432b548a42SCédric Le Goater {
9442b548a42SCédric Le Goater     ;
9452b548a42SCédric Le Goater }
9462b548a42SCédric Le Goater 
9472b548a42SCédric Le Goater static void pnv_chip_power10_intc_destroy(PnvChip *chip, PowerPCCPU *cpu)
9482b548a42SCédric Le Goater {
9492b548a42SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
9502b548a42SCédric Le Goater 
9512b548a42SCédric Le Goater     pnv_cpu->intc = NULL;
9522b548a42SCédric Le Goater }
9532b548a42SCédric Le Goater 
95485913070SGreg Kurz static void pnv_chip_power10_intc_print_info(PnvChip *chip, PowerPCCPU *cpu,
95585913070SGreg Kurz                                              Monitor *mon)
95685913070SGreg Kurz {
95785913070SGreg Kurz }
95885913070SGreg Kurz 
95959b7c1c2SBalamuruhan S /*
96059b7c1c2SBalamuruhan S  * Allowed core identifiers on a POWER8 Processor Chip :
961397a79e7SCédric Le Goater  *
962397a79e7SCédric Le Goater  * <EX0 reserved>
963397a79e7SCédric Le Goater  *  EX1  - Venice only
964397a79e7SCédric Le Goater  *  EX2  - Venice only
965397a79e7SCédric Le Goater  *  EX3  - Venice only
966397a79e7SCédric Le Goater  *  EX4
967397a79e7SCédric Le Goater  *  EX5
968397a79e7SCédric Le Goater  *  EX6
969397a79e7SCédric Le Goater  * <EX7,8 reserved> <reserved>
970397a79e7SCédric Le Goater  *  EX9  - Venice only
971397a79e7SCédric Le Goater  *  EX10 - Venice only
972397a79e7SCédric Le Goater  *  EX11 - Venice only
973397a79e7SCédric Le Goater  *  EX12
974397a79e7SCédric Le Goater  *  EX13
975397a79e7SCédric Le Goater  *  EX14
976397a79e7SCédric Le Goater  * <EX15 reserved>
977397a79e7SCédric Le Goater  */
978397a79e7SCédric Le Goater #define POWER8E_CORE_MASK  (0x7070ull)
979397a79e7SCédric Le Goater #define POWER8_CORE_MASK   (0x7e7eull)
980397a79e7SCédric Le Goater 
981397a79e7SCédric Le Goater /*
98209279d7eSCédric Le Goater  * POWER9 has 24 cores, ids starting at 0x0
983397a79e7SCédric Le Goater  */
98409279d7eSCédric Le Goater #define POWER9_CORE_MASK   (0xffffffffffffffull)
985397a79e7SCédric Le Goater 
9862b548a42SCédric Le Goater 
9872b548a42SCédric Le Goater #define POWER10_CORE_MASK  (0xffffffffffffffull)
9882b548a42SCédric Le Goater 
98977864267SCédric Le Goater static void pnv_chip_power8_instance_init(Object *obj)
99077864267SCédric Le Goater {
99177864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(obj);
99277864267SCédric Le Goater 
993f6d4dca8SThomas Huth     object_initialize_child(obj, "psi",  &chip8->psi, sizeof(chip8->psi),
994ae856055SCédric Le Goater                             TYPE_PNV8_PSI, &error_abort, NULL);
99577864267SCédric Le Goater     object_property_add_const_link(OBJECT(&chip8->psi), "xics",
99677864267SCédric Le Goater                                    OBJECT(qdev_get_machine()), &error_abort);
99777864267SCédric Le Goater 
998f6d4dca8SThomas Huth     object_initialize_child(obj, "lpc",  &chip8->lpc, sizeof(chip8->lpc),
99982514be2SCédric Le Goater                             TYPE_PNV8_LPC, &error_abort, NULL);
100077864267SCédric Le Goater 
1001f6d4dca8SThomas Huth     object_initialize_child(obj, "occ",  &chip8->occ, sizeof(chip8->occ),
10023233838cSCédric Le Goater                             TYPE_PNV8_OCC, &error_abort, NULL);
10033887d241SBalamuruhan S 
10043887d241SBalamuruhan S     object_initialize_child(obj, "homer",  &chip8->homer, sizeof(chip8->homer),
10053887d241SBalamuruhan S                             TYPE_PNV8_HOMER, &error_abort, NULL);
100677864267SCédric Le Goater }
100777864267SCédric Le Goater 
100877864267SCédric Le Goater static void pnv_chip_icp_realize(Pnv8Chip *chip8, Error **errp)
100977864267SCédric Le Goater  {
101077864267SCédric Le Goater     PnvChip *chip = PNV_CHIP(chip8);
101177864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
101277864267SCédric Le Goater     int i, j;
101377864267SCédric Le Goater     char *name;
101477864267SCédric Le Goater     XICSFabric *xi = XICS_FABRIC(qdev_get_machine());
101577864267SCédric Le Goater 
101677864267SCédric Le Goater     name = g_strdup_printf("icp-%x", chip->chip_id);
101777864267SCédric Le Goater     memory_region_init(&chip8->icp_mmio, OBJECT(chip), name, PNV_ICP_SIZE);
101877864267SCédric Le Goater     sysbus_init_mmio(SYS_BUS_DEVICE(chip), &chip8->icp_mmio);
101977864267SCédric Le Goater     g_free(name);
102077864267SCédric Le Goater 
102177864267SCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 1, PNV_ICP_BASE(chip));
102277864267SCédric Le Goater 
102377864267SCédric Le Goater     /* Map the ICP registers for each thread */
102477864267SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
10254fa28f23SGreg Kurz         PnvCore *pnv_core = chip->cores[i];
102677864267SCédric Le Goater         int core_hwid = CPU_CORE(pnv_core)->core_id;
102777864267SCédric Le Goater 
102877864267SCédric Le Goater         for (j = 0; j < CPU_CORE(pnv_core)->nr_threads; j++) {
102977864267SCédric Le Goater             uint32_t pir = pcc->core_pir(chip, core_hwid) + j;
103077864267SCédric Le Goater             PnvICPState *icp = PNV_ICP(xics_icp_get(xi, pir));
103177864267SCédric Le Goater 
103277864267SCédric Le Goater             memory_region_add_subregion(&chip8->icp_mmio, pir << 12,
103377864267SCédric Le Goater                                         &icp->mmio);
103477864267SCédric Le Goater         }
103577864267SCédric Le Goater     }
103677864267SCédric Le Goater }
103777864267SCédric Le Goater 
103877864267SCédric Le Goater static void pnv_chip_power8_realize(DeviceState *dev, Error **errp)
103977864267SCédric Le Goater {
104077864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
104177864267SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
104277864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(dev);
1043ae856055SCédric Le Goater     Pnv8Psi *psi8 = &chip8->psi;
104477864267SCédric Le Goater     Error *local_err = NULL;
104577864267SCédric Le Goater 
1046709044fdSCédric Le Goater     /* XSCOM bridge is first */
1047709044fdSCédric Le Goater     pnv_xscom_realize(chip, PNV_XSCOM_SIZE, &local_err);
1048709044fdSCédric Le Goater     if (local_err) {
1049709044fdSCédric Le Goater         error_propagate(errp, local_err);
1050709044fdSCédric Le Goater         return;
1051709044fdSCédric Le Goater     }
1052709044fdSCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV_XSCOM_BASE(chip));
1053709044fdSCédric Le Goater 
105477864267SCédric Le Goater     pcc->parent_realize(dev, &local_err);
105577864267SCédric Le Goater     if (local_err) {
105677864267SCédric Le Goater         error_propagate(errp, local_err);
105777864267SCédric Le Goater         return;
105877864267SCédric Le Goater     }
105977864267SCédric Le Goater 
106077864267SCédric Le Goater     /* Processor Service Interface (PSI) Host Bridge */
106177864267SCédric Le Goater     object_property_set_int(OBJECT(&chip8->psi), PNV_PSIHB_BASE(chip),
106277864267SCédric Le Goater                             "bar", &error_fatal);
106377864267SCédric Le Goater     object_property_set_bool(OBJECT(&chip8->psi), true, "realized", &local_err);
106477864267SCédric Le Goater     if (local_err) {
106577864267SCédric Le Goater         error_propagate(errp, local_err);
106677864267SCédric Le Goater         return;
106777864267SCédric Le Goater     }
1068ae856055SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_PSIHB_BASE,
1069ae856055SCédric Le Goater                             &PNV_PSI(psi8)->xscom_regs);
107077864267SCédric Le Goater 
107177864267SCédric Le Goater     /* Create LPC controller */
1072b63f3893SGreg Kurz     object_property_set_link(OBJECT(&chip8->lpc), OBJECT(&chip8->psi), "psi",
1073b63f3893SGreg Kurz                              &error_abort);
107477864267SCédric Le Goater     object_property_set_bool(OBJECT(&chip8->lpc), true, "realized",
107577864267SCédric Le Goater                              &error_fatal);
107677864267SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_LPC_BASE, &chip8->lpc.xscom_regs);
107777864267SCédric Le Goater 
107864d011d5SCédric Le Goater     chip->dt_isa_nodename = g_strdup_printf("/xscom@%" PRIx64 "/isa@%x",
107964d011d5SCédric Le Goater                                             (uint64_t) PNV_XSCOM_BASE(chip),
108064d011d5SCédric Le Goater                                             PNV_XSCOM_LPC_BASE);
108164d011d5SCédric Le Goater 
108259b7c1c2SBalamuruhan S     /*
108359b7c1c2SBalamuruhan S      * Interrupt Management Area. This is the memory region holding
108459b7c1c2SBalamuruhan S      * all the Interrupt Control Presenter (ICP) registers
108559b7c1c2SBalamuruhan S      */
108677864267SCédric Le Goater     pnv_chip_icp_realize(chip8, &local_err);
108777864267SCédric Le Goater     if (local_err) {
108877864267SCédric Le Goater         error_propagate(errp, local_err);
108977864267SCédric Le Goater         return;
109077864267SCédric Le Goater     }
109177864267SCédric Le Goater 
109277864267SCédric Le Goater     /* Create the simplified OCC model */
1093ee3d2713SGreg Kurz     object_property_set_link(OBJECT(&chip8->occ), OBJECT(&chip8->psi), "psi",
1094ee3d2713SGreg Kurz                              &error_abort);
109577864267SCédric Le Goater     object_property_set_bool(OBJECT(&chip8->occ), true, "realized", &local_err);
109677864267SCédric Le Goater     if (local_err) {
109777864267SCédric Le Goater         error_propagate(errp, local_err);
109877864267SCédric Le Goater         return;
109977864267SCédric Le Goater     }
110077864267SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_OCC_BASE, &chip8->occ.xscom_regs);
1101f3db8266SBalamuruhan S 
1102f3db8266SBalamuruhan S     /* OCC SRAM model */
11033a1b70b6SCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV_OCC_SENSOR_BASE(chip),
1104f3db8266SBalamuruhan S                                 &chip8->occ.sram_regs);
11053887d241SBalamuruhan S 
11063887d241SBalamuruhan S     /* HOMER */
1107f2582acfSGreg Kurz     object_property_set_link(OBJECT(&chip8->homer), OBJECT(chip), "chip",
1108f2582acfSGreg Kurz                              &error_abort);
11093887d241SBalamuruhan S     object_property_set_bool(OBJECT(&chip8->homer), true, "realized",
11103887d241SBalamuruhan S                              &local_err);
11113887d241SBalamuruhan S     if (local_err) {
11123887d241SBalamuruhan S         error_propagate(errp, local_err);
11133887d241SBalamuruhan S         return;
11143887d241SBalamuruhan S     }
11158f092316SCédric Le Goater     /* Homer Xscom region */
11168f092316SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_PBA_BASE, &chip8->homer.pba_regs);
11178f092316SCédric Le Goater 
11188f092316SCédric Le Goater     /* Homer mmio region */
11193887d241SBalamuruhan S     memory_region_add_subregion(get_system_memory(), PNV_HOMER_BASE(chip),
11203887d241SBalamuruhan S                                 &chip8->homer.regs);
112177864267SCédric Le Goater }
112277864267SCédric Le Goater 
112370c059e9SGreg Kurz static uint32_t pnv_chip_power8_xscom_pcba(PnvChip *chip, uint64_t addr)
112470c059e9SGreg Kurz {
112570c059e9SGreg Kurz     addr &= (PNV_XSCOM_SIZE - 1);
112670c059e9SGreg Kurz     return ((addr >> 4) & ~0xfull) | ((addr >> 3) & 0xf);
112770c059e9SGreg Kurz }
112870c059e9SGreg Kurz 
1129e997040eSCédric Le Goater static void pnv_chip_power8e_class_init(ObjectClass *klass, void *data)
1130e997040eSCédric Le Goater {
1131e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1132e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1133e997040eSCédric Le Goater 
1134e997040eSCédric Le Goater     k->chip_cfam_id = 0x221ef04980000000ull;  /* P8 Murano DD2.1 */
1135397a79e7SCédric Le Goater     k->cores_mask = POWER8E_CORE_MASK;
1136631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
1137d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
1138d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power8_intc_reset;
11390990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power8_intc_destroy;
114085913070SGreg Kurz     k->intc_print_info = pnv_chip_power8_intc_print_info;
114104026890SCédric Le Goater     k->isa_create = pnv_chip_power8_isa_create;
1142eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
1143d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
1144c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power8_xscom_core_base;
114570c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power8_xscom_pcba;
1146e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8E";
114777864267SCédric Le Goater 
114877864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
114977864267SCédric Le Goater                                     &k->parent_realize);
1150e997040eSCédric Le Goater }
1151e997040eSCédric Le Goater 
1152e997040eSCédric Le Goater static void pnv_chip_power8_class_init(ObjectClass *klass, void *data)
1153e997040eSCédric Le Goater {
1154e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1155e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1156e997040eSCédric Le Goater 
1157e997040eSCédric Le Goater     k->chip_cfam_id = 0x220ea04980000000ull; /* P8 Venice DD2.0 */
1158397a79e7SCédric Le Goater     k->cores_mask = POWER8_CORE_MASK;
1159631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
1160d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
1161d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power8_intc_reset;
11620990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power8_intc_destroy;
116385913070SGreg Kurz     k->intc_print_info = pnv_chip_power8_intc_print_info;
116404026890SCédric Le Goater     k->isa_create = pnv_chip_power8_isa_create;
1165eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
1166d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
1167c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power8_xscom_core_base;
116870c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power8_xscom_pcba;
1169e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8";
117077864267SCédric Le Goater 
117177864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
117277864267SCédric Le Goater                                     &k->parent_realize);
1173e997040eSCédric Le Goater }
1174e997040eSCédric Le Goater 
1175e997040eSCédric Le Goater static void pnv_chip_power8nvl_class_init(ObjectClass *klass, void *data)
1176e997040eSCédric Le Goater {
1177e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1178e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1179e997040eSCédric Le Goater 
1180e997040eSCédric Le Goater     k->chip_cfam_id = 0x120d304980000000ull;  /* P8 Naples DD1.0 */
1181397a79e7SCédric Le Goater     k->cores_mask = POWER8_CORE_MASK;
1182631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
1183d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
1184d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power8_intc_reset;
11850990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power8_intc_destroy;
118685913070SGreg Kurz     k->intc_print_info = pnv_chip_power8_intc_print_info;
118704026890SCédric Le Goater     k->isa_create = pnv_chip_power8nvl_isa_create;
1188eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
1189d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
1190c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power8_xscom_core_base;
119170c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power8_xscom_pcba;
1192e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8NVL";
119377864267SCédric Le Goater 
119477864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
119577864267SCédric Le Goater                                     &k->parent_realize);
119677864267SCédric Le Goater }
119777864267SCédric Le Goater 
119877864267SCédric Le Goater static void pnv_chip_power9_instance_init(Object *obj)
119977864267SCédric Le Goater {
12002dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(obj);
12012dfa91a2SCédric Le Goater 
12022dfa91a2SCédric Le Goater     object_initialize_child(obj, "xive", &chip9->xive, sizeof(chip9->xive),
12032dfa91a2SCédric Le Goater                             TYPE_PNV_XIVE, &error_abort, NULL);
1204c38536bcSCédric Le Goater 
1205c38536bcSCédric Le Goater     object_initialize_child(obj, "psi",  &chip9->psi, sizeof(chip9->psi),
1206c38536bcSCédric Le Goater                             TYPE_PNV9_PSI, &error_abort, NULL);
120715376c66SCédric Le Goater 
120815376c66SCédric Le Goater     object_initialize_child(obj, "lpc",  &chip9->lpc, sizeof(chip9->lpc),
120915376c66SCédric Le Goater                             TYPE_PNV9_LPC, &error_abort, NULL);
12106598a70dSCédric Le Goater 
12116598a70dSCédric Le Goater     object_initialize_child(obj, "occ",  &chip9->occ, sizeof(chip9->occ),
12126598a70dSCédric Le Goater                             TYPE_PNV9_OCC, &error_abort, NULL);
12133887d241SBalamuruhan S 
12143887d241SBalamuruhan S     object_initialize_child(obj, "homer",  &chip9->homer, sizeof(chip9->homer),
12153887d241SBalamuruhan S                             TYPE_PNV9_HOMER, &error_abort, NULL);
121677864267SCédric Le Goater }
121777864267SCédric Le Goater 
12185dad902cSCédric Le Goater static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error **errp)
12195dad902cSCédric Le Goater {
12205dad902cSCédric Le Goater     PnvChip *chip = PNV_CHIP(chip9);
12215dad902cSCédric Le Goater     int i;
12225dad902cSCédric Le Goater 
12235dad902cSCédric Le Goater     chip9->nr_quads = DIV_ROUND_UP(chip->nr_cores, 4);
12245dad902cSCédric Le Goater     chip9->quads = g_new0(PnvQuad, chip9->nr_quads);
12255dad902cSCédric Le Goater 
12265dad902cSCédric Le Goater     for (i = 0; i < chip9->nr_quads; i++) {
12275dad902cSCédric Le Goater         char eq_name[32];
12285dad902cSCédric Le Goater         PnvQuad *eq = &chip9->quads[i];
12294fa28f23SGreg Kurz         PnvCore *pnv_core = chip->cores[i * 4];
12305dad902cSCédric Le Goater         int core_id = CPU_CORE(pnv_core)->core_id;
12315dad902cSCédric Le Goater 
12325dad902cSCédric Le Goater         snprintf(eq_name, sizeof(eq_name), "eq[%d]", core_id);
1233bc4c406cSPhilippe Mathieu-Daudé         object_initialize_child(OBJECT(chip), eq_name, eq, sizeof(*eq),
1234bc4c406cSPhilippe Mathieu-Daudé                                 TYPE_PNV_QUAD, &error_fatal, NULL);
12355dad902cSCédric Le Goater 
12365dad902cSCédric Le Goater         object_property_set_int(OBJECT(eq), core_id, "id", &error_fatal);
12375dad902cSCédric Le Goater         object_property_set_bool(OBJECT(eq), true, "realized", &error_fatal);
12385dad902cSCédric Le Goater 
12395dad902cSCédric Le Goater         pnv_xscom_add_subregion(chip, PNV9_XSCOM_EQ_BASE(eq->id),
12405dad902cSCédric Le Goater                                 &eq->xscom_regs);
12415dad902cSCédric Le Goater     }
12425dad902cSCédric Le Goater }
12435dad902cSCédric Le Goater 
124477864267SCédric Le Goater static void pnv_chip_power9_realize(DeviceState *dev, Error **errp)
124577864267SCédric Le Goater {
124677864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
12472dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(dev);
12482dfa91a2SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
1249c38536bcSCédric Le Goater     Pnv9Psi *psi9 = &chip9->psi;
125077864267SCédric Le Goater     Error *local_err = NULL;
125177864267SCédric Le Goater 
1252709044fdSCédric Le Goater     /* XSCOM bridge is first */
1253709044fdSCédric Le Goater     pnv_xscom_realize(chip, PNV9_XSCOM_SIZE, &local_err);
1254709044fdSCédric Le Goater     if (local_err) {
1255709044fdSCédric Le Goater         error_propagate(errp, local_err);
1256709044fdSCédric Le Goater         return;
1257709044fdSCédric Le Goater     }
1258709044fdSCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV9_XSCOM_BASE(chip));
1259709044fdSCédric Le Goater 
126077864267SCédric Le Goater     pcc->parent_realize(dev, &local_err);
126177864267SCédric Le Goater     if (local_err) {
126277864267SCédric Le Goater         error_propagate(errp, local_err);
126377864267SCédric Le Goater         return;
126477864267SCédric Le Goater     }
12652dfa91a2SCédric Le Goater 
12665dad902cSCédric Le Goater     pnv_chip_quad_realize(chip9, &local_err);
12675dad902cSCédric Le Goater     if (local_err) {
12685dad902cSCédric Le Goater         error_propagate(errp, local_err);
12695dad902cSCédric Le Goater         return;
12705dad902cSCédric Le Goater     }
12715dad902cSCédric Le Goater 
12722dfa91a2SCédric Le Goater     /* XIVE interrupt controller (POWER9) */
12732dfa91a2SCédric Le Goater     object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_IC_BASE(chip),
12742dfa91a2SCédric Le Goater                             "ic-bar", &error_fatal);
12752dfa91a2SCédric Le Goater     object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_VC_BASE(chip),
12762dfa91a2SCédric Le Goater                             "vc-bar", &error_fatal);
12772dfa91a2SCédric Le Goater     object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_PC_BASE(chip),
12782dfa91a2SCédric Le Goater                             "pc-bar", &error_fatal);
12792dfa91a2SCédric Le Goater     object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_TM_BASE(chip),
12802dfa91a2SCédric Le Goater                             "tm-bar", &error_fatal);
12817ae54cc3SGreg Kurz     object_property_set_link(OBJECT(&chip9->xive), OBJECT(chip), "chip",
12827ae54cc3SGreg Kurz                              &error_abort);
12832dfa91a2SCédric Le Goater     object_property_set_bool(OBJECT(&chip9->xive), true, "realized",
12842dfa91a2SCédric Le Goater                              &local_err);
12852dfa91a2SCédric Le Goater     if (local_err) {
12862dfa91a2SCédric Le Goater         error_propagate(errp, local_err);
12872dfa91a2SCédric Le Goater         return;
12882dfa91a2SCédric Le Goater     }
12892dfa91a2SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_XIVE_BASE,
12902dfa91a2SCédric Le Goater                             &chip9->xive.xscom_regs);
1291c38536bcSCédric Le Goater 
1292c38536bcSCédric Le Goater     /* Processor Service Interface (PSI) Host Bridge */
1293c38536bcSCédric Le Goater     object_property_set_int(OBJECT(&chip9->psi), PNV9_PSIHB_BASE(chip),
1294c38536bcSCédric Le Goater                             "bar", &error_fatal);
1295c38536bcSCédric Le Goater     object_property_set_bool(OBJECT(&chip9->psi), true, "realized", &local_err);
1296c38536bcSCédric Le Goater     if (local_err) {
1297c38536bcSCédric Le Goater         error_propagate(errp, local_err);
1298c38536bcSCédric Le Goater         return;
1299c38536bcSCédric Le Goater     }
1300c38536bcSCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_PSIHB_BASE,
1301c38536bcSCédric Le Goater                             &PNV_PSI(psi9)->xscom_regs);
130215376c66SCédric Le Goater 
130315376c66SCédric Le Goater     /* LPC */
1304b63f3893SGreg Kurz     object_property_set_link(OBJECT(&chip9->lpc), OBJECT(&chip9->psi), "psi",
1305b63f3893SGreg Kurz                              &error_abort);
130615376c66SCédric Le Goater     object_property_set_bool(OBJECT(&chip9->lpc), true, "realized", &local_err);
130715376c66SCédric Le Goater     if (local_err) {
130815376c66SCédric Le Goater         error_propagate(errp, local_err);
130915376c66SCédric Le Goater         return;
131015376c66SCédric Le Goater     }
131115376c66SCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV9_LPCM_BASE(chip),
131215376c66SCédric Le Goater                                 &chip9->lpc.xscom_regs);
131315376c66SCédric Le Goater 
131415376c66SCédric Le Goater     chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0",
131515376c66SCédric Le Goater                                             (uint64_t) PNV9_LPCM_BASE(chip));
13166598a70dSCédric Le Goater 
13176598a70dSCédric Le Goater     /* Create the simplified OCC model */
1318ee3d2713SGreg Kurz     object_property_set_link(OBJECT(&chip9->occ), OBJECT(&chip9->psi), "psi",
1319ee3d2713SGreg Kurz                              &error_abort);
13206598a70dSCédric Le Goater     object_property_set_bool(OBJECT(&chip9->occ), true, "realized", &local_err);
13216598a70dSCédric Le Goater     if (local_err) {
13226598a70dSCédric Le Goater         error_propagate(errp, local_err);
13236598a70dSCédric Le Goater         return;
13246598a70dSCédric Le Goater     }
13256598a70dSCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_OCC_BASE, &chip9->occ.xscom_regs);
1326f3db8266SBalamuruhan S 
1327f3db8266SBalamuruhan S     /* OCC SRAM model */
13283a1b70b6SCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV9_OCC_SENSOR_BASE(chip),
1329f3db8266SBalamuruhan S                                 &chip9->occ.sram_regs);
13303887d241SBalamuruhan S 
13313887d241SBalamuruhan S     /* HOMER */
1332f2582acfSGreg Kurz     object_property_set_link(OBJECT(&chip9->homer), OBJECT(chip), "chip",
1333f2582acfSGreg Kurz                              &error_abort);
13343887d241SBalamuruhan S     object_property_set_bool(OBJECT(&chip9->homer), true, "realized",
13353887d241SBalamuruhan S                              &local_err);
13363887d241SBalamuruhan S     if (local_err) {
13373887d241SBalamuruhan S         error_propagate(errp, local_err);
13383887d241SBalamuruhan S         return;
13393887d241SBalamuruhan S     }
13408f092316SCédric Le Goater     /* Homer Xscom region */
13418f092316SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_PBA_BASE, &chip9->homer.pba_regs);
13428f092316SCédric Le Goater 
13438f092316SCédric Le Goater     /* Homer mmio region */
13443887d241SBalamuruhan S     memory_region_add_subregion(get_system_memory(), PNV9_HOMER_BASE(chip),
13453887d241SBalamuruhan S                                 &chip9->homer.regs);
1346e997040eSCédric Le Goater }
1347e997040eSCédric Le Goater 
134870c059e9SGreg Kurz static uint32_t pnv_chip_power9_xscom_pcba(PnvChip *chip, uint64_t addr)
134970c059e9SGreg Kurz {
135070c059e9SGreg Kurz     addr &= (PNV9_XSCOM_SIZE - 1);
135170c059e9SGreg Kurz     return addr >> 3;
135270c059e9SGreg Kurz }
135370c059e9SGreg Kurz 
1354e997040eSCédric Le Goater static void pnv_chip_power9_class_init(ObjectClass *klass, void *data)
1355e997040eSCédric Le Goater {
1356e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1357e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1358e997040eSCédric Le Goater 
135983028a2bSCédric Le Goater     k->chip_cfam_id = 0x220d104900008000ull; /* P9 Nimbus DD2.0 */
1360397a79e7SCédric Le Goater     k->cores_mask = POWER9_CORE_MASK;
1361631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p9;
1362d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power9_intc_create;
1363d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power9_intc_reset;
13640990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power9_intc_destroy;
136585913070SGreg Kurz     k->intc_print_info = pnv_chip_power9_intc_print_info;
136604026890SCédric Le Goater     k->isa_create = pnv_chip_power9_isa_create;
1367eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power9_dt_populate;
1368d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power9_pic_print_info;
1369c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power9_xscom_core_base;
137070c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power9_xscom_pcba;
1371e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER9";
137277864267SCédric Le Goater 
137377864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power9_realize,
137477864267SCédric Le Goater                                     &k->parent_realize);
1375e997040eSCédric Le Goater }
1376e997040eSCédric Le Goater 
13772b548a42SCédric Le Goater static void pnv_chip_power10_instance_init(Object *obj)
13782b548a42SCédric Le Goater {
13798b50ce85SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(obj);
13808b50ce85SCédric Le Goater 
13818b50ce85SCédric Le Goater     object_initialize_child(obj, "psi",  &chip10->psi, sizeof(chip10->psi),
13828b50ce85SCédric Le Goater                             TYPE_PNV10_PSI, &error_abort, NULL);
13832661f6abSCédric Le Goater     object_initialize_child(obj, "lpc",  &chip10->lpc, sizeof(chip10->lpc),
13842661f6abSCédric Le Goater                             TYPE_PNV10_LPC, &error_abort, NULL);
13852b548a42SCédric Le Goater }
13862b548a42SCédric Le Goater 
13872b548a42SCédric Le Goater static void pnv_chip_power10_realize(DeviceState *dev, Error **errp)
13882b548a42SCédric Le Goater {
13892b548a42SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
13902b548a42SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
13918b50ce85SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(dev);
13922b548a42SCédric Le Goater     Error *local_err = NULL;
13932b548a42SCédric Le Goater 
13942b548a42SCédric Le Goater     /* XSCOM bridge is first */
13952b548a42SCédric Le Goater     pnv_xscom_realize(chip, PNV10_XSCOM_SIZE, &local_err);
13962b548a42SCédric Le Goater     if (local_err) {
13972b548a42SCédric Le Goater         error_propagate(errp, local_err);
13982b548a42SCédric Le Goater         return;
13992b548a42SCédric Le Goater     }
14002b548a42SCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV10_XSCOM_BASE(chip));
14012b548a42SCédric Le Goater 
14022b548a42SCédric Le Goater     pcc->parent_realize(dev, &local_err);
14032b548a42SCédric Le Goater     if (local_err) {
14042b548a42SCédric Le Goater         error_propagate(errp, local_err);
14052b548a42SCédric Le Goater         return;
14062b548a42SCédric Le Goater     }
14078b50ce85SCédric Le Goater 
14088b50ce85SCédric Le Goater     /* Processor Service Interface (PSI) Host Bridge */
14098b50ce85SCédric Le Goater     object_property_set_int(OBJECT(&chip10->psi), PNV10_PSIHB_BASE(chip),
14108b50ce85SCédric Le Goater                             "bar", &error_fatal);
14118b50ce85SCédric Le Goater     object_property_set_bool(OBJECT(&chip10->psi), true, "realized",
14128b50ce85SCédric Le Goater                              &local_err);
14138b50ce85SCédric Le Goater     if (local_err) {
14148b50ce85SCédric Le Goater         error_propagate(errp, local_err);
14158b50ce85SCédric Le Goater         return;
14168b50ce85SCédric Le Goater     }
14178b50ce85SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV10_XSCOM_PSIHB_BASE,
14188b50ce85SCédric Le Goater                             &PNV_PSI(&chip10->psi)->xscom_regs);
14192661f6abSCédric Le Goater 
14202661f6abSCédric Le Goater     /* LPC */
14212661f6abSCédric Le Goater     object_property_set_link(OBJECT(&chip10->lpc), OBJECT(&chip10->psi), "psi",
14222661f6abSCédric Le Goater                              &error_abort);
14232661f6abSCédric Le Goater     object_property_set_bool(OBJECT(&chip10->lpc), true, "realized",
14242661f6abSCédric Le Goater                              &local_err);
14252661f6abSCédric Le Goater     if (local_err) {
14262661f6abSCédric Le Goater         error_propagate(errp, local_err);
14272661f6abSCédric Le Goater         return;
14282661f6abSCédric Le Goater     }
14292661f6abSCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV10_LPCM_BASE(chip),
14302661f6abSCédric Le Goater                                 &chip10->lpc.xscom_regs);
14312661f6abSCédric Le Goater 
14322661f6abSCédric Le Goater     chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0",
14332661f6abSCédric Le Goater                                             (uint64_t) PNV10_LPCM_BASE(chip));
14342b548a42SCédric Le Goater }
14352b548a42SCédric Le Goater 
143670c059e9SGreg Kurz static uint32_t pnv_chip_power10_xscom_pcba(PnvChip *chip, uint64_t addr)
143770c059e9SGreg Kurz {
143870c059e9SGreg Kurz     addr &= (PNV10_XSCOM_SIZE - 1);
143970c059e9SGreg Kurz     return addr >> 3;
144070c059e9SGreg Kurz }
144170c059e9SGreg Kurz 
14422b548a42SCédric Le Goater static void pnv_chip_power10_class_init(ObjectClass *klass, void *data)
14432b548a42SCédric Le Goater {
14442b548a42SCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
14452b548a42SCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
14462b548a42SCédric Le Goater 
14472b548a42SCédric Le Goater     k->chip_cfam_id = 0x120da04900008000ull; /* P10 DD1.0 (with NX) */
14482b548a42SCédric Le Goater     k->cores_mask = POWER10_CORE_MASK;
14492b548a42SCédric Le Goater     k->core_pir = pnv_chip_core_pir_p10;
14502b548a42SCédric Le Goater     k->intc_create = pnv_chip_power10_intc_create;
14512b548a42SCédric Le Goater     k->intc_reset = pnv_chip_power10_intc_reset;
14522b548a42SCédric Le Goater     k->intc_destroy = pnv_chip_power10_intc_destroy;
145385913070SGreg Kurz     k->intc_print_info = pnv_chip_power10_intc_print_info;
14542b548a42SCédric Le Goater     k->isa_create = pnv_chip_power10_isa_create;
14552b548a42SCédric Le Goater     k->dt_populate = pnv_chip_power10_dt_populate;
14562b548a42SCédric Le Goater     k->pic_print_info = pnv_chip_power10_pic_print_info;
1457c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power10_xscom_core_base;
145870c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power10_xscom_pcba;
14592b548a42SCédric Le Goater     dc->desc = "PowerNV Chip POWER10";
14602b548a42SCédric Le Goater 
14612b548a42SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power10_realize,
14622b548a42SCédric Le Goater                                     &k->parent_realize);
14632b548a42SCédric Le Goater }
14642b548a42SCédric Le Goater 
1465397a79e7SCédric Le Goater static void pnv_chip_core_sanitize(PnvChip *chip, Error **errp)
1466397a79e7SCédric Le Goater {
1467397a79e7SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
1468397a79e7SCédric Le Goater     int cores_max;
1469397a79e7SCédric Le Goater 
1470397a79e7SCédric Le Goater     /*
1471397a79e7SCédric Le Goater      * No custom mask for this chip, let's use the default one from *
1472397a79e7SCédric Le Goater      * the chip class
1473397a79e7SCédric Le Goater      */
1474397a79e7SCédric Le Goater     if (!chip->cores_mask) {
1475397a79e7SCédric Le Goater         chip->cores_mask = pcc->cores_mask;
1476397a79e7SCédric Le Goater     }
1477397a79e7SCédric Le Goater 
1478397a79e7SCédric Le Goater     /* filter alien core ids ! some are reserved */
1479397a79e7SCédric Le Goater     if ((chip->cores_mask & pcc->cores_mask) != chip->cores_mask) {
1480397a79e7SCédric Le Goater         error_setg(errp, "warning: invalid core mask for chip Ox%"PRIx64" !",
1481397a79e7SCédric Le Goater                    chip->cores_mask);
1482397a79e7SCédric Le Goater         return;
1483397a79e7SCédric Le Goater     }
1484397a79e7SCédric Le Goater     chip->cores_mask &= pcc->cores_mask;
1485397a79e7SCédric Le Goater 
1486397a79e7SCédric Le Goater     /* now that we have a sane layout, let check the number of cores */
148727d9ffd4SDavid Gibson     cores_max = ctpop64(chip->cores_mask);
1488397a79e7SCédric Le Goater     if (chip->nr_cores > cores_max) {
1489397a79e7SCédric Le Goater         error_setg(errp, "warning: too many cores for chip ! Limit is %d",
1490397a79e7SCédric Le Goater                    cores_max);
1491397a79e7SCédric Le Goater         return;
1492397a79e7SCédric Le Goater     }
1493397a79e7SCédric Le Goater }
1494397a79e7SCédric Le Goater 
149551c04728SCédric Le Goater static void pnv_chip_core_realize(PnvChip *chip, Error **errp)
1496e997040eSCédric Le Goater {
1497fe6b6346SLike Xu     MachineState *ms = MACHINE(qdev_get_machine());
1498397a79e7SCédric Le Goater     Error *error = NULL;
1499d2fd9612SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
150040abf43fSIgor Mammedov     const char *typename = pnv_chip_core_typename(chip);
1501d2fd9612SCédric Le Goater     int i, core_hwid;
1502397a79e7SCédric Le Goater 
1503d2fd9612SCédric Le Goater     if (!object_class_by_name(typename)) {
1504d2fd9612SCédric Le Goater         error_setg(errp, "Unable to find PowerNV CPU Core '%s'", typename);
1505d2fd9612SCédric Le Goater         return;
1506d2fd9612SCédric Le Goater     }
1507d2fd9612SCédric Le Goater 
1508d2fd9612SCédric Le Goater     /* Cores */
1509397a79e7SCédric Le Goater     pnv_chip_core_sanitize(chip, &error);
1510397a79e7SCédric Le Goater     if (error) {
1511397a79e7SCédric Le Goater         error_propagate(errp, error);
1512397a79e7SCédric Le Goater         return;
1513397a79e7SCédric Le Goater     }
1514d2fd9612SCédric Le Goater 
15154fa28f23SGreg Kurz     chip->cores = g_new0(PnvCore *, chip->nr_cores);
1516d2fd9612SCédric Le Goater 
1517d2fd9612SCédric Le Goater     for (i = 0, core_hwid = 0; (core_hwid < sizeof(chip->cores_mask) * 8)
1518d2fd9612SCédric Le Goater              && (i < chip->nr_cores); core_hwid++) {
1519d2fd9612SCédric Le Goater         char core_name[32];
15204fa28f23SGreg Kurz         PnvCore *pnv_core;
1521c035851aSCédric Le Goater         uint64_t xscom_core_base;
1522d2fd9612SCédric Le Goater 
1523d2fd9612SCédric Le Goater         if (!(chip->cores_mask & (1ull << core_hwid))) {
1524d2fd9612SCédric Le Goater             continue;
1525d2fd9612SCédric Le Goater         }
1526d2fd9612SCédric Le Goater 
15274fa28f23SGreg Kurz         pnv_core = PNV_CORE(object_new(typename));
15284fa28f23SGreg Kurz 
1529d2fd9612SCédric Le Goater         snprintf(core_name, sizeof(core_name), "core[%d]", core_hwid);
15304fa28f23SGreg Kurz         object_property_add_child(OBJECT(chip), core_name, OBJECT(pnv_core),
15314fa28f23SGreg Kurz                                   &error_abort);
15324fa28f23SGreg Kurz         chip->cores[i] = pnv_core;
1533fe6b6346SLike Xu         object_property_set_int(OBJECT(pnv_core), ms->smp.threads, "nr-threads",
1534d2fd9612SCédric Le Goater                                 &error_fatal);
1535d2fd9612SCédric Le Goater         object_property_set_int(OBJECT(pnv_core), core_hwid,
1536d2fd9612SCédric Le Goater                                 CPU_CORE_PROP_CORE_ID, &error_fatal);
1537d2fd9612SCédric Le Goater         object_property_set_int(OBJECT(pnv_core),
1538d2fd9612SCédric Le Goater                                 pcc->core_pir(chip, core_hwid),
1539d2fd9612SCédric Le Goater                                 "pir", &error_fatal);
1540158e17a6SGreg Kurz         object_property_set_link(OBJECT(pnv_core), OBJECT(chip), "chip",
1541158e17a6SGreg Kurz                                  &error_abort);
1542d2fd9612SCédric Le Goater         object_property_set_bool(OBJECT(pnv_core), true, "realized",
1543d2fd9612SCédric Le Goater                                  &error_fatal);
154424ece072SCédric Le Goater 
154524ece072SCédric Le Goater         /* Each core has an XSCOM MMIO region */
1546c4b2c40cSGreg Kurz         xscom_core_base = pcc->xscom_core_base(chip, core_hwid);
1547c035851aSCédric Le Goater 
1548c035851aSCédric Le Goater         pnv_xscom_add_subregion(chip, xscom_core_base,
15494fa28f23SGreg Kurz                                 &pnv_core->xscom_regs);
1550d2fd9612SCédric Le Goater         i++;
1551d2fd9612SCédric Le Goater     }
155251c04728SCédric Le Goater }
155351c04728SCédric Le Goater 
155451c04728SCédric Le Goater static void pnv_chip_realize(DeviceState *dev, Error **errp)
155551c04728SCédric Le Goater {
155651c04728SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
155751c04728SCédric Le Goater     Error *error = NULL;
155851c04728SCédric Le Goater 
155951c04728SCédric Le Goater     /* Cores */
156051c04728SCédric Le Goater     pnv_chip_core_realize(chip, &error);
156151c04728SCédric Le Goater     if (error) {
156251c04728SCédric Le Goater         error_propagate(errp, error);
156351c04728SCédric Le Goater         return;
156451c04728SCédric Le Goater     }
1565e997040eSCédric Le Goater }
1566e997040eSCédric Le Goater 
1567e997040eSCédric Le Goater static Property pnv_chip_properties[] = {
1568e997040eSCédric Le Goater     DEFINE_PROP_UINT32("chip-id", PnvChip, chip_id, 0),
1569e997040eSCédric Le Goater     DEFINE_PROP_UINT64("ram-start", PnvChip, ram_start, 0),
1570e997040eSCédric Le Goater     DEFINE_PROP_UINT64("ram-size", PnvChip, ram_size, 0),
1571397a79e7SCédric Le Goater     DEFINE_PROP_UINT32("nr-cores", PnvChip, nr_cores, 1),
1572397a79e7SCédric Le Goater     DEFINE_PROP_UINT64("cores-mask", PnvChip, cores_mask, 0x0),
1573e997040eSCédric Le Goater     DEFINE_PROP_END_OF_LIST(),
1574e997040eSCédric Le Goater };
1575e997040eSCédric Le Goater 
1576e997040eSCédric Le Goater static void pnv_chip_class_init(ObjectClass *klass, void *data)
1577e997040eSCédric Le Goater {
1578e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1579e997040eSCédric Le Goater 
15809d169fb3SThomas Huth     set_bit(DEVICE_CATEGORY_CPU, dc->categories);
1581e997040eSCédric Le Goater     dc->realize = pnv_chip_realize;
1582e997040eSCédric Le Goater     dc->props = pnv_chip_properties;
1583e997040eSCédric Le Goater     dc->desc = "PowerNV Chip";
1584e997040eSCédric Le Goater }
1585e997040eSCédric Le Goater 
1586119eaa9dSCédric Le Goater PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir)
1587119eaa9dSCédric Le Goater {
1588119eaa9dSCédric Le Goater     int i, j;
1589119eaa9dSCédric Le Goater 
1590119eaa9dSCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
1591119eaa9dSCédric Le Goater         PnvCore *pc = chip->cores[i];
1592119eaa9dSCédric Le Goater         CPUCore *cc = CPU_CORE(pc);
1593119eaa9dSCédric Le Goater 
1594119eaa9dSCédric Le Goater         for (j = 0; j < cc->nr_threads; j++) {
1595119eaa9dSCédric Le Goater             if (ppc_cpu_pir(pc->threads[j]) == pir) {
1596119eaa9dSCédric Le Goater                 return pc->threads[j];
1597119eaa9dSCédric Le Goater             }
1598119eaa9dSCédric Le Goater         }
1599119eaa9dSCédric Le Goater     }
1600119eaa9dSCédric Le Goater     return NULL;
1601119eaa9dSCédric Le Goater }
1602119eaa9dSCédric Le Goater 
160354f59d78SCédric Le Goater static ICSState *pnv_ics_get(XICSFabric *xi, int irq)
160454f59d78SCédric Le Goater {
1605b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xi);
160654f59d78SCédric Le Goater     int i;
160754f59d78SCédric Le Goater 
160854f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
160977864267SCédric Le Goater         Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
161077864267SCédric Le Goater 
161177864267SCédric Le Goater         if (ics_valid_irq(&chip8->psi.ics, irq)) {
161277864267SCédric Le Goater             return &chip8->psi.ics;
161354f59d78SCédric Le Goater         }
161454f59d78SCédric Le Goater     }
161554f59d78SCédric Le Goater     return NULL;
161654f59d78SCédric Le Goater }
161754f59d78SCédric Le Goater 
161854f59d78SCédric Le Goater static void pnv_ics_resend(XICSFabric *xi)
161954f59d78SCédric Le Goater {
1620b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xi);
162154f59d78SCédric Le Goater     int i;
162254f59d78SCédric Le Goater 
162354f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
162477864267SCédric Le Goater         Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
162577864267SCédric Le Goater         ics_resend(&chip8->psi.ics);
162654f59d78SCédric Le Goater     }
162754f59d78SCédric Le Goater }
162854f59d78SCédric Le Goater 
162936fc6f08SCédric Le Goater static ICPState *pnv_icp_get(XICSFabric *xi, int pir)
163036fc6f08SCédric Le Goater {
163136fc6f08SCédric Le Goater     PowerPCCPU *cpu = ppc_get_vcpu_by_pir(pir);
163236fc6f08SCédric Le Goater 
1633956b8f46SCédric Le Goater     return cpu ? ICP(pnv_cpu_state(cpu)->intc) : NULL;
163436fc6f08SCédric Le Goater }
163536fc6f08SCédric Le Goater 
163647fea43aSCédric Le Goater static void pnv_pic_print_info(InterruptStatsProvider *obj,
163747fea43aSCédric Le Goater                                Monitor *mon)
163847fea43aSCédric Le Goater {
1639b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
164054f59d78SCédric Le Goater     int i;
164147fea43aSCédric Le Goater     CPUState *cs;
164247fea43aSCédric Le Goater 
164347fea43aSCédric Le Goater     CPU_FOREACH(cs) {
164447fea43aSCédric Le Goater         PowerPCCPU *cpu = POWERPC_CPU(cs);
164547fea43aSCédric Le Goater 
164685913070SGreg Kurz         /* XXX: loop on each chip/core/thread instead of CPU_FOREACH() */
164785913070SGreg Kurz         PNV_CHIP_GET_CLASS(pnv->chips[0])->intc_print_info(pnv->chips[0], cpu,
164885913070SGreg Kurz                                                            mon);
1649d8e4aad5SCédric Le Goater     }
165054f59d78SCédric Le Goater 
165154f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
1652d8e4aad5SCédric Le Goater         PNV_CHIP_GET_CLASS(pnv->chips[i])->pic_print_info(pnv->chips[i], mon);
165354f59d78SCédric Le Goater     }
165447fea43aSCédric Le Goater }
165547fea43aSCédric Le Goater 
1656c722579eSCédric Le Goater static int pnv_match_nvt(XiveFabric *xfb, uint8_t format,
1657c722579eSCédric Le Goater                          uint8_t nvt_blk, uint32_t nvt_idx,
1658c722579eSCédric Le Goater                          bool cam_ignore, uint8_t priority,
1659c722579eSCédric Le Goater                          uint32_t logic_serv,
1660c722579eSCédric Le Goater                          XiveTCTXMatch *match)
1661c722579eSCédric Le Goater {
1662c722579eSCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xfb);
1663c722579eSCédric Le Goater     int total_count = 0;
1664c722579eSCédric Le Goater     int i;
1665c722579eSCédric Le Goater 
1666c722579eSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
1667c722579eSCédric Le Goater         Pnv9Chip *chip9 = PNV9_CHIP(pnv->chips[i]);
1668c722579eSCédric Le Goater         XivePresenter *xptr = XIVE_PRESENTER(&chip9->xive);
1669c722579eSCédric Le Goater         XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr);
1670c722579eSCédric Le Goater         int count;
1671c722579eSCédric Le Goater 
1672c722579eSCédric Le Goater         count = xpc->match_nvt(xptr, format, nvt_blk, nvt_idx, cam_ignore,
1673c722579eSCédric Le Goater                                priority, logic_serv, match);
1674c722579eSCédric Le Goater 
1675c722579eSCédric Le Goater         if (count < 0) {
1676c722579eSCédric Le Goater             return count;
1677c722579eSCédric Le Goater         }
1678c722579eSCédric Le Goater 
1679c722579eSCédric Le Goater         total_count += count;
1680c722579eSCédric Le Goater     }
1681c722579eSCédric Le Goater 
1682c722579eSCédric Le Goater     return total_count;
1683c722579eSCédric Le Goater }
1684c722579eSCédric Le Goater 
16855373c61dSCédric Le Goater PnvChip *pnv_get_chip(uint32_t chip_id)
16865373c61dSCédric Le Goater {
16875373c61dSCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine());
16885373c61dSCédric Le Goater     int i;
16895373c61dSCédric Le Goater 
16905373c61dSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
16915373c61dSCédric Le Goater         PnvChip *chip = pnv->chips[i];
16925373c61dSCédric Le Goater         if (chip->chip_id == chip_id) {
16935373c61dSCédric Le Goater             return chip;
16945373c61dSCédric Le Goater         }
16955373c61dSCédric Le Goater     }
16965373c61dSCédric Le Goater     return NULL;
16975373c61dSCédric Le Goater }
16985373c61dSCédric Le Goater 
1699e997040eSCédric Le Goater static void pnv_get_num_chips(Object *obj, Visitor *v, const char *name,
1700e997040eSCédric Le Goater                               void *opaque, Error **errp)
1701e997040eSCédric Le Goater {
1702b168a138SCédric Le Goater     visit_type_uint32(v, name, &PNV_MACHINE(obj)->num_chips, errp);
1703e997040eSCédric Le Goater }
1704e997040eSCédric Le Goater 
1705e997040eSCédric Le Goater static void pnv_set_num_chips(Object *obj, Visitor *v, const char *name,
1706e997040eSCédric Le Goater                               void *opaque, Error **errp)
1707e997040eSCédric Le Goater {
1708b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
1709e997040eSCédric Le Goater     uint32_t num_chips;
1710e997040eSCédric Le Goater     Error *local_err = NULL;
1711e997040eSCédric Le Goater 
1712e997040eSCédric Le Goater     visit_type_uint32(v, name, &num_chips, &local_err);
1713e997040eSCédric Le Goater     if (local_err) {
1714e997040eSCédric Le Goater         error_propagate(errp, local_err);
1715e997040eSCédric Le Goater         return;
1716e997040eSCédric Le Goater     }
1717e997040eSCédric Le Goater 
1718e997040eSCédric Le Goater     /*
1719e997040eSCédric Le Goater      * TODO: should we decide on how many chips we can create based
1720e997040eSCédric Le Goater      * on #cores and Venice vs. Murano vs. Naples chip type etc...,
1721e997040eSCédric Le Goater      */
1722e997040eSCédric Le Goater     if (!is_power_of_2(num_chips) || num_chips > 4) {
1723e997040eSCédric Le Goater         error_setg(errp, "invalid number of chips: '%d'", num_chips);
1724e997040eSCédric Le Goater         return;
1725e997040eSCédric Le Goater     }
1726e997040eSCédric Le Goater 
1727e997040eSCédric Le Goater     pnv->num_chips = num_chips;
1728e997040eSCédric Le Goater }
1729e997040eSCédric Le Goater 
173077864267SCédric Le Goater static void pnv_machine_instance_init(Object *obj)
1731e997040eSCédric Le Goater {
1732b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
1733e997040eSCédric Le Goater     pnv->num_chips = 1;
1734e997040eSCédric Le Goater }
1735e997040eSCédric Le Goater 
1736b168a138SCédric Le Goater static void pnv_machine_class_props_init(ObjectClass *oc)
1737e997040eSCédric Le Goater {
17381e507bb0SMarc-André Lureau     object_class_property_add(oc, "num-chips", "uint32",
1739e997040eSCédric Le Goater                               pnv_get_num_chips, pnv_set_num_chips,
1740e997040eSCédric Le Goater                               NULL, NULL, NULL);
1741e997040eSCédric Le Goater     object_class_property_set_description(oc, "num-chips",
1742e997040eSCédric Le Goater                               "Specifies the number of processor chips",
1743e997040eSCédric Le Goater                               NULL);
17449e933f4aSBenjamin Herrenschmidt }
17459e933f4aSBenjamin Herrenschmidt 
1746f30c843cSCédric Le Goater static void pnv_machine_power8_class_init(ObjectClass *oc, void *data)
17479e933f4aSBenjamin Herrenschmidt {
17489e933f4aSBenjamin Herrenschmidt     MachineClass *mc = MACHINE_CLASS(oc);
174936fc6f08SCédric Le Goater     XICSFabricClass *xic = XICS_FABRIC_CLASS(oc);
1750d76f2da7SGreg Kurz     PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc);
1751d76f2da7SGreg Kurz     static const char compat[] = "qemu,powernv8\0qemu,powernv\0ibm,powernv";
1752f30c843cSCédric Le Goater 
1753f30c843cSCédric Le Goater     mc->desc = "IBM PowerNV (Non-Virtualized) POWER8";
1754f30c843cSCédric Le Goater     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0");
1755f30c843cSCédric Le Goater 
1756f30c843cSCédric Le Goater     xic->icp_get = pnv_icp_get;
1757f30c843cSCédric Le Goater     xic->ics_get = pnv_ics_get;
1758f30c843cSCédric Le Goater     xic->ics_resend = pnv_ics_resend;
1759d76f2da7SGreg Kurz 
1760d76f2da7SGreg Kurz     pmc->compat = compat;
1761d76f2da7SGreg Kurz     pmc->compat_size = sizeof(compat);
1762f30c843cSCédric Le Goater }
1763f30c843cSCédric Le Goater 
1764f30c843cSCédric Le Goater static void pnv_machine_power9_class_init(ObjectClass *oc, void *data)
1765f30c843cSCédric Le Goater {
1766f30c843cSCédric Le Goater     MachineClass *mc = MACHINE_CLASS(oc);
1767c722579eSCédric Le Goater     XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc);
1768d76f2da7SGreg Kurz     PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc);
1769d76f2da7SGreg Kurz     static const char compat[] = "qemu,powernv9\0ibm,powernv";
1770f30c843cSCédric Le Goater 
1771f30c843cSCédric Le Goater     mc->desc = "IBM PowerNV (Non-Virtualized) POWER9";
1772f30c843cSCédric Le Goater     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.0");
1773c722579eSCédric Le Goater     xfc->match_nvt = pnv_match_nvt;
1774f30c843cSCédric Le Goater 
1775f30c843cSCédric Le Goater     mc->alias = "powernv";
1776d76f2da7SGreg Kurz 
1777d76f2da7SGreg Kurz     pmc->compat = compat;
1778d76f2da7SGreg Kurz     pmc->compat_size = sizeof(compat);
17797a90c6a1SGreg Kurz     pmc->dt_power_mgt = pnv_dt_power_mgt;
1780f30c843cSCédric Le Goater }
1781f30c843cSCédric Le Goater 
17822b548a42SCédric Le Goater static void pnv_machine_power10_class_init(ObjectClass *oc, void *data)
17832b548a42SCédric Le Goater {
17842b548a42SCédric Le Goater     MachineClass *mc = MACHINE_CLASS(oc);
1785d76f2da7SGreg Kurz     PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc);
1786d76f2da7SGreg Kurz     static const char compat[] = "qemu,powernv10\0ibm,powernv";
17872b548a42SCédric Le Goater 
17882b548a42SCédric Le Goater     mc->desc = "IBM PowerNV (Non-Virtualized) POWER10";
17892b548a42SCédric Le Goater     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power10_v1.0");
1790d76f2da7SGreg Kurz 
1791d76f2da7SGreg Kurz     pmc->compat = compat;
1792d76f2da7SGreg Kurz     pmc->compat_size = sizeof(compat);
17937a90c6a1SGreg Kurz     pmc->dt_power_mgt = pnv_dt_power_mgt;
17942b548a42SCédric Le Goater }
17952b548a42SCédric Le Goater 
1796f30c843cSCédric Le Goater static void pnv_machine_class_init(ObjectClass *oc, void *data)
1797f30c843cSCédric Le Goater {
1798f30c843cSCédric Le Goater     MachineClass *mc = MACHINE_CLASS(oc);
179947fea43aSCédric Le Goater     InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc);
18009e933f4aSBenjamin Herrenschmidt 
18019e933f4aSBenjamin Herrenschmidt     mc->desc = "IBM PowerNV (Non-Virtualized)";
1802b168a138SCédric Le Goater     mc->init = pnv_init;
1803b168a138SCédric Le Goater     mc->reset = pnv_reset;
18049e933f4aSBenjamin Herrenschmidt     mc->max_cpus = MAX_CPUS;
180559b7c1c2SBalamuruhan S     /* Pnv provides a AHCI device for storage */
180659b7c1c2SBalamuruhan S     mc->block_default_type = IF_IDE;
18079e933f4aSBenjamin Herrenschmidt     mc->no_parallel = 1;
18089e933f4aSBenjamin Herrenschmidt     mc->default_boot_order = NULL;
1809f1d18b0aSJoel Stanley     /*
1810f1d18b0aSJoel Stanley      * RAM defaults to less than 2048 for 32-bit hosts, and large
1811f1d18b0aSJoel Stanley      * enough to fit the maximum initrd size at it's load address
1812f1d18b0aSJoel Stanley      */
1813f1d18b0aSJoel Stanley     mc->default_ram_size = INITRD_LOAD_ADDR + INITRD_MAX_SIZE;
181447fea43aSCédric Le Goater     ispc->print_info = pnv_pic_print_info;
1815e997040eSCédric Le Goater 
1816b168a138SCédric Le Goater     pnv_machine_class_props_init(oc);
18179e933f4aSBenjamin Herrenschmidt }
18189e933f4aSBenjamin Herrenschmidt 
181977864267SCédric Le Goater #define DEFINE_PNV8_CHIP_TYPE(type, class_initfn) \
1820beba5c0fSIgor Mammedov     {                                             \
1821beba5c0fSIgor Mammedov         .name          = type,                    \
1822beba5c0fSIgor Mammedov         .class_init    = class_initfn,            \
182377864267SCédric Le Goater         .parent        = TYPE_PNV8_CHIP,          \
182477864267SCédric Le Goater     }
182577864267SCédric Le Goater 
182677864267SCédric Le Goater #define DEFINE_PNV9_CHIP_TYPE(type, class_initfn) \
182777864267SCédric Le Goater     {                                             \
182877864267SCédric Le Goater         .name          = type,                    \
182977864267SCédric Le Goater         .class_init    = class_initfn,            \
183077864267SCédric Le Goater         .parent        = TYPE_PNV9_CHIP,          \
1831beba5c0fSIgor Mammedov     }
1832beba5c0fSIgor Mammedov 
18332b548a42SCédric Le Goater #define DEFINE_PNV10_CHIP_TYPE(type, class_initfn) \
18342b548a42SCédric Le Goater     {                                              \
18352b548a42SCédric Le Goater         .name          = type,                     \
18362b548a42SCédric Le Goater         .class_init    = class_initfn,             \
18372b548a42SCédric Le Goater         .parent        = TYPE_PNV10_CHIP,          \
18382b548a42SCédric Le Goater     }
18392b548a42SCédric Le Goater 
1840beba5c0fSIgor Mammedov static const TypeInfo types[] = {
18411aba8716SCédric Le Goater     {
18422b548a42SCédric Le Goater         .name          = MACHINE_TYPE_NAME("powernv10"),
18432b548a42SCédric Le Goater         .parent        = TYPE_PNV_MACHINE,
18442b548a42SCédric Le Goater         .class_init    = pnv_machine_power10_class_init,
18452b548a42SCédric Le Goater     },
18462b548a42SCédric Le Goater     {
18471aba8716SCédric Le Goater         .name          = MACHINE_TYPE_NAME("powernv9"),
18481aba8716SCédric Le Goater         .parent        = TYPE_PNV_MACHINE,
18491aba8716SCédric Le Goater         .class_init    = pnv_machine_power9_class_init,
1850c722579eSCédric Le Goater         .interfaces = (InterfaceInfo[]) {
1851c722579eSCédric Le Goater             { TYPE_XIVE_FABRIC },
1852c722579eSCédric Le Goater             { },
1853c722579eSCédric Le Goater         },
18541aba8716SCédric Le Goater     },
18551aba8716SCédric Le Goater     {
18561aba8716SCédric Le Goater         .name          = MACHINE_TYPE_NAME("powernv8"),
18571aba8716SCédric Le Goater         .parent        = TYPE_PNV_MACHINE,
18581aba8716SCédric Le Goater         .class_init    = pnv_machine_power8_class_init,
18591aba8716SCédric Le Goater         .interfaces = (InterfaceInfo[]) {
18601aba8716SCédric Le Goater             { TYPE_XICS_FABRIC },
18611aba8716SCédric Le Goater             { },
18621aba8716SCédric Le Goater         },
18631aba8716SCédric Le Goater     },
1864beba5c0fSIgor Mammedov     {
1865b168a138SCédric Le Goater         .name          = TYPE_PNV_MACHINE,
18669e933f4aSBenjamin Herrenschmidt         .parent        = TYPE_MACHINE,
1867f30c843cSCédric Le Goater         .abstract       = true,
18689e933f4aSBenjamin Herrenschmidt         .instance_size = sizeof(PnvMachineState),
186977864267SCédric Le Goater         .instance_init = pnv_machine_instance_init,
1870b168a138SCédric Le Goater         .class_init    = pnv_machine_class_init,
1871d76f2da7SGreg Kurz         .class_size    = sizeof(PnvMachineClass),
187236fc6f08SCédric Le Goater         .interfaces = (InterfaceInfo[]) {
187347fea43aSCédric Le Goater             { TYPE_INTERRUPT_STATS_PROVIDER },
187436fc6f08SCédric Le Goater             { },
187536fc6f08SCédric Le Goater         },
1876beba5c0fSIgor Mammedov     },
1877beba5c0fSIgor Mammedov     {
1878beba5c0fSIgor Mammedov         .name          = TYPE_PNV_CHIP,
1879beba5c0fSIgor Mammedov         .parent        = TYPE_SYS_BUS_DEVICE,
1880beba5c0fSIgor Mammedov         .class_init    = pnv_chip_class_init,
1881beba5c0fSIgor Mammedov         .instance_size = sizeof(PnvChip),
1882beba5c0fSIgor Mammedov         .class_size    = sizeof(PnvChipClass),
1883beba5c0fSIgor Mammedov         .abstract      = true,
1884beba5c0fSIgor Mammedov     },
188577864267SCédric Le Goater 
188677864267SCédric Le Goater     /*
18872b548a42SCédric Le Goater      * P10 chip and variants
18882b548a42SCédric Le Goater      */
18892b548a42SCédric Le Goater     {
18902b548a42SCédric Le Goater         .name          = TYPE_PNV10_CHIP,
18912b548a42SCédric Le Goater         .parent        = TYPE_PNV_CHIP,
18922b548a42SCédric Le Goater         .instance_init = pnv_chip_power10_instance_init,
18932b548a42SCédric Le Goater         .instance_size = sizeof(Pnv10Chip),
18942b548a42SCédric Le Goater     },
18952b548a42SCédric Le Goater     DEFINE_PNV10_CHIP_TYPE(TYPE_PNV_CHIP_POWER10, pnv_chip_power10_class_init),
18962b548a42SCédric Le Goater 
18972b548a42SCédric Le Goater     /*
189877864267SCédric Le Goater      * P9 chip and variants
189977864267SCédric Le Goater      */
190077864267SCédric Le Goater     {
190177864267SCédric Le Goater         .name          = TYPE_PNV9_CHIP,
190277864267SCédric Le Goater         .parent        = TYPE_PNV_CHIP,
190377864267SCédric Le Goater         .instance_init = pnv_chip_power9_instance_init,
190477864267SCédric Le Goater         .instance_size = sizeof(Pnv9Chip),
190577864267SCédric Le Goater     },
190677864267SCédric Le Goater     DEFINE_PNV9_CHIP_TYPE(TYPE_PNV_CHIP_POWER9, pnv_chip_power9_class_init),
190777864267SCédric Le Goater 
190877864267SCédric Le Goater     /*
190977864267SCédric Le Goater      * P8 chip and variants
191077864267SCédric Le Goater      */
191177864267SCédric Le Goater     {
191277864267SCédric Le Goater         .name          = TYPE_PNV8_CHIP,
191377864267SCédric Le Goater         .parent        = TYPE_PNV_CHIP,
191477864267SCédric Le Goater         .instance_init = pnv_chip_power8_instance_init,
191577864267SCédric Le Goater         .instance_size = sizeof(Pnv8Chip),
191677864267SCédric Le Goater     },
191777864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8, pnv_chip_power8_class_init),
191877864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8E, pnv_chip_power8e_class_init),
191977864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8NVL,
1920beba5c0fSIgor Mammedov                           pnv_chip_power8nvl_class_init),
19219e933f4aSBenjamin Herrenschmidt };
19229e933f4aSBenjamin Herrenschmidt 
1923beba5c0fSIgor Mammedov DEFINE_TYPES(types)
1924