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