pci-ocelot-c.c 3.8 KB

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