1 /* 2 * SPDX-License-Identifier: GPL-2.0-or-later 3 * Copyright (C) 2019 IBM Corp. 4 * 5 * IBM On-chip Peripheral Bus 6 */ 7 8 #include "qemu/osdep.h" 9 10 #include "qapi/error.h" 11 #include "qemu/log.h" 12 13 #include "hw/fsi/bits.h" 14 #include "hw/fsi/cfam.h" 15 #include "hw/fsi/fsi.h" 16 #include "hw/fsi/engine-scratchpad.h" 17 18 #include "hw/qdev-properties.h" 19 20 #define TO_REG(x) ((x) >> 2) 21 22 #define CFAM_ENGINE_CONFIG TO_REG(0x04) 23 24 #define CFAM_CONFIG_CHIP_ID TO_REG(0x00) 25 #define CFAM_CONFIG_CHIP_ID_P9 0xc0022d15 26 #define CFAM_CONFIG_CHIP_ID_BREAK 0xc0de0000 27 28 static uint64_t cfam_config_read(void *opaque, hwaddr addr, unsigned size) 29 { 30 CFAMConfig *config; 31 CFAMState *cfam; 32 LBusNode *node; 33 int i; 34 35 config = CFAM_CONFIG(opaque); 36 cfam = container_of(config, CFAMState, config); 37 38 qemu_log_mask(LOG_UNIMP, "%s: read @0x%" HWADDR_PRIx " size=%d\n", 39 __func__, addr, size); 40 41 assert(size == 4); 42 assert(!(addr & 3)); 43 44 #if 0 /* FIXME: Make it dynamic */ 45 if (addr + size > sizeof(s->regs)) { 46 qemu_log_mask(LOG_GUEST_ERROR, 47 "%s: Out of bounds read: 0x%"HWADDR_PRIx" for %u\n", 48 __func__, addr, size); 49 return 0; 50 } 51 52 val = s->regs[TO_REG(addr)]; 53 printf("%s: read 0x%x\n", __func__, val); 54 #endif 55 56 switch (addr) { 57 case 0x00: 58 return CFAM_CONFIG_CHIP_ID_P9; 59 case 0x04: 60 return ENGINE_CONFIG_NEXT 61 | 0x00010000 /* slots */ 62 | 0x00001000 /* version */ 63 | ENGINE_CONFIG_TYPE_PEEK /* type */ 64 | 0x0000000c; /* crc */ 65 case 0x08: 66 return ENGINE_CONFIG_NEXT 67 | 0x00010000 /* slots */ 68 | 0x00005000 /* version */ 69 | ENGINE_CONFIG_TYPE_FSI /* type */ 70 | 0x0000000a; /* crc */ 71 break; 72 default: 73 /* FIXME: Improve this */ 74 i = 0xc; 75 QLIST_FOREACH(node, &cfam->lbus.devices, next) { 76 if (i == addr) { 77 return LBUS_DEVICE_GET_CLASS(node->ldev)->config; 78 } 79 i += size; 80 } 81 82 if (i == addr) { 83 return 0; 84 } 85 86 return 0xc0de0000; 87 } 88 } 89 90 static void cfam_config_write(void *opaque, hwaddr addr, uint64_t data, 91 unsigned size) 92 { 93 CFAMConfig *s = CFAM_CONFIG(opaque); 94 95 qemu_log_mask(LOG_UNIMP, "%s: write @0x%" HWADDR_PRIx " size=%d " 96 "value=%"PRIx64"\n", __func__, addr, size, data); 97 98 assert(size == 4); 99 assert(!(addr & 3)); 100 101 #if 0 102 if (addr + size > sizeof(s->regs)) { 103 qemu_log_mask(LOG_GUEST_ERROR, "%s: Out of bounds write: 0x%" 104 HWADDR_PRIx" for %u\n", 105 __func__, addr, size); 106 return; 107 } 108 #endif 109 110 switch (TO_REG(addr)) { 111 case CFAM_CONFIG_CHIP_ID: 112 case CFAM_CONFIG_CHIP_ID + 4: 113 if (data == CFAM_CONFIG_CHIP_ID_BREAK) { 114 qbus_reset_all(qdev_get_parent_bus(DEVICE(s))); 115 } 116 break; 117 } 118 } 119 120 static const struct MemoryRegionOps cfam_config_ops = { 121 .read = cfam_config_read, 122 .write = cfam_config_write, 123 .endianness = DEVICE_BIG_ENDIAN, 124 }; 125 126 static void cfam_config_realize(DeviceState *dev, Error **errp) 127 { 128 CFAMConfig *s = CFAM_CONFIG(dev); 129 130 memory_region_init_io(&s->iomem, OBJECT(s), &cfam_config_ops, s, 131 TYPE_CFAM_CONFIG, 0x400); 132 } 133 134 static void cfam_config_reset(DeviceState *dev) 135 { 136 /* Config is read-only */ 137 } 138 139 static void cfam_config_class_init(ObjectClass *klass, void *data) 140 { 141 DeviceClass *dc = DEVICE_CLASS(klass); 142 dc->bus_type = TYPE_LBUS; 143 dc->realize = cfam_config_realize; 144 dc->reset = cfam_config_reset; 145 } 146 147 static const TypeInfo cfam_config_info = { 148 .name = TYPE_CFAM_CONFIG, 149 .parent = TYPE_DEVICE, 150 .instance_size = sizeof(CFAMConfig), 151 .class_init = cfam_config_class_init, 152 }; 153 154 static void lbus_realize(BusState *bus, Error **errp) 155 { 156 LBusNode *node; 157 LBus *lbus = LBUS(bus); 158 159 memory_region_init(&lbus->mr, OBJECT(lbus), TYPE_LBUS, 160 (2 * 1024 * 1024) - 0x400); 161 162 QLIST_FOREACH(node, &lbus->devices, next) { 163 memory_region_add_subregion(&lbus->mr, node->ldev->address, 164 &node->ldev->iomem); 165 } 166 } 167 168 static void lbus_init(Object *o) 169 { 170 } 171 172 static void lbus_class_init(ObjectClass *klass, void *data) 173 { 174 BusClass *k = BUS_CLASS(klass); 175 k->realize = lbus_realize; 176 } 177 178 static const TypeInfo lbus_info = { 179 .name = TYPE_LBUS, 180 .parent = TYPE_BUS, 181 .instance_init = lbus_init, 182 .instance_size = sizeof(LBus), 183 .class_init = lbus_class_init, 184 }; 185 186 static Property lbus_device_props[] = { 187 DEFINE_PROP_UINT32("address", LBusDevice, address, 0), 188 DEFINE_PROP_END_OF_LIST(), 189 }; 190 191 DeviceState *lbus_create_device(LBus *bus, const char *type, uint32_t addr) 192 { 193 DeviceState *dev; 194 LBusNode *node; 195 196 dev = qdev_new(type); 197 qdev_prop_set_uint8(dev, "address", addr); 198 qdev_realize_and_unref(dev, &bus->bus, &error_fatal); 199 200 /* Move to post_load */ 201 node = g_malloc(sizeof(struct LBusNode)); 202 node->ldev = LBUS_DEVICE(dev); 203 QLIST_INSERT_HEAD(&bus->devices, node, next); 204 205 return dev; 206 } 207 208 static void lbus_device_class_init(ObjectClass *klass, void *data) 209 { 210 DeviceClass *dc = DEVICE_CLASS(klass); 211 212 dc->bus_type = TYPE_LBUS; 213 device_class_set_props(dc, lbus_device_props); 214 } 215 216 static const TypeInfo lbus_device_type_info = { 217 .name = TYPE_LBUS_DEVICE, 218 .parent = TYPE_DEVICE, 219 .instance_size = sizeof(LBusDevice), 220 .abstract = true, 221 .class_init = lbus_device_class_init, 222 .class_size = sizeof(LBusDeviceClass), 223 }; 224 225 static uint64_t cfam_unimplemented_read(void *opaque, hwaddr addr, 226 unsigned size) 227 { 228 qemu_log_mask(LOG_UNIMP, "%s: read @0x%" HWADDR_PRIx " size=%d\n", 229 __func__, addr, size); 230 231 return 0; 232 } 233 234 static void cfam_unimplemented_write(void *opaque, hwaddr addr, uint64_t data, 235 unsigned size) 236 { 237 qemu_log_mask(LOG_UNIMP, "%s: write @0x%" HWADDR_PRIx " size=%d " 238 "value=%"PRIx64"\n", __func__, addr, size, data); 239 } 240 241 static const struct MemoryRegionOps cfam_unimplemented_ops = { 242 .read = cfam_unimplemented_read, 243 .write = cfam_unimplemented_write, 244 .endianness = DEVICE_BIG_ENDIAN, 245 }; 246 247 static void cfam_realize(DeviceState *dev, Error **errp) 248 { 249 CFAMState *cfam = CFAM(dev); 250 FSISlaveState *slave = FSI_SLAVE(dev); 251 Error *err = NULL; 252 253 /* Each slave has a 2MiB address space */ 254 memory_region_init_io(&cfam->mr, OBJECT(cfam), &cfam_unimplemented_ops, 255 cfam, TYPE_CFAM, 2 * 1024 * 1024); 256 address_space_init(&cfam->as, &cfam->mr, TYPE_CFAM); 257 258 qbus_init(&cfam->lbus, sizeof(cfam->lbus), TYPE_LBUS, 259 DEVICE(cfam), NULL); 260 261 lbus_create_device(&cfam->lbus, TYPE_SCRATCHPAD, 0); 262 263 object_property_set_bool(OBJECT(&cfam->config), "realized", true, &err); 264 if (err) { 265 error_propagate(errp, err); 266 return; 267 } 268 qdev_set_parent_bus(DEVICE(&cfam->config), BUS(&cfam->lbus), &error_abort); 269 270 object_property_set_bool(OBJECT(&cfam->lbus), "realized", true, &err); 271 if (err) { 272 error_propagate(errp, err); 273 return; 274 } 275 276 memory_region_add_subregion(&cfam->mr, 0, &cfam->config.iomem); 277 /* memory_region_add_subregion(&cfam->mr, 0x800, &cfam->lbus.peek.iomem); */ 278 memory_region_add_subregion(&cfam->mr, 0x800, &slave->iomem); 279 memory_region_add_subregion(&cfam->mr, 0xc00, &cfam->lbus.mr); 280 } 281 282 static void cfam_reset(DeviceState *dev) 283 { 284 /* TODO: Figure out how inherited reset works */ 285 } 286 287 static void cfam_init(Object *o) 288 { 289 CFAMState *s = CFAM(o); 290 291 object_initialize_child(o, TYPE_CFAM_CONFIG, &s->config, TYPE_CFAM_CONFIG); 292 } 293 294 static void cfam_finalize(Object *o) 295 { 296 #if 0 /* TODO (clg): fix device-introspect-test */ 297 CFAMState *s = CFAM(o); 298 299 address_space_destroy(&s->as); 300 #endif 301 } 302 303 static void cfam_class_init(ObjectClass *klass, void *data) 304 { 305 DeviceClass *dc = DEVICE_CLASS(klass); 306 dc->bus_type = TYPE_FSI_BUS; 307 dc->realize = cfam_realize; 308 dc->reset = cfam_reset; 309 } 310 311 static const TypeInfo cfam_info = { 312 .name = TYPE_CFAM, 313 .parent = TYPE_FSI_SLAVE, 314 .instance_init = cfam_init, 315 .instance_finalize = cfam_finalize, 316 .instance_size = sizeof(CFAMState), 317 .class_init = cfam_class_init, 318 }; 319 320 static void cfam_register_types(void) 321 { 322 type_register_static(&cfam_config_info); 323 type_register_static(&lbus_info); 324 type_register_static(&lbus_device_type_info); 325 type_register_static(&cfam_info); 326 } 327 328 type_init(cfam_register_types); 329