pci.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  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 gt64120_pci_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 = &gt64120_pci_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. unsigned long start, end, map, start1, end1, map1, map2, map3, mask;
  81. switch (mips_revision_corid) {
  82. case MIPS_REVISION_CORID_QED_RM5261:
  83. case MIPS_REVISION_CORID_CORE_LV:
  84. case MIPS_REVISION_CORID_CORE_FPGA:
  85. case MIPS_REVISION_CORID_CORE_FPGAR2:
  86. /*
  87. * Due to a bug in the Galileo system controller, we need
  88. * to setup the PCI BAR for the Galileo internal registers.
  89. * This should be done in the bios/bootprom and will be
  90. * fixed in a later revision of YAMON (the MIPS boards
  91. * boot prom).
  92. */
  93. GT_WRITE(GT_PCI0_CFGADDR_OFS,
  94. (0 << GT_PCI0_CFGADDR_BUSNUM_SHF) | /* Local bus */
  95. (0 << GT_PCI0_CFGADDR_DEVNUM_SHF) | /* GT64120 dev */
  96. (0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) | /* Function 0*/
  97. ((0x20/4) << GT_PCI0_CFGADDR_REGNUM_SHF) | /* BAR 4*/
  98. GT_PCI0_CFGADDR_CONFIGEN_BIT);
  99. /* Perform the write */
  100. GT_WRITE(GT_PCI0_CFGDATA_OFS, CPHYSADDR(MIPS_GT_BASE));
  101. /* Set up resource ranges from the controller's registers. */
  102. start = GT_READ(GT_PCI0M0LD_OFS);
  103. end = GT_READ(GT_PCI0M0HD_OFS);
  104. map = GT_READ(GT_PCI0M0REMAP_OFS);
  105. end = (end & GT_PCI_HD_MSK) | (start & ~GT_PCI_HD_MSK);
  106. start1 = GT_READ(GT_PCI0M1LD_OFS);
  107. end1 = GT_READ(GT_PCI0M1HD_OFS);
  108. map1 = GT_READ(GT_PCI0M1REMAP_OFS);
  109. end1 = (end1 & GT_PCI_HD_MSK) | (start1 & ~GT_PCI_HD_MSK);
  110. /* Cannot support multiple windows, use the wider. */
  111. if (end1 - start1 > end - start) {
  112. start = start1;
  113. end = end1;
  114. map = map1;
  115. }
  116. mask = ~(start ^ end);
  117. /* We don't support remapping with a discontiguous mask. */
  118. BUG_ON((start & GT_PCI_HD_MSK) != (map & GT_PCI_HD_MSK) &&
  119. mask != ~((mask & -mask) - 1));
  120. gt64120_mem_resource.start = start;
  121. gt64120_mem_resource.end = end;
  122. gt64120_controller.mem_offset = (start & mask) - (map & mask);
  123. /* Addresses are 36-bit, so do shifts in the destinations. */
  124. gt64120_mem_resource.start <<= GT_PCI_DCRM_SHF;
  125. gt64120_mem_resource.end <<= GT_PCI_DCRM_SHF;
  126. gt64120_mem_resource.end |= (1 << GT_PCI_DCRM_SHF) - 1;
  127. gt64120_controller.mem_offset <<= GT_PCI_DCRM_SHF;
  128. start = GT_READ(GT_PCI0IOLD_OFS);
  129. end = GT_READ(GT_PCI0IOHD_OFS);
  130. map = GT_READ(GT_PCI0IOREMAP_OFS);
  131. end = (end & GT_PCI_HD_MSK) | (start & ~GT_PCI_HD_MSK);
  132. mask = ~(start ^ end);
  133. /* We don't support remapping with a discontiguous mask. */
  134. BUG_ON((start & GT_PCI_HD_MSK) != (map & GT_PCI_HD_MSK) &&
  135. mask != ~((mask & -mask) - 1));
  136. gt64120_io_resource.start = map & mask;
  137. gt64120_io_resource.end = (map & mask) | ~mask;
  138. gt64120_controller.io_offset = 0;
  139. /* Addresses are 36-bit, so do shifts in the destinations. */
  140. gt64120_io_resource.start <<= GT_PCI_DCRM_SHF;
  141. gt64120_io_resource.end <<= GT_PCI_DCRM_SHF;
  142. gt64120_io_resource.end |= (1 << GT_PCI_DCRM_SHF) - 1;
  143. controller = &gt64120_controller;
  144. break;
  145. case MIPS_REVISION_CORID_BONITO64:
  146. case MIPS_REVISION_CORID_CORE_20K:
  147. case MIPS_REVISION_CORID_CORE_EMUL_BON:
  148. /* Set up resource ranges from the controller's registers. */
  149. map = BONITO_PCIMAP;
  150. map1 = (BONITO_PCIMAP & BONITO_PCIMAP_PCIMAP_LO0) >>
  151. BONITO_PCIMAP_PCIMAP_LO0_SHIFT;
  152. map2 = (BONITO_PCIMAP & BONITO_PCIMAP_PCIMAP_LO1) >>
  153. BONITO_PCIMAP_PCIMAP_LO1_SHIFT;
  154. map3 = (BONITO_PCIMAP & BONITO_PCIMAP_PCIMAP_LO2) >>
  155. BONITO_PCIMAP_PCIMAP_LO2_SHIFT;
  156. /* Combine as many adjacent windows as possible. */
  157. map = map1;
  158. start = BONITO_PCILO0_BASE;
  159. end = 1;
  160. if (map3 == map2 + 1) {
  161. map = map2;
  162. start = BONITO_PCILO1_BASE;
  163. end++;
  164. }
  165. if (map2 == map1 + 1) {
  166. map = map1;
  167. start = BONITO_PCILO0_BASE;
  168. end++;
  169. }
  170. bonito64_mem_resource.start = start;
  171. bonito64_mem_resource.end = start +
  172. BONITO_PCIMAP_WINBASE(end) - 1;
  173. bonito64_controller.mem_offset = start -
  174. BONITO_PCIMAP_WINBASE(map);
  175. controller = &bonito64_controller;
  176. break;
  177. case MIPS_REVISION_CORID_CORE_MSC:
  178. case MIPS_REVISION_CORID_CORE_FPGA2:
  179. case MIPS_REVISION_CORID_CORE_FPGA3:
  180. case MIPS_REVISION_CORID_CORE_EMUL_MSC:
  181. /* Set up resource ranges from the controller's registers. */
  182. MSC_READ(MSC01_PCI_SC2PMBASL, start);
  183. MSC_READ(MSC01_PCI_SC2PMMSKL, mask);
  184. MSC_READ(MSC01_PCI_SC2PMMAPL, map);
  185. msc_mem_resource.start = start & mask;
  186. msc_mem_resource.end = (start & mask) | ~mask;
  187. msc_controller.mem_offset = (start & mask) - (map & mask);
  188. MSC_READ(MSC01_PCI_SC2PIOBASL, start);
  189. MSC_READ(MSC01_PCI_SC2PIOMSKL, mask);
  190. MSC_READ(MSC01_PCI_SC2PIOMAPL, map);
  191. msc_io_resource.start = map & mask;
  192. msc_io_resource.end = (map & mask) | ~mask;
  193. msc_controller.io_offset = 0;
  194. ioport_resource.end = ~mask;
  195. /* If ranges overlap I/O takes precedence. */
  196. start = start & mask;
  197. end = start | ~mask;
  198. if ((start >= msc_mem_resource.start &&
  199. start <= msc_mem_resource.end) ||
  200. (end >= msc_mem_resource.start &&
  201. end <= msc_mem_resource.end)) {
  202. /* Use the larger space. */
  203. start = max(start, msc_mem_resource.start);
  204. end = min(end, msc_mem_resource.end);
  205. if (start - msc_mem_resource.start >=
  206. msc_mem_resource.end - end)
  207. msc_mem_resource.end = start - 1;
  208. else
  209. msc_mem_resource.start = end + 1;
  210. }
  211. controller = &msc_controller;
  212. break;
  213. default:
  214. return;
  215. }
  216. if (controller->io_resource->start < 0x00001000UL) /* FIXME */
  217. controller->io_resource->start = 0x00001000UL;
  218. iomem_resource.end &= 0xfffffffffULL; /* 64 GB */
  219. ioport_resource.end = controller->io_resource->end;
  220. register_pci_controller (controller);
  221. }