2 * QEMU PowerPC PowerNV Emulation of a few OCC related registers
4 * Copyright (c) 2015-2017, IBM Corporation.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License, version 2, as
8 * published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, see <http://www.gnu.org/licenses/>.
19 #include "qemu/osdep.h"
21 #include "sysemu/sysemu.h"
22 #include "target/ppc/cpu.h"
23 #include "qapi/error.h"
26 #include "hw/ppc/pnv.h"
27 #include "hw/ppc/pnv_xscom.h"
28 #include "hw/ppc/pnv_occ.h"
30 #define OCB_OCI_OCCMISC 0x4020
31 #define OCB_OCI_OCCMISC_AND 0x4021
32 #define OCB_OCI_OCCMISC_OR 0x4022
34 static void pnv_occ_set_misc(PnvOCC
*occ
, uint64_t val
)
38 val
&= 0xffff000000000000ull
;
41 irq_state
= !!(val
>> 63);
42 pnv_psi_irq_set(occ
->psi
, PSIHB_IRQ_OCC
, irq_state
);
45 static uint64_t pnv_occ_xscom_read(void *opaque
, hwaddr addr
, unsigned size
)
47 PnvOCC
*occ
= PNV_OCC(opaque
);
48 uint32_t offset
= addr
>> 3;
56 qemu_log_mask(LOG_UNIMP
, "OCC Unimplemented register: Ox%"
57 HWADDR_PRIx
"\n", addr
);
62 static void pnv_occ_xscom_write(void *opaque
, hwaddr addr
,
63 uint64_t val
, unsigned size
)
65 PnvOCC
*occ
= PNV_OCC(opaque
);
66 uint32_t offset
= addr
>> 3;
69 case OCB_OCI_OCCMISC_AND
:
70 pnv_occ_set_misc(occ
, occ
->occmisc
& val
);
72 case OCB_OCI_OCCMISC_OR
:
73 pnv_occ_set_misc(occ
, occ
->occmisc
| val
);
76 pnv_occ_set_misc(occ
, val
);
79 qemu_log_mask(LOG_UNIMP
, "OCC Unimplemented register: Ox%"
80 HWADDR_PRIx
"\n", addr
);
84 static const MemoryRegionOps pnv_occ_xscom_ops
= {
85 .read
= pnv_occ_xscom_read
,
86 .write
= pnv_occ_xscom_write
,
87 .valid
.min_access_size
= 8,
88 .valid
.max_access_size
= 8,
89 .impl
.min_access_size
= 8,
90 .impl
.max_access_size
= 8,
91 .endianness
= DEVICE_BIG_ENDIAN
,
95 static void pnv_occ_realize(DeviceState
*dev
, Error
**errp
)
97 PnvOCC
*occ
= PNV_OCC(dev
);
103 /* get PSI object from chip */
104 obj
= object_property_get_link(OBJECT(dev
), "psi", &error
);
106 error_setg(errp
, "%s: required link 'psi' not found: %s",
107 __func__
, error_get_pretty(error
));
110 occ
->psi
= PNV_PSI(obj
);
112 /* XScom region for OCC registers */
113 pnv_xscom_region_init(&occ
->xscom_regs
, OBJECT(dev
), &pnv_occ_xscom_ops
,
114 occ
, "xscom-occ", PNV_XSCOM_OCC_SIZE
);
117 static void pnv_occ_class_init(ObjectClass
*klass
, void *data
)
119 DeviceClass
*dc
= DEVICE_CLASS(klass
);
121 dc
->realize
= pnv_occ_realize
;
124 static const TypeInfo pnv_occ_type_info
= {
125 .name
= TYPE_PNV_OCC
,
126 .parent
= TYPE_DEVICE
,
127 .instance_size
= sizeof(PnvOCC
),
128 .class_init
= pnv_occ_class_init
,
131 static void pnv_occ_register_types(void)
133 type_register_static(&pnv_occ_type_info
);
136 type_init(pnv_occ_register_types
)