xref: /qemu/hw/ppc/pnv_xscom.c (revision 4a1babe5)
1 /*
2  * QEMU PowerPC PowerNV XSCOM bus
3  *
4  * Copyright (c) 2016, IBM Corporation.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include "qemu/osdep.h"
21 #include "qemu/log.h"
22 #include "qemu/module.h"
23 #include "sysemu/hw_accel.h"
24 #include "target/ppc/cpu.h"
25 #include "hw/sysbus.h"
26 
27 #include "hw/ppc/fdt.h"
28 #include "hw/ppc/pnv.h"
29 #include "hw/ppc/pnv_chip.h"
30 #include "hw/ppc/pnv_xscom.h"
31 
32 #include <libfdt.h>
33 
34 /* PRD registers */
35 #define PRD_P8_IPOLL_REG_MASK           0x01020013
36 #define PRD_P8_IPOLL_REG_STATUS         0x01020014
37 #define PRD_P9_IPOLL_REG_MASK           0x000F0033
38 #define PRD_P9_IPOLL_REG_STATUS         0x000F0034
39 
40 static void xscom_complete(CPUState *cs, uint64_t hmer_bits)
41 {
42     /*
43      * TODO: When the read/write comes from the monitor, NULL is
44      * passed for the cpu, and no CPU completion is generated.
45      */
46     if (cs) {
47         /*
48          * TODO: Need a CPU helper to set HMER, also handle generation
49          * of HMIs
50          */
51         cpu_synchronize_state(cs);
52         cpu_env(cs)->spr[SPR_HMER] |= hmer_bits;
53     }
54 }
55 
56 static uint32_t pnv_xscom_pcba(PnvChip *chip, uint64_t addr)
57 {
58     return PNV_CHIP_GET_CLASS(chip)->xscom_pcba(chip, addr);
59 }
60 
61 static uint64_t xscom_read_default(PnvChip *chip, uint32_t pcba)
62 {
63     switch (pcba) {
64     case 0xf000f:
65         return PNV_CHIP_GET_CLASS(chip)->chip_cfam_id;
66     case 0x18002:       /* ECID2 */
67         return 0;
68 
69     case 0x1010c00:     /* PIBAM FIR */
70     case 0x1010c03:     /* PIBAM FIR MASK */
71 
72         /* PRD registers */
73     case PRD_P8_IPOLL_REG_MASK:
74     case PRD_P8_IPOLL_REG_STATUS:
75     case PRD_P9_IPOLL_REG_MASK:
76     case PRD_P9_IPOLL_REG_STATUS:
77 
78         /* P9 xscom reset */
79     case 0x0090018:     /* Receive status reg */
80     case 0x0090012:     /* log register */
81     case 0x0090013:     /* error register */
82 
83         /* P8 xscom reset */
84     case 0x2020007:     /* ADU stuff, log register */
85     case 0x2020009:     /* ADU stuff, error register */
86     case 0x202000f:     /* ADU stuff, receive status register*/
87         return 0;
88     case 0x2013f01:     /* PBA stuff */
89     case 0x2013f05:     /* PBA stuff */
90         return 0;
91     case 0x2013028:     /* CAPP stuff */
92     case 0x201302a:     /* CAPP stuff */
93     case 0x2013801:     /* CAPP stuff */
94     case 0x2013802:     /* CAPP stuff */
95 
96         /* P9 CAPP regs */
97     case 0x2010841:
98     case 0x2010842:
99     case 0x201082a:
100     case 0x2010828:
101     case 0x4010841:
102     case 0x4010842:
103     case 0x401082a:
104     case 0x4010828:
105         return 0;
106     default:
107         return -1;
108     }
109 }
110 
111 static bool xscom_write_default(PnvChip *chip, uint32_t pcba, uint64_t val)
112 {
113     /* We ignore writes to these */
114     switch (pcba) {
115     case 0xf000f:       /* chip id is RO */
116     case 0x1010c00:     /* PIBAM FIR */
117     case 0x1010c01:     /* PIBAM FIR */
118     case 0x1010c02:     /* PIBAM FIR */
119     case 0x1010c03:     /* PIBAM FIR MASK */
120     case 0x1010c04:     /* PIBAM FIR MASK */
121     case 0x1010c05:     /* PIBAM FIR MASK */
122         /* P9 xscom reset */
123     case 0x0090018:     /* Receive status reg */
124     case 0x0090012:     /* log register */
125     case 0x0090013:     /* error register */
126 
127         /* P8 xscom reset */
128     case 0x2020007:     /* ADU stuff, log register */
129     case 0x2020009:     /* ADU stuff, error register */
130     case 0x202000f:     /* ADU stuff, receive status register*/
131 
132     case 0x2013028:     /* CAPP stuff */
133     case 0x201302a:     /* CAPP stuff */
134     case 0x2013801:     /* CAPP stuff */
135     case 0x2013802:     /* CAPP stuff */
136 
137         /* P9 CAPP regs */
138     case 0x2010841:
139     case 0x2010842:
140     case 0x201082a:
141     case 0x2010828:
142     case 0x4010841:
143     case 0x4010842:
144     case 0x401082a:
145     case 0x4010828:
146 
147         /* P8 PRD registers */
148     case PRD_P8_IPOLL_REG_MASK:
149     case PRD_P8_IPOLL_REG_STATUS:
150     case PRD_P9_IPOLL_REG_MASK:
151     case PRD_P9_IPOLL_REG_STATUS:
152         return true;
153     default:
154         return false;
155     }
156 }
157 
158 static uint64_t xscom_read(void *opaque, hwaddr addr, unsigned width)
159 {
160     PnvChip *chip = opaque;
161     uint32_t pcba = pnv_xscom_pcba(chip, addr);
162     uint64_t val = 0;
163     MemTxResult result;
164 
165     /* Handle some SCOMs here before dispatch */
166     val = xscom_read_default(chip, pcba);
167     if (val != -1) {
168         goto complete;
169     }
170 
171     val = address_space_ldq(&chip->xscom_as, (uint64_t) pcba << 3,
172                             MEMTXATTRS_UNSPECIFIED, &result);
173     if (result != MEMTX_OK) {
174         qemu_log_mask(LOG_GUEST_ERROR, "XSCOM read failed at @0x%"
175                       HWADDR_PRIx " pcba=0x%08x\n", addr, pcba);
176         xscom_complete(current_cpu, HMER_XSCOM_FAIL | HMER_XSCOM_DONE);
177         return 0;
178     }
179 
180 complete:
181     xscom_complete(current_cpu, HMER_XSCOM_DONE);
182     return val;
183 }
184 
185 static void xscom_write(void *opaque, hwaddr addr, uint64_t val,
186                         unsigned width)
187 {
188     PnvChip *chip = opaque;
189     uint32_t pcba = pnv_xscom_pcba(chip, addr);
190     MemTxResult result;
191 
192     /* Handle some SCOMs here before dispatch */
193     if (xscom_write_default(chip, pcba, val)) {
194         goto complete;
195     }
196 
197     address_space_stq(&chip->xscom_as, (uint64_t) pcba << 3, val,
198                       MEMTXATTRS_UNSPECIFIED, &result);
199     if (result != MEMTX_OK) {
200         qemu_log_mask(LOG_GUEST_ERROR, "XSCOM write failed at @0x%"
201                       HWADDR_PRIx " pcba=0x%08x data=0x%" PRIx64 "\n",
202                       addr, pcba, val);
203         xscom_complete(current_cpu, HMER_XSCOM_FAIL | HMER_XSCOM_DONE);
204         return;
205     }
206 
207 complete:
208     xscom_complete(current_cpu, HMER_XSCOM_DONE);
209 }
210 
211 const MemoryRegionOps pnv_xscom_ops = {
212     .read = xscom_read,
213     .write = xscom_write,
214     .valid.min_access_size = 8,
215     .valid.max_access_size = 8,
216     .impl.min_access_size = 8,
217     .impl.max_access_size = 8,
218     .endianness = DEVICE_BIG_ENDIAN,
219 };
220 
221 void pnv_xscom_init(PnvChip *chip, uint64_t size, hwaddr addr)
222 {
223     char *name;
224 
225     name = g_strdup_printf("xscom-%x", chip->chip_id);
226     memory_region_init_io(&chip->xscom_mmio, OBJECT(chip), &pnv_xscom_ops,
227                           chip, name, size);
228     memory_region_add_subregion(get_system_memory(), addr, &chip->xscom_mmio);
229 
230     memory_region_init(&chip->xscom, OBJECT(chip), name, size);
231     address_space_init(&chip->xscom_as, &chip->xscom, name);
232     g_free(name);
233 }
234 
235 static const TypeInfo pnv_xscom_interface_info = {
236     .name = TYPE_PNV_XSCOM_INTERFACE,
237     .parent = TYPE_INTERFACE,
238     .class_size = sizeof(PnvXScomInterfaceClass),
239 };
240 
241 static void pnv_xscom_register_types(void)
242 {
243     type_register_static(&pnv_xscom_interface_info);
244 }
245 
246 type_init(pnv_xscom_register_types)
247 
248 typedef struct ForeachPopulateArgs {
249     void *fdt;
250     int xscom_offset;
251 } ForeachPopulateArgs;
252 
253 static int xscom_dt_child(Object *child, void *opaque)
254 {
255     if (object_dynamic_cast(child, TYPE_PNV_XSCOM_INTERFACE)) {
256         ForeachPopulateArgs *args = opaque;
257         PnvXScomInterface *xd = PNV_XSCOM_INTERFACE(child);
258         PnvXScomInterfaceClass *xc = PNV_XSCOM_INTERFACE_GET_CLASS(xd);
259 
260         /*
261          * Only "realized" devices should be configured in the DT
262          */
263         if (xc->dt_xscom && DEVICE(child)->realized) {
264             _FDT((xc->dt_xscom(xd, args->fdt, args->xscom_offset)));
265         }
266     }
267     return 0;
268 }
269 
270 int pnv_dt_xscom(PnvChip *chip, void *fdt, int root_offset,
271                  uint64_t xscom_base, uint64_t xscom_size,
272                  const char *compat, int compat_size)
273 {
274     uint64_t reg[] = { xscom_base, xscom_size };
275     int xscom_offset;
276     ForeachPopulateArgs args;
277     char *name;
278 
279     name = g_strdup_printf("xscom@%" PRIx64, be64_to_cpu(reg[0]));
280     xscom_offset = fdt_add_subnode(fdt, root_offset, name);
281     _FDT(xscom_offset);
282     g_free(name);
283     _FDT((fdt_setprop_cell(fdt, xscom_offset, "ibm,chip-id", chip->chip_id)));
284     /*
285      * On P10, the xscom bus id has been deprecated and the chip id is
286      * calculated from the "Primary topology table index". See skiboot.
287      */
288     _FDT((fdt_setprop_cell(fdt, xscom_offset, "ibm,primary-topology-index",
289                            chip->chip_id)));
290     _FDT((fdt_setprop_cell(fdt, xscom_offset, "#address-cells", 1)));
291     _FDT((fdt_setprop_cell(fdt, xscom_offset, "#size-cells", 1)));
292     _FDT((fdt_setprop(fdt, xscom_offset, "reg", reg, sizeof(reg))));
293     _FDT((fdt_setprop(fdt, xscom_offset, "compatible", compat, compat_size)));
294     _FDT((fdt_setprop(fdt, xscom_offset, "scom-controller", NULL, 0)));
295     if (chip->chip_id == 0) {
296         _FDT((fdt_setprop(fdt, xscom_offset, "primary", NULL, 0)));
297     }
298 
299     args.fdt = fdt;
300     args.xscom_offset = xscom_offset;
301 
302     /*
303      * Loop on the whole object hierarchy to catch all
304      * PnvXScomInterface objects which can lie a bit deeper than the
305      * first layer.
306      */
307     object_child_foreach_recursive(OBJECT(chip), xscom_dt_child, &args);
308     return 0;
309 }
310 
311 void pnv_xscom_add_subregion(PnvChip *chip, hwaddr offset, MemoryRegion *mr)
312 {
313     memory_region_add_subregion(&chip->xscom, offset << 3, mr);
314 }
315 
316 void pnv_xscom_region_init(MemoryRegion *mr,
317                            Object *owner,
318                            const MemoryRegionOps *ops,
319                            void *opaque,
320                            const char *name,
321                            uint64_t size)
322 {
323     memory_region_init_io(mr, owner, ops, opaque, name, size << 3);
324 }
325