| 1 | /* |
| 2 | * ARM MPS2 SCC emulation |
| 3 | * |
| 4 | * Copyright (c) 2017 Linaro Limited |
| 5 | * Written by Peter Maydell |
| 6 | * |
| 7 | * This program is free software; you can redistribute it and/or modify |
| 8 | * it under the terms of the GNU General Public License version 2 or |
| 9 | * (at your option) any later version. |
| 10 | */ |
| 11 | |
| 12 | /* This is a model of the SCC (Serial Communication Controller) |
| 13 | * found in the FPGA images of MPS2 development boards. |
| 14 | * |
| 15 | * Documentation of it can be found in the MPS2 TRM: |
| 16 | * https://developer.arm.com/documentation/100112/latest/ |
| 17 | * and also in the Application Notes documenting individual FPGA images. |
| 18 | */ |
| 19 | |
| 20 | #include "qemu/osdep.h" |
| 21 | #include "qemu/log.h" |
| 22 | #include "qemu/module.h" |
| 23 | #include "qemu/bitops.h" |
| 24 | #include "trace.h" |
| 25 | #include "hw/core/sysbus.h" |
| 26 | #include "hw/core/irq.h" |
| 27 | #include "migration/vmstate.h" |
| 28 | #include "hw/core/registerfields.h" |
| 29 | #include "hw/misc/mps2-scc.h" |
| 30 | #include "hw/misc/led.h" |
| 31 | #include "hw/core/qdev-properties.h" |
| 32 | |
| 33 | REG32(CFG0, 0) |
| 34 | REG32(CFG1, 4) |
| 35 | REG32(CFG2, 8) |
| 36 | REG32(CFG3, 0xc) |
| 37 | REG32(CFG4, 0x10) |
| 38 | REG32(CFG5, 0x14) |
| 39 | REG32(CFG6, 0x18) |
| 40 | REG32(CFG7, 0x1c) |
| 41 | REG32(CFGDATA_RTN, 0xa0) |
| 42 | REG32(CFGDATA_OUT, 0xa4) |
| 43 | REG32(CFGCTRL, 0xa8) |
| 44 | FIELD(CFGCTRL, DEVICE, 0, 12) |
| 45 | FIELD(CFGCTRL, RES1, 12, 8) |
| 46 | FIELD(CFGCTRL, FUNCTION, 20, 6) |
| 47 | FIELD(CFGCTRL, RES2, 26, 4) |
| 48 | FIELD(CFGCTRL, WRITE, 30, 1) |
| 49 | FIELD(CFGCTRL, START, 31, 1) |
| 50 | REG32(CFGSTAT, 0xac) |
| 51 | FIELD(CFGSTAT, DONE, 0, 1) |
| 52 | FIELD(CFGSTAT, ERROR, 1, 1) |
| 53 | REG32(DLL, 0x100) |
| 54 | REG32(AID, 0xFF8) |
| 55 | REG32(ID, 0xFFC) |
| 56 | |
| 57 | static int scc_partno(MPS2SCC *s) |
| 58 | { |
| 59 | /* Return the partno field of the SCC_ID (0x524, 0x511, etc) */ |
| 60 | return extract32(s->id, 4, 12); |
| 61 | } |
| 62 | |
| 63 | /* Is CFG_REG2 present? */ |
| 64 | static bool have_cfg2(MPS2SCC *s) |
| 65 | { |
| 66 | return scc_partno(s) == 0x524 || scc_partno(s) == 0x547 || |
| 67 | scc_partno(s) == 0x536; |
| 68 | } |
| 69 | |
| 70 | /* Is CFG_REG3 present? */ |
| 71 | static bool have_cfg3(MPS2SCC *s) |
| 72 | { |
| 73 | return scc_partno(s) != 0x524 && scc_partno(s) != 0x547 && |
| 74 | scc_partno(s) != 0x536; |
| 75 | } |
| 76 | |
| 77 | /* Is CFG_REG5 present? */ |
| 78 | static bool have_cfg5(MPS2SCC *s) |
| 79 | { |
| 80 | return scc_partno(s) == 0x524 || scc_partno(s) == 0x547 || |
| 81 | scc_partno(s) == 0x536; |
| 82 | } |
| 83 | |
| 84 | /* Is CFG_REG6 present? */ |
| 85 | static bool have_cfg6(MPS2SCC *s) |
| 86 | { |
| 87 | return scc_partno(s) == 0x524 || scc_partno(s) == 0x536; |
| 88 | } |
| 89 | |
| 90 | /* Is CFG_REG7 present? */ |
| 91 | static bool have_cfg7(MPS2SCC *s) |
| 92 | { |
| 93 | return scc_partno(s) == 0x536; |
| 94 | } |
| 95 | |
| 96 | /* Does CFG_REG0 drive the 'remap' GPIO output? */ |
| 97 | static bool cfg0_is_remap(MPS2SCC *s) |
| 98 | { |
| 99 | return scc_partno(s) != 0x536; |
| 100 | } |
| 101 | |
| 102 | /* Is CFG_REG1 driving a set of LEDs? */ |
| 103 | static bool cfg1_is_leds(MPS2SCC *s) |
| 104 | { |
| 105 | return scc_partno(s) != 0x536; |
| 106 | } |
| 107 | |
| 108 | /* Handle a write via the SYS_CFG channel to the specified function/device. |
| 109 | * Return false on error (reported to guest via SYS_CFGCTRL ERROR bit). |
| 110 | */ |
| 111 | static bool scc_cfg_write(MPS2SCC *s, unsigned function, |
| 112 | unsigned device, uint32_t value) |
| 113 | { |
| 114 | trace_mps2_scc_cfg_write(function, device, value); |
| 115 | |
| 116 | if (function != 1 || device >= s->num_oscclk) { |
| 117 | qemu_log_mask(LOG_GUEST_ERROR, |
| 118 | "MPS2 SCC config write: bad function %d device %d\n", |
| 119 | function, device); |
| 120 | return false; |
| 121 | } |
| 122 | |
| 123 | s->oscclk[device] = value; |
| 124 | return true; |
| 125 | } |
| 126 | |
| 127 | /* Handle a read via the SYS_CFG channel to the specified function/device. |
| 128 | * Return false on error (reported to guest via SYS_CFGCTRL ERROR bit), |
| 129 | * or set *value on success. |
| 130 | */ |
| 131 | static bool scc_cfg_read(MPS2SCC *s, unsigned function, |
| 132 | unsigned device, uint32_t *value) |
| 133 | { |
| 134 | if (function != 1 || device >= s->num_oscclk) { |
| 135 | qemu_log_mask(LOG_GUEST_ERROR, |
| 136 | "MPS2 SCC config read: bad function %d device %d\n", |
| 137 | function, device); |
| 138 | return false; |
| 139 | } |
| 140 | |
| 141 | *value = s->oscclk[device]; |
| 142 | |
| 143 | trace_mps2_scc_cfg_read(function, device, *value); |
| 144 | return true; |
| 145 | } |
| 146 | |
| 147 | static uint64_t mps2_scc_read(void *opaque, hwaddr offset, unsigned size) |
| 148 | { |
| 149 | MPS2SCC *s = MPS2_SCC(opaque); |
| 150 | uint64_t r; |
| 151 | |
| 152 | switch (offset) { |
| 153 | case A_CFG0: |
| 154 | r = s->cfg0; |
| 155 | break; |
| 156 | case A_CFG1: |
| 157 | r = s->cfg1; |
| 158 | break; |
| 159 | case A_CFG2: |
| 160 | if (!have_cfg2(s)) { |
| 161 | goto bad_offset; |
| 162 | } |
| 163 | r = s->cfg2; |
| 164 | break; |
| 165 | case A_CFG3: |
| 166 | if (!have_cfg3(s)) { |
| 167 | goto bad_offset; |
| 168 | } |
| 169 | /* |
| 170 | * These are user-settable DIP switches on the board. We don't |
| 171 | * model that, so just return zeroes. |
| 172 | * |
| 173 | * TODO: for AN536 this is MCC_MSB_ADDR "additional MCC addressing |
| 174 | * bits". These change which part of the DDR4 the motherboard |
| 175 | * configuration controller can see in its memory map (see the |
| 176 | * appnote section 2.4). QEMU doesn't model the MCC at all, so these |
| 177 | * bits are not interesting to us; read-as-zero is as good as anything |
| 178 | * else. |
| 179 | */ |
| 180 | r = 0; |
| 181 | break; |
| 182 | case A_CFG4: |
| 183 | r = s->cfg4; |
| 184 | break; |
| 185 | case A_CFG5: |
| 186 | if (!have_cfg5(s)) { |
| 187 | goto bad_offset; |
| 188 | } |
| 189 | r = s->cfg5; |
| 190 | break; |
| 191 | case A_CFG6: |
| 192 | if (!have_cfg6(s)) { |
| 193 | goto bad_offset; |
| 194 | } |
| 195 | r = s->cfg6; |
| 196 | break; |
| 197 | case A_CFG7: |
| 198 | if (!have_cfg7(s)) { |
| 199 | goto bad_offset; |
| 200 | } |
| 201 | r = s->cfg7; |
| 202 | break; |
| 203 | case A_CFGDATA_RTN: |
| 204 | r = s->cfgdata_rtn; |
| 205 | break; |
| 206 | case A_CFGDATA_OUT: |
| 207 | r = s->cfgdata_out; |
| 208 | break; |
| 209 | case A_CFGCTRL: |
| 210 | r = s->cfgctrl; |
| 211 | break; |
| 212 | case A_CFGSTAT: |
| 213 | r = s->cfgstat; |
| 214 | break; |
| 215 | case A_DLL: |
| 216 | r = s->dll; |
| 217 | break; |
| 218 | case A_AID: |
| 219 | r = s->aid; |
| 220 | break; |
| 221 | case A_ID: |
| 222 | r = s->id; |
| 223 | break; |
| 224 | default: |
| 225 | bad_offset: |
| 226 | qemu_log_mask(LOG_GUEST_ERROR, |
| 227 | "MPS2 SCC read: bad offset %x\n", (int) offset); |
| 228 | r = 0; |
| 229 | break; |
| 230 | } |
| 231 | |
| 232 | trace_mps2_scc_read(offset, r, size); |
| 233 | return r; |
| 234 | } |
| 235 | |
| 236 | static void mps2_scc_write(void *opaque, hwaddr offset, uint64_t value, |
| 237 | unsigned size) |
| 238 | { |
| 239 | MPS2SCC *s = MPS2_SCC(opaque); |
| 240 | |
| 241 | trace_mps2_scc_write(offset, value, size); |
| 242 | |
| 243 | switch (offset) { |
| 244 | case A_CFG0: |
| 245 | /* |
| 246 | * On some boards bit 0 controls board-specific remapping; |
| 247 | * we always reflect bit 0 in the 'remap' GPIO output line, |
| 248 | * and let the board wire it up or not as it chooses. |
| 249 | * TODO on some boards bit 1 is CPU_WAIT. |
| 250 | * |
| 251 | * TODO: on the AN536 this register controls reset and halt |
| 252 | * for both CPUs. For the moment we don't implement this, so the |
| 253 | * register just reads as written. |
| 254 | */ |
| 255 | s->cfg0 = value; |
| 256 | if (cfg0_is_remap(s)) { |
| 257 | qemu_set_irq(s->remap, s->cfg0 & 1); |
| 258 | } |
| 259 | break; |
| 260 | case A_CFG1: |
| 261 | s->cfg1 = value; |
| 262 | /* |
| 263 | * On most boards this register drives LEDs. |
| 264 | * |
| 265 | * TODO: for AN536 this controls whether flash and ATCM are |
| 266 | * enabled or disabled on reset. QEMU doesn't model this, and |
| 267 | * always wires up RAM in the ATCM area and ROM in the flash area. |
| 268 | */ |
| 269 | if (cfg1_is_leds(s)) { |
| 270 | for (size_t i = 0; i < ARRAY_SIZE(s->led); i++) { |
| 271 | led_set_state(s->led[i], extract32(value, i, 1)); |
| 272 | } |
| 273 | } |
| 274 | break; |
| 275 | case A_CFG2: |
| 276 | if (!have_cfg2(s)) { |
| 277 | goto bad_offset; |
| 278 | } |
| 279 | /* AN524, AN536: QSPI Select signal */ |
| 280 | s->cfg2 = value; |
| 281 | break; |
| 282 | case A_CFG5: |
| 283 | if (!have_cfg5(s)) { |
| 284 | goto bad_offset; |
| 285 | } |
| 286 | /* AN524, AN536: ACLK frequency in Hz */ |
| 287 | s->cfg5 = value; |
| 288 | break; |
| 289 | case A_CFG6: |
| 290 | if (!have_cfg6(s)) { |
| 291 | goto bad_offset; |
| 292 | } |
| 293 | /* AN524: Clock divider for BRAM */ |
| 294 | /* AN536: Core 0 vector table base address */ |
| 295 | s->cfg6 = value; |
| 296 | break; |
| 297 | case A_CFG7: |
| 298 | if (!have_cfg7(s)) { |
| 299 | goto bad_offset; |
| 300 | } |
| 301 | /* AN536: Core 1 vector table base address */ |
| 302 | s->cfg7 = value; |
| 303 | break; |
| 304 | case A_CFGDATA_OUT: |
| 305 | s->cfgdata_out = value; |
| 306 | break; |
| 307 | case A_CFGCTRL: |
| 308 | /* Writing to CFGCTRL clears SYS_CFGSTAT */ |
| 309 | s->cfgstat = 0; |
| 310 | s->cfgctrl = value & ~(R_CFGCTRL_RES1_MASK | |
| 311 | R_CFGCTRL_RES2_MASK | |
| 312 | R_CFGCTRL_START_MASK); |
| 313 | |
| 314 | if (value & R_CFGCTRL_START_MASK) { |
| 315 | /* Start bit set -- do a read or write (instantaneously) */ |
| 316 | int device = extract32(s->cfgctrl, R_CFGCTRL_DEVICE_SHIFT, |
| 317 | R_CFGCTRL_DEVICE_LENGTH); |
| 318 | int function = extract32(s->cfgctrl, R_CFGCTRL_FUNCTION_SHIFT, |
| 319 | R_CFGCTRL_FUNCTION_LENGTH); |
| 320 | |
| 321 | s->cfgstat = R_CFGSTAT_DONE_MASK; |
| 322 | if (s->cfgctrl & R_CFGCTRL_WRITE_MASK) { |
| 323 | if (!scc_cfg_write(s, function, device, s->cfgdata_out)) { |
| 324 | s->cfgstat |= R_CFGSTAT_ERROR_MASK; |
| 325 | } |
| 326 | } else { |
| 327 | uint32_t result; |
| 328 | if (!scc_cfg_read(s, function, device, &result)) { |
| 329 | s->cfgstat |= R_CFGSTAT_ERROR_MASK; |
| 330 | } else { |
| 331 | s->cfgdata_rtn = result; |
| 332 | } |
| 333 | } |
| 334 | } |
| 335 | break; |
| 336 | case A_DLL: |
| 337 | /* DLL stands for Digital Locked Loop. |
| 338 | * Bits [31:24] (DLL_LOCK_MASK) are writable, and indicate a |
| 339 | * mask of which of the DLL_LOCKED bits [16:23] should be ORed |
| 340 | * together to determine the ALL_UNMASKED_DLLS_LOCKED bit [0]. |
| 341 | * For QEMU, our DLLs are always locked, so we can leave bit 0 |
| 342 | * as 1 always and don't need to recalculate it. |
| 343 | */ |
| 344 | s->dll = deposit32(s->dll, 24, 8, extract32(value, 24, 8)); |
| 345 | break; |
| 346 | default: |
| 347 | bad_offset: |
| 348 | qemu_log_mask(LOG_GUEST_ERROR, |
| 349 | "MPS2 SCC write: bad offset 0x%x\n", (int) offset); |
| 350 | break; |
| 351 | } |
| 352 | } |
| 353 | |
| 354 | static const MemoryRegionOps mps2_scc_ops = { |
| 355 | .read = mps2_scc_read, |
| 356 | .write = mps2_scc_write, |
| 357 | .endianness = DEVICE_LITTLE_ENDIAN, |
| 358 | }; |
| 359 | |
| 360 | static void mps2_scc_reset(DeviceState *dev) |
| 361 | { |
| 362 | MPS2SCC *s = MPS2_SCC(dev); |
| 363 | int i; |
| 364 | |
| 365 | trace_mps2_scc_reset(); |
| 366 | s->cfg0 = s->cfg0_reset; |
| 367 | s->cfg1 = 0; |
| 368 | s->cfg2 = 0; |
| 369 | s->cfg5 = 0; |
| 370 | s->cfg6 = 0; |
| 371 | s->cfgdata_rtn = 0; |
| 372 | s->cfgdata_out = 0; |
| 373 | s->cfgctrl = 0x100000; |
| 374 | s->cfgstat = 0; |
| 375 | s->dll = 0xffff0001; |
| 376 | for (i = 0; i < s->num_oscclk; i++) { |
| 377 | s->oscclk[i] = s->oscclk_reset[i]; |
| 378 | } |
| 379 | for (i = 0; i < ARRAY_SIZE(s->led); i++) { |
| 380 | device_cold_reset(DEVICE(s->led[i])); |
| 381 | } |
| 382 | } |
| 383 | |
| 384 | static void mps2_scc_init(Object *obj) |
| 385 | { |
| 386 | SysBusDevice *sbd = SYS_BUS_DEVICE(obj); |
| 387 | MPS2SCC *s = MPS2_SCC(obj); |
| 388 | |
| 389 | memory_region_init_io(&s->iomem, obj, &mps2_scc_ops, s, "mps2-scc", 0x1000); |
| 390 | sysbus_init_mmio(sbd, &s->iomem); |
| 391 | qdev_init_gpio_out_named(DEVICE(obj), &s->remap, "remap", 1); |
| 392 | } |
| 393 | |
| 394 | static void mps2_scc_realize(DeviceState *dev, Error **errp) |
| 395 | { |
| 396 | MPS2SCC *s = MPS2_SCC(dev); |
| 397 | |
| 398 | for (size_t i = 0; i < ARRAY_SIZE(s->led); i++) { |
| 399 | char *name = g_strdup_printf("SCC LED%zu", i); |
| 400 | s->led[i] = led_create_simple(OBJECT(dev), GPIO_POLARITY_ACTIVE_HIGH, |
| 401 | LED_COLOR_GREEN, name); |
| 402 | g_free(name); |
| 403 | } |
| 404 | |
| 405 | s->oscclk = g_new0(uint32_t, s->num_oscclk); |
| 406 | } |
| 407 | |
| 408 | static bool cfg7_needed(void *opaque) |
| 409 | { |
| 410 | MPS2SCC *s = opaque; |
| 411 | |
| 412 | return have_cfg7(s); |
| 413 | } |
| 414 | |
| 415 | static const VMStateDescription vmstate_cfg7 = { |
| 416 | .name = "mps2-scc/cfg7", |
| 417 | .version_id = 1, |
| 418 | .minimum_version_id = 1, |
| 419 | .needed = cfg7_needed, |
| 420 | .fields = (const VMStateField[]) { |
| 421 | VMSTATE_UINT32(cfg7, MPS2SCC), |
| 422 | VMSTATE_END_OF_LIST() |
| 423 | } |
| 424 | }; |
| 425 | |
| 426 | static const VMStateDescription mps2_scc_vmstate = { |
| 427 | .name = "mps2-scc", |
| 428 | .version_id = 3, |
| 429 | .minimum_version_id = 3, |
| 430 | .fields = (const VMStateField[]) { |
| 431 | VMSTATE_UINT32(cfg0, MPS2SCC), |
| 432 | VMSTATE_UINT32(cfg1, MPS2SCC), |
| 433 | VMSTATE_UINT32(cfg2, MPS2SCC), |
| 434 | /* cfg3, cfg4 are read-only so need not be migrated */ |
| 435 | VMSTATE_UINT32(cfg5, MPS2SCC), |
| 436 | VMSTATE_UINT32(cfg6, MPS2SCC), |
| 437 | VMSTATE_UINT32(cfgdata_rtn, MPS2SCC), |
| 438 | VMSTATE_UINT32(cfgdata_out, MPS2SCC), |
| 439 | VMSTATE_UINT32(cfgctrl, MPS2SCC), |
| 440 | VMSTATE_UINT32(cfgstat, MPS2SCC), |
| 441 | VMSTATE_UINT32(dll, MPS2SCC), |
| 442 | VMSTATE_VARRAY_UINT32(oscclk, MPS2SCC, num_oscclk, |
| 443 | 0, vmstate_info_uint32, uint32_t), |
| 444 | VMSTATE_END_OF_LIST() |
| 445 | }, |
| 446 | .subsections = (const VMStateDescription * const []) { |
| 447 | &vmstate_cfg7, |
| 448 | NULL |
| 449 | } |
| 450 | }; |
| 451 | |
| 452 | static const Property mps2_scc_properties[] = { |
| 453 | /* Values for various read-only ID registers (which are specific |
| 454 | * to the board model or FPGA image) |
| 455 | */ |
| 456 | DEFINE_PROP_UINT32("scc-cfg4", MPS2SCC, cfg4, 0), |
| 457 | DEFINE_PROP_UINT32("scc-aid", MPS2SCC, aid, 0), |
| 458 | DEFINE_PROP_UINT32("scc-id", MPS2SCC, id, 0), |
| 459 | /* Reset value for CFG0 register */ |
| 460 | DEFINE_PROP_UINT32("scc-cfg0", MPS2SCC, cfg0_reset, 0), |
| 461 | /* |
| 462 | * These are the initial settings for the source clocks on the board. |
| 463 | * In hardware they can be configured via a config file read by the |
| 464 | * motherboard configuration controller to suit the FPGA image. |
| 465 | */ |
| 466 | DEFINE_PROP_ARRAY("oscclk", MPS2SCC, num_oscclk, oscclk_reset, |
| 467 | qdev_prop_uint32, uint32_t), |
| 468 | }; |
| 469 | |
| 470 | static void mps2_scc_class_init(ObjectClass *klass, const void *data) |
| 471 | { |
| 472 | DeviceClass *dc = DEVICE_CLASS(klass); |
| 473 | |
| 474 | dc->realize = mps2_scc_realize; |
| 475 | dc->vmsd = &mps2_scc_vmstate; |
| 476 | device_class_set_legacy_reset(dc, mps2_scc_reset); |
| 477 | device_class_set_props(dc, mps2_scc_properties); |
| 478 | } |
| 479 | |
| 480 | static const TypeInfo mps2_scc_info = { |
| 481 | .name = TYPE_MPS2_SCC, |
| 482 | .parent = TYPE_SYS_BUS_DEVICE, |
| 483 | .instance_size = sizeof(MPS2SCC), |
| 484 | .instance_init = mps2_scc_init, |
| 485 | .class_init = mps2_scc_class_init, |
| 486 | }; |
| 487 | |
| 488 | static void mps2_scc_register_types(void) |
| 489 | { |
| 490 | type_register_static(&mps2_scc_info); |
| 491 | } |
| 492 | |
| 493 | type_init(mps2_scc_register_types); |