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