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
9f70c5966SChetan Pant * version 2.1 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"
212c65db5eSPaolo Bonzini #include "qemu/datadir.h"
22fc6b3cf9SPhilippe Mathieu-Daudé #include "qemu/units.h"
23dd7ef911SCédric Le Goater #include "qemu/cutils.h"
249e933f4aSBenjamin Herrenschmidt #include "qapi/error.h"
2538d2448aSGreg Kurz #include "sysemu/qtest.h"
269e933f4aSBenjamin Herrenschmidt #include "sysemu/sysemu.h"
279e933f4aSBenjamin Herrenschmidt #include "sysemu/numa.h"
2871e8a915SMarkus Armbruster #include "sysemu/reset.h"
2954d31236SMarkus Armbruster #include "sysemu/runstate.h"
30d2528bdcSPaolo Bonzini #include "sysemu/cpus.h"
318d409261SCédric Le Goater #include "sysemu/device_tree.h"
3201b552b0SNicholas Piggin #include "sysemu/hw_accel.h"
33fcf5ef2aSThomas Huth #include "target/ppc/cpu.h"
349e933f4aSBenjamin Herrenschmidt #include "hw/ppc/fdt.h"
359e933f4aSBenjamin Herrenschmidt #include "hw/ppc/ppc.h"
369e933f4aSBenjamin Herrenschmidt #include "hw/ppc/pnv.h"
37d2fd9612SCédric Le Goater #include "hw/ppc/pnv_core.h"
389e933f4aSBenjamin Herrenschmidt #include "hw/loader.h"
3901b552b0SNicholas Piggin #include "hw/nmi.h"
40e997040eSCédric Le Goater #include "qapi/visitor.h"
4147fea43aSCédric Le Goater #include "hw/intc/intc.h"
42aeaef83dSCédric Le Goater #include "hw/ipmi/ipmi.h"
4358969eeeSDavid Gibson #include "target/ppc/mmu-hash64.h"
444f9924c4SBenjamin Herrenschmidt #include "hw/pci/msi.h"
451f5d6b2aSDaniel Henrique Barboza #include "hw/pci-host/pnv_phb.h"
462c6fe2e2SMarkus Armbruster #include "hw/pci-host/pnv_phb3.h"
472c6fe2e2SMarkus Armbruster #include "hw/pci-host/pnv_phb4.h"
489e933f4aSBenjamin Herrenschmidt
4936fc6f08SCédric Le Goater #include "hw/ppc/xics.h"
50a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h"
512c6fe2e2SMarkus Armbruster #include "hw/ppc/pnv_chip.h"
52967b7523SCédric Le Goater #include "hw/ppc/pnv_xscom.h"
5335dde576SCédric Le Goater #include "hw/ppc/pnv_pnor.h"
54967b7523SCédric Le Goater
553495b6b6SCédric Le Goater #include "hw/isa/isa.h"
5637b724cdSBernhard Beschow #include "hw/char/serial-isa.h"
57bcdb9064SPhilippe Mathieu-Daudé #include "hw/rtc/mc146818rtc.h"
583495b6b6SCédric Le Goater
599e933f4aSBenjamin Herrenschmidt #include <libfdt.h>
609e933f4aSBenjamin Herrenschmidt
61b268a616SMurilo Opsfelder Araujo #define FDT_MAX_SIZE (1 * MiB)
629e933f4aSBenjamin Herrenschmidt
639e933f4aSBenjamin Herrenschmidt #define FW_FILE_NAME "skiboot.lid"
649e933f4aSBenjamin Herrenschmidt #define FW_LOAD_ADDR 0x0
6583fa6e2aSCédric Le Goater #define FW_MAX_SIZE (16 * MiB)
669e933f4aSBenjamin Herrenschmidt
679e933f4aSBenjamin Herrenschmidt #define KERNEL_LOAD_ADDR 0x20000000
6805ce9b73SCédric Le Goater #define KERNEL_MAX_SIZE (128 * MiB)
6905ce9b73SCédric Le Goater #define INITRD_LOAD_ADDR 0x28000000
7005ce9b73SCédric Le Goater #define INITRD_MAX_SIZE (128 * MiB)
719e933f4aSBenjamin Herrenschmidt
pnv_chip_core_typename(const PnvChip * o)7240abf43fSIgor Mammedov static const char *pnv_chip_core_typename(const PnvChip *o)
7340abf43fSIgor Mammedov {
7440abf43fSIgor Mammedov const char *chip_type = object_class_get_name(object_get_class(OBJECT(o)));
7540abf43fSIgor Mammedov int len = strlen(chip_type) - strlen(PNV_CHIP_TYPE_SUFFIX);
7640abf43fSIgor Mammedov char *s = g_strdup_printf(PNV_CORE_TYPE_NAME("%.*s"), len, chip_type);
7740abf43fSIgor Mammedov const char *core_type = object_class_get_name(object_class_by_name(s));
7840abf43fSIgor Mammedov g_free(s);
7940abf43fSIgor Mammedov return core_type;
8040abf43fSIgor Mammedov }
8140abf43fSIgor Mammedov
829e933f4aSBenjamin Herrenschmidt /*
839e933f4aSBenjamin Herrenschmidt * On Power Systems E880 (POWER8), the max cpus (threads) should be :
849e933f4aSBenjamin Herrenschmidt * 4 * 4 sockets * 12 cores * 8 threads = 1536
859e933f4aSBenjamin Herrenschmidt * Let's make it 2^11
869e933f4aSBenjamin Herrenschmidt */
879e933f4aSBenjamin Herrenschmidt #define MAX_CPUS 2048
889e933f4aSBenjamin Herrenschmidt
899e933f4aSBenjamin Herrenschmidt /*
909e933f4aSBenjamin Herrenschmidt * Memory nodes are created by hostboot, one for each range of memory
919e933f4aSBenjamin Herrenschmidt * that has a different "affinity". In practice, it means one range
929e933f4aSBenjamin Herrenschmidt * per chip.
939e933f4aSBenjamin Herrenschmidt */
pnv_dt_memory(void * fdt,int chip_id,hwaddr start,hwaddr size)94b168a138SCédric Le Goater static void pnv_dt_memory(void *fdt, int chip_id, hwaddr start, hwaddr size)
959e933f4aSBenjamin Herrenschmidt {
969e933f4aSBenjamin Herrenschmidt char *mem_name;
979e933f4aSBenjamin Herrenschmidt uint64_t mem_reg_property[2];
989e933f4aSBenjamin Herrenschmidt int off;
999e933f4aSBenjamin Herrenschmidt
1009e933f4aSBenjamin Herrenschmidt mem_reg_property[0] = cpu_to_be64(start);
1019e933f4aSBenjamin Herrenschmidt mem_reg_property[1] = cpu_to_be64(size);
1029e933f4aSBenjamin Herrenschmidt
1039e933f4aSBenjamin Herrenschmidt mem_name = g_strdup_printf("memory@%"HWADDR_PRIx, start);
1049e933f4aSBenjamin Herrenschmidt off = fdt_add_subnode(fdt, 0, mem_name);
1059e933f4aSBenjamin Herrenschmidt g_free(mem_name);
1069e933f4aSBenjamin Herrenschmidt
1079e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, off, "device_type", "memory")));
1089e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property,
1099e933f4aSBenjamin Herrenschmidt sizeof(mem_reg_property))));
1109e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_cell(fdt, off, "ibm,chip-id", chip_id)));
1119e933f4aSBenjamin Herrenschmidt }
1129e933f4aSBenjamin Herrenschmidt
get_cpus_node(void * fdt)113d2fd9612SCédric Le Goater static int get_cpus_node(void *fdt)
114d2fd9612SCédric Le Goater {
115d2fd9612SCédric Le Goater int cpus_offset = fdt_path_offset(fdt, "/cpus");
116d2fd9612SCédric Le Goater
117d2fd9612SCédric Le Goater if (cpus_offset < 0) {
118a4f3885cSGreg Kurz cpus_offset = fdt_add_subnode(fdt, 0, "cpus");
119d2fd9612SCédric Le Goater if (cpus_offset) {
120d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, cpus_offset, "#address-cells", 0x1)));
121d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, cpus_offset, "#size-cells", 0x0)));
122d2fd9612SCédric Le Goater }
123d2fd9612SCédric Le Goater }
124d2fd9612SCédric Le Goater _FDT(cpus_offset);
125d2fd9612SCédric Le Goater return cpus_offset;
126d2fd9612SCédric Le Goater }
127d2fd9612SCédric Le Goater
128d2fd9612SCédric Le Goater /*
129d2fd9612SCédric Le Goater * The PowerNV cores (and threads) need to use real HW ids and not an
130d2fd9612SCédric Le Goater * incremental index like it has been done on other platforms. This HW
131d2fd9612SCédric Le Goater * id is stored in the CPU PIR, it is used to create cpu nodes in the
132d2fd9612SCédric Le Goater * device tree, used in XSCOM to address cores and in interrupt
133d2fd9612SCédric Le Goater * servers.
134d2fd9612SCédric Le Goater */
pnv_dt_core(PnvChip * chip,PnvCore * pc,void * fdt)135ce2b8536SNicholas Piggin static int pnv_dt_core(PnvChip *chip, PnvCore *pc, void *fdt)
136d2fd9612SCédric Le Goater {
13708304a86SDavid Gibson PowerPCCPU *cpu = pc->threads[0];
13808304a86SDavid Gibson CPUState *cs = CPU(cpu);
139d2fd9612SCédric Le Goater DeviceClass *dc = DEVICE_GET_CLASS(cs);
1408bd9530eSDavid Gibson int smt_threads = CPU_CORE(pc)->nr_threads;
141d2fd9612SCédric Le Goater CPUPPCState *env = &cpu->env;
142d2fd9612SCédric Le Goater PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs);
1439940412aSCaleb Schlossin PnvChipClass *pnv_cc = PNV_CHIP_GET_CLASS(chip);
144cf0eb929SNicholas Piggin uint32_t *servers_prop;
145d2fd9612SCédric Le Goater int i;
146cf0eb929SNicholas Piggin uint32_t pir, tir;
147d2fd9612SCédric Le Goater uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40),
148d2fd9612SCédric Le Goater 0xffffffff, 0xffffffff};
149d2fd9612SCédric Le Goater uint32_t tbfreq = PNV_TIMEBASE_FREQ;
150d2fd9612SCédric Le Goater uint32_t cpufreq = 1000000000;
151d2fd9612SCédric Le Goater uint32_t page_sizes_prop[64];
152d2fd9612SCédric Le Goater size_t page_sizes_prop_size;
153d2fd9612SCédric Le Goater int offset;
154d2fd9612SCédric Le Goater char *nodename;
155d2fd9612SCédric Le Goater int cpus_offset = get_cpus_node(fdt);
156d2fd9612SCédric Le Goater
157cf0eb929SNicholas Piggin pnv_cc->get_pir_tir(chip, pc->hwid, 0, &pir, &tir);
158cf0eb929SNicholas Piggin
159cf0eb929SNicholas Piggin /* Only one DT node per (big) core */
160cf0eb929SNicholas Piggin g_assert(tir == 0);
1619940412aSCaleb Schlossin
1629940412aSCaleb Schlossin nodename = g_strdup_printf("%s@%x", dc->fw_name, pir);
163d2fd9612SCédric Le Goater offset = fdt_add_subnode(fdt, cpus_offset, nodename);
164d2fd9612SCédric Le Goater _FDT(offset);
165d2fd9612SCédric Le Goater g_free(nodename);
166d2fd9612SCédric Le Goater
167d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id", chip->chip_id)));
168d2fd9612SCédric Le Goater
1699940412aSCaleb Schlossin _FDT((fdt_setprop_cell(fdt, offset, "reg", pir)));
1709940412aSCaleb Schlossin _FDT((fdt_setprop_cell(fdt, offset, "ibm,pir", pir)));
171d2fd9612SCédric Le Goater _FDT((fdt_setprop_string(fdt, offset, "device_type", "cpu")));
172d2fd9612SCédric Le Goater
173d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "cpu-version", env->spr[SPR_PVR])));
174d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "d-cache-block-size",
175d2fd9612SCédric Le Goater env->dcache_line_size)));
176d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "d-cache-line-size",
177d2fd9612SCédric Le Goater env->dcache_line_size)));
178d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "i-cache-block-size",
179d2fd9612SCédric Le Goater env->icache_line_size)));
180d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "i-cache-line-size",
181d2fd9612SCédric Le Goater env->icache_line_size)));
182d2fd9612SCédric Le Goater
183d2fd9612SCédric Le Goater if (pcc->l1_dcache_size) {
184d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "d-cache-size",
185d2fd9612SCédric Le Goater pcc->l1_dcache_size)));
186d2fd9612SCédric Le Goater } else {
1873dc6f869SAlistair Francis warn_report("Unknown L1 dcache size for cpu");
188d2fd9612SCédric Le Goater }
189d2fd9612SCédric Le Goater if (pcc->l1_icache_size) {
190d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "i-cache-size",
191d2fd9612SCédric Le Goater pcc->l1_icache_size)));
192d2fd9612SCédric Le Goater } else {
1933dc6f869SAlistair Francis warn_report("Unknown L1 icache size for cpu");
194d2fd9612SCédric Le Goater }
195d2fd9612SCédric Le Goater
196d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "timebase-frequency", tbfreq)));
197d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "clock-frequency", cpufreq)));
19859b7c1c2SBalamuruhan S _FDT((fdt_setprop_cell(fdt, offset, "ibm,slb-size",
19959b7c1c2SBalamuruhan S cpu->hash64_opts->slb_size)));
200d2fd9612SCédric Le Goater _FDT((fdt_setprop_string(fdt, offset, "status", "okay")));
201d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "64-bit", NULL, 0)));
202d2fd9612SCédric Le Goater
20303282a3aSLucas Mateus Castro (alqotel) if (ppc_has_spr(cpu, SPR_PURR)) {
204d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,purr", NULL, 0)));
205d2fd9612SCédric Le Goater }
206d2fd9612SCédric Le Goater
20758969eeeSDavid Gibson if (ppc_hash64_has(cpu, PPC_HASH64_1TSEG)) {
208d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,processor-segment-sizes",
209d2fd9612SCédric Le Goater segs, sizeof(segs))));
210d2fd9612SCédric Le Goater }
211d2fd9612SCédric Le Goater
21259b7c1c2SBalamuruhan S /*
21359b7c1c2SBalamuruhan S * Advertise VMX/VSX (vector extensions) if available
214d2fd9612SCédric Le Goater * 0 / no property == no vector extensions
215d2fd9612SCédric Le Goater * 1 == VMX / Altivec available
21659b7c1c2SBalamuruhan S * 2 == VSX available
21759b7c1c2SBalamuruhan S */
218d2fd9612SCédric Le Goater if (env->insns_flags & PPC_ALTIVEC) {
219d2fd9612SCédric Le Goater uint32_t vmx = (env->insns_flags2 & PPC2_VSX) ? 2 : 1;
220d2fd9612SCédric Le Goater
221d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", vmx)));
222d2fd9612SCédric Le Goater }
223d2fd9612SCédric Le Goater
22459b7c1c2SBalamuruhan S /*
22559b7c1c2SBalamuruhan S * Advertise DFP (Decimal Floating Point) if available
226d2fd9612SCédric Le Goater * 0 / no property == no DFP
22759b7c1c2SBalamuruhan S * 1 == DFP available
22859b7c1c2SBalamuruhan S */
229d2fd9612SCédric Le Goater if (env->insns_flags2 & PPC2_DFP) {
230d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "ibm,dfp", 1)));
231d2fd9612SCédric Le Goater }
232d2fd9612SCédric Le Goater
233644a2c99SDavid Gibson page_sizes_prop_size = ppc_create_page_sizes_prop(cpu, page_sizes_prop,
234d2fd9612SCédric Le Goater sizeof(page_sizes_prop));
235d2fd9612SCédric Le Goater if (page_sizes_prop_size) {
236d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,segment-page-sizes",
237d2fd9612SCédric Le Goater page_sizes_prop, page_sizes_prop_size)));
238d2fd9612SCédric Le Goater }
239d2fd9612SCédric Le Goater
240d2fd9612SCédric Le Goater /* Build interrupt servers properties */
241cf0eb929SNicholas Piggin if (pc->big_core) {
242cf0eb929SNicholas Piggin servers_prop = g_new(uint32_t, smt_threads * 2);
243cf0eb929SNicholas Piggin for (i = 0; i < smt_threads; i++) {
244cf0eb929SNicholas Piggin pnv_cc->get_pir_tir(chip, pc->hwid, i, &pir, NULL);
245cf0eb929SNicholas Piggin servers_prop[i * 2] = cpu_to_be32(pir);
246cf0eb929SNicholas Piggin
247cf0eb929SNicholas Piggin pnv_cc->get_pir_tir(chip, pc->hwid + 1, i, &pir, NULL);
248cf0eb929SNicholas Piggin servers_prop[i * 2 + 1] = cpu_to_be32(pir);
249cf0eb929SNicholas Piggin }
250cf0eb929SNicholas Piggin _FDT((fdt_setprop(fdt, offset, "ibm,ppc-interrupt-server#s",
251cf0eb929SNicholas Piggin servers_prop, sizeof(*servers_prop) * smt_threads
252cf0eb929SNicholas Piggin * 2)));
253cf0eb929SNicholas Piggin } else {
254cf0eb929SNicholas Piggin servers_prop = g_new(uint32_t, smt_threads);
255d2fd9612SCédric Le Goater for (i = 0; i < smt_threads; i++) {
25625de2822SNicholas Piggin pnv_cc->get_pir_tir(chip, pc->hwid, i, &pir, NULL);
25725de2822SNicholas Piggin servers_prop[i] = cpu_to_be32(pir);
258d2fd9612SCédric Le Goater }
259d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,ppc-interrupt-server#s",
260a580fdcdSPhilippe Mathieu-Daudé servers_prop, sizeof(*servers_prop) * smt_threads)));
261cf0eb929SNicholas Piggin }
262cf0eb929SNicholas Piggin g_free(servers_prop);
263ce2b8536SNicholas Piggin
264ce2b8536SNicholas Piggin return offset;
265d2fd9612SCédric Le Goater }
266d2fd9612SCédric Le Goater
pnv_dt_icp(PnvChip * chip,void * fdt,uint32_t hwid,uint32_t nr_threads)2679940412aSCaleb Schlossin static void pnv_dt_icp(PnvChip *chip, void *fdt, uint32_t hwid,
268bf5615e7SCédric Le Goater uint32_t nr_threads)
269bf5615e7SCédric Le Goater {
2709940412aSCaleb Schlossin PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
27125de2822SNicholas Piggin uint32_t pir;
27225de2822SNicholas Piggin uint64_t addr;
273bf5615e7SCédric Le Goater char *name;
274bf5615e7SCédric Le Goater const char compat[] = "IBM,power8-icp\0IBM,ppc-xicp";
275bf5615e7SCédric Le Goater uint32_t irange[2], i, rsize;
276bf5615e7SCédric Le Goater uint64_t *reg;
277bf5615e7SCédric Le Goater int offset;
278bf5615e7SCédric Le Goater
27925de2822SNicholas Piggin pcc->get_pir_tir(chip, hwid, 0, &pir, NULL);
28025de2822SNicholas Piggin addr = PNV_ICP_BASE(chip) | (pir << 12);
28125de2822SNicholas Piggin
282bf5615e7SCédric Le Goater irange[0] = cpu_to_be32(pir);
283bf5615e7SCédric Le Goater irange[1] = cpu_to_be32(nr_threads);
284bf5615e7SCédric Le Goater
285bf5615e7SCédric Le Goater rsize = sizeof(uint64_t) * 2 * nr_threads;
286bf5615e7SCédric Le Goater reg = g_malloc(rsize);
287bf5615e7SCédric Le Goater for (i = 0; i < nr_threads; i++) {
2889940412aSCaleb Schlossin /* We know P8 PIR is linear with thread id */
289bf5615e7SCédric Le Goater reg[i * 2] = cpu_to_be64(addr | ((pir + i) * 0x1000));
290bf5615e7SCédric Le Goater reg[i * 2 + 1] = cpu_to_be64(0x1000);
291bf5615e7SCédric Le Goater }
292bf5615e7SCédric Le Goater
293bf5615e7SCédric Le Goater name = g_strdup_printf("interrupt-controller@%"PRIX64, addr);
294bf5615e7SCédric Le Goater offset = fdt_add_subnode(fdt, 0, name);
295bf5615e7SCédric Le Goater _FDT(offset);
296bf5615e7SCédric Le Goater g_free(name);
297bf5615e7SCédric Le Goater
298bf5615e7SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "compatible", compat, sizeof(compat))));
299bf5615e7SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "reg", reg, rsize)));
300bf5615e7SCédric Le Goater _FDT((fdt_setprop_string(fdt, offset, "device_type",
301bf5615e7SCédric Le Goater "PowerPC-External-Interrupt-Presentation")));
302bf5615e7SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "interrupt-controller", NULL, 0)));
303bf5615e7SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,interrupt-server-ranges",
304bf5615e7SCédric Le Goater irange, sizeof(irange))));
305bf5615e7SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "#interrupt-cells", 1)));
306bf5615e7SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "#address-cells", 0)));
307bf5615e7SCédric Le Goater g_free(reg);
308bf5615e7SCédric Le Goater }
309bf5615e7SCédric Le Goater
310ba47c3a4SDaniel Henrique Barboza /*
311ddf0676fSFrederic Barrat * Adds a PnvPHB to the chip on P8.
312ddf0676fSFrederic Barrat * Implemented here, like for defaults PHBs
313ba47c3a4SDaniel Henrique Barboza */
pnv_chip_add_phb(PnvChip * chip,PnvPHB * phb)314ddf0676fSFrederic Barrat PnvChip *pnv_chip_add_phb(PnvChip *chip, PnvPHB *phb)
315ba47c3a4SDaniel Henrique Barboza {
3160d512c71SDaniel Henrique Barboza Pnv8Chip *chip8 = PNV8_CHIP(chip);
3170d512c71SDaniel Henrique Barboza
3180d512c71SDaniel Henrique Barboza phb->chip = chip;
3190d512c71SDaniel Henrique Barboza
3200d512c71SDaniel Henrique Barboza chip8->phbs[chip8->num_phbs] = phb;
3210d512c71SDaniel Henrique Barboza chip8->num_phbs++;
322ddf0676fSFrederic Barrat return chip;
323ba47c3a4SDaniel Henrique Barboza }
324ba47c3a4SDaniel Henrique Barboza
325ce2b8536SNicholas Piggin /*
326ce2b8536SNicholas Piggin * Same as spapr pa_features_207 except pnv always enables CI largepages bit.
327ce2b8536SNicholas Piggin * HTM is always enabled because TCG does implement HTM, it's just a
328ce2b8536SNicholas Piggin * degenerate implementation.
329ce2b8536SNicholas Piggin */
330ce2b8536SNicholas Piggin static const uint8_t pa_features_207[] = { 24, 0,
331ce2b8536SNicholas Piggin 0xf6, 0x3f, 0xc7, 0xc0, 0x00, 0xf0,
332ce2b8536SNicholas Piggin 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
333ce2b8536SNicholas Piggin 0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
334ce2b8536SNicholas Piggin 0x80, 0x00, 0x80, 0x00, 0x80, 0x00 };
335ce2b8536SNicholas Piggin
pnv_chip_power8_dt_populate(PnvChip * chip,void * fdt)336eb859a27SCédric Le Goater static void pnv_chip_power8_dt_populate(PnvChip *chip, void *fdt)
337e997040eSCédric Le Goater {
338c396c58aSGreg Kurz static const char compat[] = "ibm,power8-xscom\0ibm,xscom";
339d2fd9612SCédric Le Goater int i;
340d2fd9612SCédric Le Goater
3413f5b45caSGreg Kurz pnv_dt_xscom(chip, fdt, 0,
3423f5b45caSGreg Kurz cpu_to_be64(PNV_XSCOM_BASE(chip)),
343c396c58aSGreg Kurz cpu_to_be64(PNV_XSCOM_SIZE),
344c396c58aSGreg Kurz compat, sizeof(compat));
345967b7523SCédric Le Goater
346d2fd9612SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) {
3474fa28f23SGreg Kurz PnvCore *pnv_core = chip->cores[i];
348ce2b8536SNicholas Piggin int offset;
349d2fd9612SCédric Le Goater
350ce2b8536SNicholas Piggin offset = pnv_dt_core(chip, pnv_core, fdt);
351ce2b8536SNicholas Piggin
352ce2b8536SNicholas Piggin _FDT((fdt_setprop(fdt, offset, "ibm,pa-features",
353ce2b8536SNicholas Piggin pa_features_207, sizeof(pa_features_207))));
354bf5615e7SCédric Le Goater
355bf5615e7SCédric Le Goater /* Interrupt Control Presenters (ICP). One per core. */
3569940412aSCaleb Schlossin pnv_dt_icp(chip, fdt, pnv_core->hwid, CPU_CORE(pnv_core)->nr_threads);
357d2fd9612SCédric Le Goater }
358d2fd9612SCédric Le Goater
359e997040eSCédric Le Goater if (chip->ram_size) {
360b168a138SCédric Le Goater pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size);
361e997040eSCédric Le Goater }
362e997040eSCédric Le Goater }
363e997040eSCédric Le Goater
36424a9d20cSNicholas Piggin /*
36524a9d20cSNicholas Piggin * Same as spapr pa_features_300 except pnv always enables CI largepages bit.
36624a9d20cSNicholas Piggin */
36724a9d20cSNicholas Piggin static const uint8_t pa_features_300[] = { 66, 0,
36824a9d20cSNicholas Piggin /* 0: MMU|FPU|SLB|RUN|DABR|NX, 1: CILRG|fri[nzpm]|DABRX|SPRG3|SLB0|PP110 */
36924a9d20cSNicholas Piggin /* 2: VPM|DS205|PPR|DS202|DS206, 3: LSD|URG, 5: LE|CFAR|EB|LSQ */
37024a9d20cSNicholas Piggin 0xf6, 0x3f, 0xc7, 0xc0, 0x00, 0xf0, /* 0 - 5 */
37124a9d20cSNicholas Piggin /* 6: DS207 */
37224a9d20cSNicholas Piggin 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, /* 6 - 11 */
37324a9d20cSNicholas Piggin /* 16: Vector */
37424a9d20cSNicholas Piggin 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, /* 12 - 17 */
37524a9d20cSNicholas Piggin /* 18: Vec. Scalar, 20: Vec. XOR, 22: HTM */
37624a9d20cSNicholas Piggin 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 18 - 23 */
37724a9d20cSNicholas Piggin /* 24: Ext. Dec, 26: 64 bit ftrs, 28: PM ftrs */
37824a9d20cSNicholas Piggin 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 24 - 29 */
37924a9d20cSNicholas Piggin /* 32: LE atomic, 34: EBB + ext EBB */
38024a9d20cSNicholas Piggin 0x00, 0x00, 0x80, 0x00, 0xC0, 0x00, /* 30 - 35 */
38124a9d20cSNicholas Piggin /* 40: Radix MMU */
38224a9d20cSNicholas Piggin 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, /* 36 - 41 */
38324a9d20cSNicholas Piggin /* 42: PM, 44: PC RA, 46: SC vec'd */
38424a9d20cSNicholas Piggin 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 42 - 47 */
38524a9d20cSNicholas Piggin /* 48: SIMD, 50: QP BFP, 52: String */
38624a9d20cSNicholas Piggin 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 48 - 53 */
38724a9d20cSNicholas Piggin /* 54: DecFP, 56: DecI, 58: SHA */
38824a9d20cSNicholas Piggin 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 54 - 59 */
38924a9d20cSNicholas Piggin /* 60: NM atomic, 62: RNG */
39024a9d20cSNicholas Piggin 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 60 - 65 */
39124a9d20cSNicholas Piggin };
39224a9d20cSNicholas Piggin
pnv_chip_power9_dt_populate(PnvChip * chip,void * fdt)393eb859a27SCédric Le Goater static void pnv_chip_power9_dt_populate(PnvChip *chip, void *fdt)
394eb859a27SCédric Le Goater {
395c396c58aSGreg Kurz static const char compat[] = "ibm,power9-xscom\0ibm,xscom";
396eb859a27SCédric Le Goater int i;
397eb859a27SCédric Le Goater
3983f5b45caSGreg Kurz pnv_dt_xscom(chip, fdt, 0,
3993f5b45caSGreg Kurz cpu_to_be64(PNV9_XSCOM_BASE(chip)),
400c396c58aSGreg Kurz cpu_to_be64(PNV9_XSCOM_SIZE),
401c396c58aSGreg Kurz compat, sizeof(compat));
402eb859a27SCédric Le Goater
403eb859a27SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) {
4044fa28f23SGreg Kurz PnvCore *pnv_core = chip->cores[i];
405ce2b8536SNicholas Piggin int offset;
406eb859a27SCédric Le Goater
407ce2b8536SNicholas Piggin offset = pnv_dt_core(chip, pnv_core, fdt);
408ce2b8536SNicholas Piggin
409ce2b8536SNicholas Piggin _FDT((fdt_setprop(fdt, offset, "ibm,pa-features",
41024a9d20cSNicholas Piggin pa_features_300, sizeof(pa_features_300))));
411cf0eb929SNicholas Piggin
412cf0eb929SNicholas Piggin if (pnv_core->big_core) {
413cf0eb929SNicholas Piggin i++; /* Big-core groups two QEMU cores */
414cf0eb929SNicholas Piggin }
415eb859a27SCédric Le Goater }
416eb859a27SCédric Le Goater
417eb859a27SCédric Le Goater if (chip->ram_size) {
418eb859a27SCédric Le Goater pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size);
419eb859a27SCédric Le Goater }
42015376c66SCédric Le Goater
4212661f6abSCédric Le Goater pnv_dt_lpc(chip, fdt, 0, PNV9_LPCM_BASE(chip), PNV9_LPCM_SIZE);
422eb859a27SCédric Le Goater }
423eb859a27SCédric Le Goater
42424a9d20cSNicholas Piggin /*
42524a9d20cSNicholas Piggin * Same as spapr pa_features_31 except pnv always enables CI largepages bit,
42624a9d20cSNicholas Piggin * always disables copy/paste.
42724a9d20cSNicholas Piggin */
42824a9d20cSNicholas Piggin static const uint8_t pa_features_31[] = { 74, 0,
42924a9d20cSNicholas Piggin /* 0: MMU|FPU|SLB|RUN|DABR|NX, 1: CILRG|fri[nzpm]|DABRX|SPRG3|SLB0|PP110 */
43024a9d20cSNicholas Piggin /* 2: VPM|DS205|PPR|DS202|DS206, 3: LSD|URG, 5: LE|CFAR|EB|LSQ */
43124a9d20cSNicholas Piggin 0xf6, 0x3f, 0xc7, 0xc0, 0x00, 0xf0, /* 0 - 5 */
43224a9d20cSNicholas Piggin /* 6: DS207 */
43324a9d20cSNicholas Piggin 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, /* 6 - 11 */
43424a9d20cSNicholas Piggin /* 16: Vector */
43524a9d20cSNicholas Piggin 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, /* 12 - 17 */
43624a9d20cSNicholas Piggin /* 18: Vec. Scalar, 20: Vec. XOR */
43724a9d20cSNicholas Piggin 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 18 - 23 */
43824a9d20cSNicholas Piggin /* 24: Ext. Dec, 26: 64 bit ftrs, 28: PM ftrs */
43924a9d20cSNicholas Piggin 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 24 - 29 */
44024a9d20cSNicholas Piggin /* 32: LE atomic, 34: EBB + ext EBB */
44124a9d20cSNicholas Piggin 0x00, 0x00, 0x80, 0x00, 0xC0, 0x00, /* 30 - 35 */
44224a9d20cSNicholas Piggin /* 40: Radix MMU */
44324a9d20cSNicholas Piggin 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, /* 36 - 41 */
44424a9d20cSNicholas Piggin /* 42: PM, 44: PC RA, 46: SC vec'd */
44524a9d20cSNicholas Piggin 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 42 - 47 */
44624a9d20cSNicholas Piggin /* 48: SIMD, 50: QP BFP, 52: String */
44724a9d20cSNicholas Piggin 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 48 - 53 */
44824a9d20cSNicholas Piggin /* 54: DecFP, 56: DecI, 58: SHA */
44924a9d20cSNicholas Piggin 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 54 - 59 */
45024a9d20cSNicholas Piggin /* 60: NM atomic, 62: RNG */
45124a9d20cSNicholas Piggin 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 60 - 65 */
45224a9d20cSNicholas Piggin /* 68: DEXCR[SBHE|IBRTPDUS|SRAPD|NPHIE|PHIE] */
45324a9d20cSNicholas Piggin 0x00, 0x00, 0xce, 0x00, 0x00, 0x00, /* 66 - 71 */
45424a9d20cSNicholas Piggin /* 72: [P]HASHST/[P]HASHCHK */
45524a9d20cSNicholas Piggin 0x80, 0x00, /* 72 - 73 */
45624a9d20cSNicholas Piggin };
45724a9d20cSNicholas Piggin
pnv_chip_power10_dt_populate(PnvChip * chip,void * fdt)4582b548a42SCédric Le Goater static void pnv_chip_power10_dt_populate(PnvChip *chip, void *fdt)
4592b548a42SCédric Le Goater {
460c396c58aSGreg Kurz static const char compat[] = "ibm,power10-xscom\0ibm,xscom";
4612b548a42SCédric Le Goater int i;
4622b548a42SCédric Le Goater
4633f5b45caSGreg Kurz pnv_dt_xscom(chip, fdt, 0,
4643f5b45caSGreg Kurz cpu_to_be64(PNV10_XSCOM_BASE(chip)),
465c396c58aSGreg Kurz cpu_to_be64(PNV10_XSCOM_SIZE),
466c396c58aSGreg Kurz compat, sizeof(compat));
4672b548a42SCédric Le Goater
4682b548a42SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) {
4692b548a42SCédric Le Goater PnvCore *pnv_core = chip->cores[i];
470ce2b8536SNicholas Piggin int offset;
4712b548a42SCédric Le Goater
472ce2b8536SNicholas Piggin offset = pnv_dt_core(chip, pnv_core, fdt);
473ce2b8536SNicholas Piggin
474ce2b8536SNicholas Piggin _FDT((fdt_setprop(fdt, offset, "ibm,pa-features",
47524a9d20cSNicholas Piggin pa_features_31, sizeof(pa_features_31))));
476cf0eb929SNicholas Piggin
477cf0eb929SNicholas Piggin if (pnv_core->big_core) {
478cf0eb929SNicholas Piggin i++; /* Big-core groups two QEMU cores */
479cf0eb929SNicholas Piggin }
4802b548a42SCédric Le Goater }
4812b548a42SCédric Le Goater
4822b548a42SCédric Le Goater if (chip->ram_size) {
4832b548a42SCédric Le Goater pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size);
4842b548a42SCédric Le Goater }
4852661f6abSCédric Le Goater
4862661f6abSCédric Le Goater pnv_dt_lpc(chip, fdt, 0, PNV10_LPCM_BASE(chip), PNV10_LPCM_SIZE);
4872b548a42SCédric Le Goater }
4882b548a42SCédric Le Goater
pnv_dt_rtc(ISADevice * d,void * fdt,int lpc_off)489b168a138SCédric Le Goater static void pnv_dt_rtc(ISADevice *d, void *fdt, int lpc_off)
490c5ffdcaeSCédric Le Goater {
491c5ffdcaeSCédric Le Goater uint32_t io_base = d->ioport_id;
492c5ffdcaeSCédric Le Goater uint32_t io_regs[] = {
493c5ffdcaeSCédric Le Goater cpu_to_be32(1),
494c5ffdcaeSCédric Le Goater cpu_to_be32(io_base),
495c5ffdcaeSCédric Le Goater cpu_to_be32(2)
496c5ffdcaeSCédric Le Goater };
497c5ffdcaeSCédric Le Goater char *name;
498c5ffdcaeSCédric Le Goater int node;
499c5ffdcaeSCédric Le Goater
500c5ffdcaeSCédric Le Goater name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base);
501c5ffdcaeSCédric Le Goater node = fdt_add_subnode(fdt, lpc_off, name);
502c5ffdcaeSCédric Le Goater _FDT(node);
503c5ffdcaeSCédric Le Goater g_free(name);
504c5ffdcaeSCédric Le Goater
505c5ffdcaeSCédric Le Goater _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs))));
506c5ffdcaeSCédric Le Goater _FDT((fdt_setprop_string(fdt, node, "compatible", "pnpPNP,b00")));
507c5ffdcaeSCédric Le Goater }
508c5ffdcaeSCédric Le Goater
pnv_dt_serial(ISADevice * d,void * fdt,int lpc_off)509b168a138SCédric Le Goater static void pnv_dt_serial(ISADevice *d, void *fdt, int lpc_off)
510cb228f5aSCédric Le Goater {
511cb228f5aSCédric Le Goater const char compatible[] = "ns16550\0pnpPNP,501";
512cb228f5aSCédric Le Goater uint32_t io_base = d->ioport_id;
513cb228f5aSCédric Le Goater uint32_t io_regs[] = {
514cb228f5aSCédric Le Goater cpu_to_be32(1),
515cb228f5aSCédric Le Goater cpu_to_be32(io_base),
516cb228f5aSCédric Le Goater cpu_to_be32(8)
517cb228f5aSCédric Le Goater };
518632fc0b3SBernhard Beschow uint32_t irq;
519cb228f5aSCédric Le Goater char *name;
520cb228f5aSCédric Le Goater int node;
521cb228f5aSCédric Le Goater
522632fc0b3SBernhard Beschow irq = object_property_get_uint(OBJECT(d), "irq", &error_fatal);
523632fc0b3SBernhard Beschow
524cb228f5aSCédric Le Goater name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base);
525cb228f5aSCédric Le Goater node = fdt_add_subnode(fdt, lpc_off, name);
526cb228f5aSCédric Le Goater _FDT(node);
527cb228f5aSCédric Le Goater g_free(name);
528cb228f5aSCédric Le Goater
529cb228f5aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs))));
530cb228f5aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "compatible", compatible,
531cb228f5aSCédric Le Goater sizeof(compatible))));
532cb228f5aSCédric Le Goater
533cb228f5aSCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "clock-frequency", 1843200)));
534cb228f5aSCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "current-speed", 115200)));
535632fc0b3SBernhard Beschow _FDT((fdt_setprop_cell(fdt, node, "interrupts", irq)));
536cb228f5aSCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent",
537cb228f5aSCédric Le Goater fdt_get_phandle(fdt, lpc_off))));
538cb228f5aSCédric Le Goater
539cb228f5aSCédric Le Goater /* This is needed by Linux */
540cb228f5aSCédric Le Goater _FDT((fdt_setprop_string(fdt, node, "device_type", "serial")));
541cb228f5aSCédric Le Goater }
542cb228f5aSCédric Le Goater
pnv_dt_ipmi_bt(ISADevice * d,void * fdt,int lpc_off)543b168a138SCédric Le Goater static void pnv_dt_ipmi_bt(ISADevice *d, void *fdt, int lpc_off)
54404f6c8b2SCédric Le Goater {
54504f6c8b2SCédric Le Goater const char compatible[] = "bt\0ipmi-bt";
54604f6c8b2SCédric Le Goater uint32_t io_base;
54704f6c8b2SCédric Le Goater uint32_t io_regs[] = {
54804f6c8b2SCédric Le Goater cpu_to_be32(1),
54904f6c8b2SCédric Le Goater 0, /* 'io_base' retrieved from the 'ioport' property of 'isa-ipmi-bt' */
55004f6c8b2SCédric Le Goater cpu_to_be32(3)
55104f6c8b2SCédric Le Goater };
55204f6c8b2SCédric Le Goater uint32_t irq;
55304f6c8b2SCédric Le Goater char *name;
55404f6c8b2SCédric Le Goater int node;
55504f6c8b2SCédric Le Goater
55604f6c8b2SCédric Le Goater io_base = object_property_get_int(OBJECT(d), "ioport", &error_fatal);
55704f6c8b2SCédric Le Goater io_regs[1] = cpu_to_be32(io_base);
55804f6c8b2SCédric Le Goater
55904f6c8b2SCédric Le Goater irq = object_property_get_int(OBJECT(d), "irq", &error_fatal);
56004f6c8b2SCédric Le Goater
56104f6c8b2SCédric Le Goater name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base);
56204f6c8b2SCédric Le Goater node = fdt_add_subnode(fdt, lpc_off, name);
56304f6c8b2SCédric Le Goater _FDT(node);
56404f6c8b2SCédric Le Goater g_free(name);
56504f6c8b2SCédric Le Goater
5667032d92aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs))));
5677032d92aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "compatible", compatible,
5687032d92aSCédric Le Goater sizeof(compatible))));
56904f6c8b2SCédric Le Goater
57004f6c8b2SCédric Le Goater /* Mark it as reserved to avoid Linux trying to claim it */
57104f6c8b2SCédric Le Goater _FDT((fdt_setprop_string(fdt, node, "status", "reserved")));
57204f6c8b2SCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "interrupts", irq)));
57304f6c8b2SCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent",
57404f6c8b2SCédric Le Goater fdt_get_phandle(fdt, lpc_off))));
57504f6c8b2SCédric Le Goater }
57604f6c8b2SCédric Le Goater
577e7a3fee3SCédric Le Goater typedef struct ForeachPopulateArgs {
578e7a3fee3SCédric Le Goater void *fdt;
579e7a3fee3SCédric Le Goater int offset;
580e7a3fee3SCédric Le Goater } ForeachPopulateArgs;
581e7a3fee3SCédric Le Goater
pnv_dt_isa_device(DeviceState * dev,void * opaque)582b168a138SCédric Le Goater static int pnv_dt_isa_device(DeviceState *dev, void *opaque)
583e7a3fee3SCédric Le Goater {
584c5ffdcaeSCédric Le Goater ForeachPopulateArgs *args = opaque;
585c5ffdcaeSCédric Le Goater ISADevice *d = ISA_DEVICE(dev);
586c5ffdcaeSCédric Le Goater
587c5ffdcaeSCédric Le Goater if (object_dynamic_cast(OBJECT(dev), TYPE_MC146818_RTC)) {
588b168a138SCédric Le Goater pnv_dt_rtc(d, args->fdt, args->offset);
589cb228f5aSCédric Le Goater } else if (object_dynamic_cast(OBJECT(dev), TYPE_ISA_SERIAL)) {
590b168a138SCédric Le Goater pnv_dt_serial(d, args->fdt, args->offset);
59104f6c8b2SCédric Le Goater } else if (object_dynamic_cast(OBJECT(dev), "isa-ipmi-bt")) {
592b168a138SCédric Le Goater pnv_dt_ipmi_bt(d, args->fdt, args->offset);
593c5ffdcaeSCédric Le Goater } else {
594c5ffdcaeSCédric Le Goater error_report("unknown isa device %s@i%x", qdev_fw_name(dev),
595c5ffdcaeSCédric Le Goater d->ioport_id);
596c5ffdcaeSCédric Le Goater }
597c5ffdcaeSCédric Le Goater
598e7a3fee3SCédric Le Goater return 0;
599e7a3fee3SCédric Le Goater }
600e7a3fee3SCédric Le Goater
60159b7c1c2SBalamuruhan S /*
60259b7c1c2SBalamuruhan S * The default LPC bus of a multichip system is on chip 0. It's
603bb7ab95cSCédric Le Goater * recognized by the firmware (skiboot) using a "primary" property.
604bb7ab95cSCédric Le Goater */
pnv_dt_isa(PnvMachineState * pnv,void * fdt)605bb7ab95cSCédric Le Goater static void pnv_dt_isa(PnvMachineState *pnv, void *fdt)
606bb7ab95cSCédric Le Goater {
60764d011d5SCédric Le Goater int isa_offset = fdt_path_offset(fdt, pnv->chips[0]->dt_isa_nodename);
608e7a3fee3SCédric Le Goater ForeachPopulateArgs args = {
609e7a3fee3SCédric Le Goater .fdt = fdt,
610bb7ab95cSCédric Le Goater .offset = isa_offset,
611e7a3fee3SCédric Le Goater };
612f47a08d1SCédric Le Goater uint32_t phandle;
613e7a3fee3SCédric Le Goater
614bb7ab95cSCédric Le Goater _FDT((fdt_setprop(fdt, isa_offset, "primary", NULL, 0)));
615bb7ab95cSCédric Le Goater
616f47a08d1SCédric Le Goater phandle = qemu_fdt_alloc_phandle(fdt);
617f47a08d1SCédric Le Goater assert(phandle > 0);
618f47a08d1SCédric Le Goater _FDT((fdt_setprop_cell(fdt, isa_offset, "phandle", phandle)));
619f47a08d1SCédric Le Goater
62059b7c1c2SBalamuruhan S /*
62159b7c1c2SBalamuruhan S * ISA devices are not necessarily parented to the ISA bus so we
62259b7c1c2SBalamuruhan S * can not use object_child_foreach()
62359b7c1c2SBalamuruhan S */
624bb7ab95cSCédric Le Goater qbus_walk_children(BUS(pnv->isa_bus), pnv_dt_isa_device, NULL, NULL, NULL,
625bb7ab95cSCédric Le Goater &args);
626e7a3fee3SCédric Le Goater }
627e7a3fee3SCédric Le Goater
pnv_dt_power_mgt(PnvMachineState * pnv,void * fdt)6287a90c6a1SGreg Kurz static void pnv_dt_power_mgt(PnvMachineState *pnv, void *fdt)
629e5694793SCédric Le Goater {
630e5694793SCédric Le Goater int off;
631e5694793SCédric Le Goater
632e5694793SCédric Le Goater off = fdt_add_subnode(fdt, 0, "ibm,opal");
633e5694793SCédric Le Goater off = fdt_add_subnode(fdt, off, "power-mgt");
634e5694793SCédric Le Goater
635e5694793SCédric Le Goater _FDT(fdt_setprop_cell(fdt, off, "ibm,enabled-stop-levels", 0xc0000000));
636e5694793SCédric Le Goater }
637e5694793SCédric Le Goater
pnv_dt_create(MachineState * machine)638b168a138SCédric Le Goater static void *pnv_dt_create(MachineState *machine)
6399e933f4aSBenjamin Herrenschmidt {
640d76f2da7SGreg Kurz PnvMachineClass *pmc = PNV_MACHINE_GET_CLASS(machine);
641b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(machine);
6429e933f4aSBenjamin Herrenschmidt void *fdt;
6439e933f4aSBenjamin Herrenschmidt char *buf;
6449e933f4aSBenjamin Herrenschmidt int off;
645e997040eSCédric Le Goater int i;
6469e933f4aSBenjamin Herrenschmidt
6479e933f4aSBenjamin Herrenschmidt fdt = g_malloc0(FDT_MAX_SIZE);
6489e933f4aSBenjamin Herrenschmidt _FDT((fdt_create_empty_tree(fdt, FDT_MAX_SIZE)));
6499e933f4aSBenjamin Herrenschmidt
650ccb099b3SCédric Le Goater /* /qemu node */
651ccb099b3SCédric Le Goater _FDT((fdt_add_subnode(fdt, 0, "qemu")));
652ccb099b3SCédric Le Goater
6539e933f4aSBenjamin Herrenschmidt /* Root node */
6549e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_cell(fdt, 0, "#address-cells", 0x2)));
6559e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_cell(fdt, 0, "#size-cells", 0x2)));
6569e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, 0, "model",
6579e933f4aSBenjamin Herrenschmidt "IBM PowerNV (emulated by qemu)")));
658d76f2da7SGreg Kurz _FDT((fdt_setprop(fdt, 0, "compatible", pmc->compat, pmc->compat_size)));
6599e933f4aSBenjamin Herrenschmidt
6609e933f4aSBenjamin Herrenschmidt buf = qemu_uuid_unparse_strdup(&qemu_uuid);
6619e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, 0, "vm,uuid", buf)));
6629e933f4aSBenjamin Herrenschmidt if (qemu_uuid_set) {
663bbfbbff5SDaniel Henrique Barboza _FDT((fdt_setprop_string(fdt, 0, "system-id", buf)));
6649e933f4aSBenjamin Herrenschmidt }
6659e933f4aSBenjamin Herrenschmidt g_free(buf);
6669e933f4aSBenjamin Herrenschmidt
6679e933f4aSBenjamin Herrenschmidt off = fdt_add_subnode(fdt, 0, "chosen");
6689e933f4aSBenjamin Herrenschmidt if (machine->kernel_cmdline) {
6699e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, off, "bootargs",
6709e933f4aSBenjamin Herrenschmidt machine->kernel_cmdline)));
6719e933f4aSBenjamin Herrenschmidt }
6729e933f4aSBenjamin Herrenschmidt
6739e933f4aSBenjamin Herrenschmidt if (pnv->initrd_size) {
6749e933f4aSBenjamin Herrenschmidt uint32_t start_prop = cpu_to_be32(pnv->initrd_base);
6759e933f4aSBenjamin Herrenschmidt uint32_t end_prop = cpu_to_be32(pnv->initrd_base + pnv->initrd_size);
6769e933f4aSBenjamin Herrenschmidt
6779e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop(fdt, off, "linux,initrd-start",
6789e933f4aSBenjamin Herrenschmidt &start_prop, sizeof(start_prop))));
6799e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop(fdt, off, "linux,initrd-end",
6809e933f4aSBenjamin Herrenschmidt &end_prop, sizeof(end_prop))));
6819e933f4aSBenjamin Herrenschmidt }
6829e933f4aSBenjamin Herrenschmidt
683e997040eSCédric Le Goater /* Populate device tree for each chip */
684e997040eSCédric Le Goater for (i = 0; i < pnv->num_chips; i++) {
685eb859a27SCédric Le Goater PNV_CHIP_GET_CLASS(pnv->chips[i])->dt_populate(pnv->chips[i], fdt);
686e997040eSCédric Le Goater }
687e7a3fee3SCédric Le Goater
688e7a3fee3SCédric Le Goater /* Populate ISA devices on chip 0 */
689bb7ab95cSCédric Le Goater pnv_dt_isa(pnv, fdt);
690aeaef83dSCédric Le Goater
691aeaef83dSCédric Le Goater if (pnv->bmc) {
692b168a138SCédric Le Goater pnv_dt_bmc_sensors(pnv->bmc, fdt);
693aeaef83dSCédric Le Goater }
694aeaef83dSCédric Le Goater
6957a90c6a1SGreg Kurz /* Create an extra node for power management on machines that support it */
6967a90c6a1SGreg Kurz if (pmc->dt_power_mgt) {
6977a90c6a1SGreg Kurz pmc->dt_power_mgt(pnv, fdt);
698e5694793SCédric Le Goater }
699e5694793SCédric Le Goater
7009e933f4aSBenjamin Herrenschmidt return fdt;
7019e933f4aSBenjamin Herrenschmidt }
7029e933f4aSBenjamin Herrenschmidt
pnv_powerdown_notify(Notifier * n,void * opaque)703bce0b691SCédric Le Goater static void pnv_powerdown_notify(Notifier *n, void *opaque)
704bce0b691SCédric Le Goater {
7058f06e370SCédric Le Goater PnvMachineState *pnv = container_of(n, PnvMachineState, powerdown_notifier);
706bce0b691SCédric Le Goater
707bce0b691SCédric Le Goater if (pnv->bmc) {
708bce0b691SCédric Le Goater pnv_bmc_powerdown(pnv->bmc);
709bce0b691SCédric Le Goater }
710bce0b691SCédric Le Goater }
711bce0b691SCédric Le Goater
pnv_reset(MachineState * machine,ResetType type)7121b063fe2SJuraj Marcin static void pnv_reset(MachineState *machine, ResetType type)
7139e933f4aSBenjamin Herrenschmidt {
71425f3170bSCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(machine);
71525f3170bSCédric Le Goater IPMIBmc *bmc;
7169e933f4aSBenjamin Herrenschmidt void *fdt;
7179e933f4aSBenjamin Herrenschmidt
7181b063fe2SJuraj Marcin qemu_devices_reset(type);
7199e933f4aSBenjamin Herrenschmidt
72025f3170bSCédric Le Goater /*
72125f3170bSCédric Le Goater * The machine should provide by default an internal BMC simulator.
72225f3170bSCédric Le Goater * If not, try to use the BMC device that was provided on the command
72325f3170bSCédric Le Goater * line.
72425f3170bSCédric Le Goater */
72525f3170bSCédric Le Goater bmc = pnv_bmc_find(&error_fatal);
72625f3170bSCédric Le Goater if (!pnv->bmc) {
72725f3170bSCédric Le Goater if (!bmc) {
72838d2448aSGreg Kurz if (!qtest_enabled()) {
72925f3170bSCédric Le Goater warn_report("machine has no BMC device. Use '-device "
73025f3170bSCédric Le Goater "ipmi-bmc-sim,id=bmc0 -device isa-ipmi-bt,bmc=bmc0,irq=10' "
73125f3170bSCédric Le Goater "to define one");
73238d2448aSGreg Kurz }
73325f3170bSCédric Le Goater } else {
73425f3170bSCédric Le Goater pnv_bmc_set_pnor(bmc, pnv->pnor);
73525f3170bSCédric Le Goater pnv->bmc = bmc;
73625f3170bSCédric Le Goater }
73725f3170bSCédric Le Goater }
73825f3170bSCédric Le Goater
739*889c5c4cSAditya Gupta if (machine->fdt) {
740*889c5c4cSAditya Gupta fdt = machine->fdt;
741*889c5c4cSAditya Gupta } else {
742b168a138SCédric Le Goater fdt = pnv_dt_create(machine);
7439e933f4aSBenjamin Herrenschmidt /* Pack resulting tree */
7449e933f4aSBenjamin Herrenschmidt _FDT((fdt_pack(fdt)));
745*889c5c4cSAditya Gupta }
7469e933f4aSBenjamin Herrenschmidt
7478d409261SCédric Le Goater qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt));
7489e933f4aSBenjamin Herrenschmidt cpu_physical_memory_write(PNV_FDT_ADDR, fdt, fdt_totalsize(fdt));
749b2fb7a43SPan Nengyuan
750*889c5c4cSAditya Gupta /* Update machine->fdt with latest fdt */
751*889c5c4cSAditya Gupta if (machine->fdt != fdt) {
752adb77996SDaniel Henrique Barboza /*
753adb77996SDaniel Henrique Barboza * Set machine->fdt for 'dumpdtb' QMP/HMP command. Free
754adb77996SDaniel Henrique Barboza * the existing machine->fdt to avoid leaking it during
755adb77996SDaniel Henrique Barboza * a reset.
756adb77996SDaniel Henrique Barboza */
757adb77996SDaniel Henrique Barboza g_free(machine->fdt);
758adb77996SDaniel Henrique Barboza machine->fdt = fdt;
7599e933f4aSBenjamin Herrenschmidt }
760*889c5c4cSAditya Gupta }
7619e933f4aSBenjamin Herrenschmidt
pnv_chip_power8_isa_create(PnvChip * chip,Error ** errp)76204026890SCédric Le Goater static ISABus *pnv_chip_power8_isa_create(PnvChip *chip, Error **errp)
7633495b6b6SCédric Le Goater {
76477864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(chip);
765c05aa140SCédric Le Goater qemu_irq irq = qdev_get_gpio_in(DEVICE(&chip8->psi), PSIHB_IRQ_EXTERNAL);
766c05aa140SCédric Le Goater
76724c3caffSNicholas Piggin qdev_connect_gpio_out_named(DEVICE(&chip8->lpc), "LPCHC", 0, irq);
76824c3caffSNicholas Piggin
76977864267SCédric Le Goater return pnv_lpc_isa_create(&chip8->lpc, true, errp);
77004026890SCédric Le Goater }
7713495b6b6SCédric Le Goater
pnv_chip_power8nvl_isa_create(PnvChip * chip,Error ** errp)77204026890SCédric Le Goater static ISABus *pnv_chip_power8nvl_isa_create(PnvChip *chip, Error **errp)
77304026890SCédric Le Goater {
77477864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(chip);
775c05aa140SCédric Le Goater qemu_irq irq = qdev_get_gpio_in(DEVICE(&chip8->psi), PSIHB_IRQ_LPC_I2C);
776c05aa140SCédric Le Goater
77724c3caffSNicholas Piggin qdev_connect_gpio_out_named(DEVICE(&chip8->lpc), "LPCHC", 0, irq);
77824c3caffSNicholas Piggin
77977864267SCédric Le Goater return pnv_lpc_isa_create(&chip8->lpc, false, errp);
78004026890SCédric Le Goater }
7813495b6b6SCédric Le Goater
pnv_chip_power9_isa_create(PnvChip * chip,Error ** errp)78204026890SCédric Le Goater static ISABus *pnv_chip_power9_isa_create(PnvChip *chip, Error **errp)
78304026890SCédric Le Goater {
78415376c66SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(chip);
78524c3caffSNicholas Piggin qemu_irq irq;
786c05aa140SCédric Le Goater
78724c3caffSNicholas Piggin irq = qdev_get_gpio_in(DEVICE(&chip9->psi), PSIHB9_IRQ_LPCHC);
78824c3caffSNicholas Piggin qdev_connect_gpio_out_named(DEVICE(&chip9->lpc), "LPCHC", 0, irq);
78924c3caffSNicholas Piggin
79024c3caffSNicholas Piggin irq = qdev_get_gpio_in(DEVICE(&chip9->psi), PSIHB9_IRQ_LPC_SIRQ0);
79124c3caffSNicholas Piggin qdev_connect_gpio_out_named(DEVICE(&chip9->lpc), "SERIRQ", 0, irq);
79224c3caffSNicholas Piggin irq = qdev_get_gpio_in(DEVICE(&chip9->psi), PSIHB9_IRQ_LPC_SIRQ1);
79324c3caffSNicholas Piggin qdev_connect_gpio_out_named(DEVICE(&chip9->lpc), "SERIRQ", 1, irq);
79424c3caffSNicholas Piggin irq = qdev_get_gpio_in(DEVICE(&chip9->psi), PSIHB9_IRQ_LPC_SIRQ2);
79524c3caffSNicholas Piggin qdev_connect_gpio_out_named(DEVICE(&chip9->lpc), "SERIRQ", 2, irq);
79624c3caffSNicholas Piggin irq = qdev_get_gpio_in(DEVICE(&chip9->psi), PSIHB9_IRQ_LPC_SIRQ3);
79724c3caffSNicholas Piggin qdev_connect_gpio_out_named(DEVICE(&chip9->lpc), "SERIRQ", 3, irq);
79824c3caffSNicholas Piggin
79915376c66SCédric Le Goater return pnv_lpc_isa_create(&chip9->lpc, false, errp);
80004026890SCédric Le Goater }
8013495b6b6SCédric Le Goater
pnv_chip_power10_isa_create(PnvChip * chip,Error ** errp)8022b548a42SCédric Le Goater static ISABus *pnv_chip_power10_isa_create(PnvChip *chip, Error **errp)
8032b548a42SCédric Le Goater {
8042661f6abSCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(chip);
80524c3caffSNicholas Piggin qemu_irq irq;
806c05aa140SCédric Le Goater
80724c3caffSNicholas Piggin irq = qdev_get_gpio_in(DEVICE(&chip10->psi), PSIHB9_IRQ_LPCHC);
80824c3caffSNicholas Piggin qdev_connect_gpio_out_named(DEVICE(&chip10->lpc), "LPCHC", 0, irq);
80924c3caffSNicholas Piggin
81024c3caffSNicholas Piggin irq = qdev_get_gpio_in(DEVICE(&chip10->psi), PSIHB9_IRQ_LPC_SIRQ0);
81124c3caffSNicholas Piggin qdev_connect_gpio_out_named(DEVICE(&chip10->lpc), "SERIRQ", 0, irq);
81224c3caffSNicholas Piggin irq = qdev_get_gpio_in(DEVICE(&chip10->psi), PSIHB9_IRQ_LPC_SIRQ1);
81324c3caffSNicholas Piggin qdev_connect_gpio_out_named(DEVICE(&chip10->lpc), "SERIRQ", 1, irq);
81424c3caffSNicholas Piggin irq = qdev_get_gpio_in(DEVICE(&chip10->psi), PSIHB9_IRQ_LPC_SIRQ2);
81524c3caffSNicholas Piggin qdev_connect_gpio_out_named(DEVICE(&chip10->lpc), "SERIRQ", 2, irq);
81624c3caffSNicholas Piggin irq = qdev_get_gpio_in(DEVICE(&chip10->psi), PSIHB9_IRQ_LPC_SIRQ3);
81724c3caffSNicholas Piggin qdev_connect_gpio_out_named(DEVICE(&chip10->lpc), "SERIRQ", 3, irq);
81824c3caffSNicholas Piggin
8192661f6abSCédric Le Goater return pnv_lpc_isa_create(&chip10->lpc, false, errp);
8202b548a42SCédric Le Goater }
8212b548a42SCédric Le Goater
pnv_isa_create(PnvChip * chip,Error ** errp)82204026890SCédric Le Goater static ISABus *pnv_isa_create(PnvChip *chip, Error **errp)
82304026890SCédric Le Goater {
82404026890SCédric Le Goater return PNV_CHIP_GET_CLASS(chip)->isa_create(chip, errp);
8253495b6b6SCédric Le Goater }
8263495b6b6SCédric Le Goater
pnv_chip_power8_pic_print_info(PnvChip * chip,GString * buf)827a58e653aSPhilippe Mathieu-Daudé static void pnv_chip_power8_pic_print_info(PnvChip *chip, GString *buf)
828d8e4aad5SCédric Le Goater {
829d8e4aad5SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(chip);
8308a69bca7SDaniel Henrique Barboza int i;
831d8e4aad5SCédric Le Goater
832dd77c49eSPhilippe Mathieu-Daudé ics_pic_print_info(&chip8->psi.ics, buf);
8338a69bca7SDaniel Henrique Barboza
8348a69bca7SDaniel Henrique Barboza for (i = 0; i < chip8->num_phbs; i++) {
8350d512c71SDaniel Henrique Barboza PnvPHB *phb = chip8->phbs[i];
8361f5d6b2aSDaniel Henrique Barboza PnvPHB3 *phb3 = PNV_PHB3(phb->backend);
8378a69bca7SDaniel Henrique Barboza
838dafec001SPhilippe Mathieu-Daudé pnv_phb3_msi_pic_print_info(&phb3->msis, buf);
839dd77c49eSPhilippe Mathieu-Daudé ics_pic_print_info(&phb3->lsis, buf);
840dd77c49eSPhilippe Mathieu-Daudé }
841d8e4aad5SCédric Le Goater }
842d8e4aad5SCédric Le Goater
pnv_chip_power9_pic_print_info_child(Object * child,void * opaque)8430e6232bcSCédric Le Goater static int pnv_chip_power9_pic_print_info_child(Object *child, void *opaque)
8440e6232bcSCédric Le Goater {
845d312b62aSPhilippe Mathieu-Daudé GString *buf = opaque;
846210aacb3SDaniel Henrique Barboza PnvPHB *phb = (PnvPHB *) object_dynamic_cast(child, TYPE_PNV_PHB);
8470e6232bcSCédric Le Goater
848210aacb3SDaniel Henrique Barboza if (!phb) {
849210aacb3SDaniel Henrique Barboza return 0;
8500e6232bcSCédric Le Goater }
851210aacb3SDaniel Henrique Barboza
852dbcbb8c0SPhilippe Mathieu-Daudé pnv_phb4_pic_print_info(PNV_PHB4(phb->backend), buf);
853210aacb3SDaniel Henrique Barboza
8540e6232bcSCédric Le Goater return 0;
8550e6232bcSCédric Le Goater }
8560e6232bcSCédric Le Goater
pnv_chip_power9_pic_print_info(PnvChip * chip,GString * buf)857a58e653aSPhilippe Mathieu-Daudé static void pnv_chip_power9_pic_print_info(PnvChip *chip, GString *buf)
858d8e4aad5SCédric Le Goater {
859d8e4aad5SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(chip);
860d8e4aad5SCédric Le Goater
8610527563aSPhilippe Mathieu-Daudé pnv_xive_pic_print_info(&chip9->xive, buf);
862d88f39dbSPhilippe Mathieu-Daudé pnv_psi_pic_print_info(&chip9->psi, buf);
863d312b62aSPhilippe Mathieu-Daudé object_child_foreach_recursive(OBJECT(chip),
864d312b62aSPhilippe Mathieu-Daudé pnv_chip_power9_pic_print_info_child, buf);
865d8e4aad5SCédric Le Goater }
866d8e4aad5SCédric Le Goater
pnv_chip_power8_xscom_core_base(PnvChip * chip,uint32_t core_id)867c4b2c40cSGreg Kurz static uint64_t pnv_chip_power8_xscom_core_base(PnvChip *chip,
868c4b2c40cSGreg Kurz uint32_t core_id)
869c4b2c40cSGreg Kurz {
870c4b2c40cSGreg Kurz return PNV_XSCOM_EX_BASE(core_id);
871c4b2c40cSGreg Kurz }
872c4b2c40cSGreg Kurz
pnv_chip_power9_xscom_core_base(PnvChip * chip,uint32_t core_id)873c4b2c40cSGreg Kurz static uint64_t pnv_chip_power9_xscom_core_base(PnvChip *chip,
874c4b2c40cSGreg Kurz uint32_t core_id)
875c4b2c40cSGreg Kurz {
876c4b2c40cSGreg Kurz return PNV9_XSCOM_EC_BASE(core_id);
877c4b2c40cSGreg Kurz }
878c4b2c40cSGreg Kurz
pnv_chip_power10_xscom_core_base(PnvChip * chip,uint32_t core_id)879c4b2c40cSGreg Kurz static uint64_t pnv_chip_power10_xscom_core_base(PnvChip *chip,
880c4b2c40cSGreg Kurz uint32_t core_id)
881c4b2c40cSGreg Kurz {
882c4b2c40cSGreg Kurz return PNV10_XSCOM_EC_BASE(core_id);
883c4b2c40cSGreg Kurz }
884c4b2c40cSGreg Kurz
pnv_match_cpu(const char * default_type,const char * cpu_type)885f30c843cSCédric Le Goater static bool pnv_match_cpu(const char *default_type, const char *cpu_type)
886f30c843cSCédric Le Goater {
887f30c843cSCédric Le Goater PowerPCCPUClass *ppc_default =
888f30c843cSCédric Le Goater POWERPC_CPU_CLASS(object_class_by_name(default_type));
889f30c843cSCédric Le Goater PowerPCCPUClass *ppc =
890f30c843cSCédric Le Goater POWERPC_CPU_CLASS(object_class_by_name(cpu_type));
891f30c843cSCédric Le Goater
89221d3a78eSNicholas Piggin return ppc_default->pvr_match(ppc_default, ppc->pvr, false);
893f30c843cSCédric Le Goater }
894f30c843cSCédric Le Goater
pnv_ipmi_bt_init(ISABus * bus,IPMIBmc * bmc,uint32_t irq)895e2392d43SCédric Le Goater static void pnv_ipmi_bt_init(ISABus *bus, IPMIBmc *bmc, uint32_t irq)
896e2392d43SCédric Le Goater {
897c23e0561SMarkus Armbruster ISADevice *dev = isa_new("isa-ipmi-bt");
898e2392d43SCédric Le Goater
8995325cc34SMarkus Armbruster object_property_set_link(OBJECT(dev), "bmc", OBJECT(bmc), &error_fatal);
9005325cc34SMarkus Armbruster object_property_set_int(OBJECT(dev), "irq", irq, &error_fatal);
901c23e0561SMarkus Armbruster isa_realize_and_unref(dev, bus, &error_fatal);
902e2392d43SCédric Le Goater }
903e2392d43SCédric Le Goater
pnv_chip_power10_pic_print_info(PnvChip * chip,GString * buf)904a58e653aSPhilippe Mathieu-Daudé static void pnv_chip_power10_pic_print_info(PnvChip *chip, GString *buf)
9052b548a42SCédric Le Goater {
9068b50ce85SCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(chip);
9078b50ce85SCédric Le Goater
90870fb275dSPhilippe Mathieu-Daudé pnv_xive2_pic_print_info(&chip10->xive, buf);
909d88f39dbSPhilippe Mathieu-Daudé pnv_psi_pic_print_info(&chip10->psi, buf);
910d312b62aSPhilippe Mathieu-Daudé object_child_foreach_recursive(OBJECT(chip),
911d312b62aSPhilippe Mathieu-Daudé pnv_chip_power9_pic_print_info_child, buf);
9122b548a42SCédric Le Goater }
9132b548a42SCédric Le Goater
914458c6f01SCédric Le Goater /* Always give the first 1GB to chip 0 else we won't boot */
pnv_chip_get_ram_size(PnvMachineState * pnv,int chip_id)915458c6f01SCédric Le Goater static uint64_t pnv_chip_get_ram_size(PnvMachineState *pnv, int chip_id)
916458c6f01SCédric Le Goater {
917458c6f01SCédric Le Goater MachineState *machine = MACHINE(pnv);
918458c6f01SCédric Le Goater uint64_t ram_per_chip;
919458c6f01SCédric Le Goater
920458c6f01SCédric Le Goater assert(machine->ram_size >= 1 * GiB);
921458c6f01SCédric Le Goater
922458c6f01SCédric Le Goater ram_per_chip = machine->ram_size / pnv->num_chips;
923458c6f01SCédric Le Goater if (ram_per_chip >= 1 * GiB) {
924458c6f01SCédric Le Goater return QEMU_ALIGN_DOWN(ram_per_chip, 1 * MiB);
925458c6f01SCédric Le Goater }
926458c6f01SCédric Le Goater
927f640afecSCédric Le Goater assert(pnv->num_chips > 1);
928f640afecSCédric Le Goater
929458c6f01SCédric Le Goater ram_per_chip = (machine->ram_size - 1 * GiB) / (pnv->num_chips - 1);
930458c6f01SCédric Le Goater return chip_id == 0 ? 1 * GiB : QEMU_ALIGN_DOWN(ram_per_chip, 1 * MiB);
931458c6f01SCédric Le Goater }
932458c6f01SCédric Le Goater
pnv_init(MachineState * machine)933b168a138SCédric Le Goater static void pnv_init(MachineState *machine)
9349e933f4aSBenjamin Herrenschmidt {
935cd7b9498SPaolo Bonzini const char *bios_name = machine->firmware ?: FW_FILE_NAME;
936b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(machine);
937f30c843cSCédric Le Goater MachineClass *mc = MACHINE_GET_CLASS(machine);
93833467ecbSGlenn Miles PnvMachineClass *pmc = PNV_MACHINE_GET_CLASS(machine);
939d76cb5a5SNicholas Piggin int max_smt_threads = pmc->max_smt_threads;
9409e933f4aSBenjamin Herrenschmidt char *fw_filename;
9419e933f4aSBenjamin Herrenschmidt long fw_size;
942458c6f01SCédric Le Goater uint64_t chip_ram_start = 0;
943e997040eSCédric Le Goater int i;
944e997040eSCédric Le Goater char *chip_typename;
94535dde576SCédric Le Goater DriveInfo *pnor = drive_get(IF_MTD, 0, 0);
94635dde576SCédric Le Goater DeviceState *dev;
9479e933f4aSBenjamin Herrenschmidt
948ebe6c3faSDaniel Henrique Barboza if (kvm_enabled()) {
949518f72ecSCédric Le Goater error_report("machine %s does not support the KVM accelerator",
950518f72ecSCédric Le Goater mc->name);
951ebe6c3faSDaniel Henrique Barboza exit(EXIT_FAILURE);
952ebe6c3faSDaniel Henrique Barboza }
953ebe6c3faSDaniel Henrique Barboza
9549e933f4aSBenjamin Herrenschmidt /* allocate RAM */
955dd7ef911SCédric Le Goater if (machine->ram_size < mc->default_ram_size) {
956dd7ef911SCédric Le Goater char *sz = size_to_str(mc->default_ram_size);
957dd7ef911SCédric Le Goater error_report("Invalid RAM size, should be bigger than %s", sz);
958dd7ef911SCédric Le Goater g_free(sz);
959dd7ef911SCédric Le Goater exit(EXIT_FAILURE);
9609e933f4aSBenjamin Herrenschmidt }
961*889c5c4cSAditya Gupta
962*889c5c4cSAditya Gupta /* checks for invalid option combinations */
963*889c5c4cSAditya Gupta if (machine->dtb && (strlen(machine->kernel_cmdline) != 0)) {
964*889c5c4cSAditya Gupta error_report("-append and -dtb cannot be used together, as passed"
965*889c5c4cSAditya Gupta " command line is ignored in case of custom dtb");
966*889c5c4cSAditya Gupta exit(EXIT_FAILURE);
967*889c5c4cSAditya Gupta }
968*889c5c4cSAditya Gupta
969173a36d8SIgor Mammedov memory_region_add_subregion(get_system_memory(), 0, machine->ram);
9709e933f4aSBenjamin Herrenschmidt
97135dde576SCédric Le Goater /*
97235dde576SCédric Le Goater * Create our simple PNOR device
97335dde576SCédric Le Goater */
9743e80f690SMarkus Armbruster dev = qdev_new(TYPE_PNV_PNOR);
97535dde576SCédric Le Goater if (pnor) {
976934df912SMarkus Armbruster qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(pnor));
97735dde576SCédric Le Goater }
9783c6ef471SMarkus Armbruster sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
97935dde576SCédric Le Goater pnv->pnor = PNV_PNOR(dev);
98035dde576SCédric Le Goater
9819e933f4aSBenjamin Herrenschmidt /* load skiboot firmware */
9829e933f4aSBenjamin Herrenschmidt fw_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
98315fcedb2SCédric Le Goater if (!fw_filename) {
98415fcedb2SCédric Le Goater error_report("Could not find OPAL firmware '%s'", bios_name);
98515fcedb2SCédric Le Goater exit(1);
98615fcedb2SCédric Le Goater }
9879e933f4aSBenjamin Herrenschmidt
98808c3f3a7SCédric Le Goater fw_size = load_image_targphys(fw_filename, pnv->fw_load_addr, FW_MAX_SIZE);
9899e933f4aSBenjamin Herrenschmidt if (fw_size < 0) {
99015fcedb2SCédric Le Goater error_report("Could not load OPAL firmware '%s'", fw_filename);
9919e933f4aSBenjamin Herrenschmidt exit(1);
9929e933f4aSBenjamin Herrenschmidt }
9939e933f4aSBenjamin Herrenschmidt g_free(fw_filename);
9949e933f4aSBenjamin Herrenschmidt
9959e933f4aSBenjamin Herrenschmidt /* load kernel */
9969e933f4aSBenjamin Herrenschmidt if (machine->kernel_filename) {
9979e933f4aSBenjamin Herrenschmidt long kernel_size;
9989e933f4aSBenjamin Herrenschmidt
9999e933f4aSBenjamin Herrenschmidt kernel_size = load_image_targphys(machine->kernel_filename,
1000b45b56baSMurilo Opsfelder Araujo KERNEL_LOAD_ADDR, KERNEL_MAX_SIZE);
10019e933f4aSBenjamin Herrenschmidt if (kernel_size < 0) {
1002802fc7abSThomas Huth error_report("Could not load kernel '%s'",
10039e933f4aSBenjamin Herrenschmidt machine->kernel_filename);
10049e933f4aSBenjamin Herrenschmidt exit(1);
10059e933f4aSBenjamin Herrenschmidt }
10069e933f4aSBenjamin Herrenschmidt }
10079e933f4aSBenjamin Herrenschmidt
10089e933f4aSBenjamin Herrenschmidt /* load initrd */
10099e933f4aSBenjamin Herrenschmidt if (machine->initrd_filename) {
10109e933f4aSBenjamin Herrenschmidt pnv->initrd_base = INITRD_LOAD_ADDR;
10119e933f4aSBenjamin Herrenschmidt pnv->initrd_size = load_image_targphys(machine->initrd_filename,
1012584ea7e7SMurilo Opsfelder Araujo pnv->initrd_base, INITRD_MAX_SIZE);
10139e933f4aSBenjamin Herrenschmidt if (pnv->initrd_size < 0) {
1014802fc7abSThomas Huth error_report("Could not load initial ram disk '%s'",
10159e933f4aSBenjamin Herrenschmidt machine->initrd_filename);
10169e933f4aSBenjamin Herrenschmidt exit(1);
10179e933f4aSBenjamin Herrenschmidt }
10189e933f4aSBenjamin Herrenschmidt }
1019e997040eSCédric Le Goater
1020*889c5c4cSAditya Gupta /* load dtb if passed */
1021*889c5c4cSAditya Gupta if (machine->dtb) {
1022*889c5c4cSAditya Gupta int fdt_size;
1023*889c5c4cSAditya Gupta
1024*889c5c4cSAditya Gupta warn_report("with manually passed dtb, some options like '-append'"
1025*889c5c4cSAditya Gupta " will get ignored and the dtb passed will be used as-is");
1026*889c5c4cSAditya Gupta
1027*889c5c4cSAditya Gupta /* read the file 'machine->dtb', and load it into 'fdt' buffer */
1028*889c5c4cSAditya Gupta machine->fdt = load_device_tree(machine->dtb, &fdt_size);
1029*889c5c4cSAditya Gupta if (!machine->fdt) {
1030*889c5c4cSAditya Gupta error_report("Could not load dtb '%s'", machine->dtb);
1031*889c5c4cSAditya Gupta exit(1);
1032*889c5c4cSAditya Gupta }
1033*889c5c4cSAditya Gupta }
1034*889c5c4cSAditya Gupta
10354f9924c4SBenjamin Herrenschmidt /* MSIs are supported on this platform */
10364f9924c4SBenjamin Herrenschmidt msi_nonbroken = true;
10374f9924c4SBenjamin Herrenschmidt
1038f30c843cSCédric Le Goater /*
1039f30c843cSCédric Le Goater * Check compatibility of the specified CPU with the machine
1040f30c843cSCédric Le Goater * default.
1041f30c843cSCédric Le Goater */
1042f30c843cSCédric Le Goater if (!pnv_match_cpu(mc->default_cpu_type, machine->cpu_type)) {
1043f30c843cSCédric Le Goater error_report("invalid CPU model '%s' for %s machine",
1044f30c843cSCédric Le Goater machine->cpu_type, mc->name);
1045f30c843cSCédric Le Goater exit(1);
1046f30c843cSCédric Le Goater }
1047f30c843cSCédric Le Goater
1048e997040eSCédric Le Goater /* Create the processor chips */
10494a12c699SIgor Mammedov i = strlen(machine->cpu_type) - strlen(POWERPC_CPU_TYPE_SUFFIX);
10507fd544d8SIgor Mammedov chip_typename = g_strdup_printf(PNV_CHIP_TYPE_NAME("%.*s"),
10514a12c699SIgor Mammedov i, machine->cpu_type);
1052e997040eSCédric Le Goater if (!object_class_by_name(chip_typename)) {
1053f30c843cSCédric Le Goater error_report("invalid chip model '%.*s' for %s machine",
1054f30c843cSCédric Le Goater i, machine->cpu_type, mc->name);
1055e997040eSCédric Le Goater exit(1);
1056e997040eSCédric Le Goater }
1057e997040eSCédric Le Goater
10583b5ea01eSNicholas Piggin /* Set lpar-per-core mode if lpar-per-thread is not supported */
10593b5ea01eSNicholas Piggin if (!pmc->has_lpar_per_thread) {
10603b5ea01eSNicholas Piggin pnv->lpar_per_core = true;
10613b5ea01eSNicholas Piggin }
10623b5ea01eSNicholas Piggin
1063e44acde2SGreg Kurz pnv->num_chips =
1064e44acde2SGreg Kurz machine->smp.max_cpus / (machine->smp.cores * machine->smp.threads);
1065934676c7SNicholas Piggin
1066c26504afSNicholas Piggin if (pnv->big_core) {
1067c26504afSNicholas Piggin if (machine->smp.threads % 2 == 1) {
1068c26504afSNicholas Piggin error_report("Cannot support %d threads with big-core option "
1069c26504afSNicholas Piggin "because it must be an even number",
1070c26504afSNicholas Piggin machine->smp.threads);
1071c26504afSNicholas Piggin exit(1);
1072c26504afSNicholas Piggin }
1073c26504afSNicholas Piggin max_smt_threads *= 2;
1074c26504afSNicholas Piggin }
1075c26504afSNicholas Piggin
1076d76cb5a5SNicholas Piggin if (machine->smp.threads > max_smt_threads) {
1077d76cb5a5SNicholas Piggin error_report("Cannot support more than %d threads/core "
1078d76cb5a5SNicholas Piggin "on %s machine", max_smt_threads, mc->desc);
1079c26504afSNicholas Piggin if (pmc->max_smt_threads == 4) {
1080c26504afSNicholas Piggin error_report("(use big-core=on for 8 threads per core)");
1081c26504afSNicholas Piggin }
1082934676c7SNicholas Piggin exit(1);
1083934676c7SNicholas Piggin }
1084d76cb5a5SNicholas Piggin
1085c26504afSNicholas Piggin if (pnv->big_core) {
1086c26504afSNicholas Piggin /*
1087c26504afSNicholas Piggin * powernv models PnvCore as a SMT4 core. Big-core requires 2xPnvCore
1088c26504afSNicholas Piggin * per core, so adjust topology here. pnv_dt_core() processor
1089c26504afSNicholas Piggin * device-tree and TCG SMT code make the 2 cores appear as one big core
1090c26504afSNicholas Piggin * from software point of view. pnv pervasive models and xscoms tend to
1091c26504afSNicholas Piggin * see the big core as 2 small core halves.
1092c26504afSNicholas Piggin */
1093c26504afSNicholas Piggin machine->smp.cores *= 2;
1094c26504afSNicholas Piggin machine->smp.threads /= 2;
1095c26504afSNicholas Piggin }
1096c26504afSNicholas Piggin
1097934676c7SNicholas Piggin if (!is_power_of_2(machine->smp.threads)) {
1098934676c7SNicholas Piggin error_report("Cannot support %d threads/core on a powernv "
1099934676c7SNicholas Piggin "machine because it must be a power of 2",
1100934676c7SNicholas Piggin machine->smp.threads);
1101934676c7SNicholas Piggin exit(1);
1102934676c7SNicholas Piggin }
1103d76cb5a5SNicholas Piggin
1104e44acde2SGreg Kurz /*
1105e44acde2SGreg Kurz * TODO: should we decide on how many chips we can create based
1106e44acde2SGreg Kurz * on #cores and Venice vs. Murano vs. Naples chip type etc...,
1107e44acde2SGreg Kurz */
1108ab17a3feSCédric Le Goater if (!is_power_of_2(pnv->num_chips) || pnv->num_chips > 16) {
1109e44acde2SGreg Kurz error_report("invalid number of chips: '%d'", pnv->num_chips);
1110ab17a3feSCédric Le Goater error_printf(
1111ab17a3feSCédric Le Goater "Try '-smp sockets=N'. Valid values are : 1, 2, 4, 8 and 16.\n");
1112e44acde2SGreg Kurz exit(1);
1113e44acde2SGreg Kurz }
1114e44acde2SGreg Kurz
1115e997040eSCédric Le Goater pnv->chips = g_new0(PnvChip *, pnv->num_chips);
1116e997040eSCédric Le Goater for (i = 0; i < pnv->num_chips; i++) {
1117e997040eSCédric Le Goater char chip_name[32];
1118df707969SMarkus Armbruster Object *chip = OBJECT(qdev_new(chip_typename));
11190e5e9ff4SCédric Le Goater uint64_t chip_ram_size = pnv_chip_get_ram_size(pnv, i);
1120e997040eSCédric Le Goater
1121e997040eSCédric Le Goater pnv->chips[i] = PNV_CHIP(chip);
1122e997040eSCédric Le Goater
1123458c6f01SCédric Le Goater /* Distribute RAM among the chips */
1124458c6f01SCédric Le Goater object_property_set_int(chip, "ram-start", chip_ram_start,
1125e997040eSCédric Le Goater &error_fatal);
1126458c6f01SCédric Le Goater object_property_set_int(chip, "ram-size", chip_ram_size,
1127458c6f01SCédric Le Goater &error_fatal);
1128458c6f01SCédric Le Goater chip_ram_start += chip_ram_size;
1129e997040eSCédric Le Goater
11300e5e9ff4SCédric Le Goater snprintf(chip_name, sizeof(chip_name), "chip[%d]", i);
1131d2623129SMarkus Armbruster object_property_add_child(OBJECT(pnv), chip_name, chip);
11320e5e9ff4SCédric Le Goater object_property_set_int(chip, "chip-id", i, &error_fatal);
11335325cc34SMarkus Armbruster object_property_set_int(chip, "nr-cores", machine->smp.cores,
11345325cc34SMarkus Armbruster &error_fatal);
11355325cc34SMarkus Armbruster object_property_set_int(chip, "nr-threads", machine->smp.threads,
11365325cc34SMarkus Armbruster &error_fatal);
1137c26504afSNicholas Piggin object_property_set_bool(chip, "big-core", pnv->big_core,
1138c26504afSNicholas Piggin &error_fatal);
11393b5ea01eSNicholas Piggin object_property_set_bool(chip, "lpar-per-core", pnv->lpar_per_core,
11403b5ea01eSNicholas Piggin &error_fatal);
1141245cdb7fSCédric Le Goater /*
1142245cdb7fSCédric Le Goater * The POWER8 machine use the XICS interrupt interface.
1143245cdb7fSCédric Le Goater * Propagate the XICS fabric to the chip and its controllers.
1144245cdb7fSCédric Le Goater */
1145245cdb7fSCédric Le Goater if (object_dynamic_cast(OBJECT(pnv), TYPE_XICS_FABRIC)) {
11465325cc34SMarkus Armbruster object_property_set_link(chip, "xics", OBJECT(pnv), &error_abort);
1147245cdb7fSCédric Le Goater }
1148d1214b81SGreg Kurz if (object_dynamic_cast(OBJECT(pnv), TYPE_XIVE_FABRIC)) {
11495325cc34SMarkus Armbruster object_property_set_link(chip, "xive-fabric", OBJECT(pnv),
1150d1214b81SGreg Kurz &error_abort);
1151d1214b81SGreg Kurz }
11523c6ef471SMarkus Armbruster sysbus_realize_and_unref(SYS_BUS_DEVICE(chip), &error_fatal);
1153e997040eSCédric Le Goater }
1154e997040eSCédric Le Goater g_free(chip_typename);
11553495b6b6SCédric Le Goater
11563495b6b6SCédric Le Goater /* Instantiate ISA bus on chip 0 */
115704026890SCédric Le Goater pnv->isa_bus = pnv_isa_create(pnv->chips[0], &error_fatal);
11583495b6b6SCédric Le Goater
11593495b6b6SCédric Le Goater /* Create serial port */
1160def337ffSPeter Maydell serial_hds_isa_init(pnv->isa_bus, 0, MAX_ISA_SERIAL_PORTS);
11613495b6b6SCédric Le Goater
11623495b6b6SCédric Le Goater /* Create an RTC ISA device too */
11636c646a11SPhilippe Mathieu-Daudé mc146818_rtc_init(pnv->isa_bus, 2000, NULL);
1164bce0b691SCédric Le Goater
116525f3170bSCédric Le Goater /*
116625f3170bSCédric Le Goater * Create the machine BMC simulator and the IPMI BT device for
116725f3170bSCédric Le Goater * communication with the BMC
116825f3170bSCédric Le Goater */
116925f3170bSCédric Le Goater if (defaults_enabled()) {
117025f3170bSCédric Le Goater pnv->bmc = pnv_bmc_create(pnv->pnor);
1171e2392d43SCédric Le Goater pnv_ipmi_bt_init(pnv->isa_bus, pnv->bmc, 10);
117225f3170bSCédric Le Goater }
1173e2392d43SCédric Le Goater
117459b7c1c2SBalamuruhan S /*
1175032c226bSCédric Le Goater * The PNOR is mapped on the LPC FW address space by the BMC.
1176032c226bSCédric Le Goater * Since we can not reach the remote BMC machine with LPC memops,
1177032c226bSCédric Le Goater * map it always for now.
1178032c226bSCédric Le Goater */
1179032c226bSCédric Le Goater memory_region_add_subregion(pnv->chips[0]->fw_mr, PNOR_SPI_OFFSET,
1180032c226bSCédric Le Goater &pnv->pnor->mmio);
1181032c226bSCédric Le Goater
1182032c226bSCédric Le Goater /*
118359b7c1c2SBalamuruhan S * OpenPOWER systems use a IPMI SEL Event message to notify the
118459b7c1c2SBalamuruhan S * host to powerdown
118559b7c1c2SBalamuruhan S */
1186bce0b691SCédric Le Goater pnv->powerdown_notifier.notify = pnv_powerdown_notify;
1187bce0b691SCédric Le Goater qemu_register_powerdown_notifier(&pnv->powerdown_notifier);
118833467ecbSGlenn Miles
118933467ecbSGlenn Miles /*
119033467ecbSGlenn Miles * Create/Connect any machine-specific I2C devices
119133467ecbSGlenn Miles */
119233467ecbSGlenn Miles if (pmc->i2c_init) {
119333467ecbSGlenn Miles pmc->i2c_init(pnv);
119433467ecbSGlenn Miles }
1195e997040eSCédric Le Goater }
1196e997040eSCédric Le Goater
1197631adaffSCédric Le Goater /*
1198631adaffSCédric Le Goater * 0:21 Reserved - Read as zeros
1199631adaffSCédric Le Goater * 22:24 Chip ID
1200631adaffSCédric Le Goater * 25:28 Core number
1201631adaffSCédric Le Goater * 29:31 Thread ID
1202631adaffSCédric Le Goater */
pnv_get_pir_tir_p8(PnvChip * chip,uint32_t core_id,uint32_t thread_id,uint32_t * pir,uint32_t * tir)120325de2822SNicholas Piggin static void pnv_get_pir_tir_p8(PnvChip *chip,
120425de2822SNicholas Piggin uint32_t core_id, uint32_t thread_id,
120525de2822SNicholas Piggin uint32_t *pir, uint32_t *tir)
1206631adaffSCédric Le Goater {
120725de2822SNicholas Piggin if (pir) {
120825de2822SNicholas Piggin *pir = (chip->chip_id << 7) | (core_id << 3) | thread_id;
120925de2822SNicholas Piggin }
121025de2822SNicholas Piggin if (tir) {
121125de2822SNicholas Piggin *tir = thread_id;
121225de2822SNicholas Piggin }
1213631adaffSCédric Le Goater }
1214631adaffSCédric Le Goater
pnv_chip_power8_intc_create(PnvChip * chip,PowerPCCPU * cpu,Error ** errp)12158fa1f4efSCédric Le Goater static void pnv_chip_power8_intc_create(PnvChip *chip, PowerPCCPU *cpu,
1216d35aefa9SCédric Le Goater Error **errp)
1217d35aefa9SCédric Le Goater {
1218245cdb7fSCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(chip);
12198fa1f4efSCédric Le Goater Error *local_err = NULL;
12208fa1f4efSCédric Le Goater Object *obj;
12218907fc25SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
12228fa1f4efSCédric Le Goater
1223245cdb7fSCédric Le Goater obj = icp_create(OBJECT(cpu), TYPE_PNV_ICP, chip8->xics, &local_err);
12248fa1f4efSCédric Le Goater if (local_err) {
12258fa1f4efSCédric Le Goater error_propagate(errp, local_err);
12268fa1f4efSCédric Le Goater return;
12278fa1f4efSCédric Le Goater }
12288fa1f4efSCédric Le Goater
1229956b8f46SCédric Le Goater pnv_cpu->intc = obj;
1230d35aefa9SCédric Le Goater }
1231d35aefa9SCédric Le Goater
12320990ce6aSGreg Kurz
pnv_chip_power8_intc_reset(PnvChip * chip,PowerPCCPU * cpu)1233d49e8a9bSCédric Le Goater static void pnv_chip_power8_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
1234d49e8a9bSCédric Le Goater {
1235d49e8a9bSCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
1236d49e8a9bSCédric Le Goater
1237d49e8a9bSCédric Le Goater icp_reset(ICP(pnv_cpu->intc));
1238d49e8a9bSCédric Le Goater }
1239d49e8a9bSCédric Le Goater
pnv_chip_power8_intc_destroy(PnvChip * chip,PowerPCCPU * cpu)12400990ce6aSGreg Kurz static void pnv_chip_power8_intc_destroy(PnvChip *chip, PowerPCCPU *cpu)
12410990ce6aSGreg Kurz {
12420990ce6aSGreg Kurz PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
12430990ce6aSGreg Kurz
12440990ce6aSGreg Kurz icp_destroy(ICP(pnv_cpu->intc));
12450990ce6aSGreg Kurz pnv_cpu->intc = NULL;
12460990ce6aSGreg Kurz }
12470990ce6aSGreg Kurz
pnv_chip_power8_intc_print_info(PnvChip * chip,PowerPCCPU * cpu,GString * buf)124885913070SGreg Kurz static void pnv_chip_power8_intc_print_info(PnvChip *chip, PowerPCCPU *cpu,
1249ae08259bSPhilippe Mathieu-Daudé GString *buf)
125085913070SGreg Kurz {
12515242494cSPhilippe Mathieu-Daudé icp_pic_print_info(ICP(pnv_cpu_state(cpu)->intc), buf);
125285913070SGreg Kurz }
125385913070SGreg Kurz
1254631adaffSCédric Le Goater /*
1255631adaffSCédric Le Goater * 0:48 Reserved - Read as zeroes
1256631adaffSCédric Le Goater * 49:52 Node ID
1257631adaffSCédric Le Goater * 53:55 Chip ID
1258631adaffSCédric Le Goater * 56 Reserved - Read as zero
1259631adaffSCédric Le Goater * 57:61 Core number
1260631adaffSCédric Le Goater * 62:63 Thread ID
1261631adaffSCédric Le Goater *
1262631adaffSCédric Le Goater * We only care about the lower bits. uint32_t is fine for the moment.
1263631adaffSCédric Le Goater */
pnv_get_pir_tir_p9(PnvChip * chip,uint32_t core_id,uint32_t thread_id,uint32_t * pir,uint32_t * tir)126425de2822SNicholas Piggin static void pnv_get_pir_tir_p9(PnvChip *chip,
126525de2822SNicholas Piggin uint32_t core_id, uint32_t thread_id,
126625de2822SNicholas Piggin uint32_t *pir, uint32_t *tir)
1267631adaffSCédric Le Goater {
1268c26504afSNicholas Piggin if (chip->big_core) {
1269c26504afSNicholas Piggin /* Big-core interleaves thread ID between small-cores */
1270c26504afSNicholas Piggin thread_id <<= 1;
1271c26504afSNicholas Piggin thread_id |= core_id & 1;
1272c26504afSNicholas Piggin core_id >>= 1;
1273c26504afSNicholas Piggin
127425de2822SNicholas Piggin if (pir) {
1275c26504afSNicholas Piggin *pir = (chip->chip_id << 8) | (core_id << 3) | thread_id;
1276c26504afSNicholas Piggin }
12779940412aSCaleb Schlossin } else {
1278c26504afSNicholas Piggin if (pir) {
127925de2822SNicholas Piggin *pir = (chip->chip_id << 8) | (core_id << 2) | thread_id;
128025de2822SNicholas Piggin }
128125de2822SNicholas Piggin }
128225de2822SNicholas Piggin if (tir) {
128325de2822SNicholas Piggin *tir = thread_id;
12849940412aSCaleb Schlossin }
1285631adaffSCédric Le Goater }
1286631adaffSCédric Le Goater
12879940412aSCaleb Schlossin /*
12889940412aSCaleb Schlossin * 0:48 Reserved - Read as zeroes
12899940412aSCaleb Schlossin * 49:52 Node ID
12909940412aSCaleb Schlossin * 53:55 Chip ID
12919940412aSCaleb Schlossin * 56 Reserved - Read as zero
12929940412aSCaleb Schlossin * 57:59 Quad ID
12939940412aSCaleb Schlossin * 60 Core Chiplet Pair ID
12949940412aSCaleb Schlossin * 61:63 Thread/Core Chiplet ID t0-t2
12959940412aSCaleb Schlossin *
12969940412aSCaleb Schlossin * We only care about the lower bits. uint32_t is fine for the moment.
12979940412aSCaleb Schlossin */
pnv_get_pir_tir_p10(PnvChip * chip,uint32_t core_id,uint32_t thread_id,uint32_t * pir,uint32_t * tir)129825de2822SNicholas Piggin static void pnv_get_pir_tir_p10(PnvChip *chip,
129925de2822SNicholas Piggin uint32_t core_id, uint32_t thread_id,
130025de2822SNicholas Piggin uint32_t *pir, uint32_t *tir)
13012b548a42SCédric Le Goater {
1302c26504afSNicholas Piggin if (chip->big_core) {
1303c26504afSNicholas Piggin /* Big-core interleaves thread ID between small-cores */
1304c26504afSNicholas Piggin thread_id <<= 1;
1305c26504afSNicholas Piggin thread_id |= core_id & 1;
1306c26504afSNicholas Piggin core_id >>= 1;
1307c26504afSNicholas Piggin
130825de2822SNicholas Piggin if (pir) {
1309c26504afSNicholas Piggin *pir = (chip->chip_id << 8) | (core_id << 3) | thread_id;
1310c26504afSNicholas Piggin }
13119940412aSCaleb Schlossin } else {
1312c26504afSNicholas Piggin if (pir) {
131325de2822SNicholas Piggin *pir = (chip->chip_id << 8) | (core_id << 2) | thread_id;
131425de2822SNicholas Piggin }
131525de2822SNicholas Piggin }
131625de2822SNicholas Piggin if (tir) {
131725de2822SNicholas Piggin *tir = thread_id;
13189940412aSCaleb Schlossin }
13192b548a42SCédric Le Goater }
13202b548a42SCédric Le Goater
pnv_chip_power9_intc_create(PnvChip * chip,PowerPCCPU * cpu,Error ** errp)13218fa1f4efSCédric Le Goater static void pnv_chip_power9_intc_create(PnvChip *chip, PowerPCCPU *cpu,
1322d35aefa9SCédric Le Goater Error **errp)
1323d35aefa9SCédric Le Goater {
13242dfa91a2SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(chip);
13252dfa91a2SCédric Le Goater Error *local_err = NULL;
13262dfa91a2SCédric Le Goater Object *obj;
13272dfa91a2SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
13282dfa91a2SCédric Le Goater
13292dfa91a2SCédric Le Goater /*
13302dfa91a2SCédric Le Goater * The core creates its interrupt presenter but the XIVE interrupt
13312dfa91a2SCédric Le Goater * controller object is initialized afterwards. Hopefully, it's
13322dfa91a2SCédric Le Goater * only used at runtime.
13332dfa91a2SCédric Le Goater */
133447950946SCédric Le Goater obj = xive_tctx_create(OBJECT(cpu), XIVE_PRESENTER(&chip9->xive),
133547950946SCédric Le Goater &local_err);
13362dfa91a2SCédric Le Goater if (local_err) {
13372dfa91a2SCédric Le Goater error_propagate(errp, local_err);
13388fa1f4efSCédric Le Goater return;
1339d35aefa9SCédric Le Goater }
1340d35aefa9SCédric Le Goater
13412dfa91a2SCédric Le Goater pnv_cpu->intc = obj;
13422dfa91a2SCédric Le Goater }
13432dfa91a2SCédric Le Goater
pnv_chip_power9_intc_reset(PnvChip * chip,PowerPCCPU * cpu)1344d49e8a9bSCédric Le Goater static void pnv_chip_power9_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
1345d49e8a9bSCédric Le Goater {
1346d49e8a9bSCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
1347d49e8a9bSCédric Le Goater
1348d49e8a9bSCédric Le Goater xive_tctx_reset(XIVE_TCTX(pnv_cpu->intc));
1349d49e8a9bSCédric Le Goater }
1350d49e8a9bSCédric Le Goater
pnv_chip_power9_intc_destroy(PnvChip * chip,PowerPCCPU * cpu)13510990ce6aSGreg Kurz static void pnv_chip_power9_intc_destroy(PnvChip *chip, PowerPCCPU *cpu)
13520990ce6aSGreg Kurz {
13530990ce6aSGreg Kurz PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
13540990ce6aSGreg Kurz
13550990ce6aSGreg Kurz xive_tctx_destroy(XIVE_TCTX(pnv_cpu->intc));
13560990ce6aSGreg Kurz pnv_cpu->intc = NULL;
13570990ce6aSGreg Kurz }
13580990ce6aSGreg Kurz
pnv_chip_power9_intc_print_info(PnvChip * chip,PowerPCCPU * cpu,GString * buf)135985913070SGreg Kurz static void pnv_chip_power9_intc_print_info(PnvChip *chip, PowerPCCPU *cpu,
1360ae08259bSPhilippe Mathieu-Daudé GString *buf)
136185913070SGreg Kurz {
1362f163e270SPhilippe Mathieu-Daudé xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), buf);
136385913070SGreg Kurz }
136485913070SGreg Kurz
pnv_chip_power10_intc_create(PnvChip * chip,PowerPCCPU * cpu,Error ** errp)13652b548a42SCédric Le Goater static void pnv_chip_power10_intc_create(PnvChip *chip, PowerPCCPU *cpu,
13662b548a42SCédric Le Goater Error **errp)
13672b548a42SCédric Le Goater {
1368da71b7e3SCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(chip);
1369da71b7e3SCédric Le Goater Error *local_err = NULL;
1370da71b7e3SCédric Le Goater Object *obj;
13712b548a42SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
13722b548a42SCédric Le Goater
1373da71b7e3SCédric Le Goater /*
1374da71b7e3SCédric Le Goater * The core creates its interrupt presenter but the XIVE2 interrupt
1375da71b7e3SCédric Le Goater * controller object is initialized afterwards. Hopefully, it's
1376da71b7e3SCédric Le Goater * only used at runtime.
1377da71b7e3SCédric Le Goater */
1378da71b7e3SCédric Le Goater obj = xive_tctx_create(OBJECT(cpu), XIVE_PRESENTER(&chip10->xive),
1379da71b7e3SCédric Le Goater &local_err);
1380da71b7e3SCédric Le Goater if (local_err) {
1381da71b7e3SCédric Le Goater error_propagate(errp, local_err);
1382da71b7e3SCédric Le Goater return;
1383da71b7e3SCédric Le Goater }
1384da71b7e3SCédric Le Goater
1385da71b7e3SCédric Le Goater pnv_cpu->intc = obj;
13862b548a42SCédric Le Goater }
13872b548a42SCédric Le Goater
pnv_chip_power10_intc_reset(PnvChip * chip,PowerPCCPU * cpu)13882b548a42SCédric Le Goater static void pnv_chip_power10_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
13892b548a42SCédric Le Goater {
1390da71b7e3SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
1391da71b7e3SCédric Le Goater
1392da71b7e3SCédric Le Goater xive_tctx_reset(XIVE_TCTX(pnv_cpu->intc));
13932b548a42SCédric Le Goater }
13942b548a42SCédric Le Goater
pnv_chip_power10_intc_destroy(PnvChip * chip,PowerPCCPU * cpu)13952b548a42SCédric Le Goater static void pnv_chip_power10_intc_destroy(PnvChip *chip, PowerPCCPU *cpu)
13962b548a42SCédric Le Goater {
13972b548a42SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
13982b548a42SCédric Le Goater
1399da71b7e3SCédric Le Goater xive_tctx_destroy(XIVE_TCTX(pnv_cpu->intc));
14002b548a42SCédric Le Goater pnv_cpu->intc = NULL;
14012b548a42SCédric Le Goater }
14022b548a42SCédric Le Goater
pnv_chip_power10_intc_print_info(PnvChip * chip,PowerPCCPU * cpu,GString * buf)140385913070SGreg Kurz static void pnv_chip_power10_intc_print_info(PnvChip *chip, PowerPCCPU *cpu,
1404ae08259bSPhilippe Mathieu-Daudé GString *buf)
140585913070SGreg Kurz {
1406f163e270SPhilippe Mathieu-Daudé xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), buf);
140785913070SGreg Kurz }
140885913070SGreg Kurz
140959b7c1c2SBalamuruhan S /*
141059b7c1c2SBalamuruhan S * Allowed core identifiers on a POWER8 Processor Chip :
1411397a79e7SCédric Le Goater *
1412397a79e7SCédric Le Goater * <EX0 reserved>
1413397a79e7SCédric Le Goater * EX1 - Venice only
1414397a79e7SCédric Le Goater * EX2 - Venice only
1415397a79e7SCédric Le Goater * EX3 - Venice only
1416397a79e7SCédric Le Goater * EX4
1417397a79e7SCédric Le Goater * EX5
1418397a79e7SCédric Le Goater * EX6
1419397a79e7SCédric Le Goater * <EX7,8 reserved> <reserved>
1420397a79e7SCédric Le Goater * EX9 - Venice only
1421397a79e7SCédric Le Goater * EX10 - Venice only
1422397a79e7SCédric Le Goater * EX11 - Venice only
1423397a79e7SCédric Le Goater * EX12
1424397a79e7SCédric Le Goater * EX13
1425397a79e7SCédric Le Goater * EX14
1426397a79e7SCédric Le Goater * <EX15 reserved>
1427397a79e7SCédric Le Goater */
1428397a79e7SCédric Le Goater #define POWER8E_CORE_MASK (0x7070ull)
1429397a79e7SCédric Le Goater #define POWER8_CORE_MASK (0x7e7eull)
1430397a79e7SCédric Le Goater
1431397a79e7SCédric Le Goater /*
143209279d7eSCédric Le Goater * POWER9 has 24 cores, ids starting at 0x0
1433397a79e7SCédric Le Goater */
143409279d7eSCédric Le Goater #define POWER9_CORE_MASK (0xffffffffffffffull)
1435397a79e7SCédric Le Goater
14362b548a42SCédric Le Goater
14372b548a42SCédric Le Goater #define POWER10_CORE_MASK (0xffffffffffffffull)
14382b548a42SCédric Le Goater
pnv_chip_power8_instance_init(Object * obj)143977864267SCédric Le Goater static void pnv_chip_power8_instance_init(Object *obj)
144077864267SCédric Le Goater {
144177864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(obj);
14429ae1329eSCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj);
14439ae1329eSCédric Le Goater int i;
144477864267SCédric Le Goater
1445245cdb7fSCédric Le Goater object_property_add_link(obj, "xics", TYPE_XICS_FABRIC,
1446245cdb7fSCédric Le Goater (Object **)&chip8->xics,
1447245cdb7fSCédric Le Goater object_property_allow_set_link,
1448d2623129SMarkus Armbruster OBJ_PROP_LINK_STRONG);
1449245cdb7fSCédric Le Goater
14509fc7fc4dSMarkus Armbruster object_initialize_child(obj, "psi", &chip8->psi, TYPE_PNV8_PSI);
145177864267SCédric Le Goater
14529fc7fc4dSMarkus Armbruster object_initialize_child(obj, "lpc", &chip8->lpc, TYPE_PNV8_LPC);
145377864267SCédric Le Goater
14549fc7fc4dSMarkus Armbruster object_initialize_child(obj, "occ", &chip8->occ, TYPE_PNV8_OCC);
14553887d241SBalamuruhan S
14569fc7fc4dSMarkus Armbruster object_initialize_child(obj, "homer", &chip8->homer, TYPE_PNV8_HOMER);
14579ae1329eSCédric Le Goater
1458892c3ad0SDaniel Henrique Barboza if (defaults_enabled()) {
1459eb93c828SCédric Le Goater chip8->num_phbs = pcc->num_phbs;
14601f6a88ffSCédric Le Goater
1461eb93c828SCédric Le Goater for (i = 0; i < chip8->num_phbs; i++) {
14620d512c71SDaniel Henrique Barboza Object *phb = object_new(TYPE_PNV_PHB);
14630d512c71SDaniel Henrique Barboza
14640d512c71SDaniel Henrique Barboza /*
14650d512c71SDaniel Henrique Barboza * We need the chip to parent the PHB to allow the DT
14660d512c71SDaniel Henrique Barboza * to build correctly (via pnv_xscom_dt()).
14670d512c71SDaniel Henrique Barboza *
14680d512c71SDaniel Henrique Barboza * TODO: the PHB should be parented by a PEC device that, at
14690d512c71SDaniel Henrique Barboza * this moment, is not modelled powernv8/phb3.
14700d512c71SDaniel Henrique Barboza */
14710d512c71SDaniel Henrique Barboza object_property_add_child(obj, "phb[*]", phb);
14720d512c71SDaniel Henrique Barboza chip8->phbs[i] = PNV_PHB(phb);
14739ae1329eSCédric Le Goater }
1474892c3ad0SDaniel Henrique Barboza }
14759ae1329eSCédric Le Goater
147677864267SCédric Le Goater }
147777864267SCédric Le Goater
pnv_chip_icp_realize(Pnv8Chip * chip8,Error ** errp)147877864267SCédric Le Goater static void pnv_chip_icp_realize(Pnv8Chip *chip8, Error **errp)
147977864267SCédric Le Goater {
148077864267SCédric Le Goater PnvChip *chip = PNV_CHIP(chip8);
148177864267SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
148277864267SCédric Le Goater int i, j;
148377864267SCédric Le Goater char *name;
148477864267SCédric Le Goater
148577864267SCédric Le Goater name = g_strdup_printf("icp-%x", chip->chip_id);
148677864267SCédric Le Goater memory_region_init(&chip8->icp_mmio, OBJECT(chip), name, PNV_ICP_SIZE);
148777864267SCédric Le Goater g_free(name);
1488bf3b9754SPhilippe Mathieu-Daudé memory_region_add_subregion(get_system_memory(), PNV_ICP_BASE(chip),
1489bf3b9754SPhilippe Mathieu-Daudé &chip8->icp_mmio);
149077864267SCédric Le Goater
149177864267SCédric Le Goater /* Map the ICP registers for each thread */
149277864267SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) {
14934fa28f23SGreg Kurz PnvCore *pnv_core = chip->cores[i];
149477864267SCédric Le Goater int core_hwid = CPU_CORE(pnv_core)->core_id;
149577864267SCédric Le Goater
149677864267SCédric Le Goater for (j = 0; j < CPU_CORE(pnv_core)->nr_threads; j++) {
149725de2822SNicholas Piggin uint32_t pir;
149825de2822SNicholas Piggin PnvICPState *icp;
149925de2822SNicholas Piggin
150025de2822SNicholas Piggin pcc->get_pir_tir(chip, core_hwid, j, &pir, NULL);
150125de2822SNicholas Piggin icp = PNV_ICP(xics_icp_get(chip8->xics, pir));
150277864267SCédric Le Goater
150377864267SCédric Le Goater memory_region_add_subregion(&chip8->icp_mmio, pir << 12,
150477864267SCédric Le Goater &icp->mmio);
150577864267SCédric Le Goater }
150677864267SCédric Le Goater }
150777864267SCédric Le Goater }
150877864267SCédric Le Goater
pnv_chip_power8_realize(DeviceState * dev,Error ** errp)150977864267SCédric Le Goater static void pnv_chip_power8_realize(DeviceState *dev, Error **errp)
151077864267SCédric Le Goater {
151177864267SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
151277864267SCédric Le Goater PnvChip *chip = PNV_CHIP(dev);
151377864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(dev);
1514ae856055SCédric Le Goater Pnv8Psi *psi8 = &chip8->psi;
151577864267SCédric Le Goater Error *local_err = NULL;
15169ae1329eSCédric Le Goater int i;
151777864267SCédric Le Goater
1518245cdb7fSCédric Le Goater assert(chip8->xics);
1519245cdb7fSCédric Le Goater
1520709044fdSCédric Le Goater /* XSCOM bridge is first */
1521326f7acbSPhilippe Mathieu-Daudé pnv_xscom_init(chip, PNV_XSCOM_SIZE, PNV_XSCOM_BASE(chip));
1522709044fdSCédric Le Goater
152377864267SCédric Le Goater pcc->parent_realize(dev, &local_err);
152477864267SCédric Le Goater if (local_err) {
152577864267SCédric Le Goater error_propagate(errp, local_err);
152677864267SCédric Le Goater return;
152777864267SCédric Le Goater }
152877864267SCédric Le Goater
152977864267SCédric Le Goater /* Processor Service Interface (PSI) Host Bridge */
1530ee1004bbSPhilippe Mathieu-Daudé object_property_set_int(OBJECT(psi8), "bar", PNV_PSIHB_BASE(chip),
15315325cc34SMarkus Armbruster &error_fatal);
1532ee1004bbSPhilippe Mathieu-Daudé object_property_set_link(OBJECT(psi8), ICS_PROP_XICS,
15335325cc34SMarkus Armbruster OBJECT(chip8->xics), &error_abort);
1534ee1004bbSPhilippe Mathieu-Daudé if (!qdev_realize(DEVICE(psi8), NULL, errp)) {
153577864267SCédric Le Goater return;
153677864267SCédric Le Goater }
1537ae856055SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_PSIHB_BASE,
1538ae856055SCédric Le Goater &PNV_PSI(psi8)->xscom_regs);
153977864267SCédric Le Goater
154077864267SCédric Le Goater /* Create LPC controller */
1541ce189ab2SMarkus Armbruster qdev_realize(DEVICE(&chip8->lpc), NULL, &error_fatal);
154277864267SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_LPC_BASE, &chip8->lpc.xscom_regs);
154377864267SCédric Le Goater
1544032c226bSCédric Le Goater chip->fw_mr = &chip8->lpc.isa_fw;
154564d011d5SCédric Le Goater chip->dt_isa_nodename = g_strdup_printf("/xscom@%" PRIx64 "/isa@%x",
154664d011d5SCédric Le Goater (uint64_t) PNV_XSCOM_BASE(chip),
154764d011d5SCédric Le Goater PNV_XSCOM_LPC_BASE);
154864d011d5SCédric Le Goater
154959b7c1c2SBalamuruhan S /*
155059b7c1c2SBalamuruhan S * Interrupt Management Area. This is the memory region holding
155159b7c1c2SBalamuruhan S * all the Interrupt Control Presenter (ICP) registers
155259b7c1c2SBalamuruhan S */
155377864267SCédric Le Goater pnv_chip_icp_realize(chip8, &local_err);
155477864267SCédric Le Goater if (local_err) {
155577864267SCédric Le Goater error_propagate(errp, local_err);
155677864267SCédric Le Goater return;
155777864267SCédric Le Goater }
155877864267SCédric Le Goater
155977864267SCédric Le Goater /* Create the simplified OCC model */
1560668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip8->occ), NULL, errp)) {
156177864267SCédric Le Goater return;
156277864267SCédric Le Goater }
156377864267SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_OCC_BASE, &chip8->occ.xscom_regs);
1564b0ae5c69SCédric Le Goater qdev_connect_gpio_out(DEVICE(&chip8->occ), 0,
1565ee1004bbSPhilippe Mathieu-Daudé qdev_get_gpio_in(DEVICE(psi8), PSIHB_IRQ_OCC));
1566f3db8266SBalamuruhan S
1567f3db8266SBalamuruhan S /* OCC SRAM model */
15683a1b70b6SCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV_OCC_SENSOR_BASE(chip),
1569f3db8266SBalamuruhan S &chip8->occ.sram_regs);
15703887d241SBalamuruhan S
15713887d241SBalamuruhan S /* HOMER */
15725325cc34SMarkus Armbruster object_property_set_link(OBJECT(&chip8->homer), "chip", OBJECT(chip),
1573f2582acfSGreg Kurz &error_abort);
1574668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip8->homer), NULL, errp)) {
15753887d241SBalamuruhan S return;
15763887d241SBalamuruhan S }
15778f092316SCédric Le Goater /* Homer Xscom region */
15788f092316SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_PBA_BASE, &chip8->homer.pba_regs);
15798f092316SCédric Le Goater
15808f092316SCédric Le Goater /* Homer mmio region */
15813887d241SBalamuruhan S memory_region_add_subregion(get_system_memory(), PNV_HOMER_BASE(chip),
15823887d241SBalamuruhan S &chip8->homer.regs);
15839ae1329eSCédric Le Goater
15841f5d6b2aSDaniel Henrique Barboza /* PHB controllers */
1585eb93c828SCédric Le Goater for (i = 0; i < chip8->num_phbs; i++) {
15860d512c71SDaniel Henrique Barboza PnvPHB *phb = chip8->phbs[i];
15879ae1329eSCédric Le Goater
15885325cc34SMarkus Armbruster object_property_set_int(OBJECT(phb), "index", i, &error_fatal);
15895325cc34SMarkus Armbruster object_property_set_int(OBJECT(phb), "chip-id", chip->chip_id,
15909ae1329eSCédric Le Goater &error_fatal);
15912c4d3a50SCédric Le Goater object_property_set_link(OBJECT(phb), "chip", OBJECT(chip),
15922c4d3a50SCédric Le Goater &error_fatal);
1593668f62ecSMarkus Armbruster if (!sysbus_realize(SYS_BUS_DEVICE(phb), errp)) {
15949ae1329eSCédric Le Goater return;
15959ae1329eSCédric Le Goater }
15969ae1329eSCédric Le Goater }
159777864267SCédric Le Goater }
159877864267SCédric Le Goater
pnv_chip_power8_xscom_pcba(PnvChip * chip,uint64_t addr)159970c059e9SGreg Kurz static uint32_t pnv_chip_power8_xscom_pcba(PnvChip *chip, uint64_t addr)
160070c059e9SGreg Kurz {
160170c059e9SGreg Kurz addr &= (PNV_XSCOM_SIZE - 1);
160270c059e9SGreg Kurz return ((addr >> 4) & ~0xfull) | ((addr >> 3) & 0xf);
160370c059e9SGreg Kurz }
160470c059e9SGreg Kurz
pnv_chip_power8e_class_init(ObjectClass * klass,void * data)1605e997040eSCédric Le Goater static void pnv_chip_power8e_class_init(ObjectClass *klass, void *data)
1606e997040eSCédric Le Goater {
1607e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass);
1608e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass);
1609e997040eSCédric Le Goater
1610e997040eSCédric Le Goater k->chip_cfam_id = 0x221ef04980000000ull; /* P8 Murano DD2.1 */
1611397a79e7SCédric Le Goater k->cores_mask = POWER8E_CORE_MASK;
16129ae1329eSCédric Le Goater k->num_phbs = 3;
161325de2822SNicholas Piggin k->get_pir_tir = pnv_get_pir_tir_p8;
1614d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power8_intc_create;
1615d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power8_intc_reset;
16160990ce6aSGreg Kurz k->intc_destroy = pnv_chip_power8_intc_destroy;
161785913070SGreg Kurz k->intc_print_info = pnv_chip_power8_intc_print_info;
161804026890SCédric Le Goater k->isa_create = pnv_chip_power8_isa_create;
1619eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power8_dt_populate;
1620d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power8_pic_print_info;
1621c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power8_xscom_core_base;
162270c059e9SGreg Kurz k->xscom_pcba = pnv_chip_power8_xscom_pcba;
1623e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8E";
162477864267SCédric Le Goater
162577864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power8_realize,
162677864267SCédric Le Goater &k->parent_realize);
1627e997040eSCédric Le Goater }
1628e997040eSCédric Le Goater
pnv_chip_power8_class_init(ObjectClass * klass,void * data)1629e997040eSCédric Le Goater static void pnv_chip_power8_class_init(ObjectClass *klass, void *data)
1630e997040eSCédric Le Goater {
1631e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass);
1632e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass);
1633e997040eSCédric Le Goater
1634e997040eSCédric Le Goater k->chip_cfam_id = 0x220ea04980000000ull; /* P8 Venice DD2.0 */
1635397a79e7SCédric Le Goater k->cores_mask = POWER8_CORE_MASK;
16369ae1329eSCédric Le Goater k->num_phbs = 3;
163725de2822SNicholas Piggin k->get_pir_tir = pnv_get_pir_tir_p8;
1638d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power8_intc_create;
1639d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power8_intc_reset;
16400990ce6aSGreg Kurz k->intc_destroy = pnv_chip_power8_intc_destroy;
164185913070SGreg Kurz k->intc_print_info = pnv_chip_power8_intc_print_info;
164204026890SCédric Le Goater k->isa_create = pnv_chip_power8_isa_create;
1643eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power8_dt_populate;
1644d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power8_pic_print_info;
1645c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power8_xscom_core_base;
164670c059e9SGreg Kurz k->xscom_pcba = pnv_chip_power8_xscom_pcba;
1647e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8";
164877864267SCédric Le Goater
164977864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power8_realize,
165077864267SCédric Le Goater &k->parent_realize);
1651e997040eSCédric Le Goater }
1652e997040eSCédric Le Goater
pnv_chip_power8nvl_class_init(ObjectClass * klass,void * data)1653e997040eSCédric Le Goater static void pnv_chip_power8nvl_class_init(ObjectClass *klass, void *data)
1654e997040eSCédric Le Goater {
1655e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass);
1656e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass);
1657e997040eSCédric Le Goater
1658e997040eSCédric Le Goater k->chip_cfam_id = 0x120d304980000000ull; /* P8 Naples DD1.0 */
1659397a79e7SCédric Le Goater k->cores_mask = POWER8_CORE_MASK;
1660316717feSCédric Le Goater k->num_phbs = 4;
166125de2822SNicholas Piggin k->get_pir_tir = pnv_get_pir_tir_p8;
1662d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power8_intc_create;
1663d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power8_intc_reset;
16640990ce6aSGreg Kurz k->intc_destroy = pnv_chip_power8_intc_destroy;
166585913070SGreg Kurz k->intc_print_info = pnv_chip_power8_intc_print_info;
166604026890SCédric Le Goater k->isa_create = pnv_chip_power8nvl_isa_create;
1667eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power8_dt_populate;
1668d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power8_pic_print_info;
1669c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power8_xscom_core_base;
167070c059e9SGreg Kurz k->xscom_pcba = pnv_chip_power8_xscom_pcba;
1671e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8NVL";
167277864267SCédric Le Goater
167377864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power8_realize,
167477864267SCédric Le Goater &k->parent_realize);
167577864267SCédric Le Goater }
167677864267SCédric Le Goater
pnv_chip_power9_instance_init(Object * obj)167777864267SCédric Le Goater static void pnv_chip_power9_instance_init(Object *obj)
167877864267SCédric Le Goater {
16794f9924c4SBenjamin Herrenschmidt PnvChip *chip = PNV_CHIP(obj);
16802dfa91a2SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(obj);
16814f9924c4SBenjamin Herrenschmidt PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj);
16824f9924c4SBenjamin Herrenschmidt int i;
16832dfa91a2SCédric Le Goater
168453f18b3eSNicholas Piggin object_initialize_child(obj, "adu", &chip9->adu, TYPE_PNV_ADU);
1685db873cc5SMarkus Armbruster object_initialize_child(obj, "xive", &chip9->xive, TYPE_PNV_XIVE);
1686d1214b81SGreg Kurz object_property_add_alias(obj, "xive-fabric", OBJECT(&chip9->xive),
1687d2623129SMarkus Armbruster "xive-fabric");
1688c38536bcSCédric Le Goater
16899fc7fc4dSMarkus Armbruster object_initialize_child(obj, "psi", &chip9->psi, TYPE_PNV9_PSI);
169015376c66SCédric Le Goater
16919fc7fc4dSMarkus Armbruster object_initialize_child(obj, "lpc", &chip9->lpc, TYPE_PNV9_LPC);
16926598a70dSCédric Le Goater
1693de3ba0ccSNicholas Piggin object_initialize_child(obj, "chiptod", &chip9->chiptod, TYPE_PNV9_CHIPTOD);
1694de3ba0ccSNicholas Piggin
16959fc7fc4dSMarkus Armbruster object_initialize_child(obj, "occ", &chip9->occ, TYPE_PNV9_OCC);
16963887d241SBalamuruhan S
16970bf4d77eSNicholas Piggin object_initialize_child(obj, "sbe", &chip9->sbe, TYPE_PNV9_SBE);
16980bf4d77eSNicholas Piggin
16999fc7fc4dSMarkus Armbruster object_initialize_child(obj, "homer", &chip9->homer, TYPE_PNV9_HOMER);
17004f9924c4SBenjamin Herrenschmidt
1701422fd92eSCédric Le Goater /* Number of PECs is the chip default */
1702422fd92eSCédric Le Goater chip->num_pecs = pcc->num_pecs;
1703422fd92eSCédric Le Goater
1704422fd92eSCédric Le Goater for (i = 0; i < chip->num_pecs; i++) {
17054f9924c4SBenjamin Herrenschmidt object_initialize_child(obj, "pec[*]", &chip9->pecs[i],
17069fc7fc4dSMarkus Armbruster TYPE_PNV_PHB4_PEC);
17074f9924c4SBenjamin Herrenschmidt }
17085f066121SCédric Le Goater
17095f066121SCédric Le Goater for (i = 0; i < pcc->i2c_num_engines; i++) {
17105f066121SCédric Le Goater object_initialize_child(obj, "i2c[*]", &chip9->i2c[i], TYPE_PNV_I2C);
17115f066121SCédric Le Goater }
171277864267SCédric Le Goater }
171377864267SCédric Le Goater
pnv_chip_quad_realize_one(PnvChip * chip,PnvQuad * eq,PnvCore * pnv_core,const char * type)1714ae4c68e3SCédric Le Goater static void pnv_chip_quad_realize_one(PnvChip *chip, PnvQuad *eq,
1715fdc2b46aSJoel Stanley PnvCore *pnv_core,
1716fdc2b46aSJoel Stanley const char *type)
17175dad902cSCédric Le Goater {
17185dad902cSCédric Le Goater char eq_name[32];
17195dad902cSCédric Le Goater int core_id = CPU_CORE(pnv_core)->core_id;
17205dad902cSCédric Le Goater
17215dad902cSCédric Le Goater snprintf(eq_name, sizeof(eq_name), "eq[%d]", core_id);
17229fc7fc4dSMarkus Armbruster object_initialize_child_with_props(OBJECT(chip), eq_name, eq,
1723fdc2b46aSJoel Stanley sizeof(*eq), type,
17249fc7fc4dSMarkus Armbruster &error_fatal, NULL);
17255dad902cSCédric Le Goater
172692612f15SCédric Le Goater object_property_set_int(OBJECT(eq), "quad-id", core_id, &error_fatal);
1727ce189ab2SMarkus Armbruster qdev_realize(DEVICE(eq), NULL, &error_fatal);
1728ae4c68e3SCédric Le Goater }
1729ae4c68e3SCédric Le Goater
pnv_chip_quad_realize(Pnv9Chip * chip9,Error ** errp)1730ae4c68e3SCédric Le Goater static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error **errp)
1731ae4c68e3SCédric Le Goater {
1732ae4c68e3SCédric Le Goater PnvChip *chip = PNV_CHIP(chip9);
1733ae4c68e3SCédric Le Goater int i;
1734ae4c68e3SCédric Le Goater
1735ae4c68e3SCédric Le Goater chip9->nr_quads = DIV_ROUND_UP(chip->nr_cores, 4);
1736ae4c68e3SCédric Le Goater chip9->quads = g_new0(PnvQuad, chip9->nr_quads);
1737ae4c68e3SCédric Le Goater
1738ae4c68e3SCédric Le Goater for (i = 0; i < chip9->nr_quads; i++) {
1739ae4c68e3SCédric Le Goater PnvQuad *eq = &chip9->quads[i];
1740ae4c68e3SCédric Le Goater
1741fdc2b46aSJoel Stanley pnv_chip_quad_realize_one(chip, eq, chip->cores[i * 4],
1742fdc2b46aSJoel Stanley PNV_QUAD_TYPE_NAME("power9"));
17435dad902cSCédric Le Goater
174492612f15SCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_EQ_BASE(eq->quad_id),
17455dad902cSCédric Le Goater &eq->xscom_regs);
17465dad902cSCédric Le Goater }
17475dad902cSCédric Le Goater }
17485dad902cSCédric Le Goater
pnv_chip_power9_pec_realize(PnvChip * chip,Error ** errp)174913480fc5SCédric Le Goater static void pnv_chip_power9_pec_realize(PnvChip *chip, Error **errp)
17504f9924c4SBenjamin Herrenschmidt {
17514f9924c4SBenjamin Herrenschmidt Pnv9Chip *chip9 = PNV9_CHIP(chip);
175213480fc5SCédric Le Goater int i;
17534f9924c4SBenjamin Herrenschmidt
1754422fd92eSCédric Le Goater for (i = 0; i < chip->num_pecs; i++) {
17554f9924c4SBenjamin Herrenschmidt PnvPhb4PecState *pec = &chip9->pecs[i];
17564f9924c4SBenjamin Herrenschmidt PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec);
17574f9924c4SBenjamin Herrenschmidt uint32_t pec_nest_base;
17584f9924c4SBenjamin Herrenschmidt uint32_t pec_pci_base;
17594f9924c4SBenjamin Herrenschmidt
17605325cc34SMarkus Armbruster object_property_set_int(OBJECT(pec), "index", i, &error_fatal);
17615325cc34SMarkus Armbruster object_property_set_int(OBJECT(pec), "chip-id", chip->chip_id,
17624f9924c4SBenjamin Herrenschmidt &error_fatal);
17636f43d255SCédric Le Goater object_property_set_link(OBJECT(pec), "chip", OBJECT(chip),
17646f43d255SCédric Le Goater &error_fatal);
1765668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(pec), NULL, errp)) {
17664f9924c4SBenjamin Herrenschmidt return;
17674f9924c4SBenjamin Herrenschmidt }
17684f9924c4SBenjamin Herrenschmidt
17694f9924c4SBenjamin Herrenschmidt pec_nest_base = pecc->xscom_nest_base(pec);
17704f9924c4SBenjamin Herrenschmidt pec_pci_base = pecc->xscom_pci_base(pec);
17714f9924c4SBenjamin Herrenschmidt
17724f9924c4SBenjamin Herrenschmidt pnv_xscom_add_subregion(chip, pec_nest_base, &pec->nest_regs_mr);
17734f9924c4SBenjamin Herrenschmidt pnv_xscom_add_subregion(chip, pec_pci_base, &pec->pci_regs_mr);
17744f9924c4SBenjamin Herrenschmidt }
17754f9924c4SBenjamin Herrenschmidt }
17764f9924c4SBenjamin Herrenschmidt
pnv_chip_power9_realize(DeviceState * dev,Error ** errp)177777864267SCédric Le Goater static void pnv_chip_power9_realize(DeviceState *dev, Error **errp)
177877864267SCédric Le Goater {
177977864267SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
17802dfa91a2SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(dev);
17812dfa91a2SCédric Le Goater PnvChip *chip = PNV_CHIP(dev);
1782c38536bcSCédric Le Goater Pnv9Psi *psi9 = &chip9->psi;
178377864267SCédric Le Goater Error *local_err = NULL;
17845f066121SCédric Le Goater int i;
178577864267SCédric Le Goater
1786709044fdSCédric Le Goater /* XSCOM bridge is first */
1787326f7acbSPhilippe Mathieu-Daudé pnv_xscom_init(chip, PNV9_XSCOM_SIZE, PNV9_XSCOM_BASE(chip));
1788709044fdSCédric Le Goater
178977864267SCédric Le Goater pcc->parent_realize(dev, &local_err);
179077864267SCédric Le Goater if (local_err) {
179177864267SCédric Le Goater error_propagate(errp, local_err);
179277864267SCédric Le Goater return;
179377864267SCédric Le Goater }
17942dfa91a2SCédric Le Goater
179553f18b3eSNicholas Piggin /* ADU */
179624bd283bSNicholas Piggin object_property_set_link(OBJECT(&chip9->adu), "lpc", OBJECT(&chip9->lpc),
179724bd283bSNicholas Piggin &error_abort);
179853f18b3eSNicholas Piggin if (!qdev_realize(DEVICE(&chip9->adu), NULL, errp)) {
179953f18b3eSNicholas Piggin return;
180053f18b3eSNicholas Piggin }
180153f18b3eSNicholas Piggin pnv_xscom_add_subregion(chip, PNV9_XSCOM_ADU_BASE,
180253f18b3eSNicholas Piggin &chip9->adu.xscom_regs);
180353f18b3eSNicholas Piggin
18045dad902cSCédric Le Goater pnv_chip_quad_realize(chip9, &local_err);
18055dad902cSCédric Le Goater if (local_err) {
18065dad902cSCédric Le Goater error_propagate(errp, local_err);
18075dad902cSCédric Le Goater return;
18085dad902cSCédric Le Goater }
18095dad902cSCédric Le Goater
18102dfa91a2SCédric Le Goater /* XIVE interrupt controller (POWER9) */
18115325cc34SMarkus Armbruster object_property_set_int(OBJECT(&chip9->xive), "ic-bar",
18125325cc34SMarkus Armbruster PNV9_XIVE_IC_BASE(chip), &error_fatal);
18135325cc34SMarkus Armbruster object_property_set_int(OBJECT(&chip9->xive), "vc-bar",
18145325cc34SMarkus Armbruster PNV9_XIVE_VC_BASE(chip), &error_fatal);
18155325cc34SMarkus Armbruster object_property_set_int(OBJECT(&chip9->xive), "pc-bar",
18165325cc34SMarkus Armbruster PNV9_XIVE_PC_BASE(chip), &error_fatal);
18175325cc34SMarkus Armbruster object_property_set_int(OBJECT(&chip9->xive), "tm-bar",
18185325cc34SMarkus Armbruster PNV9_XIVE_TM_BASE(chip), &error_fatal);
18195325cc34SMarkus Armbruster object_property_set_link(OBJECT(&chip9->xive), "chip", OBJECT(chip),
18207ae54cc3SGreg Kurz &error_abort);
1821668f62ecSMarkus Armbruster if (!sysbus_realize(SYS_BUS_DEVICE(&chip9->xive), errp)) {
18222dfa91a2SCédric Le Goater return;
18232dfa91a2SCédric Le Goater }
18242dfa91a2SCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_XIVE_BASE,
18252dfa91a2SCédric Le Goater &chip9->xive.xscom_regs);
1826c38536bcSCédric Le Goater
1827c38536bcSCédric Le Goater /* Processor Service Interface (PSI) Host Bridge */
1828ee1004bbSPhilippe Mathieu-Daudé object_property_set_int(OBJECT(psi9), "bar", PNV9_PSIHB_BASE(chip),
18295325cc34SMarkus Armbruster &error_fatal);
183024c8fa96SCédric Le Goater /* This is the only device with 4k ESB pages */
1831ee1004bbSPhilippe Mathieu-Daudé object_property_set_int(OBJECT(psi9), "shift", XIVE_ESB_4K,
183224c8fa96SCédric Le Goater &error_fatal);
1833ee1004bbSPhilippe Mathieu-Daudé if (!qdev_realize(DEVICE(psi9), NULL, errp)) {
1834c38536bcSCédric Le Goater return;
1835c38536bcSCédric Le Goater }
1836c38536bcSCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_PSIHB_BASE,
1837c38536bcSCédric Le Goater &PNV_PSI(psi9)->xscom_regs);
183815376c66SCédric Le Goater
183915376c66SCédric Le Goater /* LPC */
1840668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip9->lpc), NULL, errp)) {
184115376c66SCédric Le Goater return;
184215376c66SCédric Le Goater }
184315376c66SCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV9_LPCM_BASE(chip),
184415376c66SCédric Le Goater &chip9->lpc.xscom_regs);
184515376c66SCédric Le Goater
1846032c226bSCédric Le Goater chip->fw_mr = &chip9->lpc.isa_fw;
184715376c66SCédric Le Goater chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0",
184815376c66SCédric Le Goater (uint64_t) PNV9_LPCM_BASE(chip));
18496598a70dSCédric Le Goater
1850de3ba0ccSNicholas Piggin /* ChipTOD */
1851de3ba0ccSNicholas Piggin object_property_set_bool(OBJECT(&chip9->chiptod), "primary",
1852de3ba0ccSNicholas Piggin chip->chip_id == 0, &error_abort);
1853de3ba0ccSNicholas Piggin object_property_set_bool(OBJECT(&chip9->chiptod), "secondary",
1854de3ba0ccSNicholas Piggin chip->chip_id == 1, &error_abort);
1855de3ba0ccSNicholas Piggin object_property_set_link(OBJECT(&chip9->chiptod), "chip", OBJECT(chip),
1856de3ba0ccSNicholas Piggin &error_abort);
1857de3ba0ccSNicholas Piggin if (!qdev_realize(DEVICE(&chip9->chiptod), NULL, errp)) {
1858de3ba0ccSNicholas Piggin return;
1859de3ba0ccSNicholas Piggin }
1860de3ba0ccSNicholas Piggin pnv_xscom_add_subregion(chip, PNV9_XSCOM_CHIPTOD_BASE,
1861de3ba0ccSNicholas Piggin &chip9->chiptod.xscom_regs);
1862de3ba0ccSNicholas Piggin
18636598a70dSCédric Le Goater /* Create the simplified OCC model */
1864668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip9->occ), NULL, errp)) {
18656598a70dSCédric Le Goater return;
18666598a70dSCédric Le Goater }
18676598a70dSCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_OCC_BASE, &chip9->occ.xscom_regs);
1868b0ae5c69SCédric Le Goater qdev_connect_gpio_out(DEVICE(&chip9->occ), 0, qdev_get_gpio_in(
1869ee1004bbSPhilippe Mathieu-Daudé DEVICE(psi9), PSIHB9_IRQ_OCC));
1870f3db8266SBalamuruhan S
1871f3db8266SBalamuruhan S /* OCC SRAM model */
18723a1b70b6SCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV9_OCC_SENSOR_BASE(chip),
1873f3db8266SBalamuruhan S &chip9->occ.sram_regs);
18743887d241SBalamuruhan S
18750bf4d77eSNicholas Piggin /* SBE */
18760bf4d77eSNicholas Piggin if (!qdev_realize(DEVICE(&chip9->sbe), NULL, errp)) {
18770bf4d77eSNicholas Piggin return;
18780bf4d77eSNicholas Piggin }
18790bf4d77eSNicholas Piggin pnv_xscom_add_subregion(chip, PNV9_XSCOM_SBE_CTRL_BASE,
18800bf4d77eSNicholas Piggin &chip9->sbe.xscom_ctrl_regs);
18810bf4d77eSNicholas Piggin pnv_xscom_add_subregion(chip, PNV9_XSCOM_SBE_MBOX_BASE,
18820bf4d77eSNicholas Piggin &chip9->sbe.xscom_mbox_regs);
18830bf4d77eSNicholas Piggin qdev_connect_gpio_out(DEVICE(&chip9->sbe), 0, qdev_get_gpio_in(
1884ee1004bbSPhilippe Mathieu-Daudé DEVICE(psi9), PSIHB9_IRQ_PSU));
18850bf4d77eSNicholas Piggin
18863887d241SBalamuruhan S /* HOMER */
18875325cc34SMarkus Armbruster object_property_set_link(OBJECT(&chip9->homer), "chip", OBJECT(chip),
1888f2582acfSGreg Kurz &error_abort);
1889668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip9->homer), NULL, errp)) {
18903887d241SBalamuruhan S return;
18913887d241SBalamuruhan S }
18928f092316SCédric Le Goater /* Homer Xscom region */
18938f092316SCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_PBA_BASE, &chip9->homer.pba_regs);
18948f092316SCédric Le Goater
18958f092316SCédric Le Goater /* Homer mmio region */
18963887d241SBalamuruhan S memory_region_add_subregion(get_system_memory(), PNV9_HOMER_BASE(chip),
18973887d241SBalamuruhan S &chip9->homer.regs);
18984f9924c4SBenjamin Herrenschmidt
189913480fc5SCédric Le Goater /* PEC PHBs */
190013480fc5SCédric Le Goater pnv_chip_power9_pec_realize(chip, &local_err);
19014f9924c4SBenjamin Herrenschmidt if (local_err) {
19024f9924c4SBenjamin Herrenschmidt error_propagate(errp, local_err);
19034f9924c4SBenjamin Herrenschmidt return;
19044f9924c4SBenjamin Herrenschmidt }
19055f066121SCédric Le Goater
19065f066121SCédric Le Goater /*
19075f066121SCédric Le Goater * I2C
19085f066121SCédric Le Goater */
19095f066121SCédric Le Goater for (i = 0; i < pcc->i2c_num_engines; i++) {
19105f066121SCédric Le Goater Object *obj = OBJECT(&chip9->i2c[i]);
19115f066121SCédric Le Goater
19125f066121SCédric Le Goater object_property_set_int(obj, "engine", i + 1, &error_fatal);
19130d1dcb0bSGlenn Miles object_property_set_int(obj, "num-busses",
19140d1dcb0bSGlenn Miles pcc->i2c_ports_per_engine[i],
19155f066121SCédric Le Goater &error_fatal);
19165f066121SCédric Le Goater object_property_set_link(obj, "chip", OBJECT(chip), &error_abort);
19175f066121SCédric Le Goater if (!qdev_realize(DEVICE(obj), NULL, errp)) {
19185f066121SCédric Le Goater return;
19195f066121SCédric Le Goater }
19205f066121SCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_I2CM_BASE +
192147dfdd23SGlenn Miles (chip9->i2c[i].engine - 1) *
192247dfdd23SGlenn Miles PNV9_XSCOM_I2CM_SIZE,
19235f066121SCédric Le Goater &chip9->i2c[i].xscom_regs);
19245f066121SCédric Le Goater qdev_connect_gpio_out(DEVICE(&chip9->i2c[i]), 0,
1925ee1004bbSPhilippe Mathieu-Daudé qdev_get_gpio_in(DEVICE(psi9),
19265f066121SCédric Le Goater PSIHB9_IRQ_SBE_I2C));
19275f066121SCédric Le Goater }
1928e997040eSCédric Le Goater }
1929e997040eSCédric Le Goater
pnv_chip_power9_xscom_pcba(PnvChip * chip,uint64_t addr)193070c059e9SGreg Kurz static uint32_t pnv_chip_power9_xscom_pcba(PnvChip *chip, uint64_t addr)
193170c059e9SGreg Kurz {
193270c059e9SGreg Kurz addr &= (PNV9_XSCOM_SIZE - 1);
193370c059e9SGreg Kurz return addr >> 3;
193470c059e9SGreg Kurz }
193570c059e9SGreg Kurz
pnv_chip_power9_class_init(ObjectClass * klass,void * data)1936e997040eSCédric Le Goater static void pnv_chip_power9_class_init(ObjectClass *klass, void *data)
1937e997040eSCédric Le Goater {
1938e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass);
1939e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass);
19400d1dcb0bSGlenn Miles static const int i2c_ports_per_engine[PNV9_CHIP_MAX_I2C] = {2, 13, 2, 2};
1941e997040eSCédric Le Goater
194283028a2bSCédric Le Goater k->chip_cfam_id = 0x220d104900008000ull; /* P9 Nimbus DD2.0 */
1943397a79e7SCédric Le Goater k->cores_mask = POWER9_CORE_MASK;
194425de2822SNicholas Piggin k->get_pir_tir = pnv_get_pir_tir_p9;
1945d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power9_intc_create;
1946d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power9_intc_reset;
19470990ce6aSGreg Kurz k->intc_destroy = pnv_chip_power9_intc_destroy;
194885913070SGreg Kurz k->intc_print_info = pnv_chip_power9_intc_print_info;
194904026890SCédric Le Goater k->isa_create = pnv_chip_power9_isa_create;
1950eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power9_dt_populate;
1951d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power9_pic_print_info;
1952c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power9_xscom_core_base;
195370c059e9SGreg Kurz k->xscom_pcba = pnv_chip_power9_xscom_pcba;
1954e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER9";
1955422fd92eSCédric Le Goater k->num_pecs = PNV9_CHIP_MAX_PEC;
19565f066121SCédric Le Goater k->i2c_num_engines = PNV9_CHIP_MAX_I2C;
19570d1dcb0bSGlenn Miles k->i2c_ports_per_engine = i2c_ports_per_engine;
195877864267SCédric Le Goater
195977864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power9_realize,
196077864267SCédric Le Goater &k->parent_realize);
1961e997040eSCédric Le Goater }
1962e997040eSCédric Le Goater
pnv_chip_power10_instance_init(Object * obj)19632b548a42SCédric Le Goater static void pnv_chip_power10_instance_init(Object *obj)
19642b548a42SCédric Le Goater {
1965623575e1SCédric Le Goater PnvChip *chip = PNV_CHIP(obj);
19668b50ce85SCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(obj);
1967623575e1SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj);
1968623575e1SCédric Le Goater int i;
19698b50ce85SCédric Le Goater
197053f18b3eSNicholas Piggin object_initialize_child(obj, "adu", &chip10->adu, TYPE_PNV_ADU);
1971da71b7e3SCédric Le Goater object_initialize_child(obj, "xive", &chip10->xive, TYPE_PNV_XIVE2);
1972da71b7e3SCédric Le Goater object_property_add_alias(obj, "xive-fabric", OBJECT(&chip10->xive),
1973da71b7e3SCédric Le Goater "xive-fabric");
19749fc7fc4dSMarkus Armbruster object_initialize_child(obj, "psi", &chip10->psi, TYPE_PNV10_PSI);
19759fc7fc4dSMarkus Armbruster object_initialize_child(obj, "lpc", &chip10->lpc, TYPE_PNV10_LPC);
1976de3ba0ccSNicholas Piggin object_initialize_child(obj, "chiptod", &chip10->chiptod,
1977de3ba0ccSNicholas Piggin TYPE_PNV10_CHIPTOD);
19788bf682a3SCédric Le Goater object_initialize_child(obj, "occ", &chip10->occ, TYPE_PNV10_OCC);
19790bf4d77eSNicholas Piggin object_initialize_child(obj, "sbe", &chip10->sbe, TYPE_PNV10_SBE);
198092499676SCédric Le Goater object_initialize_child(obj, "homer", &chip10->homer, TYPE_PNV10_HOMER);
1981c295d3b0SChalapathi V object_initialize_child(obj, "n1-chiplet", &chip10->n1_chiplet,
1982c295d3b0SChalapathi V TYPE_PNV_N1_CHIPLET);
1983623575e1SCédric Le Goater
1984623575e1SCédric Le Goater chip->num_pecs = pcc->num_pecs;
1985623575e1SCédric Le Goater
1986623575e1SCédric Le Goater for (i = 0; i < chip->num_pecs; i++) {
1987623575e1SCédric Le Goater object_initialize_child(obj, "pec[*]", &chip10->pecs[i],
1988623575e1SCédric Le Goater TYPE_PNV_PHB5_PEC);
1989623575e1SCédric Le Goater }
19901ceda19cSGlenn Miles
19911ceda19cSGlenn Miles for (i = 0; i < pcc->i2c_num_engines; i++) {
19921ceda19cSGlenn Miles object_initialize_child(obj, "i2c[*]", &chip10->i2c[i], TYPE_PNV_I2C);
19931ceda19cSGlenn Miles }
1994bb44dc48SChalapathi V
1995bb44dc48SChalapathi V for (i = 0; i < PNV10_CHIP_MAX_PIB_SPIC; i++) {
1996bb44dc48SChalapathi V object_initialize_child(obj, "pib_spic[*]", &chip10->pib_spic[i],
1997bb44dc48SChalapathi V TYPE_PNV_SPI);
1998bb44dc48SChalapathi V }
19992b548a42SCédric Le Goater }
20002b548a42SCédric Le Goater
pnv_chip_power10_quad_realize(Pnv10Chip * chip10,Error ** errp)2001ae4c68e3SCédric Le Goater static void pnv_chip_power10_quad_realize(Pnv10Chip *chip10, Error **errp)
2002ae4c68e3SCédric Le Goater {
2003ae4c68e3SCédric Le Goater PnvChip *chip = PNV_CHIP(chip10);
2004ae4c68e3SCédric Le Goater int i;
2005ae4c68e3SCédric Le Goater
2006ae4c68e3SCédric Le Goater chip10->nr_quads = DIV_ROUND_UP(chip->nr_cores, 4);
2007ae4c68e3SCédric Le Goater chip10->quads = g_new0(PnvQuad, chip10->nr_quads);
2008ae4c68e3SCédric Le Goater
2009ae4c68e3SCédric Le Goater for (i = 0; i < chip10->nr_quads; i++) {
2010ae4c68e3SCédric Le Goater PnvQuad *eq = &chip10->quads[i];
2011ae4c68e3SCédric Le Goater
2012fdc2b46aSJoel Stanley pnv_chip_quad_realize_one(chip, eq, chip->cores[i * 4],
2013a1d64b9eSJoel Stanley PNV_QUAD_TYPE_NAME("power10"));
2014ae4c68e3SCédric Le Goater
2015ae4c68e3SCédric Le Goater pnv_xscom_add_subregion(chip, PNV10_XSCOM_EQ_BASE(eq->quad_id),
2016ae4c68e3SCédric Le Goater &eq->xscom_regs);
2017bdb97596SJoel Stanley
2018bdb97596SJoel Stanley pnv_xscom_add_subregion(chip, PNV10_XSCOM_QME_BASE(eq->quad_id),
2019bdb97596SJoel Stanley &eq->xscom_qme_regs);
2020ae4c68e3SCédric Le Goater }
2021ae4c68e3SCédric Le Goater }
2022ae4c68e3SCédric Le Goater
pnv_chip_power10_phb_realize(PnvChip * chip,Error ** errp)2023623575e1SCédric Le Goater static void pnv_chip_power10_phb_realize(PnvChip *chip, Error **errp)
2024623575e1SCédric Le Goater {
2025623575e1SCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(chip);
2026623575e1SCédric Le Goater int i;
2027623575e1SCédric Le Goater
2028623575e1SCédric Le Goater for (i = 0; i < chip->num_pecs; i++) {
2029623575e1SCédric Le Goater PnvPhb4PecState *pec = &chip10->pecs[i];
2030623575e1SCédric Le Goater PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec);
2031623575e1SCédric Le Goater uint32_t pec_nest_base;
2032623575e1SCédric Le Goater uint32_t pec_pci_base;
2033623575e1SCédric Le Goater
2034623575e1SCédric Le Goater object_property_set_int(OBJECT(pec), "index", i, &error_fatal);
2035623575e1SCédric Le Goater object_property_set_int(OBJECT(pec), "chip-id", chip->chip_id,
2036623575e1SCédric Le Goater &error_fatal);
2037623575e1SCédric Le Goater object_property_set_link(OBJECT(pec), "chip", OBJECT(chip),
2038623575e1SCédric Le Goater &error_fatal);
2039623575e1SCédric Le Goater if (!qdev_realize(DEVICE(pec), NULL, errp)) {
2040623575e1SCédric Le Goater return;
2041623575e1SCédric Le Goater }
2042623575e1SCédric Le Goater
2043623575e1SCédric Le Goater pec_nest_base = pecc->xscom_nest_base(pec);
2044623575e1SCédric Le Goater pec_pci_base = pecc->xscom_pci_base(pec);
2045623575e1SCédric Le Goater
2046623575e1SCédric Le Goater pnv_xscom_add_subregion(chip, pec_nest_base, &pec->nest_regs_mr);
2047623575e1SCédric Le Goater pnv_xscom_add_subregion(chip, pec_pci_base, &pec->pci_regs_mr);
2048623575e1SCédric Le Goater }
2049623575e1SCédric Le Goater }
2050623575e1SCédric Le Goater
pnv_chip_power10_realize(DeviceState * dev,Error ** errp)20512b548a42SCédric Le Goater static void pnv_chip_power10_realize(DeviceState *dev, Error **errp)
20522b548a42SCédric Le Goater {
20532b548a42SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
20542b548a42SCédric Le Goater PnvChip *chip = PNV_CHIP(dev);
20558b50ce85SCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(dev);
20562b548a42SCédric Le Goater Error *local_err = NULL;
20571ceda19cSGlenn Miles int i;
20582b548a42SCédric Le Goater
20592b548a42SCédric Le Goater /* XSCOM bridge is first */
2060326f7acbSPhilippe Mathieu-Daudé pnv_xscom_init(chip, PNV10_XSCOM_SIZE, PNV10_XSCOM_BASE(chip));
20612b548a42SCédric Le Goater
20622b548a42SCédric Le Goater pcc->parent_realize(dev, &local_err);
20632b548a42SCédric Le Goater if (local_err) {
20642b548a42SCédric Le Goater error_propagate(errp, local_err);
20652b548a42SCédric Le Goater return;
20662b548a42SCédric Le Goater }
20678b50ce85SCédric Le Goater
206853f18b3eSNicholas Piggin /* ADU */
206924bd283bSNicholas Piggin object_property_set_link(OBJECT(&chip10->adu), "lpc", OBJECT(&chip10->lpc),
207024bd283bSNicholas Piggin &error_abort);
207153f18b3eSNicholas Piggin if (!qdev_realize(DEVICE(&chip10->adu), NULL, errp)) {
207253f18b3eSNicholas Piggin return;
207353f18b3eSNicholas Piggin }
207453f18b3eSNicholas Piggin pnv_xscom_add_subregion(chip, PNV10_XSCOM_ADU_BASE,
207553f18b3eSNicholas Piggin &chip10->adu.xscom_regs);
207653f18b3eSNicholas Piggin
2077ae4c68e3SCédric Le Goater pnv_chip_power10_quad_realize(chip10, &local_err);
2078ae4c68e3SCédric Le Goater if (local_err) {
2079ae4c68e3SCédric Le Goater error_propagate(errp, local_err);
2080ae4c68e3SCédric Le Goater return;
2081ae4c68e3SCédric Le Goater }
2082ae4c68e3SCédric Le Goater
2083da71b7e3SCédric Le Goater /* XIVE2 interrupt controller (POWER10) */
2084da71b7e3SCédric Le Goater object_property_set_int(OBJECT(&chip10->xive), "ic-bar",
2085da71b7e3SCédric Le Goater PNV10_XIVE2_IC_BASE(chip), &error_fatal);
2086da71b7e3SCédric Le Goater object_property_set_int(OBJECT(&chip10->xive), "esb-bar",
2087da71b7e3SCédric Le Goater PNV10_XIVE2_ESB_BASE(chip), &error_fatal);
2088da71b7e3SCédric Le Goater object_property_set_int(OBJECT(&chip10->xive), "end-bar",
2089da71b7e3SCédric Le Goater PNV10_XIVE2_END_BASE(chip), &error_fatal);
2090da71b7e3SCédric Le Goater object_property_set_int(OBJECT(&chip10->xive), "nvpg-bar",
2091da71b7e3SCédric Le Goater PNV10_XIVE2_NVPG_BASE(chip), &error_fatal);
2092da71b7e3SCédric Le Goater object_property_set_int(OBJECT(&chip10->xive), "nvc-bar",
2093da71b7e3SCédric Le Goater PNV10_XIVE2_NVC_BASE(chip), &error_fatal);
2094da71b7e3SCédric Le Goater object_property_set_int(OBJECT(&chip10->xive), "tm-bar",
2095da71b7e3SCédric Le Goater PNV10_XIVE2_TM_BASE(chip), &error_fatal);
2096da71b7e3SCédric Le Goater object_property_set_link(OBJECT(&chip10->xive), "chip", OBJECT(chip),
2097da71b7e3SCédric Le Goater &error_abort);
2098da71b7e3SCédric Le Goater if (!sysbus_realize(SYS_BUS_DEVICE(&chip10->xive), errp)) {
2099da71b7e3SCédric Le Goater return;
2100da71b7e3SCédric Le Goater }
2101da71b7e3SCédric Le Goater pnv_xscom_add_subregion(chip, PNV10_XSCOM_XIVE2_BASE,
2102da71b7e3SCédric Le Goater &chip10->xive.xscom_regs);
2103da71b7e3SCédric Le Goater
21048b50ce85SCédric Le Goater /* Processor Service Interface (PSI) Host Bridge */
21055325cc34SMarkus Armbruster object_property_set_int(OBJECT(&chip10->psi), "bar",
21065325cc34SMarkus Armbruster PNV10_PSIHB_BASE(chip), &error_fatal);
210724c8fa96SCédric Le Goater /* PSI can now be configured to use 64k ESB pages on POWER10 */
210824c8fa96SCédric Le Goater object_property_set_int(OBJECT(&chip10->psi), "shift", XIVE_ESB_64K,
210924c8fa96SCédric Le Goater &error_fatal);
2110668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip10->psi), NULL, errp)) {
21118b50ce85SCédric Le Goater return;
21128b50ce85SCédric Le Goater }
21138b50ce85SCédric Le Goater pnv_xscom_add_subregion(chip, PNV10_XSCOM_PSIHB_BASE,
21148b50ce85SCédric Le Goater &PNV_PSI(&chip10->psi)->xscom_regs);
21152661f6abSCédric Le Goater
21162661f6abSCédric Le Goater /* LPC */
2117668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip10->lpc), NULL, errp)) {
21182661f6abSCédric Le Goater return;
21192661f6abSCédric Le Goater }
21202661f6abSCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV10_LPCM_BASE(chip),
21212661f6abSCédric Le Goater &chip10->lpc.xscom_regs);
21222661f6abSCédric Le Goater
2123032c226bSCédric Le Goater chip->fw_mr = &chip10->lpc.isa_fw;
21242661f6abSCédric Le Goater chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0",
21252661f6abSCédric Le Goater (uint64_t) PNV10_LPCM_BASE(chip));
21268bf682a3SCédric Le Goater
2127de3ba0ccSNicholas Piggin /* ChipTOD */
2128de3ba0ccSNicholas Piggin object_property_set_bool(OBJECT(&chip10->chiptod), "primary",
2129de3ba0ccSNicholas Piggin chip->chip_id == 0, &error_abort);
2130de3ba0ccSNicholas Piggin object_property_set_bool(OBJECT(&chip10->chiptod), "secondary",
2131de3ba0ccSNicholas Piggin chip->chip_id == 1, &error_abort);
2132de3ba0ccSNicholas Piggin object_property_set_link(OBJECT(&chip10->chiptod), "chip", OBJECT(chip),
2133de3ba0ccSNicholas Piggin &error_abort);
2134de3ba0ccSNicholas Piggin if (!qdev_realize(DEVICE(&chip10->chiptod), NULL, errp)) {
2135de3ba0ccSNicholas Piggin return;
2136de3ba0ccSNicholas Piggin }
2137de3ba0ccSNicholas Piggin pnv_xscom_add_subregion(chip, PNV10_XSCOM_CHIPTOD_BASE,
2138de3ba0ccSNicholas Piggin &chip10->chiptod.xscom_regs);
2139de3ba0ccSNicholas Piggin
21408bf682a3SCédric Le Goater /* Create the simplified OCC model */
21418bf682a3SCédric Le Goater if (!qdev_realize(DEVICE(&chip10->occ), NULL, errp)) {
21428bf682a3SCédric Le Goater return;
21438bf682a3SCédric Le Goater }
21448bf682a3SCédric Le Goater pnv_xscom_add_subregion(chip, PNV10_XSCOM_OCC_BASE,
21458bf682a3SCédric Le Goater &chip10->occ.xscom_regs);
2146b0ae5c69SCédric Le Goater qdev_connect_gpio_out(DEVICE(&chip10->occ), 0, qdev_get_gpio_in(
2147b0ae5c69SCédric Le Goater DEVICE(&chip10->psi), PSIHB9_IRQ_OCC));
2148623575e1SCédric Le Goater
214992499676SCédric Le Goater /* OCC SRAM model */
215092499676SCédric Le Goater memory_region_add_subregion(get_system_memory(),
215192499676SCédric Le Goater PNV10_OCC_SENSOR_BASE(chip),
215292499676SCédric Le Goater &chip10->occ.sram_regs);
215392499676SCédric Le Goater
21540bf4d77eSNicholas Piggin /* SBE */
21550bf4d77eSNicholas Piggin if (!qdev_realize(DEVICE(&chip10->sbe), NULL, errp)) {
21560bf4d77eSNicholas Piggin return;
21570bf4d77eSNicholas Piggin }
21580bf4d77eSNicholas Piggin pnv_xscom_add_subregion(chip, PNV10_XSCOM_SBE_CTRL_BASE,
21590bf4d77eSNicholas Piggin &chip10->sbe.xscom_ctrl_regs);
21600bf4d77eSNicholas Piggin pnv_xscom_add_subregion(chip, PNV10_XSCOM_SBE_MBOX_BASE,
21610bf4d77eSNicholas Piggin &chip10->sbe.xscom_mbox_regs);
21620bf4d77eSNicholas Piggin qdev_connect_gpio_out(DEVICE(&chip10->sbe), 0, qdev_get_gpio_in(
21630bf4d77eSNicholas Piggin DEVICE(&chip10->psi), PSIHB9_IRQ_PSU));
21640bf4d77eSNicholas Piggin
216592499676SCédric Le Goater /* HOMER */
216692499676SCédric Le Goater object_property_set_link(OBJECT(&chip10->homer), "chip", OBJECT(chip),
216792499676SCédric Le Goater &error_abort);
216892499676SCédric Le Goater if (!qdev_realize(DEVICE(&chip10->homer), NULL, errp)) {
216992499676SCédric Le Goater return;
217092499676SCédric Le Goater }
217192499676SCédric Le Goater /* Homer Xscom region */
217292499676SCédric Le Goater pnv_xscom_add_subregion(chip, PNV10_XSCOM_PBA_BASE,
217392499676SCédric Le Goater &chip10->homer.pba_regs);
217492499676SCédric Le Goater
217592499676SCédric Le Goater /* Homer mmio region */
217692499676SCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV10_HOMER_BASE(chip),
217792499676SCédric Le Goater &chip10->homer.regs);
217892499676SCédric Le Goater
2179c295d3b0SChalapathi V /* N1 chiplet */
2180c295d3b0SChalapathi V if (!qdev_realize(DEVICE(&chip10->n1_chiplet), NULL, errp)) {
2181c295d3b0SChalapathi V return;
2182c295d3b0SChalapathi V }
2183c295d3b0SChalapathi V pnv_xscom_add_subregion(chip, PNV10_XSCOM_N1_CHIPLET_CTRL_REGS_BASE,
2184c295d3b0SChalapathi V &chip10->n1_chiplet.nest_pervasive.xscom_ctrl_regs_mr);
2185c295d3b0SChalapathi V
2186c295d3b0SChalapathi V pnv_xscom_add_subregion(chip, PNV10_XSCOM_N1_PB_SCOM_EQ_BASE,
2187c295d3b0SChalapathi V &chip10->n1_chiplet.xscom_pb_eq_mr);
2188c295d3b0SChalapathi V
2189c295d3b0SChalapathi V pnv_xscom_add_subregion(chip, PNV10_XSCOM_N1_PB_SCOM_ES_BASE,
2190c295d3b0SChalapathi V &chip10->n1_chiplet.xscom_pb_es_mr);
2191c295d3b0SChalapathi V
2192623575e1SCédric Le Goater /* PHBs */
2193623575e1SCédric Le Goater pnv_chip_power10_phb_realize(chip, &local_err);
2194623575e1SCédric Le Goater if (local_err) {
2195623575e1SCédric Le Goater error_propagate(errp, local_err);
2196623575e1SCédric Le Goater return;
2197623575e1SCédric Le Goater }
21981ceda19cSGlenn Miles
21991ceda19cSGlenn Miles
22001ceda19cSGlenn Miles /*
22011ceda19cSGlenn Miles * I2C
22021ceda19cSGlenn Miles */
22031ceda19cSGlenn Miles for (i = 0; i < pcc->i2c_num_engines; i++) {
22041ceda19cSGlenn Miles Object *obj = OBJECT(&chip10->i2c[i]);
22051ceda19cSGlenn Miles
22061ceda19cSGlenn Miles object_property_set_int(obj, "engine", i + 1, &error_fatal);
22070d1dcb0bSGlenn Miles object_property_set_int(obj, "num-busses",
22080d1dcb0bSGlenn Miles pcc->i2c_ports_per_engine[i],
22091ceda19cSGlenn Miles &error_fatal);
22101ceda19cSGlenn Miles object_property_set_link(obj, "chip", OBJECT(chip), &error_abort);
22111ceda19cSGlenn Miles if (!qdev_realize(DEVICE(obj), NULL, errp)) {
22121ceda19cSGlenn Miles return;
22131ceda19cSGlenn Miles }
22141ceda19cSGlenn Miles pnv_xscom_add_subregion(chip, PNV10_XSCOM_I2CM_BASE +
221547dfdd23SGlenn Miles (chip10->i2c[i].engine - 1) *
221647dfdd23SGlenn Miles PNV10_XSCOM_I2CM_SIZE,
22171ceda19cSGlenn Miles &chip10->i2c[i].xscom_regs);
22181ceda19cSGlenn Miles qdev_connect_gpio_out(DEVICE(&chip10->i2c[i]), 0,
22191ceda19cSGlenn Miles qdev_get_gpio_in(DEVICE(&chip10->psi),
22201ceda19cSGlenn Miles PSIHB9_IRQ_SBE_I2C));
22211ceda19cSGlenn Miles }
2222bb44dc48SChalapathi V /* PIB SPI Controller */
2223bb44dc48SChalapathi V for (i = 0; i < PNV10_CHIP_MAX_PIB_SPIC; i++) {
2224bb44dc48SChalapathi V object_property_set_int(OBJECT(&chip10->pib_spic[i]), "spic_num",
2225bb44dc48SChalapathi V i, &error_fatal);
2226bb44dc48SChalapathi V /* pib_spic[2] connected to 25csm04 which implements 1 byte transfer */
2227bb44dc48SChalapathi V object_property_set_int(OBJECT(&chip10->pib_spic[i]), "transfer_len",
2228bb44dc48SChalapathi V (i == 2) ? 1 : 4, &error_fatal);
2229bb44dc48SChalapathi V if (!sysbus_realize(SYS_BUS_DEVICE(OBJECT
2230bb44dc48SChalapathi V (&chip10->pib_spic[i])), errp)) {
2231bb44dc48SChalapathi V return;
2232bb44dc48SChalapathi V }
2233bb44dc48SChalapathi V pnv_xscom_add_subregion(chip, PNV10_XSCOM_PIB_SPIC_BASE +
2234bb44dc48SChalapathi V i * PNV10_XSCOM_PIB_SPIC_SIZE,
2235bb44dc48SChalapathi V &chip10->pib_spic[i].xscom_spic_regs);
2236bb44dc48SChalapathi V }
223733467ecbSGlenn Miles }
223833467ecbSGlenn Miles
pnv_rainier_i2c_init(PnvMachineState * pnv)223933467ecbSGlenn Miles static void pnv_rainier_i2c_init(PnvMachineState *pnv)
224033467ecbSGlenn Miles {
224133467ecbSGlenn Miles int i;
224233467ecbSGlenn Miles for (i = 0; i < pnv->num_chips; i++) {
224333467ecbSGlenn Miles Pnv10Chip *chip10 = PNV10_CHIP(pnv->chips[i]);
224433467ecbSGlenn Miles
224533467ecbSGlenn Miles /*
224633467ecbSGlenn Miles * Add a PCA9552 I2C device for PCIe hotplug control
224733467ecbSGlenn Miles * to engine 2, bus 1, address 0x63
224833467ecbSGlenn Miles */
22496f86885aSGlenn Miles I2CSlave *dev = i2c_slave_create_simple(chip10->i2c[2].busses[1],
22506f86885aSGlenn Miles "pca9552", 0x63);
22516f86885aSGlenn Miles
22526f86885aSGlenn Miles /*
22536f86885aSGlenn Miles * Connect PCA9552 GPIO pins 0-4 (SLOTx_EN) outputs to GPIO pins 5-9
22546f86885aSGlenn Miles * (SLOTx_PG) inputs in order to fake the pgood state of PCIe slots
22556f86885aSGlenn Miles * after hypervisor code sets a SLOTx_EN pin high.
22566f86885aSGlenn Miles */
22576f86885aSGlenn Miles qdev_connect_gpio_out(DEVICE(dev), 0, qdev_get_gpio_in(DEVICE(dev), 5));
22586f86885aSGlenn Miles qdev_connect_gpio_out(DEVICE(dev), 1, qdev_get_gpio_in(DEVICE(dev), 6));
22596f86885aSGlenn Miles qdev_connect_gpio_out(DEVICE(dev), 2, qdev_get_gpio_in(DEVICE(dev), 7));
22606f86885aSGlenn Miles qdev_connect_gpio_out(DEVICE(dev), 3, qdev_get_gpio_in(DEVICE(dev), 8));
22616f86885aSGlenn Miles qdev_connect_gpio_out(DEVICE(dev), 4, qdev_get_gpio_in(DEVICE(dev), 9));
22626aa4ef32SGlenn Miles
22636aa4ef32SGlenn Miles /*
22646aa4ef32SGlenn Miles * Add a PCA9554 I2C device for cable card presence detection
22656aa4ef32SGlenn Miles * to engine 2, bus 1, address 0x25
22666aa4ef32SGlenn Miles */
22676aa4ef32SGlenn Miles i2c_slave_create_simple(chip10->i2c[2].busses[1], "pca9554", 0x25);
226833467ecbSGlenn Miles }
22692b548a42SCédric Le Goater }
22702b548a42SCédric Le Goater
pnv_chip_power10_xscom_pcba(PnvChip * chip,uint64_t addr)227170c059e9SGreg Kurz static uint32_t pnv_chip_power10_xscom_pcba(PnvChip *chip, uint64_t addr)
227270c059e9SGreg Kurz {
227370c059e9SGreg Kurz addr &= (PNV10_XSCOM_SIZE - 1);
227470c059e9SGreg Kurz return addr >> 3;
227570c059e9SGreg Kurz }
227670c059e9SGreg Kurz
pnv_chip_power10_class_init(ObjectClass * klass,void * data)22772b548a42SCédric Le Goater static void pnv_chip_power10_class_init(ObjectClass *klass, void *data)
22782b548a42SCédric Le Goater {
22792b548a42SCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass);
22802b548a42SCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass);
22810d1dcb0bSGlenn Miles static const int i2c_ports_per_engine[PNV10_CHIP_MAX_I2C] = {14, 14, 2, 16};
22822b548a42SCédric Le Goater
2283977e789cSAditya Gupta k->chip_cfam_id = 0x220da04980000000ull; /* P10 DD2.0 (with NX) */
22842b548a42SCédric Le Goater k->cores_mask = POWER10_CORE_MASK;
228525de2822SNicholas Piggin k->get_pir_tir = pnv_get_pir_tir_p10;
22862b548a42SCédric Le Goater k->intc_create = pnv_chip_power10_intc_create;
22872b548a42SCédric Le Goater k->intc_reset = pnv_chip_power10_intc_reset;
22882b548a42SCédric Le Goater k->intc_destroy = pnv_chip_power10_intc_destroy;
228985913070SGreg Kurz k->intc_print_info = pnv_chip_power10_intc_print_info;
22902b548a42SCédric Le Goater k->isa_create = pnv_chip_power10_isa_create;
22912b548a42SCédric Le Goater k->dt_populate = pnv_chip_power10_dt_populate;
22922b548a42SCédric Le Goater k->pic_print_info = pnv_chip_power10_pic_print_info;
2293c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power10_xscom_core_base;
229470c059e9SGreg Kurz k->xscom_pcba = pnv_chip_power10_xscom_pcba;
22952b548a42SCédric Le Goater dc->desc = "PowerNV Chip POWER10";
2296623575e1SCédric Le Goater k->num_pecs = PNV10_CHIP_MAX_PEC;
22971ceda19cSGlenn Miles k->i2c_num_engines = PNV10_CHIP_MAX_I2C;
22980d1dcb0bSGlenn Miles k->i2c_ports_per_engine = i2c_ports_per_engine;
22992b548a42SCédric Le Goater
23002b548a42SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power10_realize,
23012b548a42SCédric Le Goater &k->parent_realize);
23022b548a42SCédric Le Goater }
23032b548a42SCédric Le Goater
pnv_chip_core_sanitize(PnvMachineState * pnv,PnvChip * chip,Error ** errp)2304c26504afSNicholas Piggin static void pnv_chip_core_sanitize(PnvMachineState *pnv, PnvChip *chip,
2305c26504afSNicholas Piggin Error **errp)
2306397a79e7SCédric Le Goater {
2307397a79e7SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
2308397a79e7SCédric Le Goater int cores_max;
2309397a79e7SCédric Le Goater
2310397a79e7SCédric Le Goater /*
2311397a79e7SCédric Le Goater * No custom mask for this chip, let's use the default one from *
2312397a79e7SCédric Le Goater * the chip class
2313397a79e7SCédric Le Goater */
2314397a79e7SCédric Le Goater if (!chip->cores_mask) {
2315397a79e7SCédric Le Goater chip->cores_mask = pcc->cores_mask;
2316397a79e7SCédric Le Goater }
2317397a79e7SCédric Le Goater
2318397a79e7SCédric Le Goater /* filter alien core ids ! some are reserved */
2319397a79e7SCédric Le Goater if ((chip->cores_mask & pcc->cores_mask) != chip->cores_mask) {
2320397a79e7SCédric Le Goater error_setg(errp, "warning: invalid core mask for chip Ox%"PRIx64" !",
2321397a79e7SCédric Le Goater chip->cores_mask);
2322397a79e7SCédric Le Goater return;
2323397a79e7SCédric Le Goater }
2324397a79e7SCédric Le Goater chip->cores_mask &= pcc->cores_mask;
2325397a79e7SCédric Le Goater
2326c26504afSNicholas Piggin /* Ensure small-cores a paired up in big-core mode */
2327c26504afSNicholas Piggin if (pnv->big_core) {
2328c26504afSNicholas Piggin uint64_t even_cores = chip->cores_mask & 0x5555555555555555ULL;
2329c26504afSNicholas Piggin uint64_t odd_cores = chip->cores_mask & 0xaaaaaaaaaaaaaaaaULL;
2330c26504afSNicholas Piggin
2331c26504afSNicholas Piggin if (even_cores ^ (odd_cores >> 1)) {
2332c26504afSNicholas Piggin error_setg(errp, "warning: unpaired cores in big-core mode !");
2333c26504afSNicholas Piggin return;
2334c26504afSNicholas Piggin }
2335c26504afSNicholas Piggin }
2336c26504afSNicholas Piggin
2337397a79e7SCédric Le Goater /* now that we have a sane layout, let check the number of cores */
233827d9ffd4SDavid Gibson cores_max = ctpop64(chip->cores_mask);
2339397a79e7SCédric Le Goater if (chip->nr_cores > cores_max) {
2340397a79e7SCédric Le Goater error_setg(errp, "warning: too many cores for chip ! Limit is %d",
2341397a79e7SCédric Le Goater cores_max);
2342397a79e7SCédric Le Goater return;
2343397a79e7SCédric Le Goater }
2344397a79e7SCédric Le Goater }
2345397a79e7SCédric Le Goater
pnv_chip_core_realize(PnvChip * chip,Error ** errp)234651c04728SCédric Le Goater static void pnv_chip_core_realize(PnvChip *chip, Error **errp)
2347e997040eSCédric Le Goater {
234878be3218SNicholas Piggin PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine());
234978be3218SNicholas Piggin PnvMachineClass *pmc = PNV_MACHINE_GET_CLASS(pnv);
2350397a79e7SCédric Le Goater Error *error = NULL;
2351d2fd9612SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
235240abf43fSIgor Mammedov const char *typename = pnv_chip_core_typename(chip);
2353d2fd9612SCédric Le Goater int i, core_hwid;
2354397a79e7SCédric Le Goater
2355d2fd9612SCédric Le Goater if (!object_class_by_name(typename)) {
2356d2fd9612SCédric Le Goater error_setg(errp, "Unable to find PowerNV CPU Core '%s'", typename);
2357d2fd9612SCédric Le Goater return;
2358d2fd9612SCédric Le Goater }
2359d2fd9612SCédric Le Goater
2360d2fd9612SCédric Le Goater /* Cores */
2361c26504afSNicholas Piggin pnv_chip_core_sanitize(pnv, chip, &error);
2362397a79e7SCédric Le Goater if (error) {
2363397a79e7SCédric Le Goater error_propagate(errp, error);
2364397a79e7SCédric Le Goater return;
2365397a79e7SCédric Le Goater }
2366d2fd9612SCédric Le Goater
23674fa28f23SGreg Kurz chip->cores = g_new0(PnvCore *, chip->nr_cores);
2368d2fd9612SCédric Le Goater
2369d2fd9612SCédric Le Goater for (i = 0, core_hwid = 0; (core_hwid < sizeof(chip->cores_mask) * 8)
2370d2fd9612SCédric Le Goater && (i < chip->nr_cores); core_hwid++) {
2371d2fd9612SCédric Le Goater char core_name[32];
23724fa28f23SGreg Kurz PnvCore *pnv_core;
2373c035851aSCédric Le Goater uint64_t xscom_core_base;
2374d2fd9612SCédric Le Goater
2375d2fd9612SCédric Le Goater if (!(chip->cores_mask & (1ull << core_hwid))) {
2376d2fd9612SCédric Le Goater continue;
2377d2fd9612SCédric Le Goater }
2378d2fd9612SCédric Le Goater
23794fa28f23SGreg Kurz pnv_core = PNV_CORE(object_new(typename));
23804fa28f23SGreg Kurz
2381d2fd9612SCédric Le Goater snprintf(core_name, sizeof(core_name), "core[%d]", core_hwid);
2382d2623129SMarkus Armbruster object_property_add_child(OBJECT(chip), core_name, OBJECT(pnv_core));
23834fa28f23SGreg Kurz chip->cores[i] = pnv_core;
23845325cc34SMarkus Armbruster object_property_set_int(OBJECT(pnv_core), "nr-threads",
23855325cc34SMarkus Armbruster chip->nr_threads, &error_fatal);
23865325cc34SMarkus Armbruster object_property_set_int(OBJECT(pnv_core), CPU_CORE_PROP_CORE_ID,
23875325cc34SMarkus Armbruster core_hwid, &error_fatal);
23889940412aSCaleb Schlossin object_property_set_int(OBJECT(pnv_core), "hwid", core_hwid,
23899940412aSCaleb Schlossin &error_fatal);
23905325cc34SMarkus Armbruster object_property_set_int(OBJECT(pnv_core), "hrmor", pnv->fw_load_addr,
23915325cc34SMarkus Armbruster &error_fatal);
2392c26504afSNicholas Piggin object_property_set_bool(OBJECT(pnv_core), "big-core", chip->big_core,
2393c26504afSNicholas Piggin &error_fatal);
239478be3218SNicholas Piggin object_property_set_bool(OBJECT(pnv_core), "quirk-tb-big-core",
239578be3218SNicholas Piggin pmc->quirk_tb_big_core, &error_fatal);
23963b5ea01eSNicholas Piggin object_property_set_bool(OBJECT(pnv_core), "lpar-per-core",
23973b5ea01eSNicholas Piggin chip->lpar_per_core, &error_fatal);
23985325cc34SMarkus Armbruster object_property_set_link(OBJECT(pnv_core), "chip", OBJECT(chip),
2399158e17a6SGreg Kurz &error_abort);
240078be3218SNicholas Piggin
2401ce189ab2SMarkus Armbruster qdev_realize(DEVICE(pnv_core), NULL, &error_fatal);
240224ece072SCédric Le Goater
240324ece072SCédric Le Goater /* Each core has an XSCOM MMIO region */
2404c4b2c40cSGreg Kurz xscom_core_base = pcc->xscom_core_base(chip, core_hwid);
2405c035851aSCédric Le Goater
2406c035851aSCédric Le Goater pnv_xscom_add_subregion(chip, xscom_core_base,
24074fa28f23SGreg Kurz &pnv_core->xscom_regs);
2408d2fd9612SCédric Le Goater i++;
2409d2fd9612SCédric Le Goater }
241051c04728SCédric Le Goater }
241151c04728SCédric Le Goater
pnv_chip_realize(DeviceState * dev,Error ** errp)241251c04728SCédric Le Goater static void pnv_chip_realize(DeviceState *dev, Error **errp)
241351c04728SCédric Le Goater {
241451c04728SCédric Le Goater PnvChip *chip = PNV_CHIP(dev);
241551c04728SCédric Le Goater Error *error = NULL;
241651c04728SCédric Le Goater
241751c04728SCédric Le Goater /* Cores */
241851c04728SCédric Le Goater pnv_chip_core_realize(chip, &error);
241951c04728SCédric Le Goater if (error) {
242051c04728SCédric Le Goater error_propagate(errp, error);
242151c04728SCédric Le Goater return;
242251c04728SCédric Le Goater }
2423e997040eSCédric Le Goater }
2424e997040eSCédric Le Goater
2425e997040eSCédric Le Goater static Property pnv_chip_properties[] = {
2426e997040eSCédric Le Goater DEFINE_PROP_UINT32("chip-id", PnvChip, chip_id, 0),
2427e997040eSCédric Le Goater DEFINE_PROP_UINT64("ram-start", PnvChip, ram_start, 0),
2428e997040eSCédric Le Goater DEFINE_PROP_UINT64("ram-size", PnvChip, ram_size, 0),
2429397a79e7SCédric Le Goater DEFINE_PROP_UINT32("nr-cores", PnvChip, nr_cores, 1),
2430397a79e7SCédric Le Goater DEFINE_PROP_UINT64("cores-mask", PnvChip, cores_mask, 0x0),
2431764f9b25SGreg Kurz DEFINE_PROP_UINT32("nr-threads", PnvChip, nr_threads, 1),
2432c26504afSNicholas Piggin DEFINE_PROP_BOOL("big-core", PnvChip, big_core, false),
24333b5ea01eSNicholas Piggin DEFINE_PROP_BOOL("lpar-per-core", PnvChip, lpar_per_core, false),
2434e997040eSCédric Le Goater DEFINE_PROP_END_OF_LIST(),
2435e997040eSCédric Le Goater };
2436e997040eSCédric Le Goater
pnv_chip_class_init(ObjectClass * klass,void * data)2437e997040eSCédric Le Goater static void pnv_chip_class_init(ObjectClass *klass, void *data)
2438e997040eSCédric Le Goater {
2439e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass);
2440e997040eSCédric Le Goater
24419d169fb3SThomas Huth set_bit(DEVICE_CATEGORY_CPU, dc->categories);
2442e997040eSCédric Le Goater dc->realize = pnv_chip_realize;
24434f67d30bSMarc-André Lureau device_class_set_props(dc, pnv_chip_properties);
2444e997040eSCédric Le Goater dc->desc = "PowerNV Chip";
2445e997040eSCédric Le Goater }
2446e997040eSCédric Le Goater
pnv_chip_find_core(PnvChip * chip,uint32_t core_id)2447cde2ba34SNicholas Piggin PnvCore *pnv_chip_find_core(PnvChip *chip, uint32_t core_id)
2448cde2ba34SNicholas Piggin {
2449cde2ba34SNicholas Piggin int i;
2450cde2ba34SNicholas Piggin
2451cde2ba34SNicholas Piggin for (i = 0; i < chip->nr_cores; i++) {
2452cde2ba34SNicholas Piggin PnvCore *pc = chip->cores[i];
2453cde2ba34SNicholas Piggin CPUCore *cc = CPU_CORE(pc);
2454cde2ba34SNicholas Piggin
2455cde2ba34SNicholas Piggin if (cc->core_id == core_id) {
2456cde2ba34SNicholas Piggin return pc;
2457cde2ba34SNicholas Piggin }
2458cde2ba34SNicholas Piggin }
2459cde2ba34SNicholas Piggin return NULL;
2460cde2ba34SNicholas Piggin }
2461cde2ba34SNicholas Piggin
pnv_chip_find_cpu(PnvChip * chip,uint32_t pir)2462119eaa9dSCédric Le Goater PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir)
2463119eaa9dSCédric Le Goater {
2464119eaa9dSCédric Le Goater int i, j;
2465119eaa9dSCédric Le Goater
2466119eaa9dSCédric Le Goater for (i = 0; i < chip->nr_cores; i++) {
2467119eaa9dSCédric Le Goater PnvCore *pc = chip->cores[i];
2468119eaa9dSCédric Le Goater CPUCore *cc = CPU_CORE(pc);
2469119eaa9dSCédric Le Goater
2470119eaa9dSCédric Le Goater for (j = 0; j < cc->nr_threads; j++) {
2471119eaa9dSCédric Le Goater if (ppc_cpu_pir(pc->threads[j]) == pir) {
2472119eaa9dSCédric Le Goater return pc->threads[j];
2473119eaa9dSCédric Le Goater }
2474119eaa9dSCédric Le Goater }
2475119eaa9dSCédric Le Goater }
2476119eaa9dSCédric Le Goater return NULL;
2477119eaa9dSCédric Le Goater }
2478119eaa9dSCédric Le Goater
pnv_chip_foreach_cpu(PnvChip * chip,void (* fn)(PnvChip * chip,PowerPCCPU * cpu,void * opaque),void * opaque)247980ce0d58SCédric Le Goater static void pnv_chip_foreach_cpu(PnvChip *chip,
248080ce0d58SCédric Le Goater void (*fn)(PnvChip *chip, PowerPCCPU *cpu, void *opaque),
248180ce0d58SCédric Le Goater void *opaque)
248280ce0d58SCédric Le Goater {
248380ce0d58SCédric Le Goater int i, j;
248480ce0d58SCédric Le Goater
248580ce0d58SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) {
248680ce0d58SCédric Le Goater PnvCore *pc = chip->cores[i];
248780ce0d58SCédric Le Goater
248880ce0d58SCédric Le Goater for (j = 0; j < CPU_CORE(pc)->nr_threads; j++) {
248980ce0d58SCédric Le Goater fn(chip, pc->threads[j], opaque);
249080ce0d58SCédric Le Goater }
249180ce0d58SCédric Le Goater }
249280ce0d58SCédric Le Goater }
249380ce0d58SCédric Le Goater
pnv_ics_get(XICSFabric * xi,int irq)249454f59d78SCédric Le Goater static ICSState *pnv_ics_get(XICSFabric *xi, int irq)
249554f59d78SCédric Le Goater {
2496b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(xi);
2497da6be501SDaniel Henrique Barboza int i, j;
249854f59d78SCédric Le Goater
249954f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) {
250077864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
250177864267SCédric Le Goater
250277864267SCédric Le Goater if (ics_valid_irq(&chip8->psi.ics, irq)) {
250377864267SCédric Le Goater return &chip8->psi.ics;
250454f59d78SCédric Le Goater }
25052ff73ddaSCédric Le Goater
2506da6be501SDaniel Henrique Barboza for (j = 0; j < chip8->num_phbs; j++) {
25070d512c71SDaniel Henrique Barboza PnvPHB *phb = chip8->phbs[j];
25081f5d6b2aSDaniel Henrique Barboza PnvPHB3 *phb3 = PNV_PHB3(phb->backend);
2509da6be501SDaniel Henrique Barboza
2510da6be501SDaniel Henrique Barboza if (ics_valid_irq(&phb3->lsis, irq)) {
2511da6be501SDaniel Henrique Barboza return &phb3->lsis;
2512da6be501SDaniel Henrique Barboza }
2513da6be501SDaniel Henrique Barboza
2514da6be501SDaniel Henrique Barboza if (ics_valid_irq(ICS(&phb3->msis), irq)) {
2515da6be501SDaniel Henrique Barboza return ICS(&phb3->msis);
2516da6be501SDaniel Henrique Barboza }
25179ae1329eSCédric Le Goater }
251854f59d78SCédric Le Goater }
251954f59d78SCédric Le Goater return NULL;
252054f59d78SCédric Le Goater }
252154f59d78SCédric Le Goater
pnv_get_chip(PnvMachineState * pnv,uint32_t chip_id)25221f6a88ffSCédric Le Goater PnvChip *pnv_get_chip(PnvMachineState *pnv, uint32_t chip_id)
25231f6a88ffSCédric Le Goater {
25241f6a88ffSCédric Le Goater int i;
25251f6a88ffSCédric Le Goater
25261f6a88ffSCédric Le Goater for (i = 0; i < pnv->num_chips; i++) {
25271f6a88ffSCédric Le Goater PnvChip *chip = pnv->chips[i];
25281f6a88ffSCédric Le Goater if (chip->chip_id == chip_id) {
25291f6a88ffSCédric Le Goater return chip;
25301f6a88ffSCédric Le Goater }
25311f6a88ffSCédric Le Goater }
25321f6a88ffSCédric Le Goater return NULL;
25331f6a88ffSCédric Le Goater }
25341f6a88ffSCédric Le Goater
pnv_ics_resend(XICSFabric * xi)253554f59d78SCédric Le Goater static void pnv_ics_resend(XICSFabric *xi)
253654f59d78SCédric Le Goater {
2537b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(xi);
2538ca459489SDaniel Henrique Barboza int i, j;
253954f59d78SCédric Le Goater
254054f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) {
254177864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
25429ae1329eSCédric Le Goater
254377864267SCédric Le Goater ics_resend(&chip8->psi.ics);
2544ca459489SDaniel Henrique Barboza
2545ca459489SDaniel Henrique Barboza for (j = 0; j < chip8->num_phbs; j++) {
25460d512c71SDaniel Henrique Barboza PnvPHB *phb = chip8->phbs[j];
25471f5d6b2aSDaniel Henrique Barboza PnvPHB3 *phb3 = PNV_PHB3(phb->backend);
2548ca459489SDaniel Henrique Barboza
2549ca459489SDaniel Henrique Barboza ics_resend(&phb3->lsis);
2550ca459489SDaniel Henrique Barboza ics_resend(ICS(&phb3->msis));
2551ca459489SDaniel Henrique Barboza }
255254f59d78SCédric Le Goater }
255354f59d78SCédric Le Goater }
255454f59d78SCédric Le Goater
pnv_icp_get(XICSFabric * xi,int pir)255536fc6f08SCédric Le Goater static ICPState *pnv_icp_get(XICSFabric *xi, int pir)
255636fc6f08SCédric Le Goater {
255736fc6f08SCédric Le Goater PowerPCCPU *cpu = ppc_get_vcpu_by_pir(pir);
255836fc6f08SCédric Le Goater
2559956b8f46SCédric Le Goater return cpu ? ICP(pnv_cpu_state(cpu)->intc) : NULL;
256036fc6f08SCédric Le Goater }
256136fc6f08SCédric Le Goater
pnv_pic_intc_print_info(PnvChip * chip,PowerPCCPU * cpu,void * opaque)256280ce0d58SCédric Le Goater static void pnv_pic_intc_print_info(PnvChip *chip, PowerPCCPU *cpu,
256380ce0d58SCédric Le Goater void *opaque)
256480ce0d58SCédric Le Goater {
256580ce0d58SCédric Le Goater PNV_CHIP_GET_CLASS(chip)->intc_print_info(chip, cpu, opaque);
256680ce0d58SCédric Le Goater }
256780ce0d58SCédric Le Goater
pnv_pic_print_info(InterruptStatsProvider * obj,GString * buf)2568b2580720SPhilippe Mathieu-Daudé static void pnv_pic_print_info(InterruptStatsProvider *obj, GString *buf)
256947fea43aSCédric Le Goater {
2570b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(obj);
257154f59d78SCédric Le Goater int i;
257254f59d78SCédric Le Goater
257354f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) {
257480ce0d58SCédric Le Goater PnvChip *chip = pnv->chips[i];
257580ce0d58SCédric Le Goater
257680ce0d58SCédric Le Goater /* First CPU presenters */
257780ce0d58SCédric Le Goater pnv_chip_foreach_cpu(chip, pnv_pic_intc_print_info, buf);
257880ce0d58SCédric Le Goater
257980ce0d58SCédric Le Goater /* Then other devices, PHB, PSI, XIVE */
258080ce0d58SCédric Le Goater PNV_CHIP_GET_CLASS(chip)->pic_print_info(chip, buf);
258154f59d78SCédric Le Goater }
258247fea43aSCédric Le Goater }
258347fea43aSCédric Le Goater
pnv_match_nvt(XiveFabric * xfb,uint8_t format,uint8_t nvt_blk,uint32_t nvt_idx,bool cam_ignore,uint8_t priority,uint32_t logic_serv,XiveTCTXMatch * match)2584c722579eSCédric Le Goater static int pnv_match_nvt(XiveFabric *xfb, uint8_t format,
2585c722579eSCédric Le Goater uint8_t nvt_blk, uint32_t nvt_idx,
2586c722579eSCédric Le Goater bool cam_ignore, uint8_t priority,
2587c722579eSCédric Le Goater uint32_t logic_serv,
2588c722579eSCédric Le Goater XiveTCTXMatch *match)
2589c722579eSCédric Le Goater {
2590c722579eSCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(xfb);
2591c722579eSCédric Le Goater int total_count = 0;
2592c722579eSCédric Le Goater int i;
2593c722579eSCédric Le Goater
2594c722579eSCédric Le Goater for (i = 0; i < pnv->num_chips; i++) {
2595c722579eSCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(pnv->chips[i]);
2596c722579eSCédric Le Goater XivePresenter *xptr = XIVE_PRESENTER(&chip9->xive);
2597c722579eSCédric Le Goater XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr);
2598c722579eSCédric Le Goater int count;
2599c722579eSCédric Le Goater
2600c722579eSCédric Le Goater count = xpc->match_nvt(xptr, format, nvt_blk, nvt_idx, cam_ignore,
2601c722579eSCédric Le Goater priority, logic_serv, match);
2602c722579eSCédric Le Goater
2603c722579eSCédric Le Goater if (count < 0) {
2604c722579eSCédric Le Goater return count;
2605c722579eSCédric Le Goater }
2606c722579eSCédric Le Goater
2607c722579eSCédric Le Goater total_count += count;
2608c722579eSCédric Le Goater }
2609c722579eSCédric Le Goater
2610c722579eSCédric Le Goater return total_count;
2611c722579eSCédric Le Goater }
2612c722579eSCédric Le Goater
pnv10_xive_match_nvt(XiveFabric * xfb,uint8_t format,uint8_t nvt_blk,uint32_t nvt_idx,bool cam_ignore,uint8_t priority,uint32_t logic_serv,XiveTCTXMatch * match)2613da71b7e3SCédric Le Goater static int pnv10_xive_match_nvt(XiveFabric *xfb, uint8_t format,
2614da71b7e3SCédric Le Goater uint8_t nvt_blk, uint32_t nvt_idx,
2615da71b7e3SCédric Le Goater bool cam_ignore, uint8_t priority,
2616da71b7e3SCédric Le Goater uint32_t logic_serv,
2617da71b7e3SCédric Le Goater XiveTCTXMatch *match)
2618da71b7e3SCédric Le Goater {
2619da71b7e3SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(xfb);
2620da71b7e3SCédric Le Goater int total_count = 0;
2621da71b7e3SCédric Le Goater int i;
2622da71b7e3SCédric Le Goater
2623da71b7e3SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) {
2624da71b7e3SCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(pnv->chips[i]);
2625da71b7e3SCédric Le Goater XivePresenter *xptr = XIVE_PRESENTER(&chip10->xive);
2626da71b7e3SCédric Le Goater XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr);
2627da71b7e3SCédric Le Goater int count;
2628da71b7e3SCédric Le Goater
2629da71b7e3SCédric Le Goater count = xpc->match_nvt(xptr, format, nvt_blk, nvt_idx, cam_ignore,
2630da71b7e3SCédric Le Goater priority, logic_serv, match);
2631da71b7e3SCédric Le Goater
2632da71b7e3SCédric Le Goater if (count < 0) {
2633da71b7e3SCédric Le Goater return count;
2634da71b7e3SCédric Le Goater }
2635da71b7e3SCédric Le Goater
2636da71b7e3SCédric Le Goater total_count += count;
2637da71b7e3SCédric Le Goater }
2638da71b7e3SCédric Le Goater
2639da71b7e3SCédric Le Goater return total_count;
2640da71b7e3SCédric Le Goater }
2641da71b7e3SCédric Le Goater
pnv_machine_get_big_core(Object * obj,Error ** errp)2642b1beb692SNicholas Piggin static bool pnv_machine_get_big_core(Object *obj, Error **errp)
2643b1beb692SNicholas Piggin {
2644b1beb692SNicholas Piggin PnvMachineState *pnv = PNV_MACHINE(obj);
2645b1beb692SNicholas Piggin return pnv->big_core;
2646b1beb692SNicholas Piggin }
2647b1beb692SNicholas Piggin
pnv_machine_set_big_core(Object * obj,bool value,Error ** errp)2648b1beb692SNicholas Piggin static void pnv_machine_set_big_core(Object *obj, bool value, Error **errp)
2649b1beb692SNicholas Piggin {
2650b1beb692SNicholas Piggin PnvMachineState *pnv = PNV_MACHINE(obj);
2651b1beb692SNicholas Piggin pnv->big_core = value;
2652b1beb692SNicholas Piggin }
2653b1beb692SNicholas Piggin
pnv_machine_get_lpar_per_core(Object * obj,Error ** errp)26543b5ea01eSNicholas Piggin static bool pnv_machine_get_lpar_per_core(Object *obj, Error **errp)
26553b5ea01eSNicholas Piggin {
26563b5ea01eSNicholas Piggin PnvMachineState *pnv = PNV_MACHINE(obj);
26573b5ea01eSNicholas Piggin return pnv->lpar_per_core;
26583b5ea01eSNicholas Piggin }
26593b5ea01eSNicholas Piggin
pnv_machine_set_lpar_per_core(Object * obj,bool value,Error ** errp)26603b5ea01eSNicholas Piggin static void pnv_machine_set_lpar_per_core(Object *obj, bool value, Error **errp)
26613b5ea01eSNicholas Piggin {
26623b5ea01eSNicholas Piggin PnvMachineState *pnv = PNV_MACHINE(obj);
26633b5ea01eSNicholas Piggin pnv->lpar_per_core = value;
26643b5ea01eSNicholas Piggin }
26653b5ea01eSNicholas Piggin
pnv_machine_get_hb(Object * obj,Error ** errp)2666b1beb692SNicholas Piggin static bool pnv_machine_get_hb(Object *obj, Error **errp)
2667b1beb692SNicholas Piggin {
2668b1beb692SNicholas Piggin PnvMachineState *pnv = PNV_MACHINE(obj);
2669b1beb692SNicholas Piggin
2670b1beb692SNicholas Piggin return !!pnv->fw_load_addr;
2671b1beb692SNicholas Piggin }
2672b1beb692SNicholas Piggin
pnv_machine_set_hb(Object * obj,bool value,Error ** errp)2673b1beb692SNicholas Piggin static void pnv_machine_set_hb(Object *obj, bool value, Error **errp)
2674b1beb692SNicholas Piggin {
2675b1beb692SNicholas Piggin PnvMachineState *pnv = PNV_MACHINE(obj);
2676b1beb692SNicholas Piggin
2677b1beb692SNicholas Piggin if (value) {
2678b1beb692SNicholas Piggin pnv->fw_load_addr = 0x8000000;
2679b1beb692SNicholas Piggin }
2680b1beb692SNicholas Piggin }
2681b1beb692SNicholas Piggin
pnv_machine_power8_class_init(ObjectClass * oc,void * data)2682f30c843cSCédric Le Goater static void pnv_machine_power8_class_init(ObjectClass *oc, void *data)
26839e933f4aSBenjamin Herrenschmidt {
26849e933f4aSBenjamin Herrenschmidt MachineClass *mc = MACHINE_CLASS(oc);
268536fc6f08SCédric Le Goater XICSFabricClass *xic = XICS_FABRIC_CLASS(oc);
2686d76f2da7SGreg Kurz PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc);
2687d76f2da7SGreg Kurz static const char compat[] = "qemu,powernv8\0qemu,powernv\0ibm,powernv";
2688f30c843cSCédric Le Goater
26891f5d6b2aSDaniel Henrique Barboza static GlobalProperty phb_compat[] = {
26901f5d6b2aSDaniel Henrique Barboza { TYPE_PNV_PHB, "version", "3" },
269180515061SDaniel Henrique Barboza { TYPE_PNV_PHB_ROOT_PORT, "version", "3" },
26921f5d6b2aSDaniel Henrique Barboza };
26931f5d6b2aSDaniel Henrique Barboza
2694f30c843cSCédric Le Goater mc->desc = "IBM PowerNV (Non-Virtualized) POWER8";
2695f30c843cSCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0");
26961f5d6b2aSDaniel Henrique Barboza compat_props_add(mc->compat_props, phb_compat, G_N_ELEMENTS(phb_compat));
2697f30c843cSCédric Le Goater
2698f30c843cSCédric Le Goater xic->icp_get = pnv_icp_get;
2699f30c843cSCédric Le Goater xic->ics_get = pnv_ics_get;
2700f30c843cSCédric Le Goater xic->ics_resend = pnv_ics_resend;
2701d76f2da7SGreg Kurz
2702d76f2da7SGreg Kurz pmc->compat = compat;
2703d76f2da7SGreg Kurz pmc->compat_size = sizeof(compat);
2704d76cb5a5SNicholas Piggin pmc->max_smt_threads = 8;
27053b5ea01eSNicholas Piggin /* POWER8 is always lpar-per-core mode */
27063b5ea01eSNicholas Piggin pmc->has_lpar_per_thread = false;
2707892c3ad0SDaniel Henrique Barboza
2708892c3ad0SDaniel Henrique Barboza machine_class_allow_dynamic_sysbus_dev(mc, TYPE_PNV_PHB);
2709f30c843cSCédric Le Goater }
2710f30c843cSCédric Le Goater
pnv_machine_power9_class_init(ObjectClass * oc,void * data)2711f30c843cSCédric Le Goater static void pnv_machine_power9_class_init(ObjectClass *oc, void *data)
2712f30c843cSCédric Le Goater {
2713f30c843cSCédric Le Goater MachineClass *mc = MACHINE_CLASS(oc);
2714c722579eSCédric Le Goater XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc);
2715d76f2da7SGreg Kurz PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc);
2716d76f2da7SGreg Kurz static const char compat[] = "qemu,powernv9\0ibm,powernv";
2717f30c843cSCédric Le Goater
2718210aacb3SDaniel Henrique Barboza static GlobalProperty phb_compat[] = {
2719210aacb3SDaniel Henrique Barboza { TYPE_PNV_PHB, "version", "4" },
2720c8d14603SDaniel Henrique Barboza { TYPE_PNV_PHB_ROOT_PORT, "version", "4" },
2721210aacb3SDaniel Henrique Barboza };
2722210aacb3SDaniel Henrique Barboza
2723f30c843cSCédric Le Goater mc->desc = "IBM PowerNV (Non-Virtualized) POWER9";
2724277ee172SNicholas Piggin mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.2");
2725210aacb3SDaniel Henrique Barboza compat_props_add(mc->compat_props, phb_compat, G_N_ELEMENTS(phb_compat));
2726210aacb3SDaniel Henrique Barboza
2727c722579eSCédric Le Goater xfc->match_nvt = pnv_match_nvt;
2728f30c843cSCédric Le Goater
2729d76f2da7SGreg Kurz pmc->compat = compat;
2730d76f2da7SGreg Kurz pmc->compat_size = sizeof(compat);
2731d76cb5a5SNicholas Piggin pmc->max_smt_threads = 4;
27323b5ea01eSNicholas Piggin pmc->has_lpar_per_thread = true;
27337a90c6a1SGreg Kurz pmc->dt_power_mgt = pnv_dt_power_mgt;
2734d786be3fSDaniel Henrique Barboza
2735d786be3fSDaniel Henrique Barboza machine_class_allow_dynamic_sysbus_dev(mc, TYPE_PNV_PHB);
2736b1beb692SNicholas Piggin
2737b1beb692SNicholas Piggin object_class_property_add_bool(oc, "big-core",
2738b1beb692SNicholas Piggin pnv_machine_get_big_core,
2739b1beb692SNicholas Piggin pnv_machine_set_big_core);
2740b1beb692SNicholas Piggin object_class_property_set_description(oc, "big-core",
2741b1beb692SNicholas Piggin "Use big-core (aka fused-core) mode");
27423b5ea01eSNicholas Piggin
27433b5ea01eSNicholas Piggin object_class_property_add_bool(oc, "lpar-per-core",
27443b5ea01eSNicholas Piggin pnv_machine_get_lpar_per_core,
27453b5ea01eSNicholas Piggin pnv_machine_set_lpar_per_core);
27463b5ea01eSNicholas Piggin object_class_property_set_description(oc, "lpar-per-core",
27473b5ea01eSNicholas Piggin "Use 1 LPAR per core mode");
2748f30c843cSCédric Le Goater }
2749f30c843cSCédric Le Goater
pnv_machine_p10_common_class_init(ObjectClass * oc,void * data)2750ab874668SGlenn Miles static void pnv_machine_p10_common_class_init(ObjectClass *oc, void *data)
27512b548a42SCédric Le Goater {
27522b548a42SCédric Le Goater MachineClass *mc = MACHINE_CLASS(oc);
2753d76f2da7SGreg Kurz PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc);
2754da71b7e3SCédric Le Goater XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc);
2755d76f2da7SGreg Kurz static const char compat[] = "qemu,powernv10\0ibm,powernv";
27562b548a42SCédric Le Goater
2757210aacb3SDaniel Henrique Barboza static GlobalProperty phb_compat[] = {
2758210aacb3SDaniel Henrique Barboza { TYPE_PNV_PHB, "version", "5" },
2759c8d14603SDaniel Henrique Barboza { TYPE_PNV_PHB_ROOT_PORT, "version", "5" },
2760210aacb3SDaniel Henrique Barboza };
2761210aacb3SDaniel Henrique Barboza
27626bc8c046SCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power10_v2.0");
2763210aacb3SDaniel Henrique Barboza compat_props_add(mc->compat_props, phb_compat, G_N_ELEMENTS(phb_compat));
2764d76f2da7SGreg Kurz
276521465adeSNicholas Piggin mc->alias = "powernv";
276621465adeSNicholas Piggin
2767d76f2da7SGreg Kurz pmc->compat = compat;
2768d76f2da7SGreg Kurz pmc->compat_size = sizeof(compat);
2769d76cb5a5SNicholas Piggin pmc->max_smt_threads = 4;
27703b5ea01eSNicholas Piggin pmc->has_lpar_per_thread = true;
277178be3218SNicholas Piggin pmc->quirk_tb_big_core = true;
27727a90c6a1SGreg Kurz pmc->dt_power_mgt = pnv_dt_power_mgt;
2773da71b7e3SCédric Le Goater
2774da71b7e3SCédric Le Goater xfc->match_nvt = pnv10_xive_match_nvt;
2775f1327fdeSDaniel Henrique Barboza
2776f1327fdeSDaniel Henrique Barboza machine_class_allow_dynamic_sysbus_dev(mc, TYPE_PNV_PHB);
27772b548a42SCédric Le Goater }
27782b548a42SCédric Le Goater
pnv_machine_power10_class_init(ObjectClass * oc,void * data)2779ab874668SGlenn Miles static void pnv_machine_power10_class_init(ObjectClass *oc, void *data)
2780ab874668SGlenn Miles {
2781ab874668SGlenn Miles MachineClass *mc = MACHINE_CLASS(oc);
2782ab874668SGlenn Miles
2783ab874668SGlenn Miles pnv_machine_p10_common_class_init(oc, data);
2784ab874668SGlenn Miles mc->desc = "IBM PowerNV (Non-Virtualized) POWER10";
2785b1beb692SNicholas Piggin
2786b1beb692SNicholas Piggin /*
2787b1beb692SNicholas Piggin * This is the parent of POWER10 Rainier class, so properies go here
2788b1beb692SNicholas Piggin * rather than common init (which would add them to both parent and
2789b1beb692SNicholas Piggin * child which is invalid).
2790b1beb692SNicholas Piggin */
2791b1beb692SNicholas Piggin object_class_property_add_bool(oc, "big-core",
2792b1beb692SNicholas Piggin pnv_machine_get_big_core,
2793b1beb692SNicholas Piggin pnv_machine_set_big_core);
2794b1beb692SNicholas Piggin object_class_property_set_description(oc, "big-core",
2795b1beb692SNicholas Piggin "Use big-core (aka fused-core) mode");
27963b5ea01eSNicholas Piggin
27973b5ea01eSNicholas Piggin object_class_property_add_bool(oc, "lpar-per-core",
27983b5ea01eSNicholas Piggin pnv_machine_get_lpar_per_core,
27993b5ea01eSNicholas Piggin pnv_machine_set_lpar_per_core);
28003b5ea01eSNicholas Piggin object_class_property_set_description(oc, "lpar-per-core",
28013b5ea01eSNicholas Piggin "Use 1 LPAR per core mode");
2802ab874668SGlenn Miles }
2803ab874668SGlenn Miles
pnv_machine_p10_rainier_class_init(ObjectClass * oc,void * data)2804ab874668SGlenn Miles static void pnv_machine_p10_rainier_class_init(ObjectClass *oc, void *data)
2805ab874668SGlenn Miles {
2806ab874668SGlenn Miles MachineClass *mc = MACHINE_CLASS(oc);
280733467ecbSGlenn Miles PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc);
2808ab874668SGlenn Miles
2809ab874668SGlenn Miles pnv_machine_p10_common_class_init(oc, data);
2810ab874668SGlenn Miles mc->desc = "IBM PowerNV (Non-Virtualized) POWER10 Rainier";
281133467ecbSGlenn Miles pmc->i2c_init = pnv_rainier_i2c_init;
2812ab874668SGlenn Miles }
2813ab874668SGlenn Miles
pnv_cpu_do_nmi_on_cpu(CPUState * cs,run_on_cpu_data arg)281401b552b0SNicholas Piggin static void pnv_cpu_do_nmi_on_cpu(CPUState *cs, run_on_cpu_data arg)
281501b552b0SNicholas Piggin {
2816794511bcSPhilippe Mathieu-Daudé CPUPPCState *env = cpu_env(cs);
281701b552b0SNicholas Piggin
281801b552b0SNicholas Piggin cpu_synchronize_state(cs);
281901b552b0SNicholas Piggin ppc_cpu_do_system_reset(cs);
28200911a60cSLeonardo Bras if (env->spr[SPR_SRR1] & SRR1_WAKESTATE) {
282101b552b0SNicholas Piggin /*
2822fe837714SNicholas Piggin * Power-save wakeups, as indicated by non-zero SRR1[46:47] put the
2823fe837714SNicholas Piggin * wakeup reason in SRR1[42:45], system reset is indicated with 0b0100
2824fe837714SNicholas Piggin * (PPC_BIT(43)).
282501b552b0SNicholas Piggin */
28260911a60cSLeonardo Bras if (!(env->spr[SPR_SRR1] & SRR1_WAKERESET)) {
2827fe837714SNicholas Piggin warn_report("ppc_cpu_do_system_reset does not set system reset wakeup reason");
28280911a60cSLeonardo Bras env->spr[SPR_SRR1] |= SRR1_WAKERESET;
282901b552b0SNicholas Piggin }
2830fe837714SNicholas Piggin } else {
2831fe837714SNicholas Piggin /*
2832fe837714SNicholas Piggin * For non-powersave system resets, SRR1[42:45] are defined to be
2833fe837714SNicholas Piggin * implementation-dependent. The POWER9 User Manual specifies that
2834fe837714SNicholas Piggin * an external (SCOM driven, which may come from a BMC nmi command or
2835fe837714SNicholas Piggin * another CPU requesting a NMI IPI) system reset exception should be
2836fe837714SNicholas Piggin * 0b0010 (PPC_BIT(44)).
2837fe837714SNicholas Piggin */
28380911a60cSLeonardo Bras env->spr[SPR_SRR1] |= SRR1_WAKESCOM;
2839fe837714SNicholas Piggin }
2840ca4f4775SNicholas Piggin if (arg.host_int == 1) {
2841ca4f4775SNicholas Piggin cpu_resume(cs);
2842ca4f4775SNicholas Piggin }
2843ca4f4775SNicholas Piggin }
2844ca4f4775SNicholas Piggin
2845ca4f4775SNicholas Piggin /*
2846ca4f4775SNicholas Piggin * Send a SRESET (NMI) interrupt to the CPU, and resume execution if it was
2847ca4f4775SNicholas Piggin * paused.
2848ca4f4775SNicholas Piggin */
pnv_cpu_do_nmi_resume(CPUState * cs)2849ca4f4775SNicholas Piggin void pnv_cpu_do_nmi_resume(CPUState *cs)
2850ca4f4775SNicholas Piggin {
2851ca4f4775SNicholas Piggin async_run_on_cpu(cs, pnv_cpu_do_nmi_on_cpu, RUN_ON_CPU_HOST_INT(1));
2852fe837714SNicholas Piggin }
285301b552b0SNicholas Piggin
pnv_cpu_do_nmi(PnvChip * chip,PowerPCCPU * cpu,void * opaque)285480ce0d58SCédric Le Goater static void pnv_cpu_do_nmi(PnvChip *chip, PowerPCCPU *cpu, void *opaque)
285580ce0d58SCédric Le Goater {
2856ca4f4775SNicholas Piggin async_run_on_cpu(CPU(cpu), pnv_cpu_do_nmi_on_cpu, RUN_ON_CPU_HOST_INT(0));
285780ce0d58SCédric Le Goater }
285880ce0d58SCédric Le Goater
pnv_nmi(NMIState * n,int cpu_index,Error ** errp)285901b552b0SNicholas Piggin static void pnv_nmi(NMIState *n, int cpu_index, Error **errp)
286001b552b0SNicholas Piggin {
286180ce0d58SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine());
286280ce0d58SCédric Le Goater int i;
286301b552b0SNicholas Piggin
286480ce0d58SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) {
286580ce0d58SCédric Le Goater pnv_chip_foreach_cpu(pnv->chips[i], pnv_cpu_do_nmi, NULL);
286601b552b0SNicholas Piggin }
286701b552b0SNicholas Piggin }
286801b552b0SNicholas Piggin
pnv_machine_class_init(ObjectClass * oc,void * data)2869f30c843cSCédric Le Goater static void pnv_machine_class_init(ObjectClass *oc, void *data)
2870f30c843cSCédric Le Goater {
2871f30c843cSCédric Le Goater MachineClass *mc = MACHINE_CLASS(oc);
287247fea43aSCédric Le Goater InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc);
287301b552b0SNicholas Piggin NMIClass *nc = NMI_CLASS(oc);
28749e933f4aSBenjamin Herrenschmidt
28759e933f4aSBenjamin Herrenschmidt mc->desc = "IBM PowerNV (Non-Virtualized)";
2876b168a138SCédric Le Goater mc->init = pnv_init;
2877b168a138SCédric Le Goater mc->reset = pnv_reset;
28789e933f4aSBenjamin Herrenschmidt mc->max_cpus = MAX_CPUS;
287959b7c1c2SBalamuruhan S /* Pnv provides a AHCI device for storage */
288059b7c1c2SBalamuruhan S mc->block_default_type = IF_IDE;
28819e933f4aSBenjamin Herrenschmidt mc->no_parallel = 1;
28829e933f4aSBenjamin Herrenschmidt mc->default_boot_order = NULL;
2883f1d18b0aSJoel Stanley /*
2884f1d18b0aSJoel Stanley * RAM defaults to less than 2048 for 32-bit hosts, and large
2885f1d18b0aSJoel Stanley * enough to fit the maximum initrd size at it's load address
2886f1d18b0aSJoel Stanley */
2887dd7ef911SCédric Le Goater mc->default_ram_size = 1 * GiB;
2888173a36d8SIgor Mammedov mc->default_ram_id = "pnv.ram";
288947fea43aSCédric Le Goater ispc->print_info = pnv_pic_print_info;
289001b552b0SNicholas Piggin nc->nmi_monitor_handler = pnv_nmi;
289108c3f3a7SCédric Le Goater
289208c3f3a7SCédric Le Goater object_class_property_add_bool(oc, "hb-mode",
2893d2623129SMarkus Armbruster pnv_machine_get_hb, pnv_machine_set_hb);
289408c3f3a7SCédric Le Goater object_class_property_set_description(oc, "hb-mode",
28957eecec7dSMarkus Armbruster "Use a hostboot like boot loader");
28969e933f4aSBenjamin Herrenschmidt }
28979e933f4aSBenjamin Herrenschmidt
289877864267SCédric Le Goater #define DEFINE_PNV8_CHIP_TYPE(type, class_initfn) \
2899beba5c0fSIgor Mammedov { \
2900beba5c0fSIgor Mammedov .name = type, \
2901beba5c0fSIgor Mammedov .class_init = class_initfn, \
290277864267SCédric Le Goater .parent = TYPE_PNV8_CHIP, \
290377864267SCédric Le Goater }
290477864267SCédric Le Goater
290577864267SCédric Le Goater #define DEFINE_PNV9_CHIP_TYPE(type, class_initfn) \
290677864267SCédric Le Goater { \
290777864267SCédric Le Goater .name = type, \
290877864267SCédric Le Goater .class_init = class_initfn, \
290977864267SCédric Le Goater .parent = TYPE_PNV9_CHIP, \
2910beba5c0fSIgor Mammedov }
2911beba5c0fSIgor Mammedov
29122b548a42SCédric Le Goater #define DEFINE_PNV10_CHIP_TYPE(type, class_initfn) \
29132b548a42SCédric Le Goater { \
29142b548a42SCédric Le Goater .name = type, \
29152b548a42SCédric Le Goater .class_init = class_initfn, \
29162b548a42SCédric Le Goater .parent = TYPE_PNV10_CHIP, \
29172b548a42SCédric Le Goater }
29182b548a42SCédric Le Goater
2919beba5c0fSIgor Mammedov static const TypeInfo types[] = {
29201aba8716SCédric Le Goater {
2921ab874668SGlenn Miles .name = MACHINE_TYPE_NAME("powernv10-rainier"),
2922ab874668SGlenn Miles .parent = MACHINE_TYPE_NAME("powernv10"),
2923ab874668SGlenn Miles .class_init = pnv_machine_p10_rainier_class_init,
2924ab874668SGlenn Miles },
2925ab874668SGlenn Miles {
29262b548a42SCédric Le Goater .name = MACHINE_TYPE_NAME("powernv10"),
29272b548a42SCédric Le Goater .parent = TYPE_PNV_MACHINE,
29282b548a42SCédric Le Goater .class_init = pnv_machine_power10_class_init,
2929da71b7e3SCédric Le Goater .interfaces = (InterfaceInfo[]) {
2930da71b7e3SCédric Le Goater { TYPE_XIVE_FABRIC },
2931da71b7e3SCédric Le Goater { },
2932da71b7e3SCédric Le Goater },
29332b548a42SCédric Le Goater },
29342b548a42SCédric Le Goater {
29351aba8716SCédric Le Goater .name = MACHINE_TYPE_NAME("powernv9"),
29361aba8716SCédric Le Goater .parent = TYPE_PNV_MACHINE,
29371aba8716SCédric Le Goater .class_init = pnv_machine_power9_class_init,
2938c722579eSCédric Le Goater .interfaces = (InterfaceInfo[]) {
2939c722579eSCédric Le Goater { TYPE_XIVE_FABRIC },
2940c722579eSCédric Le Goater { },
2941c722579eSCédric Le Goater },
29421aba8716SCédric Le Goater },
29431aba8716SCédric Le Goater {
29441aba8716SCédric Le Goater .name = MACHINE_TYPE_NAME("powernv8"),
29451aba8716SCédric Le Goater .parent = TYPE_PNV_MACHINE,
29461aba8716SCédric Le Goater .class_init = pnv_machine_power8_class_init,
29471aba8716SCédric Le Goater .interfaces = (InterfaceInfo[]) {
29481aba8716SCédric Le Goater { TYPE_XICS_FABRIC },
29491aba8716SCédric Le Goater { },
29501aba8716SCédric Le Goater },
29511aba8716SCédric Le Goater },
2952beba5c0fSIgor Mammedov {
2953b168a138SCédric Le Goater .name = TYPE_PNV_MACHINE,
29549e933f4aSBenjamin Herrenschmidt .parent = TYPE_MACHINE,
2955f30c843cSCédric Le Goater .abstract = true,
29569e933f4aSBenjamin Herrenschmidt .instance_size = sizeof(PnvMachineState),
2957b168a138SCédric Le Goater .class_init = pnv_machine_class_init,
2958d76f2da7SGreg Kurz .class_size = sizeof(PnvMachineClass),
295936fc6f08SCédric Le Goater .interfaces = (InterfaceInfo[]) {
296047fea43aSCédric Le Goater { TYPE_INTERRUPT_STATS_PROVIDER },
296101b552b0SNicholas Piggin { TYPE_NMI },
296236fc6f08SCédric Le Goater { },
296336fc6f08SCédric Le Goater },
2964beba5c0fSIgor Mammedov },
2965beba5c0fSIgor Mammedov {
2966beba5c0fSIgor Mammedov .name = TYPE_PNV_CHIP,
2967beba5c0fSIgor Mammedov .parent = TYPE_SYS_BUS_DEVICE,
2968beba5c0fSIgor Mammedov .class_init = pnv_chip_class_init,
2969beba5c0fSIgor Mammedov .instance_size = sizeof(PnvChip),
2970beba5c0fSIgor Mammedov .class_size = sizeof(PnvChipClass),
2971beba5c0fSIgor Mammedov .abstract = true,
2972beba5c0fSIgor Mammedov },
297377864267SCédric Le Goater
297477864267SCédric Le Goater /*
29752b548a42SCédric Le Goater * P10 chip and variants
29762b548a42SCédric Le Goater */
29772b548a42SCédric Le Goater {
29782b548a42SCédric Le Goater .name = TYPE_PNV10_CHIP,
29792b548a42SCédric Le Goater .parent = TYPE_PNV_CHIP,
29802b548a42SCédric Le Goater .instance_init = pnv_chip_power10_instance_init,
29812b548a42SCédric Le Goater .instance_size = sizeof(Pnv10Chip),
29822b548a42SCédric Le Goater },
29832b548a42SCédric Le Goater DEFINE_PNV10_CHIP_TYPE(TYPE_PNV_CHIP_POWER10, pnv_chip_power10_class_init),
29842b548a42SCédric Le Goater
29852b548a42SCédric Le Goater /*
298677864267SCédric Le Goater * P9 chip and variants
298777864267SCédric Le Goater */
298877864267SCédric Le Goater {
298977864267SCédric Le Goater .name = TYPE_PNV9_CHIP,
299077864267SCédric Le Goater .parent = TYPE_PNV_CHIP,
299177864267SCédric Le Goater .instance_init = pnv_chip_power9_instance_init,
299277864267SCédric Le Goater .instance_size = sizeof(Pnv9Chip),
299377864267SCédric Le Goater },
299477864267SCédric Le Goater DEFINE_PNV9_CHIP_TYPE(TYPE_PNV_CHIP_POWER9, pnv_chip_power9_class_init),
299577864267SCédric Le Goater
299677864267SCédric Le Goater /*
299777864267SCédric Le Goater * P8 chip and variants
299877864267SCédric Le Goater */
299977864267SCédric Le Goater {
300077864267SCédric Le Goater .name = TYPE_PNV8_CHIP,
300177864267SCédric Le Goater .parent = TYPE_PNV_CHIP,
300277864267SCédric Le Goater .instance_init = pnv_chip_power8_instance_init,
300377864267SCédric Le Goater .instance_size = sizeof(Pnv8Chip),
300477864267SCédric Le Goater },
300577864267SCédric Le Goater DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8, pnv_chip_power8_class_init),
300677864267SCédric Le Goater DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8E, pnv_chip_power8e_class_init),
300777864267SCédric Le Goater DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8NVL,
3008beba5c0fSIgor Mammedov pnv_chip_power8nvl_class_init),
30099e933f4aSBenjamin Herrenschmidt };
30109e933f4aSBenjamin Herrenschmidt
3011beba5c0fSIgor Mammedov DEFINE_TYPES(types)
3012