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 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->sram_size = PNV_OCC_COMMON_AREA_SIZE; 171 poc->xscom_ops = &pnv_occ_power8_xscom_ops; 172 poc->sram_ops = &pnv_occ_sram_ops; 173 poc->psi_irq = PSIHB_IRQ_OCC; 174 } 175 176 static const TypeInfo pnv_occ_power8_type_info = { 177 .name = TYPE_PNV8_OCC, 178 .parent = TYPE_PNV_OCC, 179 .instance_size = sizeof(PnvOCC), 180 .class_init = pnv_occ_power8_class_init, 181 }; 182 183 #define P9_OCB_OCI_OCCMISC 0x6080 184 #define P9_OCB_OCI_OCCMISC_CLEAR 0x6081 185 #define P9_OCB_OCI_OCCMISC_OR 0x6082 186 187 188 static uint64_t pnv_occ_power9_xscom_read(void *opaque, hwaddr addr, 189 unsigned size) 190 { 191 PnvOCC *occ = PNV_OCC(opaque); 192 uint32_t offset = addr >> 3; 193 uint64_t val = 0; 194 195 switch (offset) { 196 case P9_OCB_OCI_OCCMISC: 197 val = occ->occmisc; 198 break; 199 default: 200 qemu_log_mask(LOG_UNIMP, "OCC Unimplemented register: Ox%" 201 HWADDR_PRIx "\n", addr >> 3); 202 } 203 return val; 204 } 205 206 static void pnv_occ_power9_xscom_write(void *opaque, hwaddr addr, 207 uint64_t val, unsigned size) 208 { 209 PnvOCC *occ = PNV_OCC(opaque); 210 uint32_t offset = addr >> 3; 211 212 switch (offset) { 213 case P9_OCB_OCI_OCCMISC_CLEAR: 214 pnv_occ_set_misc(occ, 0); 215 break; 216 case P9_OCB_OCI_OCCMISC_OR: 217 pnv_occ_set_misc(occ, occ->occmisc | val); 218 break; 219 case P9_OCB_OCI_OCCMISC: 220 pnv_occ_set_misc(occ, val); 221 break; 222 default: 223 qemu_log_mask(LOG_UNIMP, "OCC Unimplemented register: Ox%" 224 HWADDR_PRIx "\n", addr >> 3); 225 } 226 } 227 228 static const MemoryRegionOps pnv_occ_power9_xscom_ops = { 229 .read = pnv_occ_power9_xscom_read, 230 .write = pnv_occ_power9_xscom_write, 231 .valid.min_access_size = 8, 232 .valid.max_access_size = 8, 233 .impl.min_access_size = 8, 234 .impl.max_access_size = 8, 235 .endianness = DEVICE_BIG_ENDIAN, 236 }; 237 238 static void pnv_occ_power9_class_init(ObjectClass *klass, void *data) 239 { 240 PnvOCCClass *poc = PNV_OCC_CLASS(klass); 241 242 poc->xscom_size = PNV9_XSCOM_OCC_SIZE; 243 poc->sram_size = PNV9_OCC_COMMON_AREA_SIZE; 244 poc->xscom_ops = &pnv_occ_power9_xscom_ops; 245 poc->sram_ops = &pnv_occ_sram_ops; 246 poc->psi_irq = PSIHB9_IRQ_OCC; 247 } 248 249 static const TypeInfo pnv_occ_power9_type_info = { 250 .name = TYPE_PNV9_OCC, 251 .parent = TYPE_PNV_OCC, 252 .instance_size = sizeof(PnvOCC), 253 .class_init = pnv_occ_power9_class_init, 254 }; 255 256 static void pnv_occ_realize(DeviceState *dev, Error **errp) 257 { 258 PnvOCC *occ = PNV_OCC(dev); 259 PnvOCCClass *poc = PNV_OCC_GET_CLASS(occ); 260 Object *obj; 261 Error *local_err = NULL; 262 263 occ->occmisc = 0; 264 265 obj = object_property_get_link(OBJECT(dev), "psi", &local_err); 266 if (!obj) { 267 error_propagate(errp, local_err); 268 error_prepend(errp, "required link 'psi' not found: "); 269 return; 270 } 271 occ->psi = PNV_PSI(obj); 272 273 /* XScom region for OCC registers */ 274 pnv_xscom_region_init(&occ->xscom_regs, OBJECT(dev), poc->xscom_ops, 275 occ, "xscom-occ", poc->xscom_size); 276 277 /* XScom region for OCC SRAM registers */ 278 pnv_xscom_region_init(&occ->sram_regs, OBJECT(dev), poc->sram_ops, 279 occ, "occ-common-area", poc->sram_size); 280 } 281 282 static void pnv_occ_class_init(ObjectClass *klass, void *data) 283 { 284 DeviceClass *dc = DEVICE_CLASS(klass); 285 286 dc->realize = pnv_occ_realize; 287 dc->desc = "PowerNV OCC Controller"; 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 } 305 306 type_init(pnv_occ_register_types); 307