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