aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/mips-boards/generic/pci.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/mips-boards/generic/pci.c')
-rw-r--r--arch/mips/mips-boards/generic/pci.c167
1 files changed, 126 insertions, 41 deletions
diff --git a/arch/mips/mips-boards/generic/pci.c b/arch/mips/mips-boards/generic/pci.c
index 92c34bda02ae..1f6f9df74ab2 100644
--- a/arch/mips/mips-boards/generic/pci.c
+++ b/arch/mips/mips-boards/generic/pci.c
@@ -1,6 +1,8 @@
1/* 1/*
2 * Carsten Langgaard, carstenl@mips.com 2 * Copyright (C) 1999, 2000, 2004, 2005 MIPS Technologies, Inc.
3 * Copyright (C) 1999, 2000 MIPS Technologies, Inc. All rights reserved. 3 * All rights reserved.
4 * Authors: Carsten Langgaard <carstenl@mips.com>
5 * Maciej W. Rozycki <macro@mips.com>
4 * 6 *
5 * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org) 7 * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org)
6 * 8 *
@@ -19,65 +21,46 @@
19 * 21 *
20 * MIPS boards specific PCI support. 22 * MIPS boards specific PCI support.
21 */ 23 */
22#include <linux/config.h>
23#include <linux/types.h> 24#include <linux/types.h>
24#include <linux/pci.h> 25#include <linux/pci.h>
25#include <linux/kernel.h> 26#include <linux/kernel.h>
26#include <linux/init.h> 27#include <linux/init.h>
27 28
28#include <asm/mips-boards/generic.h>
29#include <asm/gt64120.h> 29#include <asm/gt64120.h>
30
31#include <asm/mips-boards/generic.h>
30#include <asm/mips-boards/bonito64.h> 32#include <asm/mips-boards/bonito64.h>
31#include <asm/mips-boards/msc01_pci.h> 33#include <asm/mips-boards/msc01_pci.h>
32#ifdef CONFIG_MIPS_MALTA
33#include <asm/mips-boards/malta.h>
34#endif
35 34
36static struct resource bonito64_mem_resource = { 35static struct resource bonito64_mem_resource = {
37 .name = "Bonito PCI MEM", 36 .name = "Bonito PCI MEM",
38 .start = 0x10000000UL,
39 .end = 0x1bffffffUL,
40 .flags = IORESOURCE_MEM, 37 .flags = IORESOURCE_MEM,
41}; 38};
42 39
43static struct resource bonito64_io_resource = { 40static struct resource bonito64_io_resource = {
44 .name = "Bonito IO MEM", 41 .name = "Bonito PCI I/O",
45 .start = 0x00002000UL, /* avoid conflicts with YAMON allocated I/O addresses */ 42 .start = 0x00000000UL,
46 .end = 0x000fffffUL, 43 .end = 0x000fffffUL,
47 .flags = IORESOURCE_IO, 44 .flags = IORESOURCE_IO,
48}; 45};
49 46
50static struct resource gt64120_mem_resource = { 47static struct resource gt64120_mem_resource = {
51 .name = "GT64120 PCI MEM", 48 .name = "GT-64120 PCI MEM",
52 .start = 0x10000000UL,
53 .end = 0x1bdfffffUL,
54 .flags = IORESOURCE_MEM, 49 .flags = IORESOURCE_MEM,
55}; 50};
56 51
57static struct resource gt64120_io_resource = { 52static struct resource gt64120_io_resource = {
58 .name = "GT64120 IO MEM", 53 .name = "GT-64120 PCI I/O",
59#ifdef CONFIG_MIPS_ATLAS
60 .start = 0x18000000UL,
61 .end = 0x181fffffUL,
62#endif
63#ifdef CONFIG_MIPS_MALTA
64 .start = 0x00002000UL,
65 .end = 0x001fffffUL,
66#endif
67 .flags = IORESOURCE_IO, 54 .flags = IORESOURCE_IO,
68}; 55};
69 56
70static struct resource msc_mem_resource = { 57static struct resource msc_mem_resource = {
71 .name = "MSC PCI MEM", 58 .name = "MSC PCI MEM",
72 .start = 0x10000000UL,
73 .end = 0x1fffffffUL,
74 .flags = IORESOURCE_MEM, 59 .flags = IORESOURCE_MEM,
75}; 60};
76 61
77static struct resource msc_io_resource = { 62static struct resource msc_io_resource = {
78 .name = "MSC IO MEM", 63 .name = "MSC PCI I/O",
79 .start = 0x00002000UL,
80 .end = 0x007fffffUL,
81 .flags = IORESOURCE_IO, 64 .flags = IORESOURCE_IO,
82}; 65};
83 66
@@ -89,7 +72,6 @@ static struct pci_controller bonito64_controller = {
89 .pci_ops = &bonito64_pci_ops, 72 .pci_ops = &bonito64_pci_ops,
90 .io_resource = &bonito64_io_resource, 73 .io_resource = &bonito64_io_resource,
91 .mem_resource = &bonito64_mem_resource, 74 .mem_resource = &bonito64_mem_resource,
92 .mem_offset = 0x10000000UL,
93 .io_offset = 0x00000000UL, 75 .io_offset = 0x00000000UL,
94}; 76};
95 77
@@ -97,21 +79,18 @@ static struct pci_controller gt64120_controller = {
97 .pci_ops = &gt64120_pci_ops, 79 .pci_ops = &gt64120_pci_ops,
98 .io_resource = &gt64120_io_resource, 80 .io_resource = &gt64120_io_resource,
99 .mem_resource = &gt64120_mem_resource, 81 .mem_resource = &gt64120_mem_resource,
100 .mem_offset = 0x00000000UL,
101 .io_offset = 0x00000000UL,
102}; 82};
103 83
104static struct pci_controller msc_controller = { 84static struct pci_controller msc_controller = {
105 .pci_ops = &msc_pci_ops, 85 .pci_ops = &msc_pci_ops,
106 .io_resource = &msc_io_resource, 86 .io_resource = &msc_io_resource,
107 .mem_resource = &msc_mem_resource, 87 .mem_resource = &msc_mem_resource,
108 .mem_offset = 0x10000000UL,
109 .io_offset = 0x00000000UL,
110}; 88};
111 89
112static int __init pcibios_init(void) 90void __init mips_pcibios_init(void)
113{ 91{
114 struct pci_controller *controller; 92 struct pci_controller *controller;
93 unsigned long start, end, map, start1, end1, map1, map2, map3, mask;
115 94
116 switch (mips_revision_corid) { 95 switch (mips_revision_corid) {
117 case MIPS_REVISION_CORID_QED_RM5261: 96 case MIPS_REVISION_CORID_QED_RM5261:
@@ -130,34 +109,140 @@ static int __init pcibios_init(void)
130 (0 << GT_PCI0_CFGADDR_DEVNUM_SHF) | /* GT64120 dev */ 109 (0 << GT_PCI0_CFGADDR_DEVNUM_SHF) | /* GT64120 dev */
131 (0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) | /* Function 0*/ 110 (0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) | /* Function 0*/
132 ((0x20/4) << GT_PCI0_CFGADDR_REGNUM_SHF) | /* BAR 4*/ 111 ((0x20/4) << GT_PCI0_CFGADDR_REGNUM_SHF) | /* BAR 4*/
133 GT_PCI0_CFGADDR_CONFIGEN_BIT ); 112 GT_PCI0_CFGADDR_CONFIGEN_BIT);
134 113
135 /* Perform the write */ 114 /* Perform the write */
136 GT_WRITE(GT_PCI0_CFGDATA_OFS, CPHYSADDR(MIPS_GT_BASE)); 115 GT_WRITE(GT_PCI0_CFGDATA_OFS, CPHYSADDR(MIPS_GT_BASE));
137 116
117 /* Set up resource ranges from the controller's registers. */
118 start = GT_READ(GT_PCI0M0LD_OFS);
119 end = GT_READ(GT_PCI0M0HD_OFS);
120 map = GT_READ(GT_PCI0M0REMAP_OFS);
121 end = (end & GT_PCI_HD_MSK) | (start & ~GT_PCI_HD_MSK);
122 start1 = GT_READ(GT_PCI0M1LD_OFS);
123 end1 = GT_READ(GT_PCI0M1HD_OFS);
124 map1 = GT_READ(GT_PCI0M1REMAP_OFS);
125 end1 = (end1 & GT_PCI_HD_MSK) | (start1 & ~GT_PCI_HD_MSK);
126 /* Cannot support multiple windows, use the wider. */
127 if (end1 - start1 > end - start) {
128 start = start1;
129 end = end1;
130 map = map1;
131 }
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_mem_resource.start = start;
137 gt64120_mem_resource.end = end;
138 gt64120_controller.mem_offset = (start & mask) - (map & mask);
139 /* Addresses are 36-bit, so do shifts in the destinations. */
140 gt64120_mem_resource.start <<= GT_PCI_DCRM_SHF;
141 gt64120_mem_resource.end <<= GT_PCI_DCRM_SHF;
142 gt64120_mem_resource.end |= (1 << GT_PCI_DCRM_SHF) - 1;
143 gt64120_controller.mem_offset <<= GT_PCI_DCRM_SHF;
144
145 start = GT_READ(GT_PCI0IOLD_OFS);
146 end = GT_READ(GT_PCI0IOHD_OFS);
147 map = GT_READ(GT_PCI0IOREMAP_OFS);
148 end = (end & GT_PCI_HD_MSK) | (start & ~GT_PCI_HD_MSK);
149 mask = ~(start ^ end);
150 /* We don't support remapping with a discontiguous mask. */
151 BUG_ON((start & GT_PCI_HD_MSK) != (map & GT_PCI_HD_MSK) &&
152 mask != ~((mask & -mask) - 1));
153 gt64120_io_resource.start = map & mask;
154 gt64120_io_resource.end = (map & mask) | ~mask;
155 gt64120_controller.io_offset = 0;
156 /* Addresses are 36-bit, so do shifts in the destinations. */
157 gt64120_io_resource.start <<= GT_PCI_DCRM_SHF;
158 gt64120_io_resource.end <<= GT_PCI_DCRM_SHF;
159 gt64120_io_resource.end |= (1 << GT_PCI_DCRM_SHF) - 1;
160
138 controller = &gt64120_controller; 161 controller = &gt64120_controller;
139 break; 162 break;
140 163
141 case MIPS_REVISION_CORID_BONITO64: 164 case MIPS_REVISION_CORID_BONITO64:
142 case MIPS_REVISION_CORID_CORE_20K: 165 case MIPS_REVISION_CORID_CORE_20K:
143 case MIPS_REVISION_CORID_CORE_EMUL_BON: 166 case MIPS_REVISION_CORID_CORE_EMUL_BON:
167 /* Set up resource ranges from the controller's registers. */
168 map = BONITO_PCIMAP;
169 map1 = (BONITO_PCIMAP & BONITO_PCIMAP_PCIMAP_LO0) >>
170 BONITO_PCIMAP_PCIMAP_LO0_SHIFT;
171 map2 = (BONITO_PCIMAP & BONITO_PCIMAP_PCIMAP_LO1) >>
172 BONITO_PCIMAP_PCIMAP_LO1_SHIFT;
173 map3 = (BONITO_PCIMAP & BONITO_PCIMAP_PCIMAP_LO2) >>
174 BONITO_PCIMAP_PCIMAP_LO2_SHIFT;
175 /* Combine as many adjacent windows as possible. */
176 map = map1;
177 start = BONITO_PCILO0_BASE;
178 end = 1;
179 if (map3 == map2 + 1) {
180 map = map2;
181 start = BONITO_PCILO1_BASE;
182 end++;
183 }
184 if (map2 == map1 + 1) {
185 map = map1;
186 start = BONITO_PCILO0_BASE;
187 end++;
188 }
189 bonito64_mem_resource.start = start;
190 bonito64_mem_resource.end = start +
191 BONITO_PCIMAP_WINBASE(end) - 1;
192 bonito64_controller.mem_offset = start -
193 BONITO_PCIMAP_WINBASE(map);
194
144 controller = &bonito64_controller; 195 controller = &bonito64_controller;
145 break; 196 break;
146 197
147 case MIPS_REVISION_CORID_CORE_MSC: 198 case MIPS_REVISION_CORID_CORE_MSC:
148 case MIPS_REVISION_CORID_CORE_FPGA2: 199 case MIPS_REVISION_CORID_CORE_FPGA2:
200 case MIPS_REVISION_CORID_CORE_FPGA3:
149 case MIPS_REVISION_CORID_CORE_EMUL_MSC: 201 case MIPS_REVISION_CORID_CORE_EMUL_MSC:
202 /* Set up resource ranges from the controller's registers. */
203 MSC_READ(MSC01_PCI_SC2PMBASL, start);
204 MSC_READ(MSC01_PCI_SC2PMMSKL, mask);
205 MSC_READ(MSC01_PCI_SC2PMMAPL, map);
206 msc_mem_resource.start = start & mask;
207 msc_mem_resource.end = (start & mask) | ~mask;
208 msc_controller.mem_offset = (start & mask) - (map & mask);
209
210 MSC_READ(MSC01_PCI_SC2PIOBASL, start);
211 MSC_READ(MSC01_PCI_SC2PIOMSKL, mask);
212 MSC_READ(MSC01_PCI_SC2PIOMAPL, map);
213 msc_io_resource.start = map & mask;
214 msc_io_resource.end = (map & mask) | ~mask;
215 msc_controller.io_offset = 0;
216 ioport_resource.end = ~mask;
217
218 /* If ranges overlap I/O takes precedence. */
219 start = start & mask;
220 end = start | ~mask;
221 if ((start >= msc_mem_resource.start &&
222 start <= msc_mem_resource.end) ||
223 (end >= msc_mem_resource.start &&
224 end <= msc_mem_resource.end)) {
225 /* Use the larger space. */
226 start = max(start, msc_mem_resource.start);
227 end = min(end, msc_mem_resource.end);
228 if (start - msc_mem_resource.start >=
229 msc_mem_resource.end - end)
230 msc_mem_resource.end = start - 1;
231 else
232 msc_mem_resource.start = end + 1;
233 }
234
150 controller = &msc_controller; 235 controller = &msc_controller;
151 break; 236 break;
152 default: 237 default:
153 return 1; 238 return;
154 } 239 }
155 240
241 if (controller->io_resource->start < 0x00001000UL) /* FIXME */
242 controller->io_resource->start = 0x00001000UL;
243
244 iomem_resource.end &= 0xfffffffffULL; /* 64 GB */
156 ioport_resource.end = controller->io_resource->end; 245 ioport_resource.end = controller->io_resource->end;
157 246
158 register_pci_controller (controller); 247 register_pci_controller (controller);
159
160 return 0;
161} 248}
162
163early_initcall(pcibios_init);