1 /* 2 * QEMU PowerPC PowerNV Emulation of a few OCC related registers 3 * 4 * Copyright (c) 2015-2017, IBM Corporation. 5 * 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. 9 * 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. 14 * 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/>. 17 */ 18 19 #include "qemu/osdep.h" 20 #include "target/ppc/cpu.h" 21 #include "qapi/error.h" 22 #include "qemu/log.h" 23 #include "qemu/module.h" 24 #include "hw/qdev-properties.h" 25 #include "hw/ppc/pnv.h" 26 #include "hw/ppc/pnv_xscom.h" 27 #include "hw/ppc/pnv_occ.h" 28 29 #define OCB_OCI_OCCMISC 0x4020 30 #define OCB_OCI_OCCMISC_AND 0x4021 31 #define OCB_OCI_OCCMISC_OR 0x4022 32 33 /* OCC sensors */ 34 #define OCC_SENSOR_DATA_BLOCK_OFFSET 0x580000 35 #define OCC_SENSOR_DATA_VALID 0x580001 36 #define OCC_SENSOR_DATA_VERSION 0x580002 37 #define OCC_SENSOR_DATA_READING_VERSION 0x580004 38 #define OCC_SENSOR_DATA_NR_SENSORS 0x580008 39 #define OCC_SENSOR_DATA_NAMES_OFFSET 0x580010 40 #define OCC_SENSOR_DATA_READING_PING_OFFSET 0x580014 41 #define OCC_SENSOR_DATA_READING_PONG_OFFSET 0x58000c 42 #define OCC_SENSOR_DATA_NAME_LENGTH 0x58000d 43 #define OCC_SENSOR_NAME_STRUCTURE_TYPE 0x580023 44 #define OCC_SENSOR_LOC_CORE 0x580022 45 #define OCC_SENSOR_LOC_GPU 0x580020 46 #define OCC_SENSOR_TYPE_POWER 0x580003 47 #define OCC_SENSOR_NAME 0x580005 48 #define HWMON_SENSORS_MASK 0x58001e 49 #define SLW_IMAGE_BASE 0x0 50 51 static void pnv_occ_set_misc(PnvOCC *occ, uint64_t val) 52 { 53 bool irq_state; 54 PnvOCCClass *poc = PNV_OCC_GET_CLASS(occ); 55 56 val &= 0xffff000000000000ull; 57 58 occ->occmisc = val; 59 irq_state = !!(val >> 63); 60 pnv_psi_irq_set(occ->psi, poc->psi_irq, irq_state); 61 } 62 63 static uint64_t pnv_occ_power8_xscom_read(void *opaque, hwaddr addr, 64 unsigned size) 65 { 66 PnvOCC *occ = PNV_OCC(opaque); 67 uint32_t offset = addr >> 3; 68 uint64_t val = 0; 69 70 switch (offset) { 71 case OCB_OCI_OCCMISC: 72 val = occ->occmisc; 73 break; 74 default: 75 qemu_log_mask(LOG_UNIMP, "OCC Unimplemented register: Ox%" 76 HWADDR_PRIx "\n", addr >> 3); 77 } 78 return val; 79 } 80 81 static void pnv_occ_power8_xscom_write(void *opaque, hwaddr addr, 82 uint64_t val, unsigned size) 83 { 84 PnvOCC *occ = PNV_OCC(opaque); 85 uint32_t offset = addr >> 3; 86 87 switch (offset) { 88 case OCB_OCI_OCCMISC_AND: 89 pnv_occ_set_misc(occ, occ->occmisc & val); 90 break; 91 case OCB_OCI_OCCMISC_OR: 92 pnv_occ_set_misc(occ, occ->occmisc | val); 93 break; 94 case OCB_OCI_OCCMISC: 95 pnv_occ_set_misc(occ, val); 96 break; 97 default: 98 qemu_log_mask(LOG_UNIMP, "OCC Unimplemented register: Ox%" 99 HWADDR_PRIx "\n", addr >> 3); 100 } 101 } 102 103 static uint64_t pnv_occ_common_area_read(void *opaque, hwaddr addr, 104 unsigned width) 105 { 106 switch (addr) { 107 /* 108 * occ-sensor sanity check that asserts the sensor 109 * header block 110 */ 111 case OCC_SENSOR_DATA_BLOCK_OFFSET: 112 case OCC_SENSOR_DATA_VALID: 113 case OCC_SENSOR_DATA_VERSION: 114 case OCC_SENSOR_DATA_READING_VERSION: 115 case OCC_SENSOR_DATA_NR_SENSORS: 116 case OCC_SENSOR_DATA_NAMES_OFFSET: 117 case OCC_SENSOR_DATA_READING_PING_OFFSET: 118 case OCC_SENSOR_DATA_READING_PONG_OFFSET: 119 case OCC_SENSOR_NAME_STRUCTURE_TYPE: 120 return 1; 121 case OCC_SENSOR_DATA_NAME_LENGTH: 122 return 0x30; 123 case OCC_SENSOR_LOC_CORE: 124 return 0x0040; 125 case OCC_SENSOR_TYPE_POWER: 126 return 0x0080; 127 case OCC_SENSOR_NAME: 128 return 0x1000; 129 case HWMON_SENSORS_MASK: 130 case OCC_SENSOR_LOC_GPU: 131 return 0x8e00; 132 case SLW_IMAGE_BASE: 133 return 0x1000000000000000; 134 } 135 return 0; 136 } 137 138 static void pnv_occ_common_area_write(void *opaque, hwaddr addr, 139 uint64_t val, unsigned width) 140 { 141 /* callback function defined to occ common area write */ 142 return; 143 } 144 145 static const MemoryRegionOps pnv_occ_power8_xscom_ops = { 146 .read = pnv_occ_power8_xscom_read, 147 .write = pnv_occ_power8_xscom_write, 148 .valid.min_access_size = 8, 149 .valid.max_access_size = 8, 150 .impl.min_access_size = 8, 151 .impl.max_access_size = 8, 152 .endianness = DEVICE_BIG_ENDIAN, 153 }; 154 155 const MemoryRegionOps pnv_occ_sram_ops = { 156 .read = pnv_occ_common_area_read, 157 .write = pnv_occ_common_area_write, 158 .valid.min_access_size = 1, 159 .valid.max_access_size = 8, 160 .impl.min_access_size = 1, 161 .impl.max_access_size = 8, 162 .endianness = DEVICE_BIG_ENDIAN, 163 }; 164 165 static void pnv_occ_power8_class_init(ObjectClass *klass, void *data) 166 { 167 PnvOCCClass *poc = PNV_OCC_CLASS(klass); 168 169 poc->xscom_size = PNV_XSCOM_OCC_SIZE; 170 poc->xscom_ops = &pnv_occ_power8_xscom_ops; 171 poc->psi_irq = PSIHB_IRQ_OCC; 172 } 173 174 static const TypeInfo pnv_occ_power8_type_info = { 175 .name = TYPE_PNV8_OCC, 176 .parent = TYPE_PNV_OCC, 177 .instance_size = sizeof(PnvOCC), 178 .class_init = pnv_occ_power8_class_init, 179 }; 180 181 #define P9_OCB_OCI_OCCMISC 0x6080 182 #define P9_OCB_OCI_OCCMISC_CLEAR 0x6081 183 #define P9_OCB_OCI_OCCMISC_OR 0x6082 184 185 186 static uint64_t pnv_occ_power9_xscom_read(void *opaque, hwaddr addr, 187 unsigned size) 188 { 189 PnvOCC *occ = PNV_OCC(opaque); 190 uint32_t offset = addr >> 3; 191 uint64_t val = 0; 192 193 switch (offset) { 194 case P9_OCB_OCI_OCCMISC: 195 val = occ->occmisc; 196 break; 197 default: 198 qemu_log_mask(LOG_UNIMP, "OCC Unimplemented register: Ox%" 199 HWADDR_PRIx "\n", addr >> 3); 200 } 201 return val; 202 } 203 204 static void pnv_occ_power9_xscom_write(void *opaque, hwaddr addr, 205 uint64_t val, unsigned size) 206 { 207 PnvOCC *occ = PNV_OCC(opaque); 208 uint32_t offset = addr >> 3; 209 210 switch (offset) { 211 case P9_OCB_OCI_OCCMISC_CLEAR: 212 pnv_occ_set_misc(occ, 0); 213 break; 214 case P9_OCB_OCI_OCCMISC_OR: 215 pnv_occ_set_misc(occ, occ->occmisc | val); 216 break; 217 case P9_OCB_OCI_OCCMISC: 218 pnv_occ_set_misc(occ, val); 219 break; 220 default: 221 qemu_log_mask(LOG_UNIMP, "OCC Unimplemented register: Ox%" 222 HWADDR_PRIx "\n", addr >> 3); 223 } 224 } 225 226 static const MemoryRegionOps pnv_occ_power9_xscom_ops = { 227 .read = pnv_occ_power9_xscom_read, 228 .write = pnv_occ_power9_xscom_write, 229 .valid.min_access_size = 8, 230 .valid.max_access_size = 8, 231 .impl.min_access_size = 8, 232 .impl.max_access_size = 8, 233 .endianness = DEVICE_BIG_ENDIAN, 234 }; 235 236 static void pnv_occ_power9_class_init(ObjectClass *klass, void *data) 237 { 238 PnvOCCClass *poc = PNV_OCC_CLASS(klass); 239 240 poc->xscom_size = PNV9_XSCOM_OCC_SIZE; 241 poc->xscom_ops = &pnv_occ_power9_xscom_ops; 242 poc->psi_irq = PSIHB9_IRQ_OCC; 243 } 244 245 static const TypeInfo pnv_occ_power9_type_info = { 246 .name = TYPE_PNV9_OCC, 247 .parent = TYPE_PNV_OCC, 248 .instance_size = sizeof(PnvOCC), 249 .class_init = pnv_occ_power9_class_init, 250 }; 251 252 static void pnv_occ_realize(DeviceState *dev, Error **errp) 253 { 254 PnvOCC *occ = PNV_OCC(dev); 255 PnvOCCClass *poc = PNV_OCC_GET_CLASS(occ); 256 257 assert(occ->psi); 258 259 occ->occmisc = 0; 260 261 /* XScom region for OCC registers */ 262 pnv_xscom_region_init(&occ->xscom_regs, OBJECT(dev), poc->xscom_ops, 263 occ, "xscom-occ", poc->xscom_size); 264 265 /* OCC common area mmio region for OCC SRAM registers */ 266 memory_region_init_io(&occ->sram_regs, OBJECT(dev), &pnv_occ_sram_ops, 267 occ, "occ-common-area", 268 PNV_OCC_SENSOR_DATA_BLOCK_SIZE); 269 } 270 271 static Property pnv_occ_properties[] = { 272 DEFINE_PROP_LINK("psi", PnvOCC, psi, TYPE_PNV_PSI, PnvPsi *), 273 DEFINE_PROP_END_OF_LIST(), 274 }; 275 276 static void pnv_occ_class_init(ObjectClass *klass, void *data) 277 { 278 DeviceClass *dc = DEVICE_CLASS(klass); 279 280 dc->realize = pnv_occ_realize; 281 dc->desc = "PowerNV OCC Controller"; 282 device_class_set_props(dc, pnv_occ_properties); 283 dc->user_creatable = false; 284 } 285 286 static const TypeInfo pnv_occ_type_info = { 287 .name = TYPE_PNV_OCC, 288 .parent = TYPE_DEVICE, 289 .instance_size = sizeof(PnvOCC), 290 .class_init = pnv_occ_class_init, 291 .class_size = sizeof(PnvOCCClass), 292 .abstract = true, 293 }; 294 295 static void pnv_occ_register_types(void) 296 { 297 type_register_static(&pnv_occ_type_info); 298 type_register_static(&pnv_occ_power8_type_info); 299 type_register_static(&pnv_occ_power9_type_info); 300 } 301 302 type_init(pnv_occ_register_types); 303