pci-malta.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  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-cps.h>
  30. #include <asm/mips-boards/generic.h>
  31. #include <asm/mips-boards/bonito64.h>
  32. #include <asm/mips-boards/msc01_pci.h>
  33. static struct resource bonito64_mem_resource = {
  34. .name = "Bonito PCI MEM",
  35. .flags = IORESOURCE_MEM,
  36. };
  37. static struct resource bonito64_io_resource = {
  38. .name = "Bonito PCI I/O",
  39. .start = 0x00000000UL,
  40. .end = 0x000fffffUL,
  41. .flags = IORESOURCE_IO,
  42. };
  43. static struct resource gt64120_mem_resource = {
  44. .name = "GT-64120 PCI MEM",
  45. .flags = IORESOURCE_MEM,
  46. };
  47. static struct resource gt64120_io_resource = {
  48. .name = "GT-64120 PCI I/O",
  49. .flags = IORESOURCE_IO,
  50. };
  51. static struct resource msc_mem_resource = {
  52. .name = "MSC PCI MEM",
  53. .flags = IORESOURCE_MEM,
  54. };
  55. static struct resource msc_io_resource = {
  56. .name = "MSC PCI I/O",
  57. .flags = IORESOURCE_IO,
  58. };
  59. extern struct pci_ops bonito64_pci_ops;
  60. extern struct pci_ops gt64xxx_pci0_ops;
  61. extern struct pci_ops msc_pci_ops;
  62. static struct pci_controller bonito64_controller = {
  63. .pci_ops = &bonito64_pci_ops,
  64. .io_resource = &bonito64_io_resource,
  65. .mem_resource = &bonito64_mem_resource,
  66. .io_offset = 0x00000000UL,
  67. };
  68. static struct pci_controller gt64120_controller = {
  69. .pci_ops = &gt64xxx_pci0_ops,
  70. .io_resource = &gt64120_io_resource,
  71. .mem_resource = &gt64120_mem_resource,
  72. };
  73. static struct pci_controller msc_controller = {
  74. .pci_ops = &msc_pci_ops,
  75. .io_resource = &msc_io_resource,
  76. .mem_resource = &msc_mem_resource,
  77. };
  78. void __init mips_pcibios_init(void)
  79. {
  80. struct pci_controller *controller;
  81. resource_size_t start, end, map, start1, end1, map1, map2, map3, mask;
  82. switch (mips_revision_sconid) {
  83. case MIPS_REVISION_SCON_GT64120:
  84. /*
  85. * Due to a bug in the Galileo system controller, we need
  86. * to setup the PCI BAR for the Galileo internal registers.
  87. * This should be done in the bios/bootprom and will be
  88. * fixed in a later revision of YAMON (the MIPS boards
  89. * boot prom).
  90. */
  91. GT_WRITE(GT_PCI0_CFGADDR_OFS,
  92. (0 << GT_PCI0_CFGADDR_BUSNUM_SHF) | /* Local bus */
  93. (0 << GT_PCI0_CFGADDR_DEVNUM_SHF) | /* GT64120 dev */
  94. (0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) | /* Function 0*/
  95. ((0x20/4) << GT_PCI0_CFGADDR_REGNUM_SHF) | /* BAR 4*/
  96. GT_PCI0_CFGADDR_CONFIGEN_BIT);
  97. /* Perform the write */
  98. GT_WRITE(GT_PCI0_CFGDATA_OFS, CPHYSADDR(MIPS_GT_BASE));
  99. /* Set up resource ranges from the controller's registers. */
  100. start = GT_READ(GT_PCI0M0LD_OFS);
  101. end = GT_READ(GT_PCI0M0HD_OFS);
  102. map = GT_READ(GT_PCI0M0REMAP_OFS);
  103. end = (end & GT_PCI_HD_MSK) | (start & ~GT_PCI_HD_MSK);
  104. start1 = GT_READ(GT_PCI0M1LD_OFS);
  105. end1 = GT_READ(GT_PCI0M1HD_OFS);
  106. map1 = GT_READ(GT_PCI0M1REMAP_OFS);
  107. end1 = (end1 & GT_PCI_HD_MSK) | (start1 & ~GT_PCI_HD_MSK);
  108. /* Cannot support multiple windows, use the wider. */
  109. if (end1 - start1 > end - start) {
  110. start = start1;
  111. end = end1;
  112. map = map1;
  113. }
  114. mask = ~(start ^ end);
  115. /* We don't support remapping with a discontiguous mask. */
  116. BUG_ON((start & GT_PCI_HD_MSK) != (map & GT_PCI_HD_MSK) &&
  117. mask != ~((mask & -mask) - 1));
  118. gt64120_mem_resource.start = start;
  119. gt64120_mem_resource.end = end;
  120. gt64120_controller.mem_offset = (start & mask) - (map & mask);
  121. /* Addresses are 36-bit, so do shifts in the destinations. */
  122. gt64120_mem_resource.start <<= GT_PCI_DCRM_SHF;
  123. gt64120_mem_resource.end <<= GT_PCI_DCRM_SHF;
  124. gt64120_mem_resource.end |= (1 << GT_PCI_DCRM_SHF) - 1;
  125. gt64120_controller.mem_offset <<= GT_PCI_DCRM_SHF;
  126. start = GT_READ(GT_PCI0IOLD_OFS);
  127. end = GT_READ(GT_PCI0IOHD_OFS);
  128. map = GT_READ(GT_PCI0IOREMAP_OFS);
  129. end = (end & GT_PCI_HD_MSK) | (start & ~GT_PCI_HD_MSK);
  130. mask = ~(start ^ end);
  131. /* We don't support remapping with a discontiguous mask. */
  132. BUG_ON((start & GT_PCI_HD_MSK) != (map & GT_PCI_HD_MSK) &&
  133. mask != ~((mask & -mask) - 1));
  134. gt64120_io_resource.start = map & mask;
  135. gt64120_io_resource.end = (map & mask) | ~mask;
  136. gt64120_controller.io_offset = 0;
  137. /* Addresses are 36-bit, so do shifts in the destinations. */
  138. gt64120_io_resource.start <<= GT_PCI_DCRM_SHF;
  139. gt64120_io_resource.end <<= GT_PCI_DCRM_SHF;
  140. gt64120_io_resource.end |= (1 << GT_PCI_DCRM_SHF) - 1;
  141. controller = &gt64120_controller;
  142. break;
  143. case MIPS_REVISION_SCON_BONITO:
  144. /* Set up resource ranges from the controller's registers. */
  145. map = BONITO_PCIMAP;
  146. map1 = (BONITO_PCIMAP & BONITO_PCIMAP_PCIMAP_LO0) >>
  147. BONITO_PCIMAP_PCIMAP_LO0_SHIFT;
  148. map2 = (BONITO_PCIMAP & BONITO_PCIMAP_PCIMAP_LO1) >>
  149. BONITO_PCIMAP_PCIMAP_LO1_SHIFT;
  150. map3 = (BONITO_PCIMAP & BONITO_PCIMAP_PCIMAP_LO2) >>
  151. BONITO_PCIMAP_PCIMAP_LO2_SHIFT;
  152. /* Combine as many adjacent windows as possible. */
  153. map = map1;
  154. start = BONITO_PCILO0_BASE;
  155. end = 1;
  156. if (map3 == map2 + 1) {
  157. map = map2;
  158. start = BONITO_PCILO1_BASE;
  159. end++;
  160. }
  161. if (map2 == map1 + 1) {
  162. map = map1;
  163. start = BONITO_PCILO0_BASE;
  164. end++;
  165. }
  166. bonito64_mem_resource.start = start;
  167. bonito64_mem_resource.end = start +
  168. BONITO_PCIMAP_WINBASE(end) - 1;
  169. bonito64_controller.mem_offset = start -
  170. BONITO_PCIMAP_WINBASE(map);
  171. controller = &bonito64_controller;
  172. break;
  173. case MIPS_REVISION_SCON_SOCIT:
  174. case MIPS_REVISION_SCON_ROCIT:
  175. case MIPS_REVISION_SCON_SOCITSC:
  176. case MIPS_REVISION_SCON_SOCITSCP:
  177. /* Set up resource ranges from the controller's registers. */
  178. MSC_READ(MSC01_PCI_SC2PMBASL, start);
  179. MSC_READ(MSC01_PCI_SC2PMMSKL, mask);
  180. MSC_READ(MSC01_PCI_SC2PMMAPL, map);
  181. msc_mem_resource.start = start & mask;
  182. msc_mem_resource.end = (start & mask) | ~mask;
  183. msc_controller.mem_offset = (start & mask) - (map & mask);
  184. if (mips_cps_numiocu(0)) {
  185. write_gcr_reg0_base(start);
  186. write_gcr_reg0_mask(mask |
  187. CM_GCR_REGn_MASK_CMTGT_IOCU0);
  188. }
  189. MSC_READ(MSC01_PCI_SC2PIOBASL, start);
  190. MSC_READ(MSC01_PCI_SC2PIOMSKL, mask);
  191. MSC_READ(MSC01_PCI_SC2PIOMAPL, map);
  192. msc_io_resource.start = map & mask;
  193. msc_io_resource.end = (map & mask) | ~mask;
  194. msc_controller.io_offset = 0;
  195. ioport_resource.end = ~mask;
  196. if (mips_cps_numiocu(0)) {
  197. write_gcr_reg1_base(start);
  198. write_gcr_reg1_mask(mask |
  199. CM_GCR_REGn_MASK_CMTGT_IOCU0);
  200. }
  201. /* If ranges overlap I/O takes precedence. */
  202. start = start & mask;
  203. end = start | ~mask;
  204. if ((start >= msc_mem_resource.start &&
  205. start <= msc_mem_resource.end) ||
  206. (end >= msc_mem_resource.start &&
  207. end <= msc_mem_resource.end)) {
  208. /* Use the larger space. */
  209. start = max(start, msc_mem_resource.start);
  210. end = min(end, msc_mem_resource.end);
  211. if (start - msc_mem_resource.start >=
  212. msc_mem_resource.end - end)
  213. msc_mem_resource.end = start - 1;
  214. else
  215. msc_mem_resource.start = end + 1;
  216. }
  217. controller = &msc_controller;
  218. break;
  219. default:
  220. return;
  221. }
  222. /* PIIX4 ACPI starts at 0x1000 */
  223. if (controller->io_resource->start < 0x00001000UL)
  224. controller->io_resource->start = 0x00001000UL;
  225. iomem_resource.end &= 0xfffffffffULL; /* 64 GB */
  226. ioport_resource.end = controller->io_resource->end;
  227. controller->io_map_base = mips_io_port_base;
  228. register_pci_controller(controller);
  229. }