versatile_pci.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. /*
  2. * ARM Versatile/PB PCI host controller
  3. *
  4. * Copyright (c) 2006 CodeSourcery.
  5. * Written by Paul Brook
  6. *
  7. * This code is licenced under the LGPL.
  8. */
  9. #include "hw.h"
  10. #include "pci.h"
  11. #include "primecell.h"
  12. static inline uint32_t vpb_pci_config_addr(target_phys_addr_t addr)
  13. {
  14. return addr & 0xffffff;
  15. }
  16. static void pci_vpb_config_writeb (void *opaque, target_phys_addr_t addr,
  17. uint32_t val)
  18. {
  19. pci_data_write(opaque, vpb_pci_config_addr (addr), val, 1);
  20. }
  21. static void pci_vpb_config_writew (void *opaque, target_phys_addr_t addr,
  22. uint32_t val)
  23. {
  24. #ifdef TARGET_WORDS_BIGENDIAN
  25. val = bswap16(val);
  26. #endif
  27. pci_data_write(opaque, vpb_pci_config_addr (addr), val, 2);
  28. }
  29. static void pci_vpb_config_writel (void *opaque, target_phys_addr_t addr,
  30. uint32_t val)
  31. {
  32. #ifdef TARGET_WORDS_BIGENDIAN
  33. val = bswap32(val);
  34. #endif
  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. #ifdef TARGET_WORDS_BIGENDIAN
  48. val = bswap16(val);
  49. #endif
  50. return val;
  51. }
  52. static uint32_t pci_vpb_config_readl (void *opaque, target_phys_addr_t addr)
  53. {
  54. uint32_t val;
  55. val = pci_data_read(opaque, vpb_pci_config_addr (addr), 4);
  56. #ifdef TARGET_WORDS_BIGENDIAN
  57. val = bswap32(val);
  58. #endif
  59. return val;
  60. }
  61. static CPUWriteMemoryFunc *pci_vpb_config_write[] = {
  62. &pci_vpb_config_writeb,
  63. &pci_vpb_config_writew,
  64. &pci_vpb_config_writel,
  65. };
  66. static CPUReadMemoryFunc *pci_vpb_config_read[] = {
  67. &pci_vpb_config_readb,
  68. &pci_vpb_config_readw,
  69. &pci_vpb_config_readl,
  70. };
  71. static int pci_vpb_irq;
  72. static int pci_vpb_map_irq(PCIDevice *d, int irq_num)
  73. {
  74. return irq_num;
  75. }
  76. static void pci_vpb_set_irq(qemu_irq *pic, int irq_num, int level)
  77. {
  78. qemu_set_irq(pic[pci_vpb_irq + irq_num], level);
  79. }
  80. PCIBus *pci_vpb_init(qemu_irq *pic, int irq, int realview)
  81. {
  82. PCIBus *s;
  83. PCIDevice *d;
  84. int mem_config;
  85. uint32_t base;
  86. const char * name;
  87. pci_vpb_irq = irq;
  88. if (realview) {
  89. base = 0x60000000;
  90. name = "RealView EB PCI Controller";
  91. } else {
  92. base = 0x40000000;
  93. name = "Versatile/PB PCI Controller";
  94. }
  95. s = pci_register_bus(pci_vpb_set_irq, pci_vpb_map_irq, pic, 11 << 3, 4);
  96. /* ??? Register memory space. */
  97. mem_config = cpu_register_io_memory(0, pci_vpb_config_read,
  98. pci_vpb_config_write, s);
  99. /* Selfconfig area. */
  100. cpu_register_physical_memory(base + 0x01000000, 0x1000000, mem_config);
  101. /* Normal config area. */
  102. cpu_register_physical_memory(base + 0x02000000, 0x1000000, mem_config);
  103. d = pci_register_device(s, name, sizeof(PCIDevice), -1, NULL, NULL);
  104. if (realview) {
  105. /* IO memory area. */
  106. isa_mmio_init(base + 0x03000000, 0x00100000);
  107. }
  108. pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_XILINX);
  109. /* Both boards have the same device ID. Oh well. */
  110. pci_config_set_device_id(d->config, 0x0300); // device_id
  111. d->config[0x04] = 0x00;
  112. d->config[0x05] = 0x00;
  113. d->config[0x06] = 0x20;
  114. d->config[0x07] = 0x02;
  115. d->config[0x08] = 0x00; // revision
  116. d->config[0x09] = 0x00; // programming i/f
  117. pci_config_set_class(d->config, PCI_CLASS_PROCESSOR_CO);
  118. d->config[0x0D] = 0x10; // latency_timer
  119. return s;
  120. }