xref: /qemu/hw/ppc/pnv.c (revision 70c059e9)
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 {
564b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine());
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 
1123*70c059e9SGreg Kurz static uint32_t pnv_chip_power8_xscom_pcba(PnvChip *chip, uint64_t addr)
1124*70c059e9SGreg Kurz {
1125*70c059e9SGreg Kurz     addr &= (PNV_XSCOM_SIZE - 1);
1126*70c059e9SGreg Kurz     return ((addr >> 4) & ~0xfull) | ((addr >> 3) & 0xf);
1127*70c059e9SGreg Kurz }
1128*70c059e9SGreg 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_type = PNV_CHIP_POWER8E;
1135e997040eSCédric Le Goater     k->chip_cfam_id = 0x221ef04980000000ull;  /* P8 Murano DD2.1 */
1136397a79e7SCédric Le Goater     k->cores_mask = POWER8E_CORE_MASK;
1137631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
1138d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
1139d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power8_intc_reset;
11400990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power8_intc_destroy;
114185913070SGreg Kurz     k->intc_print_info = pnv_chip_power8_intc_print_info;
114204026890SCédric Le Goater     k->isa_create = pnv_chip_power8_isa_create;
1143eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
1144d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
1145c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power8_xscom_core_base;
1146*70c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power8_xscom_pcba;
1147e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8E";
114877864267SCédric Le Goater 
114977864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
115077864267SCédric Le Goater                                     &k->parent_realize);
1151e997040eSCédric Le Goater }
1152e997040eSCédric Le Goater 
1153e997040eSCédric Le Goater static void pnv_chip_power8_class_init(ObjectClass *klass, void *data)
1154e997040eSCédric Le Goater {
1155e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1156e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1157e997040eSCédric Le Goater 
1158e997040eSCédric Le Goater     k->chip_type = PNV_CHIP_POWER8;
1159e997040eSCédric Le Goater     k->chip_cfam_id = 0x220ea04980000000ull; /* P8 Venice DD2.0 */
1160397a79e7SCédric Le Goater     k->cores_mask = POWER8_CORE_MASK;
1161631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
1162d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
1163d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power8_intc_reset;
11640990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power8_intc_destroy;
116585913070SGreg Kurz     k->intc_print_info = pnv_chip_power8_intc_print_info;
116604026890SCédric Le Goater     k->isa_create = pnv_chip_power8_isa_create;
1167eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
1168d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
1169c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power8_xscom_core_base;
1170*70c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power8_xscom_pcba;
1171e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8";
117277864267SCédric Le Goater 
117377864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
117477864267SCédric Le Goater                                     &k->parent_realize);
1175e997040eSCédric Le Goater }
1176e997040eSCédric Le Goater 
1177e997040eSCédric Le Goater static void pnv_chip_power8nvl_class_init(ObjectClass *klass, void *data)
1178e997040eSCédric Le Goater {
1179e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1180e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1181e997040eSCédric Le Goater 
1182e997040eSCédric Le Goater     k->chip_type = PNV_CHIP_POWER8NVL;
1183e997040eSCédric Le Goater     k->chip_cfam_id = 0x120d304980000000ull;  /* P8 Naples DD1.0 */
1184397a79e7SCédric Le Goater     k->cores_mask = POWER8_CORE_MASK;
1185631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
1186d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
1187d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power8_intc_reset;
11880990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power8_intc_destroy;
118985913070SGreg Kurz     k->intc_print_info = pnv_chip_power8_intc_print_info;
119004026890SCédric Le Goater     k->isa_create = pnv_chip_power8nvl_isa_create;
1191eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
1192d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
1193c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power8_xscom_core_base;
1194*70c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power8_xscom_pcba;
1195e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8NVL";
119677864267SCédric Le Goater 
119777864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
119877864267SCédric Le Goater                                     &k->parent_realize);
119977864267SCédric Le Goater }
120077864267SCédric Le Goater 
120177864267SCédric Le Goater static void pnv_chip_power9_instance_init(Object *obj)
120277864267SCédric Le Goater {
12032dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(obj);
12042dfa91a2SCédric Le Goater 
12052dfa91a2SCédric Le Goater     object_initialize_child(obj, "xive", &chip9->xive, sizeof(chip9->xive),
12062dfa91a2SCédric Le Goater                             TYPE_PNV_XIVE, &error_abort, NULL);
1207c38536bcSCédric Le Goater 
1208c38536bcSCédric Le Goater     object_initialize_child(obj, "psi",  &chip9->psi, sizeof(chip9->psi),
1209c38536bcSCédric Le Goater                             TYPE_PNV9_PSI, &error_abort, NULL);
121015376c66SCédric Le Goater 
121115376c66SCédric Le Goater     object_initialize_child(obj, "lpc",  &chip9->lpc, sizeof(chip9->lpc),
121215376c66SCédric Le Goater                             TYPE_PNV9_LPC, &error_abort, NULL);
12136598a70dSCédric Le Goater 
12146598a70dSCédric Le Goater     object_initialize_child(obj, "occ",  &chip9->occ, sizeof(chip9->occ),
12156598a70dSCédric Le Goater                             TYPE_PNV9_OCC, &error_abort, NULL);
12163887d241SBalamuruhan S 
12173887d241SBalamuruhan S     object_initialize_child(obj, "homer",  &chip9->homer, sizeof(chip9->homer),
12183887d241SBalamuruhan S                             TYPE_PNV9_HOMER, &error_abort, NULL);
121977864267SCédric Le Goater }
122077864267SCédric Le Goater 
12215dad902cSCédric Le Goater static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error **errp)
12225dad902cSCédric Le Goater {
12235dad902cSCédric Le Goater     PnvChip *chip = PNV_CHIP(chip9);
12245dad902cSCédric Le Goater     int i;
12255dad902cSCédric Le Goater 
12265dad902cSCédric Le Goater     chip9->nr_quads = DIV_ROUND_UP(chip->nr_cores, 4);
12275dad902cSCédric Le Goater     chip9->quads = g_new0(PnvQuad, chip9->nr_quads);
12285dad902cSCédric Le Goater 
12295dad902cSCédric Le Goater     for (i = 0; i < chip9->nr_quads; i++) {
12305dad902cSCédric Le Goater         char eq_name[32];
12315dad902cSCédric Le Goater         PnvQuad *eq = &chip9->quads[i];
12324fa28f23SGreg Kurz         PnvCore *pnv_core = chip->cores[i * 4];
12335dad902cSCédric Le Goater         int core_id = CPU_CORE(pnv_core)->core_id;
12345dad902cSCédric Le Goater 
12355dad902cSCédric Le Goater         snprintf(eq_name, sizeof(eq_name), "eq[%d]", core_id);
1236bc4c406cSPhilippe Mathieu-Daudé         object_initialize_child(OBJECT(chip), eq_name, eq, sizeof(*eq),
1237bc4c406cSPhilippe Mathieu-Daudé                                 TYPE_PNV_QUAD, &error_fatal, NULL);
12385dad902cSCédric Le Goater 
12395dad902cSCédric Le Goater         object_property_set_int(OBJECT(eq), core_id, "id", &error_fatal);
12405dad902cSCédric Le Goater         object_property_set_bool(OBJECT(eq), true, "realized", &error_fatal);
12415dad902cSCédric Le Goater 
12425dad902cSCédric Le Goater         pnv_xscom_add_subregion(chip, PNV9_XSCOM_EQ_BASE(eq->id),
12435dad902cSCédric Le Goater                                 &eq->xscom_regs);
12445dad902cSCédric Le Goater     }
12455dad902cSCédric Le Goater }
12465dad902cSCédric Le Goater 
124777864267SCédric Le Goater static void pnv_chip_power9_realize(DeviceState *dev, Error **errp)
124877864267SCédric Le Goater {
124977864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
12502dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(dev);
12512dfa91a2SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
1252c38536bcSCédric Le Goater     Pnv9Psi *psi9 = &chip9->psi;
125377864267SCédric Le Goater     Error *local_err = NULL;
125477864267SCédric Le Goater 
1255709044fdSCédric Le Goater     /* XSCOM bridge is first */
1256709044fdSCédric Le Goater     pnv_xscom_realize(chip, PNV9_XSCOM_SIZE, &local_err);
1257709044fdSCédric Le Goater     if (local_err) {
1258709044fdSCédric Le Goater         error_propagate(errp, local_err);
1259709044fdSCédric Le Goater         return;
1260709044fdSCédric Le Goater     }
1261709044fdSCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV9_XSCOM_BASE(chip));
1262709044fdSCédric Le Goater 
126377864267SCédric Le Goater     pcc->parent_realize(dev, &local_err);
126477864267SCédric Le Goater     if (local_err) {
126577864267SCédric Le Goater         error_propagate(errp, local_err);
126677864267SCédric Le Goater         return;
126777864267SCédric Le Goater     }
12682dfa91a2SCédric Le Goater 
12695dad902cSCédric Le Goater     pnv_chip_quad_realize(chip9, &local_err);
12705dad902cSCédric Le Goater     if (local_err) {
12715dad902cSCédric Le Goater         error_propagate(errp, local_err);
12725dad902cSCédric Le Goater         return;
12735dad902cSCédric Le Goater     }
12745dad902cSCédric Le Goater 
12752dfa91a2SCédric Le Goater     /* XIVE interrupt controller (POWER9) */
12762dfa91a2SCédric Le Goater     object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_IC_BASE(chip),
12772dfa91a2SCédric Le Goater                             "ic-bar", &error_fatal);
12782dfa91a2SCédric Le Goater     object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_VC_BASE(chip),
12792dfa91a2SCédric Le Goater                             "vc-bar", &error_fatal);
12802dfa91a2SCédric Le Goater     object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_PC_BASE(chip),
12812dfa91a2SCédric Le Goater                             "pc-bar", &error_fatal);
12822dfa91a2SCédric Le Goater     object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_TM_BASE(chip),
12832dfa91a2SCédric Le Goater                             "tm-bar", &error_fatal);
12847ae54cc3SGreg Kurz     object_property_set_link(OBJECT(&chip9->xive), OBJECT(chip), "chip",
12857ae54cc3SGreg Kurz                              &error_abort);
12862dfa91a2SCédric Le Goater     object_property_set_bool(OBJECT(&chip9->xive), true, "realized",
12872dfa91a2SCédric Le Goater                              &local_err);
12882dfa91a2SCédric Le Goater     if (local_err) {
12892dfa91a2SCédric Le Goater         error_propagate(errp, local_err);
12902dfa91a2SCédric Le Goater         return;
12912dfa91a2SCédric Le Goater     }
12922dfa91a2SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_XIVE_BASE,
12932dfa91a2SCédric Le Goater                             &chip9->xive.xscom_regs);
1294c38536bcSCédric Le Goater 
1295c38536bcSCédric Le Goater     /* Processor Service Interface (PSI) Host Bridge */
1296c38536bcSCédric Le Goater     object_property_set_int(OBJECT(&chip9->psi), PNV9_PSIHB_BASE(chip),
1297c38536bcSCédric Le Goater                             "bar", &error_fatal);
1298c38536bcSCédric Le Goater     object_property_set_bool(OBJECT(&chip9->psi), true, "realized", &local_err);
1299c38536bcSCédric Le Goater     if (local_err) {
1300c38536bcSCédric Le Goater         error_propagate(errp, local_err);
1301c38536bcSCédric Le Goater         return;
1302c38536bcSCédric Le Goater     }
1303c38536bcSCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_PSIHB_BASE,
1304c38536bcSCédric Le Goater                             &PNV_PSI(psi9)->xscom_regs);
130515376c66SCédric Le Goater 
130615376c66SCédric Le Goater     /* LPC */
1307b63f3893SGreg Kurz     object_property_set_link(OBJECT(&chip9->lpc), OBJECT(&chip9->psi), "psi",
1308b63f3893SGreg Kurz                              &error_abort);
130915376c66SCédric Le Goater     object_property_set_bool(OBJECT(&chip9->lpc), true, "realized", &local_err);
131015376c66SCédric Le Goater     if (local_err) {
131115376c66SCédric Le Goater         error_propagate(errp, local_err);
131215376c66SCédric Le Goater         return;
131315376c66SCédric Le Goater     }
131415376c66SCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV9_LPCM_BASE(chip),
131515376c66SCédric Le Goater                                 &chip9->lpc.xscom_regs);
131615376c66SCédric Le Goater 
131715376c66SCédric Le Goater     chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0",
131815376c66SCédric Le Goater                                             (uint64_t) PNV9_LPCM_BASE(chip));
13196598a70dSCédric Le Goater 
13206598a70dSCédric Le Goater     /* Create the simplified OCC model */
1321ee3d2713SGreg Kurz     object_property_set_link(OBJECT(&chip9->occ), OBJECT(&chip9->psi), "psi",
1322ee3d2713SGreg Kurz                              &error_abort);
13236598a70dSCédric Le Goater     object_property_set_bool(OBJECT(&chip9->occ), true, "realized", &local_err);
13246598a70dSCédric Le Goater     if (local_err) {
13256598a70dSCédric Le Goater         error_propagate(errp, local_err);
13266598a70dSCédric Le Goater         return;
13276598a70dSCédric Le Goater     }
13286598a70dSCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_OCC_BASE, &chip9->occ.xscom_regs);
1329f3db8266SBalamuruhan S 
1330f3db8266SBalamuruhan S     /* OCC SRAM model */
13313a1b70b6SCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV9_OCC_SENSOR_BASE(chip),
1332f3db8266SBalamuruhan S                                 &chip9->occ.sram_regs);
13333887d241SBalamuruhan S 
13343887d241SBalamuruhan S     /* HOMER */
1335f2582acfSGreg Kurz     object_property_set_link(OBJECT(&chip9->homer), OBJECT(chip), "chip",
1336f2582acfSGreg Kurz                              &error_abort);
13373887d241SBalamuruhan S     object_property_set_bool(OBJECT(&chip9->homer), true, "realized",
13383887d241SBalamuruhan S                              &local_err);
13393887d241SBalamuruhan S     if (local_err) {
13403887d241SBalamuruhan S         error_propagate(errp, local_err);
13413887d241SBalamuruhan S         return;
13423887d241SBalamuruhan S     }
13438f092316SCédric Le Goater     /* Homer Xscom region */
13448f092316SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_PBA_BASE, &chip9->homer.pba_regs);
13458f092316SCédric Le Goater 
13468f092316SCédric Le Goater     /* Homer mmio region */
13473887d241SBalamuruhan S     memory_region_add_subregion(get_system_memory(), PNV9_HOMER_BASE(chip),
13483887d241SBalamuruhan S                                 &chip9->homer.regs);
1349e997040eSCédric Le Goater }
1350e997040eSCédric Le Goater 
1351*70c059e9SGreg Kurz static uint32_t pnv_chip_power9_xscom_pcba(PnvChip *chip, uint64_t addr)
1352*70c059e9SGreg Kurz {
1353*70c059e9SGreg Kurz     addr &= (PNV9_XSCOM_SIZE - 1);
1354*70c059e9SGreg Kurz     return addr >> 3;
1355*70c059e9SGreg Kurz }
1356*70c059e9SGreg Kurz 
1357e997040eSCédric Le Goater static void pnv_chip_power9_class_init(ObjectClass *klass, void *data)
1358e997040eSCédric Le Goater {
1359e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1360e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1361e997040eSCédric Le Goater 
1362e997040eSCédric Le Goater     k->chip_type = PNV_CHIP_POWER9;
136383028a2bSCédric Le Goater     k->chip_cfam_id = 0x220d104900008000ull; /* P9 Nimbus DD2.0 */
1364397a79e7SCédric Le Goater     k->cores_mask = POWER9_CORE_MASK;
1365631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p9;
1366d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power9_intc_create;
1367d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power9_intc_reset;
13680990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power9_intc_destroy;
136985913070SGreg Kurz     k->intc_print_info = pnv_chip_power9_intc_print_info;
137004026890SCédric Le Goater     k->isa_create = pnv_chip_power9_isa_create;
1371eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power9_dt_populate;
1372d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power9_pic_print_info;
1373c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power9_xscom_core_base;
1374*70c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power9_xscom_pcba;
1375e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER9";
137677864267SCédric Le Goater 
137777864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power9_realize,
137877864267SCédric Le Goater                                     &k->parent_realize);
1379e997040eSCédric Le Goater }
1380e997040eSCédric Le Goater 
13812b548a42SCédric Le Goater static void pnv_chip_power10_instance_init(Object *obj)
13822b548a42SCédric Le Goater {
13838b50ce85SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(obj);
13848b50ce85SCédric Le Goater 
13858b50ce85SCédric Le Goater     object_initialize_child(obj, "psi",  &chip10->psi, sizeof(chip10->psi),
13868b50ce85SCédric Le Goater                             TYPE_PNV10_PSI, &error_abort, NULL);
13872661f6abSCédric Le Goater     object_initialize_child(obj, "lpc",  &chip10->lpc, sizeof(chip10->lpc),
13882661f6abSCédric Le Goater                             TYPE_PNV10_LPC, &error_abort, NULL);
13892b548a42SCédric Le Goater }
13902b548a42SCédric Le Goater 
13912b548a42SCédric Le Goater static void pnv_chip_power10_realize(DeviceState *dev, Error **errp)
13922b548a42SCédric Le Goater {
13932b548a42SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
13942b548a42SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
13958b50ce85SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(dev);
13962b548a42SCédric Le Goater     Error *local_err = NULL;
13972b548a42SCédric Le Goater 
13982b548a42SCédric Le Goater     /* XSCOM bridge is first */
13992b548a42SCédric Le Goater     pnv_xscom_realize(chip, PNV10_XSCOM_SIZE, &local_err);
14002b548a42SCédric Le Goater     if (local_err) {
14012b548a42SCédric Le Goater         error_propagate(errp, local_err);
14022b548a42SCédric Le Goater         return;
14032b548a42SCédric Le Goater     }
14042b548a42SCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV10_XSCOM_BASE(chip));
14052b548a42SCédric Le Goater 
14062b548a42SCédric Le Goater     pcc->parent_realize(dev, &local_err);
14072b548a42SCédric Le Goater     if (local_err) {
14082b548a42SCédric Le Goater         error_propagate(errp, local_err);
14092b548a42SCédric Le Goater         return;
14102b548a42SCédric Le Goater     }
14118b50ce85SCédric Le Goater 
14128b50ce85SCédric Le Goater     /* Processor Service Interface (PSI) Host Bridge */
14138b50ce85SCédric Le Goater     object_property_set_int(OBJECT(&chip10->psi), PNV10_PSIHB_BASE(chip),
14148b50ce85SCédric Le Goater                             "bar", &error_fatal);
14158b50ce85SCédric Le Goater     object_property_set_bool(OBJECT(&chip10->psi), true, "realized",
14168b50ce85SCédric Le Goater                              &local_err);
14178b50ce85SCédric Le Goater     if (local_err) {
14188b50ce85SCédric Le Goater         error_propagate(errp, local_err);
14198b50ce85SCédric Le Goater         return;
14208b50ce85SCédric Le Goater     }
14218b50ce85SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV10_XSCOM_PSIHB_BASE,
14228b50ce85SCédric Le Goater                             &PNV_PSI(&chip10->psi)->xscom_regs);
14232661f6abSCédric Le Goater 
14242661f6abSCédric Le Goater     /* LPC */
14252661f6abSCédric Le Goater     object_property_set_link(OBJECT(&chip10->lpc), OBJECT(&chip10->psi), "psi",
14262661f6abSCédric Le Goater                              &error_abort);
14272661f6abSCédric Le Goater     object_property_set_bool(OBJECT(&chip10->lpc), true, "realized",
14282661f6abSCédric Le Goater                              &local_err);
14292661f6abSCédric Le Goater     if (local_err) {
14302661f6abSCédric Le Goater         error_propagate(errp, local_err);
14312661f6abSCédric Le Goater         return;
14322661f6abSCédric Le Goater     }
14332661f6abSCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV10_LPCM_BASE(chip),
14342661f6abSCédric Le Goater                                 &chip10->lpc.xscom_regs);
14352661f6abSCédric Le Goater 
14362661f6abSCédric Le Goater     chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0",
14372661f6abSCédric Le Goater                                             (uint64_t) PNV10_LPCM_BASE(chip));
14382b548a42SCédric Le Goater }
14392b548a42SCédric Le Goater 
1440*70c059e9SGreg Kurz static uint32_t pnv_chip_power10_xscom_pcba(PnvChip *chip, uint64_t addr)
1441*70c059e9SGreg Kurz {
1442*70c059e9SGreg Kurz     addr &= (PNV10_XSCOM_SIZE - 1);
1443*70c059e9SGreg Kurz     return addr >> 3;
1444*70c059e9SGreg Kurz }
1445*70c059e9SGreg Kurz 
14462b548a42SCédric Le Goater static void pnv_chip_power10_class_init(ObjectClass *klass, void *data)
14472b548a42SCédric Le Goater {
14482b548a42SCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
14492b548a42SCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
14502b548a42SCédric Le Goater 
14512b548a42SCédric Le Goater     k->chip_type = PNV_CHIP_POWER10;
14522b548a42SCédric Le Goater     k->chip_cfam_id = 0x120da04900008000ull; /* P10 DD1.0 (with NX) */
14532b548a42SCédric Le Goater     k->cores_mask = POWER10_CORE_MASK;
14542b548a42SCédric Le Goater     k->core_pir = pnv_chip_core_pir_p10;
14552b548a42SCédric Le Goater     k->intc_create = pnv_chip_power10_intc_create;
14562b548a42SCédric Le Goater     k->intc_reset = pnv_chip_power10_intc_reset;
14572b548a42SCédric Le Goater     k->intc_destroy = pnv_chip_power10_intc_destroy;
145885913070SGreg Kurz     k->intc_print_info = pnv_chip_power10_intc_print_info;
14592b548a42SCédric Le Goater     k->isa_create = pnv_chip_power10_isa_create;
14602b548a42SCédric Le Goater     k->dt_populate = pnv_chip_power10_dt_populate;
14612b548a42SCédric Le Goater     k->pic_print_info = pnv_chip_power10_pic_print_info;
1462c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power10_xscom_core_base;
1463*70c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power10_xscom_pcba;
14642b548a42SCédric Le Goater     dc->desc = "PowerNV Chip POWER10";
14652b548a42SCédric Le Goater 
14662b548a42SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power10_realize,
14672b548a42SCédric Le Goater                                     &k->parent_realize);
14682b548a42SCédric Le Goater }
14692b548a42SCédric Le Goater 
1470397a79e7SCédric Le Goater static void pnv_chip_core_sanitize(PnvChip *chip, Error **errp)
1471397a79e7SCédric Le Goater {
1472397a79e7SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
1473397a79e7SCédric Le Goater     int cores_max;
1474397a79e7SCédric Le Goater 
1475397a79e7SCédric Le Goater     /*
1476397a79e7SCédric Le Goater      * No custom mask for this chip, let's use the default one from *
1477397a79e7SCédric Le Goater      * the chip class
1478397a79e7SCédric Le Goater      */
1479397a79e7SCédric Le Goater     if (!chip->cores_mask) {
1480397a79e7SCédric Le Goater         chip->cores_mask = pcc->cores_mask;
1481397a79e7SCédric Le Goater     }
1482397a79e7SCédric Le Goater 
1483397a79e7SCédric Le Goater     /* filter alien core ids ! some are reserved */
1484397a79e7SCédric Le Goater     if ((chip->cores_mask & pcc->cores_mask) != chip->cores_mask) {
1485397a79e7SCédric Le Goater         error_setg(errp, "warning: invalid core mask for chip Ox%"PRIx64" !",
1486397a79e7SCédric Le Goater                    chip->cores_mask);
1487397a79e7SCédric Le Goater         return;
1488397a79e7SCédric Le Goater     }
1489397a79e7SCédric Le Goater     chip->cores_mask &= pcc->cores_mask;
1490397a79e7SCédric Le Goater 
1491397a79e7SCédric Le Goater     /* now that we have a sane layout, let check the number of cores */
149227d9ffd4SDavid Gibson     cores_max = ctpop64(chip->cores_mask);
1493397a79e7SCédric Le Goater     if (chip->nr_cores > cores_max) {
1494397a79e7SCédric Le Goater         error_setg(errp, "warning: too many cores for chip ! Limit is %d",
1495397a79e7SCédric Le Goater                    cores_max);
1496397a79e7SCédric Le Goater         return;
1497397a79e7SCédric Le Goater     }
1498397a79e7SCédric Le Goater }
1499397a79e7SCédric Le Goater 
150051c04728SCédric Le Goater static void pnv_chip_core_realize(PnvChip *chip, Error **errp)
1501e997040eSCédric Le Goater {
1502fe6b6346SLike Xu     MachineState *ms = MACHINE(qdev_get_machine());
1503397a79e7SCédric Le Goater     Error *error = NULL;
1504d2fd9612SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
150540abf43fSIgor Mammedov     const char *typename = pnv_chip_core_typename(chip);
1506d2fd9612SCédric Le Goater     int i, core_hwid;
1507397a79e7SCédric Le Goater 
1508d2fd9612SCédric Le Goater     if (!object_class_by_name(typename)) {
1509d2fd9612SCédric Le Goater         error_setg(errp, "Unable to find PowerNV CPU Core '%s'", typename);
1510d2fd9612SCédric Le Goater         return;
1511d2fd9612SCédric Le Goater     }
1512d2fd9612SCédric Le Goater 
1513d2fd9612SCédric Le Goater     /* Cores */
1514397a79e7SCédric Le Goater     pnv_chip_core_sanitize(chip, &error);
1515397a79e7SCédric Le Goater     if (error) {
1516397a79e7SCédric Le Goater         error_propagate(errp, error);
1517397a79e7SCédric Le Goater         return;
1518397a79e7SCédric Le Goater     }
1519d2fd9612SCédric Le Goater 
15204fa28f23SGreg Kurz     chip->cores = g_new0(PnvCore *, chip->nr_cores);
1521d2fd9612SCédric Le Goater 
1522d2fd9612SCédric Le Goater     for (i = 0, core_hwid = 0; (core_hwid < sizeof(chip->cores_mask) * 8)
1523d2fd9612SCédric Le Goater              && (i < chip->nr_cores); core_hwid++) {
1524d2fd9612SCédric Le Goater         char core_name[32];
15254fa28f23SGreg Kurz         PnvCore *pnv_core;
1526c035851aSCédric Le Goater         uint64_t xscom_core_base;
1527d2fd9612SCédric Le Goater 
1528d2fd9612SCédric Le Goater         if (!(chip->cores_mask & (1ull << core_hwid))) {
1529d2fd9612SCédric Le Goater             continue;
1530d2fd9612SCédric Le Goater         }
1531d2fd9612SCédric Le Goater 
15324fa28f23SGreg Kurz         pnv_core = PNV_CORE(object_new(typename));
15334fa28f23SGreg Kurz 
1534d2fd9612SCédric Le Goater         snprintf(core_name, sizeof(core_name), "core[%d]", core_hwid);
15354fa28f23SGreg Kurz         object_property_add_child(OBJECT(chip), core_name, OBJECT(pnv_core),
15364fa28f23SGreg Kurz                                   &error_abort);
15374fa28f23SGreg Kurz         chip->cores[i] = pnv_core;
1538fe6b6346SLike Xu         object_property_set_int(OBJECT(pnv_core), ms->smp.threads, "nr-threads",
1539d2fd9612SCédric Le Goater                                 &error_fatal);
1540d2fd9612SCédric Le Goater         object_property_set_int(OBJECT(pnv_core), core_hwid,
1541d2fd9612SCédric Le Goater                                 CPU_CORE_PROP_CORE_ID, &error_fatal);
1542d2fd9612SCédric Le Goater         object_property_set_int(OBJECT(pnv_core),
1543d2fd9612SCédric Le Goater                                 pcc->core_pir(chip, core_hwid),
1544d2fd9612SCédric Le Goater                                 "pir", &error_fatal);
1545158e17a6SGreg Kurz         object_property_set_link(OBJECT(pnv_core), OBJECT(chip), "chip",
1546158e17a6SGreg Kurz                                  &error_abort);
1547d2fd9612SCédric Le Goater         object_property_set_bool(OBJECT(pnv_core), true, "realized",
1548d2fd9612SCédric Le Goater                                  &error_fatal);
154924ece072SCédric Le Goater 
155024ece072SCédric Le Goater         /* Each core has an XSCOM MMIO region */
1551c4b2c40cSGreg Kurz         xscom_core_base = pcc->xscom_core_base(chip, core_hwid);
1552c035851aSCédric Le Goater 
1553c035851aSCédric Le Goater         pnv_xscom_add_subregion(chip, xscom_core_base,
15544fa28f23SGreg Kurz                                 &pnv_core->xscom_regs);
1555d2fd9612SCédric Le Goater         i++;
1556d2fd9612SCédric Le Goater     }
155751c04728SCédric Le Goater }
155851c04728SCédric Le Goater 
155951c04728SCédric Le Goater static void pnv_chip_realize(DeviceState *dev, Error **errp)
156051c04728SCédric Le Goater {
156151c04728SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
156251c04728SCédric Le Goater     Error *error = NULL;
156351c04728SCédric Le Goater 
156451c04728SCédric Le Goater     /* Cores */
156551c04728SCédric Le Goater     pnv_chip_core_realize(chip, &error);
156651c04728SCédric Le Goater     if (error) {
156751c04728SCédric Le Goater         error_propagate(errp, error);
156851c04728SCédric Le Goater         return;
156951c04728SCédric Le Goater     }
1570e997040eSCédric Le Goater }
1571e997040eSCédric Le Goater 
1572e997040eSCédric Le Goater static Property pnv_chip_properties[] = {
1573e997040eSCédric Le Goater     DEFINE_PROP_UINT32("chip-id", PnvChip, chip_id, 0),
1574e997040eSCédric Le Goater     DEFINE_PROP_UINT64("ram-start", PnvChip, ram_start, 0),
1575e997040eSCédric Le Goater     DEFINE_PROP_UINT64("ram-size", PnvChip, ram_size, 0),
1576397a79e7SCédric Le Goater     DEFINE_PROP_UINT32("nr-cores", PnvChip, nr_cores, 1),
1577397a79e7SCédric Le Goater     DEFINE_PROP_UINT64("cores-mask", PnvChip, cores_mask, 0x0),
1578e997040eSCédric Le Goater     DEFINE_PROP_END_OF_LIST(),
1579e997040eSCédric Le Goater };
1580e997040eSCédric Le Goater 
1581e997040eSCédric Le Goater static void pnv_chip_class_init(ObjectClass *klass, void *data)
1582e997040eSCédric Le Goater {
1583e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1584e997040eSCédric Le Goater 
15859d169fb3SThomas Huth     set_bit(DEVICE_CATEGORY_CPU, dc->categories);
1586e997040eSCédric Le Goater     dc->realize = pnv_chip_realize;
1587e997040eSCédric Le Goater     dc->props = pnv_chip_properties;
1588e997040eSCédric Le Goater     dc->desc = "PowerNV Chip";
1589e997040eSCédric Le Goater }
1590e997040eSCédric Le Goater 
1591119eaa9dSCédric Le Goater PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir)
1592119eaa9dSCédric Le Goater {
1593119eaa9dSCédric Le Goater     int i, j;
1594119eaa9dSCédric Le Goater 
1595119eaa9dSCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
1596119eaa9dSCédric Le Goater         PnvCore *pc = chip->cores[i];
1597119eaa9dSCédric Le Goater         CPUCore *cc = CPU_CORE(pc);
1598119eaa9dSCédric Le Goater 
1599119eaa9dSCédric Le Goater         for (j = 0; j < cc->nr_threads; j++) {
1600119eaa9dSCédric Le Goater             if (ppc_cpu_pir(pc->threads[j]) == pir) {
1601119eaa9dSCédric Le Goater                 return pc->threads[j];
1602119eaa9dSCédric Le Goater             }
1603119eaa9dSCédric Le Goater         }
1604119eaa9dSCédric Le Goater     }
1605119eaa9dSCédric Le Goater     return NULL;
1606119eaa9dSCédric Le Goater }
1607119eaa9dSCédric Le Goater 
160854f59d78SCédric Le Goater static ICSState *pnv_ics_get(XICSFabric *xi, int irq)
160954f59d78SCédric Le Goater {
1610b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xi);
161154f59d78SCédric Le Goater     int i;
161254f59d78SCédric Le Goater 
161354f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
161477864267SCédric Le Goater         Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
161577864267SCédric Le Goater 
161677864267SCédric Le Goater         if (ics_valid_irq(&chip8->psi.ics, irq)) {
161777864267SCédric Le Goater             return &chip8->psi.ics;
161854f59d78SCédric Le Goater         }
161954f59d78SCédric Le Goater     }
162054f59d78SCédric Le Goater     return NULL;
162154f59d78SCédric Le Goater }
162254f59d78SCédric Le Goater 
162354f59d78SCédric Le Goater static void pnv_ics_resend(XICSFabric *xi)
162454f59d78SCédric Le Goater {
1625b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xi);
162654f59d78SCédric Le Goater     int i;
162754f59d78SCédric Le Goater 
162854f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
162977864267SCédric Le Goater         Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
163077864267SCédric Le Goater         ics_resend(&chip8->psi.ics);
163154f59d78SCédric Le Goater     }
163254f59d78SCédric Le Goater }
163354f59d78SCédric Le Goater 
163436fc6f08SCédric Le Goater static ICPState *pnv_icp_get(XICSFabric *xi, int pir)
163536fc6f08SCédric Le Goater {
163636fc6f08SCédric Le Goater     PowerPCCPU *cpu = ppc_get_vcpu_by_pir(pir);
163736fc6f08SCédric Le Goater 
1638956b8f46SCédric Le Goater     return cpu ? ICP(pnv_cpu_state(cpu)->intc) : NULL;
163936fc6f08SCédric Le Goater }
164036fc6f08SCédric Le Goater 
164147fea43aSCédric Le Goater static void pnv_pic_print_info(InterruptStatsProvider *obj,
164247fea43aSCédric Le Goater                                Monitor *mon)
164347fea43aSCédric Le Goater {
1644b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
164554f59d78SCédric Le Goater     int i;
164647fea43aSCédric Le Goater     CPUState *cs;
164747fea43aSCédric Le Goater 
164847fea43aSCédric Le Goater     CPU_FOREACH(cs) {
164947fea43aSCédric Le Goater         PowerPCCPU *cpu = POWERPC_CPU(cs);
165047fea43aSCédric Le Goater 
165185913070SGreg Kurz         /* XXX: loop on each chip/core/thread instead of CPU_FOREACH() */
165285913070SGreg Kurz         PNV_CHIP_GET_CLASS(pnv->chips[0])->intc_print_info(pnv->chips[0], cpu,
165385913070SGreg Kurz                                                            mon);
1654d8e4aad5SCédric Le Goater     }
165554f59d78SCédric Le Goater 
165654f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
1657d8e4aad5SCédric Le Goater         PNV_CHIP_GET_CLASS(pnv->chips[i])->pic_print_info(pnv->chips[i], mon);
165854f59d78SCédric Le Goater     }
165947fea43aSCédric Le Goater }
166047fea43aSCédric Le Goater 
1661c722579eSCédric Le Goater static int pnv_match_nvt(XiveFabric *xfb, uint8_t format,
1662c722579eSCédric Le Goater                          uint8_t nvt_blk, uint32_t nvt_idx,
1663c722579eSCédric Le Goater                          bool cam_ignore, uint8_t priority,
1664c722579eSCédric Le Goater                          uint32_t logic_serv,
1665c722579eSCédric Le Goater                          XiveTCTXMatch *match)
1666c722579eSCédric Le Goater {
1667c722579eSCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xfb);
1668c722579eSCédric Le Goater     int total_count = 0;
1669c722579eSCédric Le Goater     int i;
1670c722579eSCédric Le Goater 
1671c722579eSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
1672c722579eSCédric Le Goater         Pnv9Chip *chip9 = PNV9_CHIP(pnv->chips[i]);
1673c722579eSCédric Le Goater         XivePresenter *xptr = XIVE_PRESENTER(&chip9->xive);
1674c722579eSCédric Le Goater         XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr);
1675c722579eSCédric Le Goater         int count;
1676c722579eSCédric Le Goater 
1677c722579eSCédric Le Goater         count = xpc->match_nvt(xptr, format, nvt_blk, nvt_idx, cam_ignore,
1678c722579eSCédric Le Goater                                priority, logic_serv, match);
1679c722579eSCédric Le Goater 
1680c722579eSCédric Le Goater         if (count < 0) {
1681c722579eSCédric Le Goater             return count;
1682c722579eSCédric Le Goater         }
1683c722579eSCédric Le Goater 
1684c722579eSCédric Le Goater         total_count += count;
1685c722579eSCédric Le Goater     }
1686c722579eSCédric Le Goater 
1687c722579eSCédric Le Goater     return total_count;
1688c722579eSCédric Le Goater }
1689c722579eSCédric Le Goater 
16905373c61dSCédric Le Goater PnvChip *pnv_get_chip(uint32_t chip_id)
16915373c61dSCédric Le Goater {
16925373c61dSCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine());
16935373c61dSCédric Le Goater     int i;
16945373c61dSCédric Le Goater 
16955373c61dSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
16965373c61dSCédric Le Goater         PnvChip *chip = pnv->chips[i];
16975373c61dSCédric Le Goater         if (chip->chip_id == chip_id) {
16985373c61dSCédric Le Goater             return chip;
16995373c61dSCédric Le Goater         }
17005373c61dSCédric Le Goater     }
17015373c61dSCédric Le Goater     return NULL;
17025373c61dSCédric Le Goater }
17035373c61dSCédric Le Goater 
1704e997040eSCédric Le Goater static void pnv_get_num_chips(Object *obj, Visitor *v, const char *name,
1705e997040eSCédric Le Goater                               void *opaque, Error **errp)
1706e997040eSCédric Le Goater {
1707b168a138SCédric Le Goater     visit_type_uint32(v, name, &PNV_MACHINE(obj)->num_chips, errp);
1708e997040eSCédric Le Goater }
1709e997040eSCédric Le Goater 
1710e997040eSCédric Le Goater static void pnv_set_num_chips(Object *obj, Visitor *v, const char *name,
1711e997040eSCédric Le Goater                               void *opaque, Error **errp)
1712e997040eSCédric Le Goater {
1713b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
1714e997040eSCédric Le Goater     uint32_t num_chips;
1715e997040eSCédric Le Goater     Error *local_err = NULL;
1716e997040eSCédric Le Goater 
1717e997040eSCédric Le Goater     visit_type_uint32(v, name, &num_chips, &local_err);
1718e997040eSCédric Le Goater     if (local_err) {
1719e997040eSCédric Le Goater         error_propagate(errp, local_err);
1720e997040eSCédric Le Goater         return;
1721e997040eSCédric Le Goater     }
1722e997040eSCédric Le Goater 
1723e997040eSCédric Le Goater     /*
1724e997040eSCédric Le Goater      * TODO: should we decide on how many chips we can create based
1725e997040eSCédric Le Goater      * on #cores and Venice vs. Murano vs. Naples chip type etc...,
1726e997040eSCédric Le Goater      */
1727e997040eSCédric Le Goater     if (!is_power_of_2(num_chips) || num_chips > 4) {
1728e997040eSCédric Le Goater         error_setg(errp, "invalid number of chips: '%d'", num_chips);
1729e997040eSCédric Le Goater         return;
1730e997040eSCédric Le Goater     }
1731e997040eSCédric Le Goater 
1732e997040eSCédric Le Goater     pnv->num_chips = num_chips;
1733e997040eSCédric Le Goater }
1734e997040eSCédric Le Goater 
173577864267SCédric Le Goater static void pnv_machine_instance_init(Object *obj)
1736e997040eSCédric Le Goater {
1737b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
1738e997040eSCédric Le Goater     pnv->num_chips = 1;
1739e997040eSCédric Le Goater }
1740e997040eSCédric Le Goater 
1741b168a138SCédric Le Goater static void pnv_machine_class_props_init(ObjectClass *oc)
1742e997040eSCédric Le Goater {
17431e507bb0SMarc-André Lureau     object_class_property_add(oc, "num-chips", "uint32",
1744e997040eSCédric Le Goater                               pnv_get_num_chips, pnv_set_num_chips,
1745e997040eSCédric Le Goater                               NULL, NULL, NULL);
1746e997040eSCédric Le Goater     object_class_property_set_description(oc, "num-chips",
1747e997040eSCédric Le Goater                               "Specifies the number of processor chips",
1748e997040eSCédric Le Goater                               NULL);
17499e933f4aSBenjamin Herrenschmidt }
17509e933f4aSBenjamin Herrenschmidt 
1751f30c843cSCédric Le Goater static void pnv_machine_power8_class_init(ObjectClass *oc, void *data)
17529e933f4aSBenjamin Herrenschmidt {
17539e933f4aSBenjamin Herrenschmidt     MachineClass *mc = MACHINE_CLASS(oc);
175436fc6f08SCédric Le Goater     XICSFabricClass *xic = XICS_FABRIC_CLASS(oc);
1755d76f2da7SGreg Kurz     PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc);
1756d76f2da7SGreg Kurz     static const char compat[] = "qemu,powernv8\0qemu,powernv\0ibm,powernv";
1757f30c843cSCédric Le Goater 
1758f30c843cSCédric Le Goater     mc->desc = "IBM PowerNV (Non-Virtualized) POWER8";
1759f30c843cSCédric Le Goater     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0");
1760f30c843cSCédric Le Goater 
1761f30c843cSCédric Le Goater     xic->icp_get = pnv_icp_get;
1762f30c843cSCédric Le Goater     xic->ics_get = pnv_ics_get;
1763f30c843cSCédric Le Goater     xic->ics_resend = pnv_ics_resend;
1764d76f2da7SGreg Kurz 
1765d76f2da7SGreg Kurz     pmc->compat = compat;
1766d76f2da7SGreg Kurz     pmc->compat_size = sizeof(compat);
1767f30c843cSCédric Le Goater }
1768f30c843cSCédric Le Goater 
1769f30c843cSCédric Le Goater static void pnv_machine_power9_class_init(ObjectClass *oc, void *data)
1770f30c843cSCédric Le Goater {
1771f30c843cSCédric Le Goater     MachineClass *mc = MACHINE_CLASS(oc);
1772c722579eSCédric Le Goater     XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc);
1773d76f2da7SGreg Kurz     PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc);
1774d76f2da7SGreg Kurz     static const char compat[] = "qemu,powernv9\0ibm,powernv";
1775f30c843cSCédric Le Goater 
1776f30c843cSCédric Le Goater     mc->desc = "IBM PowerNV (Non-Virtualized) POWER9";
1777f30c843cSCédric Le Goater     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.0");
1778c722579eSCédric Le Goater     xfc->match_nvt = pnv_match_nvt;
1779f30c843cSCédric Le Goater 
1780f30c843cSCédric Le Goater     mc->alias = "powernv";
1781d76f2da7SGreg Kurz 
1782d76f2da7SGreg Kurz     pmc->compat = compat;
1783d76f2da7SGreg Kurz     pmc->compat_size = sizeof(compat);
17847a90c6a1SGreg Kurz     pmc->dt_power_mgt = pnv_dt_power_mgt;
1785f30c843cSCédric Le Goater }
1786f30c843cSCédric Le Goater 
17872b548a42SCédric Le Goater static void pnv_machine_power10_class_init(ObjectClass *oc, void *data)
17882b548a42SCédric Le Goater {
17892b548a42SCédric Le Goater     MachineClass *mc = MACHINE_CLASS(oc);
1790d76f2da7SGreg Kurz     PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc);
1791d76f2da7SGreg Kurz     static const char compat[] = "qemu,powernv10\0ibm,powernv";
17922b548a42SCédric Le Goater 
17932b548a42SCédric Le Goater     mc->desc = "IBM PowerNV (Non-Virtualized) POWER10";
17942b548a42SCédric Le Goater     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power10_v1.0");
1795d76f2da7SGreg Kurz 
1796d76f2da7SGreg Kurz     pmc->compat = compat;
1797d76f2da7SGreg Kurz     pmc->compat_size = sizeof(compat);
17987a90c6a1SGreg Kurz     pmc->dt_power_mgt = pnv_dt_power_mgt;
17992b548a42SCédric Le Goater }
18002b548a42SCédric Le Goater 
1801f30c843cSCédric Le Goater static void pnv_machine_class_init(ObjectClass *oc, void *data)
1802f30c843cSCédric Le Goater {
1803f30c843cSCédric Le Goater     MachineClass *mc = MACHINE_CLASS(oc);
180447fea43aSCédric Le Goater     InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc);
18059e933f4aSBenjamin Herrenschmidt 
18069e933f4aSBenjamin Herrenschmidt     mc->desc = "IBM PowerNV (Non-Virtualized)";
1807b168a138SCédric Le Goater     mc->init = pnv_init;
1808b168a138SCédric Le Goater     mc->reset = pnv_reset;
18099e933f4aSBenjamin Herrenschmidt     mc->max_cpus = MAX_CPUS;
181059b7c1c2SBalamuruhan S     /* Pnv provides a AHCI device for storage */
181159b7c1c2SBalamuruhan S     mc->block_default_type = IF_IDE;
18129e933f4aSBenjamin Herrenschmidt     mc->no_parallel = 1;
18139e933f4aSBenjamin Herrenschmidt     mc->default_boot_order = NULL;
1814f1d18b0aSJoel Stanley     /*
1815f1d18b0aSJoel Stanley      * RAM defaults to less than 2048 for 32-bit hosts, and large
1816f1d18b0aSJoel Stanley      * enough to fit the maximum initrd size at it's load address
1817f1d18b0aSJoel Stanley      */
1818f1d18b0aSJoel Stanley     mc->default_ram_size = INITRD_LOAD_ADDR + INITRD_MAX_SIZE;
181947fea43aSCédric Le Goater     ispc->print_info = pnv_pic_print_info;
1820e997040eSCédric Le Goater 
1821b168a138SCédric Le Goater     pnv_machine_class_props_init(oc);
18229e933f4aSBenjamin Herrenschmidt }
18239e933f4aSBenjamin Herrenschmidt 
182477864267SCédric Le Goater #define DEFINE_PNV8_CHIP_TYPE(type, class_initfn) \
1825beba5c0fSIgor Mammedov     {                                             \
1826beba5c0fSIgor Mammedov         .name          = type,                    \
1827beba5c0fSIgor Mammedov         .class_init    = class_initfn,            \
182877864267SCédric Le Goater         .parent        = TYPE_PNV8_CHIP,          \
182977864267SCédric Le Goater     }
183077864267SCédric Le Goater 
183177864267SCédric Le Goater #define DEFINE_PNV9_CHIP_TYPE(type, class_initfn) \
183277864267SCédric Le Goater     {                                             \
183377864267SCédric Le Goater         .name          = type,                    \
183477864267SCédric Le Goater         .class_init    = class_initfn,            \
183577864267SCédric Le Goater         .parent        = TYPE_PNV9_CHIP,          \
1836beba5c0fSIgor Mammedov     }
1837beba5c0fSIgor Mammedov 
18382b548a42SCédric Le Goater #define DEFINE_PNV10_CHIP_TYPE(type, class_initfn) \
18392b548a42SCédric Le Goater     {                                              \
18402b548a42SCédric Le Goater         .name          = type,                     \
18412b548a42SCédric Le Goater         .class_init    = class_initfn,             \
18422b548a42SCédric Le Goater         .parent        = TYPE_PNV10_CHIP,          \
18432b548a42SCédric Le Goater     }
18442b548a42SCédric Le Goater 
1845beba5c0fSIgor Mammedov static const TypeInfo types[] = {
18461aba8716SCédric Le Goater     {
18472b548a42SCédric Le Goater         .name          = MACHINE_TYPE_NAME("powernv10"),
18482b548a42SCédric Le Goater         .parent        = TYPE_PNV_MACHINE,
18492b548a42SCédric Le Goater         .class_init    = pnv_machine_power10_class_init,
18502b548a42SCédric Le Goater     },
18512b548a42SCédric Le Goater     {
18521aba8716SCédric Le Goater         .name          = MACHINE_TYPE_NAME("powernv9"),
18531aba8716SCédric Le Goater         .parent        = TYPE_PNV_MACHINE,
18541aba8716SCédric Le Goater         .class_init    = pnv_machine_power9_class_init,
1855c722579eSCédric Le Goater         .interfaces = (InterfaceInfo[]) {
1856c722579eSCédric Le Goater             { TYPE_XIVE_FABRIC },
1857c722579eSCédric Le Goater             { },
1858c722579eSCédric Le Goater         },
18591aba8716SCédric Le Goater     },
18601aba8716SCédric Le Goater     {
18611aba8716SCédric Le Goater         .name          = MACHINE_TYPE_NAME("powernv8"),
18621aba8716SCédric Le Goater         .parent        = TYPE_PNV_MACHINE,
18631aba8716SCédric Le Goater         .class_init    = pnv_machine_power8_class_init,
18641aba8716SCédric Le Goater         .interfaces = (InterfaceInfo[]) {
18651aba8716SCédric Le Goater             { TYPE_XICS_FABRIC },
18661aba8716SCédric Le Goater             { },
18671aba8716SCédric Le Goater         },
18681aba8716SCédric Le Goater     },
1869beba5c0fSIgor Mammedov     {
1870b168a138SCédric Le Goater         .name          = TYPE_PNV_MACHINE,
18719e933f4aSBenjamin Herrenschmidt         .parent        = TYPE_MACHINE,
1872f30c843cSCédric Le Goater         .abstract       = true,
18739e933f4aSBenjamin Herrenschmidt         .instance_size = sizeof(PnvMachineState),
187477864267SCédric Le Goater         .instance_init = pnv_machine_instance_init,
1875b168a138SCédric Le Goater         .class_init    = pnv_machine_class_init,
1876d76f2da7SGreg Kurz         .class_size    = sizeof(PnvMachineClass),
187736fc6f08SCédric Le Goater         .interfaces = (InterfaceInfo[]) {
187847fea43aSCédric Le Goater             { TYPE_INTERRUPT_STATS_PROVIDER },
187936fc6f08SCédric Le Goater             { },
188036fc6f08SCédric Le Goater         },
1881beba5c0fSIgor Mammedov     },
1882beba5c0fSIgor Mammedov     {
1883beba5c0fSIgor Mammedov         .name          = TYPE_PNV_CHIP,
1884beba5c0fSIgor Mammedov         .parent        = TYPE_SYS_BUS_DEVICE,
1885beba5c0fSIgor Mammedov         .class_init    = pnv_chip_class_init,
1886beba5c0fSIgor Mammedov         .instance_size = sizeof(PnvChip),
1887beba5c0fSIgor Mammedov         .class_size    = sizeof(PnvChipClass),
1888beba5c0fSIgor Mammedov         .abstract      = true,
1889beba5c0fSIgor Mammedov     },
189077864267SCédric Le Goater 
189177864267SCédric Le Goater     /*
18922b548a42SCédric Le Goater      * P10 chip and variants
18932b548a42SCédric Le Goater      */
18942b548a42SCédric Le Goater     {
18952b548a42SCédric Le Goater         .name          = TYPE_PNV10_CHIP,
18962b548a42SCédric Le Goater         .parent        = TYPE_PNV_CHIP,
18972b548a42SCédric Le Goater         .instance_init = pnv_chip_power10_instance_init,
18982b548a42SCédric Le Goater         .instance_size = sizeof(Pnv10Chip),
18992b548a42SCédric Le Goater     },
19002b548a42SCédric Le Goater     DEFINE_PNV10_CHIP_TYPE(TYPE_PNV_CHIP_POWER10, pnv_chip_power10_class_init),
19012b548a42SCédric Le Goater 
19022b548a42SCédric Le Goater     /*
190377864267SCédric Le Goater      * P9 chip and variants
190477864267SCédric Le Goater      */
190577864267SCédric Le Goater     {
190677864267SCédric Le Goater         .name          = TYPE_PNV9_CHIP,
190777864267SCédric Le Goater         .parent        = TYPE_PNV_CHIP,
190877864267SCédric Le Goater         .instance_init = pnv_chip_power9_instance_init,
190977864267SCédric Le Goater         .instance_size = sizeof(Pnv9Chip),
191077864267SCédric Le Goater     },
191177864267SCédric Le Goater     DEFINE_PNV9_CHIP_TYPE(TYPE_PNV_CHIP_POWER9, pnv_chip_power9_class_init),
191277864267SCédric Le Goater 
191377864267SCédric Le Goater     /*
191477864267SCédric Le Goater      * P8 chip and variants
191577864267SCédric Le Goater      */
191677864267SCédric Le Goater     {
191777864267SCédric Le Goater         .name          = TYPE_PNV8_CHIP,
191877864267SCédric Le Goater         .parent        = TYPE_PNV_CHIP,
191977864267SCédric Le Goater         .instance_init = pnv_chip_power8_instance_init,
192077864267SCédric Le Goater         .instance_size = sizeof(Pnv8Chip),
192177864267SCédric Le Goater     },
192277864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8, pnv_chip_power8_class_init),
192377864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8E, pnv_chip_power8e_class_init),
192477864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8NVL,
1925beba5c0fSIgor Mammedov                           pnv_chip_power8nvl_class_init),
19269e933f4aSBenjamin Herrenschmidt };
19279e933f4aSBenjamin Herrenschmidt 
1928beba5c0fSIgor Mammedov DEFINE_TYPES(types)
1929