Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/mips/mti-malta/malta-pci.c
10818 views
1
/*
2
* Copyright (C) 1999, 2000, 2004, 2005 MIPS Technologies, Inc.
3
* All rights reserved.
4
* Authors: Carsten Langgaard <[email protected]>
5
* Maciej W. Rozycki <[email protected]>
6
*
7
* Copyright (C) 2004 by Ralf Baechle ([email protected])
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
29
#include <asm/gt64120.h>
30
#include <asm/gcmpregs.h>
31
#include <asm/mips-boards/generic.h>
32
#include <asm/mips-boards/bonito64.h>
33
#include <asm/mips-boards/msc01_pci.h>
34
35
static struct resource bonito64_mem_resource = {
36
.name = "Bonito PCI MEM",
37
.flags = IORESOURCE_MEM,
38
};
39
40
static struct resource bonito64_io_resource = {
41
.name = "Bonito PCI I/O",
42
.start = 0x00000000UL,
43
.end = 0x000fffffUL,
44
.flags = IORESOURCE_IO,
45
};
46
47
static struct resource gt64120_mem_resource = {
48
.name = "GT-64120 PCI MEM",
49
.flags = IORESOURCE_MEM,
50
};
51
52
static struct resource gt64120_io_resource = {
53
.name = "GT-64120 PCI I/O",
54
.flags = IORESOURCE_IO,
55
};
56
57
static struct resource msc_mem_resource = {
58
.name = "MSC PCI MEM",
59
.flags = IORESOURCE_MEM,
60
};
61
62
static struct resource msc_io_resource = {
63
.name = "MSC PCI I/O",
64
.flags = IORESOURCE_IO,
65
};
66
67
extern struct pci_ops bonito64_pci_ops;
68
extern struct pci_ops gt64xxx_pci0_ops;
69
extern struct pci_ops msc_pci_ops;
70
71
static struct pci_controller bonito64_controller = {
72
.pci_ops = &bonito64_pci_ops,
73
.io_resource = &bonito64_io_resource,
74
.mem_resource = &bonito64_mem_resource,
75
.io_offset = 0x00000000UL,
76
};
77
78
static struct pci_controller gt64120_controller = {
79
.pci_ops = &gt64xxx_pci0_ops,
80
.io_resource = &gt64120_io_resource,
81
.mem_resource = &gt64120_mem_resource,
82
};
83
84
static struct pci_controller msc_controller = {
85
.pci_ops = &msc_pci_ops,
86
.io_resource = &msc_io_resource,
87
.mem_resource = &msc_mem_resource,
88
};
89
90
void __init mips_pcibios_init(void)
91
{
92
struct pci_controller *controller;
93
resource_size_t start, end, map, start1, end1, map1, map2, map3, mask;
94
95
switch (mips_revision_sconid) {
96
case MIPS_REVISION_SCON_GT64120:
97
/*
98
* Due to a bug in the Galileo system controller, we need
99
* to setup the PCI BAR for the Galileo internal registers.
100
* This should be done in the bios/bootprom and will be
101
* fixed in a later revision of YAMON (the MIPS boards
102
* boot prom).
103
*/
104
GT_WRITE(GT_PCI0_CFGADDR_OFS,
105
(0 << GT_PCI0_CFGADDR_BUSNUM_SHF) | /* Local bus */
106
(0 << GT_PCI0_CFGADDR_DEVNUM_SHF) | /* GT64120 dev */
107
(0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) | /* Function 0*/
108
((0x20/4) << GT_PCI0_CFGADDR_REGNUM_SHF) | /* BAR 4*/
109
GT_PCI0_CFGADDR_CONFIGEN_BIT);
110
111
/* Perform the write */
112
GT_WRITE(GT_PCI0_CFGDATA_OFS, CPHYSADDR(MIPS_GT_BASE));
113
114
/* Set up resource ranges from the controller's registers. */
115
start = GT_READ(GT_PCI0M0LD_OFS);
116
end = GT_READ(GT_PCI0M0HD_OFS);
117
map = GT_READ(GT_PCI0M0REMAP_OFS);
118
end = (end & GT_PCI_HD_MSK) | (start & ~GT_PCI_HD_MSK);
119
start1 = GT_READ(GT_PCI0M1LD_OFS);
120
end1 = GT_READ(GT_PCI0M1HD_OFS);
121
map1 = GT_READ(GT_PCI0M1REMAP_OFS);
122
end1 = (end1 & GT_PCI_HD_MSK) | (start1 & ~GT_PCI_HD_MSK);
123
/* Cannot support multiple windows, use the wider. */
124
if (end1 - start1 > end - start) {
125
start = start1;
126
end = end1;
127
map = map1;
128
}
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_mem_resource.start = start;
134
gt64120_mem_resource.end = end;
135
gt64120_controller.mem_offset = (start & mask) - (map & mask);
136
/* Addresses are 36-bit, so do shifts in the destinations. */
137
gt64120_mem_resource.start <<= GT_PCI_DCRM_SHF;
138
gt64120_mem_resource.end <<= GT_PCI_DCRM_SHF;
139
gt64120_mem_resource.end |= (1 << GT_PCI_DCRM_SHF) - 1;
140
gt64120_controller.mem_offset <<= GT_PCI_DCRM_SHF;
141
142
start = GT_READ(GT_PCI0IOLD_OFS);
143
end = GT_READ(GT_PCI0IOHD_OFS);
144
map = GT_READ(GT_PCI0IOREMAP_OFS);
145
end = (end & GT_PCI_HD_MSK) | (start & ~GT_PCI_HD_MSK);
146
mask = ~(start ^ end);
147
/* We don't support remapping with a discontiguous mask. */
148
BUG_ON((start & GT_PCI_HD_MSK) != (map & GT_PCI_HD_MSK) &&
149
mask != ~((mask & -mask) - 1));
150
gt64120_io_resource.start = map & mask;
151
gt64120_io_resource.end = (map & mask) | ~mask;
152
gt64120_controller.io_offset = 0;
153
/* Addresses are 36-bit, so do shifts in the destinations. */
154
gt64120_io_resource.start <<= GT_PCI_DCRM_SHF;
155
gt64120_io_resource.end <<= GT_PCI_DCRM_SHF;
156
gt64120_io_resource.end |= (1 << GT_PCI_DCRM_SHF) - 1;
157
158
controller = &gt64120_controller;
159
break;
160
161
case MIPS_REVISION_SCON_BONITO:
162
/* Set up resource ranges from the controller's registers. */
163
map = BONITO_PCIMAP;
164
map1 = (BONITO_PCIMAP & BONITO_PCIMAP_PCIMAP_LO0) >>
165
BONITO_PCIMAP_PCIMAP_LO0_SHIFT;
166
map2 = (BONITO_PCIMAP & BONITO_PCIMAP_PCIMAP_LO1) >>
167
BONITO_PCIMAP_PCIMAP_LO1_SHIFT;
168
map3 = (BONITO_PCIMAP & BONITO_PCIMAP_PCIMAP_LO2) >>
169
BONITO_PCIMAP_PCIMAP_LO2_SHIFT;
170
/* Combine as many adjacent windows as possible. */
171
map = map1;
172
start = BONITO_PCILO0_BASE;
173
end = 1;
174
if (map3 == map2 + 1) {
175
map = map2;
176
start = BONITO_PCILO1_BASE;
177
end++;
178
}
179
if (map2 == map1 + 1) {
180
map = map1;
181
start = BONITO_PCILO0_BASE;
182
end++;
183
}
184
bonito64_mem_resource.start = start;
185
bonito64_mem_resource.end = start +
186
BONITO_PCIMAP_WINBASE(end) - 1;
187
bonito64_controller.mem_offset = start -
188
BONITO_PCIMAP_WINBASE(map);
189
190
controller = &bonito64_controller;
191
break;
192
193
case MIPS_REVISION_SCON_SOCIT:
194
case MIPS_REVISION_SCON_ROCIT:
195
case MIPS_REVISION_SCON_SOCITSC:
196
case MIPS_REVISION_SCON_SOCITSCP:
197
/* Set up resource ranges from the controller's registers. */
198
MSC_READ(MSC01_PCI_SC2PMBASL, start);
199
MSC_READ(MSC01_PCI_SC2PMMSKL, mask);
200
MSC_READ(MSC01_PCI_SC2PMMAPL, map);
201
msc_mem_resource.start = start & mask;
202
msc_mem_resource.end = (start & mask) | ~mask;
203
msc_controller.mem_offset = (start & mask) - (map & mask);
204
#ifdef CONFIG_MIPS_CMP
205
if (gcmp_niocu())
206
gcmp_setregion(0, start, mask,
207
GCMP_GCB_GCMPB_CMDEFTGT_IOCU1);
208
#endif
209
MSC_READ(MSC01_PCI_SC2PIOBASL, start);
210
MSC_READ(MSC01_PCI_SC2PIOMSKL, mask);
211
MSC_READ(MSC01_PCI_SC2PIOMAPL, map);
212
msc_io_resource.start = map & mask;
213
msc_io_resource.end = (map & mask) | ~mask;
214
msc_controller.io_offset = 0;
215
ioport_resource.end = ~mask;
216
#ifdef CONFIG_MIPS_CMP
217
if (gcmp_niocu())
218
gcmp_setregion(1, start, mask,
219
GCMP_GCB_GCMPB_CMDEFTGT_IOCU1);
220
#endif
221
/* If ranges overlap I/O takes precedence. */
222
start = start & mask;
223
end = start | ~mask;
224
if ((start >= msc_mem_resource.start &&
225
start <= msc_mem_resource.end) ||
226
(end >= msc_mem_resource.start &&
227
end <= msc_mem_resource.end)) {
228
/* Use the larger space. */
229
start = max(start, msc_mem_resource.start);
230
end = min(end, msc_mem_resource.end);
231
if (start - msc_mem_resource.start >=
232
msc_mem_resource.end - end)
233
msc_mem_resource.end = start - 1;
234
else
235
msc_mem_resource.start = end + 1;
236
}
237
238
controller = &msc_controller;
239
break;
240
default:
241
return;
242
}
243
244
if (controller->io_resource->start < 0x00001000UL) /* FIXME */
245
controller->io_resource->start = 0x00001000UL;
246
247
iomem_resource.end &= 0xfffffffffULL; /* 64 GB */
248
ioport_resource.end = controller->io_resource->end;
249
250
controller->io_map_base = mips_io_port_base;
251
252
register_pci_controller(controller);
253
}
254
255
/* Enable PCI 2.1 compatibility in PIIX4 */
256
static void __init quirk_dlcsetup(struct pci_dev *dev)
257
{
258
u8 odlc, ndlc;
259
(void) pci_read_config_byte(dev, 0x82, &odlc);
260
/* Enable passive releases and delayed transaction */
261
ndlc = odlc | 7;
262
(void) pci_write_config_byte(dev, 0x82, ndlc);
263
}
264
265
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0,
266
quirk_dlcsetup);
267
268