tpci200.c (19098B)
1/* 2 * QEMU TEWS TPCI200 IndustryPack carrier emulation 3 * 4 * Copyright (C) 2012 Igalia, S.L. 5 * Author: Alberto Garcia <berto@igalia.com> 6 * 7 * This code is licensed under the GNU GPL v2 or (at your option) any 8 * later version. 9 */ 10 11#include "qemu/osdep.h" 12#include "qemu/units.h" 13#include "hw/ipack/ipack.h" 14#include "hw/irq.h" 15#include "hw/pci/pci.h" 16#include "migration/vmstate.h" 17#include "qemu/bitops.h" 18#include "qemu/module.h" 19#include "qom/object.h" 20 21/* #define DEBUG_TPCI */ 22 23#ifdef DEBUG_TPCI 24#define DPRINTF(fmt, ...) \ 25 do { fprintf(stderr, "TPCI200: " fmt, ## __VA_ARGS__); } while (0) 26#else 27#define DPRINTF(fmt, ...) do { } while (0) 28#endif 29 30#define N_MODULES 4 31 32#define IP_ID_SPACE 2 33#define IP_INT_SPACE 3 34#define IP_IO_SPACE_ADDR_MASK 0x7F 35#define IP_ID_SPACE_ADDR_MASK 0x3F 36#define IP_INT_SPACE_ADDR_MASK 0x3F 37 38#define STATUS_INT(IP, INTNO) BIT((IP) * 2 + (INTNO)) 39#define STATUS_TIME(IP) BIT((IP) + 12) 40#define STATUS_ERR_ANY 0xF00 41 42#define CTRL_CLKRATE BIT(0) 43#define CTRL_RECOVER BIT(1) 44#define CTRL_TIME_INT BIT(2) 45#define CTRL_ERR_INT BIT(3) 46#define CTRL_INT_EDGE(INTNO) BIT(4 + (INTNO)) 47#define CTRL_INT(INTNO) BIT(6 + (INTNO)) 48 49#define REG_REV_ID 0x00 50#define REG_IP_A_CTRL 0x02 51#define REG_IP_B_CTRL 0x04 52#define REG_IP_C_CTRL 0x06 53#define REG_IP_D_CTRL 0x08 54#define REG_RESET 0x0A 55#define REG_STATUS 0x0C 56#define IP_N_FROM_REG(REG) ((REG) / 2 - 1) 57 58struct TPCI200State { 59 PCIDevice dev; 60 IPackBus bus; 61 MemoryRegion mmio; 62 MemoryRegion io; 63 MemoryRegion las0; 64 MemoryRegion las1; 65 MemoryRegion las2; 66 MemoryRegion las3; 67 bool big_endian[3]; 68 uint8_t ctrl[N_MODULES]; 69 uint16_t status; 70 uint8_t int_set; 71}; 72 73#define TYPE_TPCI200 "tpci200" 74 75OBJECT_DECLARE_SIMPLE_TYPE(TPCI200State, TPCI200) 76 77static const uint8_t local_config_regs[] = { 78 0x00, 0xFF, 0xFF, 0x0F, 0x00, 0xFC, 0xFF, 0x0F, 0x00, 0x00, 0x00, 79 0x0E, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 80 0x00, 0x08, 0x01, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x00, 0x01, 81 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0xA0, 0x60, 0x41, 0xD4, 82 0xA2, 0x20, 0x41, 0x14, 0xA2, 0x20, 0x41, 0x14, 0xA2, 0x20, 0x01, 83 0x14, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x08, 0x01, 0x02, 84 0x00, 0x04, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x80, 0x02, 0x41, 85 0x00, 0x00, 0x00, 0x00, 0x40, 0x7A, 0x00, 0x52, 0x92, 0x24, 0x02 86}; 87 88static void adjust_addr(bool big_endian, hwaddr *addr, unsigned size) 89{ 90 /* During 8 bit access in big endian mode, 91 odd and even addresses are swapped */ 92 if (big_endian && size == 1) { 93 *addr ^= 1; 94 } 95} 96 97static uint64_t adjust_value(bool big_endian, uint64_t *val, unsigned size) 98{ 99 /* Local spaces only support 8/16 bit access, 100 * so there's no need to care for sizes > 2 */ 101 if (big_endian && size == 2) { 102 *val = bswap16(*val); 103 } 104 return *val; 105} 106 107static void tpci200_set_irq(void *opaque, int intno, int level) 108{ 109 IPackDevice *ip = opaque; 110 IPackBus *bus = IPACK_BUS(qdev_get_parent_bus(DEVICE(ip))); 111 PCIDevice *pcidev = PCI_DEVICE(BUS(bus)->parent); 112 TPCI200State *dev = TPCI200(pcidev); 113 unsigned ip_n = ip->slot; 114 uint16_t prev_status = dev->status; 115 116 assert(ip->slot >= 0 && ip->slot < N_MODULES); 117 118 /* The requested interrupt must be enabled in the IP CONTROL 119 * register */ 120 if (!(dev->ctrl[ip_n] & CTRL_INT(intno))) { 121 return; 122 } 123 124 /* Update the interrupt status in the IP STATUS register */ 125 if (level) { 126 dev->status |= STATUS_INT(ip_n, intno); 127 } else { 128 dev->status &= ~STATUS_INT(ip_n, intno); 129 } 130 131 /* Return if there are no changes */ 132 if (dev->status == prev_status) { 133 return; 134 } 135 136 DPRINTF("IP %u INT%u#: %u\n", ip_n, intno, level); 137 138 /* Check if the interrupt is edge sensitive */ 139 if (dev->ctrl[ip_n] & CTRL_INT_EDGE(intno)) { 140 if (level) { 141 pci_set_irq(&dev->dev, !dev->int_set); 142 pci_set_irq(&dev->dev, dev->int_set); 143 } 144 } else { 145 unsigned i, j; 146 uint16_t level_status = dev->status; 147 148 /* Check if there are any level sensitive interrupts set by 149 removing the ones that are edge sensitive from the status 150 register */ 151 for (i = 0; i < N_MODULES; i++) { 152 for (j = 0; j < 2; j++) { 153 if (dev->ctrl[i] & CTRL_INT_EDGE(j)) { 154 level_status &= ~STATUS_INT(i, j); 155 } 156 } 157 } 158 159 if (level_status && !dev->int_set) { 160 pci_irq_assert(&dev->dev); 161 dev->int_set = 1; 162 } else if (!level_status && dev->int_set) { 163 pci_irq_deassert(&dev->dev); 164 dev->int_set = 0; 165 } 166 } 167} 168 169static uint64_t tpci200_read_cfg(void *opaque, hwaddr addr, unsigned size) 170{ 171 TPCI200State *s = opaque; 172 uint8_t ret = 0; 173 if (addr < ARRAY_SIZE(local_config_regs)) { 174 ret = local_config_regs[addr]; 175 } 176 /* Endianness is stored in the first bit of these registers */ 177 if ((addr == 0x2b && s->big_endian[0]) || 178 (addr == 0x2f && s->big_endian[1]) || 179 (addr == 0x33 && s->big_endian[2])) { 180 ret |= 1; 181 } 182 DPRINTF("Read from LCR 0x%x: 0x%x\n", (unsigned) addr, (unsigned) ret); 183 return ret; 184} 185 186static void tpci200_write_cfg(void *opaque, hwaddr addr, uint64_t val, 187 unsigned size) 188{ 189 TPCI200State *s = opaque; 190 /* Endianness is stored in the first bit of these registers */ 191 if (addr == 0x2b || addr == 0x2f || addr == 0x33) { 192 unsigned las = (addr - 0x2b) / 4; 193 s->big_endian[las] = val & 1; 194 DPRINTF("LAS%u big endian mode: %u\n", las, (unsigned) val & 1); 195 } else { 196 DPRINTF("Write to LCR 0x%x: 0x%x\n", (unsigned) addr, (unsigned) val); 197 } 198} 199 200static uint64_t tpci200_read_las0(void *opaque, hwaddr addr, unsigned size) 201{ 202 TPCI200State *s = opaque; 203 uint64_t ret = 0; 204 205 switch (addr) { 206 207 case REG_REV_ID: 208 DPRINTF("Read REVISION ID\n"); /* Current value is 0x00 */ 209 break; 210 211 case REG_IP_A_CTRL: 212 case REG_IP_B_CTRL: 213 case REG_IP_C_CTRL: 214 case REG_IP_D_CTRL: 215 { 216 unsigned ip_n = IP_N_FROM_REG(addr); 217 ret = s->ctrl[ip_n]; 218 DPRINTF("Read IP %c CONTROL: 0x%x\n", 'A' + ip_n, (unsigned) ret); 219 } 220 break; 221 222 case REG_RESET: 223 DPRINTF("Read RESET\n"); /* Not implemented */ 224 break; 225 226 case REG_STATUS: 227 ret = s->status; 228 DPRINTF("Read STATUS: 0x%x\n", (unsigned) ret); 229 break; 230 231 /* Reserved */ 232 default: 233 DPRINTF("Unsupported read from LAS0 0x%x\n", (unsigned) addr); 234 break; 235 } 236 237 return adjust_value(s->big_endian[0], &ret, size); 238} 239 240static void tpci200_write_las0(void *opaque, hwaddr addr, uint64_t val, 241 unsigned size) 242{ 243 TPCI200State *s = opaque; 244 245 adjust_value(s->big_endian[0], &val, size); 246 247 switch (addr) { 248 249 case REG_REV_ID: 250 DPRINTF("Write Revision ID: 0x%x\n", (unsigned) val); /* No effect */ 251 break; 252 253 case REG_IP_A_CTRL: 254 case REG_IP_B_CTRL: 255 case REG_IP_C_CTRL: 256 case REG_IP_D_CTRL: 257 { 258 unsigned ip_n = IP_N_FROM_REG(addr); 259 s->ctrl[ip_n] = val; 260 DPRINTF("Write IP %c CONTROL: 0x%x\n", 'A' + ip_n, (unsigned) val); 261 } 262 break; 263 264 case REG_RESET: 265 DPRINTF("Write RESET: 0x%x\n", (unsigned) val); /* Not implemented */ 266 break; 267 268 case REG_STATUS: 269 { 270 unsigned i; 271 272 for (i = 0; i < N_MODULES; i++) { 273 IPackDevice *ip = ipack_device_find(&s->bus, i); 274 275 if (ip != NULL) { 276 if (val & STATUS_INT(i, 0)) { 277 DPRINTF("Clear IP %c INT0# status\n", 'A' + i); 278 qemu_irq_lower(ip->irq[0]); 279 } 280 if (val & STATUS_INT(i, 1)) { 281 DPRINTF("Clear IP %c INT1# status\n", 'A' + i); 282 qemu_irq_lower(ip->irq[1]); 283 } 284 } 285 286 if (val & STATUS_TIME(i)) { 287 DPRINTF("Clear IP %c timeout\n", 'A' + i); 288 s->status &= ~STATUS_TIME(i); 289 } 290 } 291 292 if (val & STATUS_ERR_ANY) { 293 DPRINTF("Unexpected write to STATUS register: 0x%x\n", 294 (unsigned) val); 295 } 296 } 297 break; 298 299 /* Reserved */ 300 default: 301 DPRINTF("Unsupported write to LAS0 0x%x: 0x%x\n", 302 (unsigned) addr, (unsigned) val); 303 break; 304 } 305} 306 307static uint64_t tpci200_read_las1(void *opaque, hwaddr addr, unsigned size) 308{ 309 TPCI200State *s = opaque; 310 IPackDevice *ip; 311 uint64_t ret = 0; 312 unsigned ip_n, space; 313 uint8_t offset; 314 315 adjust_addr(s->big_endian[1], &addr, size); 316 317 /* 318 * The address is divided into the IP module number (0-4), the IP 319 * address space (I/O, ID, INT) and the offset within that space. 320 */ 321 ip_n = addr >> 8; 322 space = (addr >> 6) & 3; 323 ip = ipack_device_find(&s->bus, ip_n); 324 325 if (ip == NULL) { 326 DPRINTF("Read LAS1: IP module %u not installed\n", ip_n); 327 } else { 328 IPackDeviceClass *k = IPACK_DEVICE_GET_CLASS(ip); 329 switch (space) { 330 331 case IP_ID_SPACE: 332 offset = addr & IP_ID_SPACE_ADDR_MASK; 333 if (k->id_read) { 334 ret = k->id_read(ip, offset); 335 } 336 break; 337 338 case IP_INT_SPACE: 339 offset = addr & IP_INT_SPACE_ADDR_MASK; 340 341 /* Read address 0 to ACK IP INT0# and address 2 to ACK IP INT1# */ 342 if (offset == 0 || offset == 2) { 343 unsigned intno = offset / 2; 344 bool int_set = s->status & STATUS_INT(ip_n, intno); 345 bool int_edge_sensitive = s->ctrl[ip_n] & CTRL_INT_EDGE(intno); 346 if (int_set && !int_edge_sensitive) { 347 qemu_irq_lower(ip->irq[intno]); 348 } 349 } 350 351 if (k->int_read) { 352 ret = k->int_read(ip, offset); 353 } 354 break; 355 356 default: 357 offset = addr & IP_IO_SPACE_ADDR_MASK; 358 if (k->io_read) { 359 ret = k->io_read(ip, offset); 360 } 361 break; 362 } 363 } 364 365 return adjust_value(s->big_endian[1], &ret, size); 366} 367 368static void tpci200_write_las1(void *opaque, hwaddr addr, uint64_t val, 369 unsigned size) 370{ 371 TPCI200State *s = opaque; 372 IPackDevice *ip; 373 unsigned ip_n, space; 374 uint8_t offset; 375 376 adjust_addr(s->big_endian[1], &addr, size); 377 adjust_value(s->big_endian[1], &val, size); 378 379 /* 380 * The address is divided into the IP module number, the IP 381 * address space (I/O, ID, INT) and the offset within that space. 382 */ 383 ip_n = addr >> 8; 384 space = (addr >> 6) & 3; 385 ip = ipack_device_find(&s->bus, ip_n); 386 387 if (ip == NULL) { 388 DPRINTF("Write LAS1: IP module %u not installed\n", ip_n); 389 } else { 390 IPackDeviceClass *k = IPACK_DEVICE_GET_CLASS(ip); 391 switch (space) { 392 393 case IP_ID_SPACE: 394 offset = addr & IP_ID_SPACE_ADDR_MASK; 395 if (k->id_write) { 396 k->id_write(ip, offset, val); 397 } 398 break; 399 400 case IP_INT_SPACE: 401 offset = addr & IP_INT_SPACE_ADDR_MASK; 402 if (k->int_write) { 403 k->int_write(ip, offset, val); 404 } 405 break; 406 407 default: 408 offset = addr & IP_IO_SPACE_ADDR_MASK; 409 if (k->io_write) { 410 k->io_write(ip, offset, val); 411 } 412 break; 413 } 414 } 415} 416 417static uint64_t tpci200_read_las2(void *opaque, hwaddr addr, unsigned size) 418{ 419 TPCI200State *s = opaque; 420 IPackDevice *ip; 421 uint64_t ret = 0; 422 unsigned ip_n; 423 uint32_t offset; 424 425 adjust_addr(s->big_endian[2], &addr, size); 426 427 /* 428 * The address is divided into the IP module number and the offset 429 * within the IP module MEM space. 430 */ 431 ip_n = addr >> 23; 432 offset = addr & 0x7fffff; 433 ip = ipack_device_find(&s->bus, ip_n); 434 435 if (ip == NULL) { 436 DPRINTF("Read LAS2: IP module %u not installed\n", ip_n); 437 } else { 438 IPackDeviceClass *k = IPACK_DEVICE_GET_CLASS(ip); 439 if (k->mem_read16) { 440 ret = k->mem_read16(ip, offset); 441 } 442 } 443 444 return adjust_value(s->big_endian[2], &ret, size); 445} 446 447static void tpci200_write_las2(void *opaque, hwaddr addr, uint64_t val, 448 unsigned size) 449{ 450 TPCI200State *s = opaque; 451 IPackDevice *ip; 452 unsigned ip_n; 453 uint32_t offset; 454 455 adjust_addr(s->big_endian[2], &addr, size); 456 adjust_value(s->big_endian[2], &val, size); 457 458 /* 459 * The address is divided into the IP module number and the offset 460 * within the IP module MEM space. 461 */ 462 ip_n = addr >> 23; 463 offset = addr & 0x7fffff; 464 ip = ipack_device_find(&s->bus, ip_n); 465 466 if (ip == NULL) { 467 DPRINTF("Write LAS2: IP module %u not installed\n", ip_n); 468 } else { 469 IPackDeviceClass *k = IPACK_DEVICE_GET_CLASS(ip); 470 if (k->mem_write16) { 471 k->mem_write16(ip, offset, val); 472 } 473 } 474} 475 476static uint64_t tpci200_read_las3(void *opaque, hwaddr addr, unsigned size) 477{ 478 TPCI200State *s = opaque; 479 IPackDevice *ip; 480 uint64_t ret = 0; 481 /* 482 * The address is divided into the IP module number and the offset 483 * within the IP module MEM space. 484 */ 485 unsigned ip_n = addr >> 22; 486 uint32_t offset = addr & 0x3fffff; 487 488 ip = ipack_device_find(&s->bus, ip_n); 489 490 if (ip == NULL) { 491 DPRINTF("Read LAS3: IP module %u not installed\n", ip_n); 492 } else { 493 IPackDeviceClass *k = IPACK_DEVICE_GET_CLASS(ip); 494 if (k->mem_read8) { 495 ret = k->mem_read8(ip, offset); 496 } 497 } 498 499 return ret; 500} 501 502static void tpci200_write_las3(void *opaque, hwaddr addr, uint64_t val, 503 unsigned size) 504{ 505 TPCI200State *s = opaque; 506 IPackDevice *ip; 507 /* 508 * The address is divided into the IP module number and the offset 509 * within the IP module MEM space. 510 */ 511 unsigned ip_n = addr >> 22; 512 uint32_t offset = addr & 0x3fffff; 513 514 ip = ipack_device_find(&s->bus, ip_n); 515 516 if (ip == NULL) { 517 DPRINTF("Write LAS3: IP module %u not installed\n", ip_n); 518 } else { 519 IPackDeviceClass *k = IPACK_DEVICE_GET_CLASS(ip); 520 if (k->mem_write8) { 521 k->mem_write8(ip, offset, val); 522 } 523 } 524} 525 526static const MemoryRegionOps tpci200_cfg_ops = { 527 .read = tpci200_read_cfg, 528 .write = tpci200_write_cfg, 529 .endianness = DEVICE_NATIVE_ENDIAN, 530 .valid = { 531 .min_access_size = 1, 532 .max_access_size = 4 533 }, 534 .impl = { 535 .min_access_size = 1, 536 .max_access_size = 1 537 } 538}; 539 540static const MemoryRegionOps tpci200_las0_ops = { 541 .read = tpci200_read_las0, 542 .write = tpci200_write_las0, 543 .endianness = DEVICE_NATIVE_ENDIAN, 544 .valid = { 545 .min_access_size = 2, 546 .max_access_size = 2 547 } 548}; 549 550static const MemoryRegionOps tpci200_las1_ops = { 551 .read = tpci200_read_las1, 552 .write = tpci200_write_las1, 553 .endianness = DEVICE_NATIVE_ENDIAN, 554 .valid = { 555 .min_access_size = 1, 556 .max_access_size = 2 557 } 558}; 559 560static const MemoryRegionOps tpci200_las2_ops = { 561 .read = tpci200_read_las2, 562 .write = tpci200_write_las2, 563 .endianness = DEVICE_NATIVE_ENDIAN, 564 .valid = { 565 .min_access_size = 1, 566 .max_access_size = 2 567 } 568}; 569 570static const MemoryRegionOps tpci200_las3_ops = { 571 .read = tpci200_read_las3, 572 .write = tpci200_write_las3, 573 .endianness = DEVICE_NATIVE_ENDIAN, 574 .valid = { 575 .min_access_size = 1, 576 .max_access_size = 1 577 } 578}; 579 580static void tpci200_realize(PCIDevice *pci_dev, Error **errp) 581{ 582 TPCI200State *s = TPCI200(pci_dev); 583 uint8_t *c = s->dev.config; 584 585 pci_set_word(c + PCI_COMMAND, 0x0003); 586 pci_set_word(c + PCI_STATUS, 0x0280); 587 588 pci_set_byte(c + PCI_INTERRUPT_PIN, 0x01); /* Interrupt pin A */ 589 590 pci_set_byte(c + PCI_CAPABILITY_LIST, 0x40); 591 pci_set_long(c + 0x40, 0x48014801); 592 pci_set_long(c + 0x48, 0x00024C06); 593 pci_set_long(c + 0x4C, 0x00000003); 594 595 memory_region_init_io(&s->mmio, OBJECT(s), &tpci200_cfg_ops, 596 s, "tpci200_mmio", 128); 597 memory_region_init_io(&s->io, OBJECT(s), &tpci200_cfg_ops, 598 s, "tpci200_io", 128); 599 memory_region_init_io(&s->las0, OBJECT(s), &tpci200_las0_ops, 600 s, "tpci200_las0", 256); 601 memory_region_init_io(&s->las1, OBJECT(s), &tpci200_las1_ops, 602 s, "tpci200_las1", 1024); 603 memory_region_init_io(&s->las2, OBJECT(s), &tpci200_las2_ops, 604 s, "tpci200_las2", 32 * MiB); 605 memory_region_init_io(&s->las3, OBJECT(s), &tpci200_las3_ops, 606 s, "tpci200_las3", 16 * MiB); 607 pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mmio); 608 pci_register_bar(&s->dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &s->io); 609 pci_register_bar(&s->dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->las0); 610 pci_register_bar(&s->dev, 3, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->las1); 611 pci_register_bar(&s->dev, 4, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->las2); 612 pci_register_bar(&s->dev, 5, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->las3); 613 614 ipack_bus_init(&s->bus, sizeof(s->bus), DEVICE(pci_dev), 615 N_MODULES, tpci200_set_irq); 616} 617 618static const VMStateDescription vmstate_tpci200 = { 619 .name = "tpci200", 620 .version_id = 1, 621 .minimum_version_id = 1, 622 .fields = (VMStateField[]) { 623 VMSTATE_PCI_DEVICE(dev, TPCI200State), 624 VMSTATE_BOOL_ARRAY(big_endian, TPCI200State, 3), 625 VMSTATE_UINT8_ARRAY(ctrl, TPCI200State, N_MODULES), 626 VMSTATE_UINT16(status, TPCI200State), 627 VMSTATE_UINT8(int_set, TPCI200State), 628 VMSTATE_END_OF_LIST() 629 } 630}; 631 632static void tpci200_class_init(ObjectClass *klass, void *data) 633{ 634 DeviceClass *dc = DEVICE_CLASS(klass); 635 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); 636 637 k->realize = tpci200_realize; 638 k->vendor_id = PCI_VENDOR_ID_TEWS; 639 k->device_id = PCI_DEVICE_ID_TEWS_TPCI200; 640 k->class_id = PCI_CLASS_BRIDGE_OTHER; 641 k->subsystem_vendor_id = PCI_VENDOR_ID_TEWS; 642 k->subsystem_id = 0x300A; 643 set_bit(DEVICE_CATEGORY_INPUT, dc->categories); 644 dc->desc = "TEWS TPCI200 IndustryPack carrier"; 645 dc->vmsd = &vmstate_tpci200; 646} 647 648static const TypeInfo tpci200_info = { 649 .name = TYPE_TPCI200, 650 .parent = TYPE_PCI_DEVICE, 651 .instance_size = sizeof(TPCI200State), 652 .class_init = tpci200_class_init, 653 .interfaces = (InterfaceInfo[]) { 654 { INTERFACE_CONVENTIONAL_PCI_DEVICE }, 655 { }, 656 }, 657}; 658 659static void tpci200_register_types(void) 660{ 661 type_register_static(&tpci200_info); 662} 663 664type_init(tpci200_register_types)