1 /* 2 * SPDX-License-Identifier: GPL-2.0-or-later 3 * Copyright (C) 2024 IBM Corp. 4 * 5 * ASPEED APB-OPB FSI interface 6 * IBM On-chip Peripheral Bus 7 */ 8 9 #include "qemu/osdep.h" 10 #include "qemu/log.h" 11 #include "qom/object.h" 12 #include "qapi/error.h" 13 #include "trace.h" 14 15 #include "hw/fsi/aspeed_apb2opb.h" 16 #include "hw/qdev-core.h" 17 18 #define TO_REG(x) (x >> 2) 19 20 #define APB2OPB_VERSION TO_REG(0x00) 21 #define APB2OPB_TRIGGER TO_REG(0x04) 22 23 #define APB2OPB_CONTROL TO_REG(0x08) 24 #define APB2OPB_CONTROL_OFF BE_GENMASK(31, 13) 25 26 #define APB2OPB_OPB2FSI TO_REG(0x0c) 27 #define APB2OPB_OPB2FSI_OFF BE_GENMASK(31, 22) 28 29 #define APB2OPB_OPB0_SEL TO_REG(0x10) 30 #define APB2OPB_OPB1_SEL TO_REG(0x28) 31 #define APB2OPB_OPB_SEL_EN BIT(0) 32 33 #define APB2OPB_OPB0_MODE TO_REG(0x14) 34 #define APB2OPB_OPB1_MODE TO_REG(0x2c) 35 #define APB2OPB_OPB_MODE_RD BIT(0) 36 37 #define APB2OPB_OPB0_XFER TO_REG(0x18) 38 #define APB2OPB_OPB1_XFER TO_REG(0x30) 39 #define APB2OPB_OPB_XFER_FULL BIT(1) 40 #define APB2OPB_OPB_XFER_HALF BIT(0) 41 42 #define APB2OPB_OPB0_ADDR TO_REG(0x1c) 43 #define APB2OPB_OPB0_WRITE_DATA TO_REG(0x20) 44 45 #define APB2OPB_OPB1_ADDR TO_REG(0x34) 46 #define APB2OPB_OPB1_WRITE_DATA TO_REG(0x38) 47 48 #define APB2OPB_IRQ_STS TO_REG(0x48) 49 #define APB2OPB_IRQ_STS_OPB1_TX_ACK BIT(17) 50 #define APB2OPB_IRQ_STS_OPB0_TX_ACK BIT(16) 51 52 #define APB2OPB_OPB0_WRITE_WORD_ENDIAN TO_REG(0x4c) 53 #define APB2OPB_OPB0_WRITE_WORD_ENDIAN_BE 0x0011101b 54 #define APB2OPB_OPB0_WRITE_BYTE_ENDIAN TO_REG(0x50) 55 #define APB2OPB_OPB0_WRITE_BYTE_ENDIAN_BE 0x0c330f3f 56 #define APB2OPB_OPB1_WRITE_WORD_ENDIAN TO_REG(0x54) 57 #define APB2OPB_OPB1_WRITE_BYTE_ENDIAN TO_REG(0x58) 58 #define APB2OPB_OPB0_READ_BYTE_ENDIAN TO_REG(0x5c) 59 #define APB2OPB_OPB1_READ_BYTE_ENDIAN TO_REG(0x60) 60 #define APB2OPB_OPB0_READ_WORD_ENDIAN_BE 0x00030b1b 61 62 #define APB2OPB_OPB0_READ_DATA TO_REG(0x84) 63 #define APB2OPB_OPB1_READ_DATA TO_REG(0x90) 64 65 /* 66 * The following magic values came from AST2600 data sheet 67 * The register values are defined under section "FSI controller" 68 * as initial values. 69 */ 70 static const uint32_t aspeed_apb2opb_reset[ASPEED_APB2OPB_NR_REGS] = { 71 [APB2OPB_VERSION] = 0x000000a1, 72 [APB2OPB_OPB0_WRITE_WORD_ENDIAN] = 0x0044eee4, 73 [APB2OPB_OPB0_WRITE_BYTE_ENDIAN] = 0x0055aaff, 74 [APB2OPB_OPB1_WRITE_WORD_ENDIAN] = 0x00117717, 75 [APB2OPB_OPB1_WRITE_BYTE_ENDIAN] = 0xffaa5500, 76 [APB2OPB_OPB0_READ_BYTE_ENDIAN] = 0x0044eee4, 77 [APB2OPB_OPB1_READ_BYTE_ENDIAN] = 0x00117717 78 }; 79 80 static void fsi_opb_fsi_master_address(FSIMasterState *fsi, hwaddr addr) 81 { 82 memory_region_transaction_begin(); 83 memory_region_set_address(&fsi->iomem, addr); 84 memory_region_transaction_commit(); 85 } 86 87 static void fsi_opb_opb2fsi_address(FSIMasterState *fsi, hwaddr addr) 88 { 89 memory_region_transaction_begin(); 90 memory_region_set_address(&fsi->opb2fsi, addr); 91 memory_region_transaction_commit(); 92 } 93 94 static uint64_t fsi_aspeed_apb2opb_read(void *opaque, hwaddr addr, 95 unsigned size) 96 { 97 AspeedAPB2OPBState *s = ASPEED_APB2OPB(opaque); 98 unsigned int reg = TO_REG(addr); 99 100 trace_fsi_aspeed_apb2opb_read(addr, size); 101 102 if (reg >= ASPEED_APB2OPB_NR_REGS) { 103 qemu_log_mask(LOG_GUEST_ERROR, 104 "%s: Out of bounds read: 0x%"HWADDR_PRIx" for %u\n", 105 __func__, addr, size); 106 return 0; 107 } 108 109 return s->regs[reg]; 110 } 111 112 static MemTxResult fsi_aspeed_apb2opb_rw(AddressSpace *as, hwaddr addr, 113 MemTxAttrs attrs, uint32_t *data, 114 uint32_t size, bool is_write) 115 { 116 MemTxResult res; 117 118 if (is_write) { 119 switch (size) { 120 case 4: 121 address_space_stl_le(as, addr, *data, attrs, &res); 122 break; 123 case 2: 124 address_space_stw_le(as, addr, *data, attrs, &res); 125 break; 126 case 1: 127 address_space_stb(as, addr, *data, attrs, &res); 128 break; 129 default: 130 g_assert_not_reached(); 131 } 132 } else { 133 switch (size) { 134 case 4: 135 *data = address_space_ldl_le(as, addr, attrs, &res); 136 break; 137 case 2: 138 *data = address_space_lduw_le(as, addr, attrs, &res); 139 break; 140 case 1: 141 *data = address_space_ldub(as, addr, attrs, &res); 142 break; 143 default: 144 g_assert_not_reached(); 145 } 146 } 147 return res; 148 } 149 150 static void fsi_aspeed_apb2opb_write(void *opaque, hwaddr addr, uint64_t data, 151 unsigned size) 152 { 153 AspeedAPB2OPBState *s = ASPEED_APB2OPB(opaque); 154 unsigned int reg = TO_REG(addr); 155 156 trace_fsi_aspeed_apb2opb_write(addr, size, data); 157 158 if (reg >= ASPEED_APB2OPB_NR_REGS) { 159 qemu_log_mask(LOG_GUEST_ERROR, 160 "%s: Out of bounds write: %"HWADDR_PRIx" for %u\n", 161 __func__, addr, size); 162 return; 163 } 164 165 switch (reg) { 166 case APB2OPB_CONTROL: 167 fsi_opb_fsi_master_address(&s->fsi[0], 168 data & APB2OPB_CONTROL_OFF); 169 break; 170 case APB2OPB_OPB2FSI: 171 fsi_opb_opb2fsi_address(&s->fsi[0], 172 data & APB2OPB_OPB2FSI_OFF); 173 break; 174 case APB2OPB_OPB0_WRITE_WORD_ENDIAN: 175 if (data != APB2OPB_OPB0_WRITE_WORD_ENDIAN_BE) { 176 qemu_log_mask(LOG_GUEST_ERROR, 177 "%s: Bridge needs to be driven as BE (0x%x)\n", 178 __func__, APB2OPB_OPB0_WRITE_WORD_ENDIAN_BE); 179 } 180 break; 181 case APB2OPB_OPB0_WRITE_BYTE_ENDIAN: 182 if (data != APB2OPB_OPB0_WRITE_BYTE_ENDIAN_BE) { 183 qemu_log_mask(LOG_GUEST_ERROR, 184 "%s: Bridge needs to be driven as BE (0x%x)\n", 185 __func__, APB2OPB_OPB0_WRITE_BYTE_ENDIAN_BE); 186 } 187 break; 188 case APB2OPB_OPB0_READ_BYTE_ENDIAN: 189 if (data != APB2OPB_OPB0_READ_WORD_ENDIAN_BE) { 190 qemu_log_mask(LOG_GUEST_ERROR, 191 "%s: Bridge needs to be driven as BE (0x%x)\n", 192 __func__, APB2OPB_OPB0_READ_WORD_ENDIAN_BE); 193 } 194 break; 195 case APB2OPB_TRIGGER: 196 { 197 uint32_t opb, op_mode, op_size, op_addr, op_data; 198 MemTxResult result; 199 bool is_write; 200 int index; 201 AddressSpace *as; 202 203 assert((s->regs[APB2OPB_OPB0_SEL] & APB2OPB_OPB_SEL_EN) ^ 204 (s->regs[APB2OPB_OPB1_SEL] & APB2OPB_OPB_SEL_EN)); 205 206 if (s->regs[APB2OPB_OPB0_SEL] & APB2OPB_OPB_SEL_EN) { 207 opb = 0; 208 op_mode = s->regs[APB2OPB_OPB0_MODE]; 209 op_size = s->regs[APB2OPB_OPB0_XFER]; 210 op_addr = s->regs[APB2OPB_OPB0_ADDR]; 211 op_data = s->regs[APB2OPB_OPB0_WRITE_DATA]; 212 } else if (s->regs[APB2OPB_OPB1_SEL] & APB2OPB_OPB_SEL_EN) { 213 opb = 1; 214 op_mode = s->regs[APB2OPB_OPB1_MODE]; 215 op_size = s->regs[APB2OPB_OPB1_XFER]; 216 op_addr = s->regs[APB2OPB_OPB1_ADDR]; 217 op_data = s->regs[APB2OPB_OPB1_WRITE_DATA]; 218 } else { 219 qemu_log_mask(LOG_GUEST_ERROR, 220 "%s: Invalid operation: 0x%"HWADDR_PRIx" for %u\n", 221 __func__, addr, size); 222 return; 223 } 224 225 if (op_size & ~(APB2OPB_OPB_XFER_HALF | APB2OPB_OPB_XFER_FULL)) { 226 qemu_log_mask(LOG_GUEST_ERROR, 227 "OPB transaction failed: Unrecognized access width: %d\n", 228 op_size); 229 return; 230 } 231 232 op_size += 1; 233 is_write = !(op_mode & APB2OPB_OPB_MODE_RD); 234 index = opb ? APB2OPB_OPB1_READ_DATA : APB2OPB_OPB0_READ_DATA; 235 as = &s->opb[opb].as; 236 237 result = fsi_aspeed_apb2opb_rw(as, op_addr, MEMTXATTRS_UNSPECIFIED, 238 &op_data, op_size, is_write); 239 if (result != MEMTX_OK) { 240 qemu_log_mask(LOG_GUEST_ERROR, "%s: OPB %s failed @%08x\n", 241 __func__, is_write ? "write" : "read", op_addr); 242 return; 243 } 244 245 if (!is_write) { 246 s->regs[index] = op_data; 247 } 248 249 s->regs[APB2OPB_IRQ_STS] |= opb ? APB2OPB_IRQ_STS_OPB1_TX_ACK 250 : APB2OPB_IRQ_STS_OPB0_TX_ACK; 251 break; 252 } 253 } 254 255 s->regs[reg] = data; 256 } 257 258 static const struct MemoryRegionOps aspeed_apb2opb_ops = { 259 .read = fsi_aspeed_apb2opb_read, 260 .write = fsi_aspeed_apb2opb_write, 261 .valid.max_access_size = 4, 262 .valid.min_access_size = 4, 263 .impl.max_access_size = 4, 264 .impl.min_access_size = 4, 265 .endianness = DEVICE_LITTLE_ENDIAN, 266 }; 267 268 static void fsi_aspeed_apb2opb_init(Object *o) 269 { 270 AspeedAPB2OPBState *s = ASPEED_APB2OPB(o); 271 int i; 272 273 for (i = 0; i < ASPEED_FSI_NUM; i++) { 274 object_initialize_child(o, "fsi-master[*]", &s->fsi[i], 275 TYPE_FSI_MASTER); 276 } 277 } 278 279 static void fsi_aspeed_apb2opb_realize(DeviceState *dev, Error **errp) 280 { 281 SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 282 AspeedAPB2OPBState *s = ASPEED_APB2OPB(dev); 283 int i; 284 285 /* 286 * TODO: The OPBus model initializes the OPB address space in 287 * the .instance_init handler and this is problematic for test 288 * device-introspect-test. To avoid a memory corruption and a QEMU 289 * crash, qbus_init() should be called from realize(). Something to 290 * improve. Possibly, OPBus could also be removed. 291 */ 292 for (i = 0; i < ASPEED_FSI_NUM; i++) { 293 qbus_init(&s->opb[i], sizeof(s->opb[i]), TYPE_OP_BUS, DEVICE(s), 294 NULL); 295 } 296 297 sysbus_init_irq(sbd, &s->irq); 298 299 memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_apb2opb_ops, s, 300 TYPE_ASPEED_APB2OPB, 0x1000); 301 sysbus_init_mmio(sbd, &s->iomem); 302 303 for (i = 0; i < ASPEED_FSI_NUM; i++) { 304 if (!qdev_realize(DEVICE(&s->fsi[i]), BUS(&s->opb[i]), errp)) { 305 return; 306 } 307 308 memory_region_add_subregion(&s->opb[i].mr, 0x80000000, 309 &s->fsi[i].iomem); 310 311 memory_region_add_subregion(&s->opb[i].mr, 0xa0000000, 312 &s->fsi[i].opb2fsi); 313 } 314 } 315 316 static void fsi_aspeed_apb2opb_reset(DeviceState *dev) 317 { 318 AspeedAPB2OPBState *s = ASPEED_APB2OPB(dev); 319 320 memcpy(s->regs, aspeed_apb2opb_reset, ASPEED_APB2OPB_NR_REGS); 321 } 322 323 static void fsi_aspeed_apb2opb_class_init(ObjectClass *klass, void *data) 324 { 325 DeviceClass *dc = DEVICE_CLASS(klass); 326 327 dc->desc = "ASPEED APB2OPB Bridge"; 328 dc->realize = fsi_aspeed_apb2opb_realize; 329 dc->reset = fsi_aspeed_apb2opb_reset; 330 } 331 332 static const TypeInfo aspeed_apb2opb_info = { 333 .name = TYPE_ASPEED_APB2OPB, 334 .parent = TYPE_SYS_BUS_DEVICE, 335 .instance_init = fsi_aspeed_apb2opb_init, 336 .instance_size = sizeof(AspeedAPB2OPBState), 337 .class_init = fsi_aspeed_apb2opb_class_init, 338 }; 339 340 static void aspeed_apb2opb_register_types(void) 341 { 342 type_register_static(&aspeed_apb2opb_info); 343 } 344 345 type_init(aspeed_apb2opb_register_types); 346 347 static void fsi_opb_init(Object *o) 348 { 349 OPBus *opb = OP_BUS(o); 350 351 memory_region_init(&opb->mr, 0, TYPE_FSI_OPB, UINT32_MAX); 352 address_space_init(&opb->as, &opb->mr, TYPE_FSI_OPB); 353 } 354 355 static const TypeInfo opb_info = { 356 .name = TYPE_OP_BUS, 357 .parent = TYPE_BUS, 358 .instance_init = fsi_opb_init, 359 .instance_size = sizeof(OPBus), 360 }; 361 362 static void fsi_opb_register_types(void) 363 { 364 type_register_static(&opb_info); 365 } 366 367 type_init(fsi_opb_register_types); 368