2
0

versatile_pci.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. /*
  2. * ARM Versatile/PB PCI host controller
  3. *
  4. * Copyright (c) 2006-2009 CodeSourcery.
  5. * Written by Paul Brook
  6. *
  7. * This code is licensed under the LGPL.
  8. */
  9. #include "sysbus.h"
  10. #include "pci.h"
  11. #include "pci_host.h"
  12. typedef struct {
  13. SysBusDevice busdev;
  14. qemu_irq irq[4];
  15. int realview;
  16. int mem_config;
  17. } PCIVPBState;
  18. static inline uint32_t vpb_pci_config_addr(target_phys_addr_t addr)
  19. {
  20. return addr & 0xffffff;
  21. }
  22. static void pci_vpb_config_writeb (void *opaque, target_phys_addr_t addr,
  23. uint32_t val)
  24. {
  25. pci_data_write(opaque, vpb_pci_config_addr (addr), val, 1);
  26. }
  27. static void pci_vpb_config_writew (void *opaque, target_phys_addr_t addr,
  28. uint32_t val)
  29. {
  30. pci_data_write(opaque, vpb_pci_config_addr (addr), val, 2);
  31. }
  32. static void pci_vpb_config_writel (void *opaque, target_phys_addr_t addr,
  33. uint32_t val)
  34. {
  35. pci_data_write(opaque, vpb_pci_config_addr (addr), val, 4);
  36. }
  37. static uint32_t pci_vpb_config_readb (void *opaque, target_phys_addr_t addr)
  38. {
  39. uint32_t val;
  40. val = pci_data_read(opaque, vpb_pci_config_addr (addr), 1);
  41. return val;
  42. }
  43. static uint32_t pci_vpb_config_readw (void *opaque, target_phys_addr_t addr)
  44. {
  45. uint32_t val;
  46. val = pci_data_read(opaque, vpb_pci_config_addr (addr), 2);
  47. return val;
  48. }
  49. static uint32_t pci_vpb_config_readl (void *opaque, target_phys_addr_t addr)
  50. {
  51. uint32_t val;
  52. val = pci_data_read(opaque, vpb_pci_config_addr (addr), 4);
  53. return val;
  54. }
  55. static CPUWriteMemoryFunc * const pci_vpb_config_write[] = {
  56. &pci_vpb_config_writeb,
  57. &pci_vpb_config_writew,
  58. &pci_vpb_config_writel,
  59. };
  60. static CPUReadMemoryFunc * const pci_vpb_config_read[] = {
  61. &pci_vpb_config_readb,
  62. &pci_vpb_config_readw,
  63. &pci_vpb_config_readl,
  64. };
  65. static int pci_vpb_map_irq(PCIDevice *d, int irq_num)
  66. {
  67. return irq_num;
  68. }
  69. static void pci_vpb_set_irq(void *opaque, int irq_num, int level)
  70. {
  71. qemu_irq *pic = opaque;
  72. qemu_set_irq(pic[irq_num], level);
  73. }
  74. static void pci_vpb_map(SysBusDevice *dev, target_phys_addr_t base)
  75. {
  76. PCIVPBState *s = (PCIVPBState *)dev;
  77. /* Selfconfig area. */
  78. cpu_register_physical_memory(base + 0x01000000, 0x1000000, s->mem_config);
  79. /* Normal config area. */
  80. cpu_register_physical_memory(base + 0x02000000, 0x1000000, s->mem_config);
  81. if (s->realview) {
  82. /* IO memory area. */
  83. isa_mmio_init(base + 0x03000000, 0x00100000);
  84. }
  85. }
  86. static int pci_vpb_init(SysBusDevice *dev)
  87. {
  88. PCIVPBState *s = FROM_SYSBUS(PCIVPBState, dev);
  89. PCIBus *bus;
  90. int i;
  91. for (i = 0; i < 4; i++) {
  92. sysbus_init_irq(dev, &s->irq[i]);
  93. }
  94. bus = pci_register_bus(&dev->qdev, "pci",
  95. pci_vpb_set_irq, pci_vpb_map_irq, s->irq,
  96. PCI_DEVFN(11, 0), 4);
  97. /* ??? Register memory space. */
  98. s->mem_config = cpu_register_io_memory(pci_vpb_config_read,
  99. pci_vpb_config_write, bus,
  100. DEVICE_LITTLE_ENDIAN);
  101. sysbus_init_mmio_cb(dev, 0x04000000, pci_vpb_map);
  102. pci_create_simple(bus, -1, "versatile_pci_host");
  103. return 0;
  104. }
  105. static int pci_realview_init(SysBusDevice *dev)
  106. {
  107. PCIVPBState *s = FROM_SYSBUS(PCIVPBState, dev);
  108. s->realview = 1;
  109. return pci_vpb_init(dev);
  110. }
  111. static int versatile_pci_host_init(PCIDevice *d)
  112. {
  113. pci_set_word(d->config + PCI_STATUS,
  114. PCI_STATUS_66MHZ | PCI_STATUS_DEVSEL_MEDIUM);
  115. pci_set_byte(d->config + PCI_LATENCY_TIMER, 0x10);
  116. return 0;
  117. }
  118. static PCIDeviceInfo versatile_pci_host_info = {
  119. .qdev.name = "versatile_pci_host",
  120. .qdev.size = sizeof(PCIDevice),
  121. .init = versatile_pci_host_init,
  122. .vendor_id = PCI_VENDOR_ID_XILINX,
  123. /* Both boards have the same device ID. Oh well. */
  124. .device_id = PCI_DEVICE_ID_XILINX_XC2VP30,
  125. .class_id = PCI_CLASS_PROCESSOR_CO,
  126. };
  127. static void versatile_pci_register_devices(void)
  128. {
  129. sysbus_register_dev("versatile_pci", sizeof(PCIVPBState), pci_vpb_init);
  130. sysbus_register_dev("realview_pci", sizeof(PCIVPBState),
  131. pci_realview_init);
  132. pci_qdev_register(&versatile_pci_host_info);
  133. }
  134. device_init(versatile_pci_register_devices)