pci.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. /*
  2. * Copyright (C) 1999, 2000, 2004, 2005 MIPS Technologies, Inc.
  3. * All rights reserved.
  4. * Authors: Carsten Langgaard <carstenl@mips.com>
  5. * Maciej W. Rozycki <macro@mips.com>
  6. *
  7. * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org)
  8. *
  9. * This program is free software; you can distribute it and/or modify it
  10. * under the terms of the GNU General Public License (Version 2) as
  11. * published by the Free Software Foundation.
  12. *
  13. * This program is distributed in the hope it will be useful, but WITHOUT
  14. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  15. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  16. * for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License along
  19. * with this program; if not, write to the Free Software Foundation, Inc.,
  20. * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
  21. *
  22. * MIPS boards specific PCI support.
  23. */
  24. #include <linux/types.h>
  25. #include <linux/pci.h>
  26. #include <linux/kernel.h>
  27. #include <linux/init.h>
  28. #include <asm/gt64120.h>
  29. #include <asm/mips-boards/generic.h>
  30. #include <asm/mips-boards/bonito64.h>
  31. #include <asm/mips-boards/msc01_pci.h>
  32. static struct resource bonito64_mem_resource = {
  33. .name = "Bonito PCI MEM",
  34. .flags = IORESOURCE_MEM,
  35. };
  36. static struct resource bonito64_io_resource = {
  37. .name = "Bonito PCI I/O",
  38. .start = 0x00000000UL,
  39. .end = 0x000fffffUL,
  40. .flags = IORESOURCE_IO,
  41. };
  42. static struct resource gt64120_mem_resource = {
  43. .name = "GT-64120 PCI MEM",
  44. .flags = IORESOURCE_MEM,
  45. };
  46. static struct resource gt64120_io_resource = {
  47. .name = "GT-64120 PCI I/O",
  48. .flags = IORESOURCE_IO,
  49. };
  50. static struct resource msc_mem_resource = {
  51. .name = "MSC PCI MEM",
  52. .flags = IORESOURCE_MEM,
  53. };
  54. static struct resource msc_io_resource = {
  55. .name = "MSC PCI I/O",
  56. .flags = IORESOURCE_IO,
  57. };
  58. extern struct pci_ops bonito64_pci_ops;
  59. extern struct pci_ops gt64xxx_pci0_ops;
  60. extern struct pci_ops msc_pci_ops;
  61. static struct pci_controller bonito64_controller = {
  62. .pci_ops = &bonito64_pci_ops,
  63. .io_resource = &bonito64_io_resource,
  64. .mem_resource = &bonito64_mem_resource,
  65. .io_offset = 0x00000000UL,
  66. };
  67. static struct pci_controller gt64120_controller = {
  68. .pci_ops = &gt64xxx_pci0_ops,
  69. .io_resource = &gt64120_io_resource,
  70. .mem_resource = &gt64120_mem_resource,
  71. };
  72. static struct pci_controller msc_controller = {
  73. .pci_ops = &msc_pci_ops,
  74. .io_resource = &msc_io_resource,
  75. .mem_resource = &msc_mem_resource,
  76. };
  77. void __init mips_pcibios_init(void)
  78. {
  79. struct pci_controller *controller;
  80. resource_size_t start, end, map, start1, end1, map1, map2, map3, mask;
  81. switch (mips_revision_sconid) {
  82. case MIPS_REVISION_SCON_GT64120:
  83. /*
  84. * Due to a bug in the Galileo system controller, we need
  85. * to setup the PCI BAR for the Galileo internal registers.
  86. * This should be done in the bios/bootprom and will be
  87. * fixed in a later revision of YAMON (the MIPS boards
  88. * boot prom).
  89. */
  90. GT_WRITE(GT_PCI0_CFGADDR_OFS,
  91. (0 << GT_PCI0_CFGADDR_BUSNUM_SHF) | /* Local bus */
  92. (0 << GT_PCI0_CFGADDR_DEVNUM_SHF) | /* GT64120 dev */
  93. (0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) | /* Function 0*/
  94. ((0x20/4) << GT_PCI0_CFGADDR_REGNUM_SHF) | /* BAR 4*/
  95. GT_PCI0_CFGADDR_CONFIGEN_BIT);
  96. /* Perform the write */
  97. GT_WRITE(GT_PCI0_CFGDATA_OFS, CPHYSADDR(MIPS_GT_BASE));
  98. /* Set up resource ranges from the controller's registers. */
  99. start = GT_READ(GT_PCI0M0LD_OFS);
  100. end = GT_READ(GT_PCI0M0HD_OFS);
  101. map = GT_READ(GT_PCI0M0REMAP_OFS);
  102. end = (end & GT_PCI_HD_MSK) | (start & ~GT_PCI_HD_MSK);
  103. start1 = GT_READ(GT_PCI0M1LD_OFS);
  104. end1 = GT_READ(GT_PCI0M1HD_OFS);
  105. map1 = GT_READ(GT_PCI0M1REMAP_OFS);
  106. end1 = (end1 & GT_PCI_HD_MSK) | (start1 & ~GT_PCI_HD_MSK);
  107. /* Cannot support multiple windows, use the wider. */
  108. if (end1 - start1 > end - start) {
  109. start = start1;
  110. end = end1;
  111. map = map1;
  112. }
  113. mask = ~(start ^ end);
  114. /* We don't support remapping with a discontiguous mask. */
  115. BUG_ON((start & GT_PCI_HD_MSK) != (map & GT_PCI_HD_MSK) &&
  116. mask != ~((mask & -mask) - 1));
  117. gt64120_mem_resource.start = start;
  118. gt64120_mem_resource.end = end;
  119. gt64120_controller.mem_offset = (start & mask) - (map & mask);
  120. /* Addresses are 36-bit, so do shifts in the destinations. */
  121. gt64120_mem_resource.start <<= GT_PCI_DCRM_SHF;
  122. gt64120_mem_resource.end <<= GT_PCI_DCRM_SHF;
  123. gt64120_mem_resource.end |= (1 << GT_PCI_DCRM_SHF) - 1;
  124. gt64120_controller.mem_offset <<= GT_PCI_DCRM_SHF;
  125. start = GT_READ(GT_PCI0IOLD_OFS);
  126. end = GT_READ(GT_PCI0IOHD_OFS);
  127. map = GT_READ(GT_PCI0IOREMAP_OFS);
  128. end = (end & GT_PCI_HD_MSK) | (start & ~GT_PCI_HD_MSK);
  129. mask = ~(start ^ end);
  130. /* We don't support remapping with a discontiguous mask. */
  131. BUG_ON((start & GT_PCI_HD_MSK) != (map & GT_PCI_HD_MSK) &&
  132. mask != ~((mask & -mask) - 1));
  133. gt64120_io_resource.start = map & mask;
  134. gt64120_io_resource.end = (map & mask) | ~mask;
  135. gt64120_controller.io_offset = 0;
  136. /* Addresses are 36-bit, so do shifts in the destinations. */
  137. gt64120_io_resource.start <<= GT_PCI_DCRM_SHF;
  138. gt64120_io_resource.end <<= GT_PCI_DCRM_SHF;
  139. gt64120_io_resource.end |= (1 << GT_PCI_DCRM_SHF) - 1;
  140. controller = &gt64120_controller;
  141. break;
  142. case MIPS_REVISION_SCON_BONITO:
  143. /* Set up resource ranges from the controller's registers. */
  144. map = BONITO_PCIMAP;
  145. map1 = (BONITO_PCIMAP & BONITO_PCIMAP_PCIMAP_LO0) >>
  146. BONITO_PCIMAP_PCIMAP_LO0_SHIFT;
  147. map2 = (BONITO_PCIMAP & BONITO_PCIMAP_PCIMAP_LO1) >>
  148. BONITO_PCIMAP_PCIMAP_LO1_SHIFT;
  149. map3 = (BONITO_PCIMAP & BONITO_PCIMAP_PCIMAP_LO2) >>
  150. BONITO_PCIMAP_PCIMAP_LO2_SHIFT;
  151. /* Combine as many adjacent windows as possible. */
  152. map = map1;
  153. start = BONITO_PCILO0_BASE;
  154. end = 1;
  155. if (map3 == map2 + 1) {
  156. map = map2;
  157. start = BONITO_PCILO1_BASE;
  158. end++;
  159. }
  160. if (map2 == map1 + 1) {
  161. map = map1;
  162. start = BONITO_PCILO0_BASE;
  163. end++;
  164. }
  165. bonito64_mem_resource.start = start;
  166. bonito64_mem_resource.end = start +
  167. BONITO_PCIMAP_WINBASE(end) - 1;
  168. bonito64_controller.mem_offset = start -
  169. BONITO_PCIMAP_WINBASE(map);
  170. controller = &bonito64_controller;
  171. break;
  172. case MIPS_REVISION_SCON_SOCIT:
  173. case MIPS_REVISION_SCON_ROCIT:
  174. case MIPS_REVISION_SCON_SOCITSC:
  175. case MIPS_REVISION_SCON_SOCITSCP:
  176. /* Set up resource ranges from the controller's registers. */
  177. MSC_READ(MSC01_PCI_SC2PMBASL, start);
  178. MSC_READ(MSC01_PCI_SC2PMMSKL, mask);
  179. MSC_READ(MSC01_PCI_SC2PMMAPL, map);
  180. msc_mem_resource.start = start & mask;
  181. msc_mem_resource.end = (start & mask) | ~mask;
  182. msc_controller.mem_offset = (start & mask) - (map & mask);
  183. MSC_READ(MSC01_PCI_SC2PIOBASL, start);
  184. MSC_READ(MSC01_PCI_SC2PIOMSKL, mask);
  185. MSC_READ(MSC01_PCI_SC2PIOMAPL, map);
  186. msc_io_resource.start = map & mask;
  187. msc_io_resource.end = (map & mask) | ~mask;
  188. msc_controller.io_offset = 0;
  189. ioport_resource.end = ~mask;
  190. /* If ranges overlap I/O takes precedence. */
  191. start = start & mask;
  192. end = start | ~mask;
  193. if ((start >= msc_mem_resource.start &&
  194. start <= msc_mem_resource.end) ||
  195. (end >= msc_mem_resource.start &&
  196. end <= msc_mem_resource.end)) {
  197. /* Use the larger space. */
  198. start = max(start, msc_mem_resource.start);
  199. end = min(end, msc_mem_resource.end);
  200. if (start - msc_mem_resource.start >=
  201. msc_mem_resource.end - end)
  202. msc_mem_resource.end = start - 1;
  203. else
  204. msc_mem_resource.start = end + 1;
  205. }
  206. controller = &msc_controller;
  207. break;
  208. default:
  209. return;
  210. }
  211. if (controller->io_resource->start < 0x00001000UL) /* FIXME */
  212. controller->io_resource->start = 0x00001000UL;
  213. iomem_resource.end &= 0xfffffffffULL; /* 64 GB */
  214. ioport_resource.end = controller->io_resource->end;
  215. register_pci_controller(controller);
  216. }