pci-ocelot-c.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. /*
  2. * This file is subject to the terms and conditions of the GNU General Public
  3. * License. See the file "COPYING" in the main directory of this archive
  4. * for more details.
  5. *
  6. * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org)
  7. */
  8. #include <linux/types.h>
  9. #include <linux/pci.h>
  10. #include <asm/mv64340.h>
  11. #include <linux/init.h>
  12. /*
  13. * We assume the address ranges have already been setup appropriately by
  14. * the firmware. PMON in case of the Ocelot C does that.
  15. */
  16. static struct resource mv_pci_io_mem0_resource = {
  17. .name = "MV64340 PCI0 IO MEM",
  18. .flags = IORESOURCE_IO
  19. };
  20. static struct resource mv_pci_mem0_resource = {
  21. .name = "MV64340 PCI0 MEM",
  22. .flags = IORESOURCE_MEM
  23. };
  24. static struct mv_pci_controller mv_bus0_controller = {
  25. .pcic = {
  26. .pci_ops = &mv_pci_ops,
  27. .mem_resource = &mv_pci_mem0_resource,
  28. .io_resource = &mv_pci_io_mem0_resource,
  29. },
  30. .config_addr = MV64340_PCI_0_CONFIG_ADDR,
  31. .config_vreg = MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG,
  32. };
  33. static uint32_t mv_io_base, mv_io_size;
  34. static void mv64340_pci0_init(void)
  35. {
  36. uint32_t mem0_base, mem0_size;
  37. uint32_t io_base, io_size;
  38. io_base = MV_READ(MV64340_PCI_0_IO_BASE_ADDR) << 16;
  39. io_size = (MV_READ(MV64340_PCI_0_IO_SIZE) + 1) << 16;
  40. mem0_base = MV_READ(MV64340_PCI_0_MEMORY0_BASE_ADDR) << 16;
  41. mem0_size = (MV_READ(MV64340_PCI_0_MEMORY0_SIZE) + 1) << 16;
  42. mv_pci_io_mem0_resource.start = 0;
  43. mv_pci_io_mem0_resource.end = io_size - 1;
  44. mv_pci_mem0_resource.start = mem0_base;
  45. mv_pci_mem0_resource.end = mem0_base + mem0_size - 1;
  46. mv_bus0_controller.pcic.mem_offset = mem0_base;
  47. mv_bus0_controller.pcic.io_offset = 0;
  48. ioport_resource.end = io_size - 1;
  49. register_pci_controller(&mv_bus0_controller.pcic);
  50. mv_io_base = io_base;
  51. mv_io_size = io_size;
  52. }
  53. static struct resource mv_pci_io_mem1_resource = {
  54. .name = "MV64340 PCI1 IO MEM",
  55. .flags = IORESOURCE_IO
  56. };
  57. static struct resource mv_pci_mem1_resource = {
  58. .name = "MV64340 PCI1 MEM",
  59. .flags = IORESOURCE_MEM
  60. };
  61. static struct mv_pci_controller mv_bus1_controller = {
  62. .pcic = {
  63. .pci_ops = &mv_pci_ops,
  64. .mem_resource = &mv_pci_mem1_resource,
  65. .io_resource = &mv_pci_io_mem1_resource,
  66. },
  67. .config_addr = MV64340_PCI_1_CONFIG_ADDR,
  68. .config_vreg = MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG,
  69. };
  70. static __init void mv64340_pci1_init(void)
  71. {
  72. uint32_t mem0_base, mem0_size;
  73. uint32_t io_base, io_size;
  74. io_base = MV_READ(MV64340_PCI_1_IO_BASE_ADDR) << 16;
  75. io_size = (MV_READ(MV64340_PCI_1_IO_SIZE) + 1) << 16;
  76. mem0_base = MV_READ(MV64340_PCI_1_MEMORY0_BASE_ADDR) << 16;
  77. mem0_size = (MV_READ(MV64340_PCI_1_MEMORY0_SIZE) + 1) << 16;
  78. /*
  79. * Here we assume the I/O window of second bus to be contiguous with
  80. * the first. A gap is no problem but would waste address space for
  81. * remapping the port space.
  82. */
  83. mv_pci_io_mem1_resource.start = mv_io_size;
  84. mv_pci_io_mem1_resource.end = mv_io_size + io_size - 1;
  85. mv_pci_mem1_resource.start = mem0_base;
  86. mv_pci_mem1_resource.end = mem0_base + mem0_size - 1;
  87. mv_bus1_controller.pcic.mem_offset = mem0_base;
  88. mv_bus1_controller.pcic.io_offset = 0;
  89. ioport_resource.end = io_base + io_size -mv_io_base - 1;
  90. register_pci_controller(&mv_bus1_controller.pcic);
  91. mv_io_size = io_base + io_size - mv_io_base;
  92. }
  93. static __init int __init ocelot_c_pci_init(void)
  94. {
  95. unsigned long io_v_base;
  96. uint32_t enable;
  97. enable = ~MV_READ(MV64340_BASE_ADDR_ENABLE);
  98. /*
  99. * We require at least one enabled I/O or PCI memory window or we
  100. * will ignore this PCI bus. We ignore PCI windows 1, 2 and 3.
  101. */
  102. if (enable & (0x01 << 9) || enable & (0x01 << 10))
  103. mv64340_pci0_init();
  104. if (enable & (0x01 << 14) || enable & (0x01 << 15))
  105. mv64340_pci1_init();
  106. if (mv_io_size) {
  107. io_v_base = (unsigned long) ioremap(mv_io_base, mv_io_size);
  108. if (!io_v_base)
  109. panic("Could not ioremap I/O port range");
  110. set_io_port_base(io_v_base);
  111. }
  112. return 0;
  113. }
  114. arch_initcall(ocelot_c_pci_init);