Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/xtensa/lib/pci-auto.c
26425 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
* arch/xtensa/lib/pci-auto.c
4
*
5
* PCI autoconfiguration library
6
*
7
* Copyright (C) 2001 - 2005 Tensilica Inc.
8
*
9
* Chris Zankel <[email protected], [email protected]>
10
*
11
* Based on work from Matt Porter <[email protected]>
12
*/
13
14
#include <linux/bitfield.h>
15
#include <linux/kernel.h>
16
#include <linux/init.h>
17
#include <linux/pci.h>
18
19
#include <asm/pci-bridge.h>
20
21
22
/*
23
*
24
* Setting up a PCI
25
*
26
* pci_ctrl->first_busno = <first bus number (0)>
27
* pci_ctrl->last_busno = <last bus number (0xff)>
28
* pci_ctrl->ops = <PCI config operations>
29
* pci_ctrl->map_irq = <function to return the interrupt number for a device>
30
*
31
* pci_ctrl->io_space.start = <IO space start address (PCI view)>
32
* pci_ctrl->io_space.end = <IO space end address (PCI view)>
33
* pci_ctrl->io_space.base = <IO space offset: address 0 from CPU space>
34
* pci_ctrl->mem_space.start = <MEM space start address (PCI view)>
35
* pci_ctrl->mem_space.end = <MEM space end address (PCI view)>
36
* pci_ctrl->mem_space.base = <MEM space offset: address 0 from CPU space>
37
*
38
* pcibios_init_resource(&pci_ctrl->io_resource, <IO space start>,
39
* <IO space end>, IORESOURCE_IO, "PCI host bridge");
40
* pcibios_init_resource(&pci_ctrl->mem_resources[0], <MEM space start>,
41
* <MEM space end>, IORESOURCE_MEM, "PCI host bridge");
42
*
43
* pci_ctrl->last_busno = pciauto_bus_scan(pci_ctrl,pci_ctrl->first_busno);
44
*
45
* int __init pciauto_bus_scan(struct pci_controller *pci_ctrl, int current_bus)
46
*
47
*/
48
49
static int pciauto_upper_iospc;
50
static int pciauto_upper_memspc;
51
52
static struct pci_dev pciauto_dev;
53
static struct pci_bus pciauto_bus;
54
55
/*
56
* Helper functions
57
*/
58
59
/* Initialize the bars of a PCI device. */
60
61
static void __init
62
pciauto_setup_bars(struct pci_dev *dev, int bar_limit)
63
{
64
int bar_size;
65
int bar, bar_nr;
66
int *upper_limit;
67
int found_mem64 = 0;
68
69
for (bar = PCI_BASE_ADDRESS_0, bar_nr = 0;
70
bar <= bar_limit;
71
bar+=4, bar_nr++)
72
{
73
/* Tickle the BAR and get the size */
74
pci_write_config_dword(dev, bar, 0xffffffff);
75
pci_read_config_dword(dev, bar, &bar_size);
76
77
/* If BAR is not implemented go to the next BAR */
78
if (!bar_size)
79
continue;
80
81
/* Check the BAR type and set our address mask */
82
if (bar_size & PCI_BASE_ADDRESS_SPACE_IO)
83
{
84
bar_size &= PCI_BASE_ADDRESS_IO_MASK;
85
upper_limit = &pciauto_upper_iospc;
86
pr_debug("PCI Autoconfig: BAR %d, I/O, ", bar_nr);
87
}
88
else
89
{
90
if ((bar_size & PCI_BASE_ADDRESS_MEM_TYPE_MASK) ==
91
PCI_BASE_ADDRESS_MEM_TYPE_64)
92
found_mem64 = 1;
93
94
bar_size &= PCI_BASE_ADDRESS_MEM_MASK;
95
upper_limit = &pciauto_upper_memspc;
96
pr_debug("PCI Autoconfig: BAR %d, Mem, ", bar_nr);
97
}
98
99
/* Allocate a base address (bar_size is negative!) */
100
*upper_limit = (*upper_limit + bar_size) & bar_size;
101
102
/* Write it out and update our limit */
103
pci_write_config_dword(dev, bar, *upper_limit);
104
105
/*
106
* If we are a 64-bit decoder then increment to the
107
* upper 32 bits of the bar and force it to locate
108
* in the lower 4GB of memory.
109
*/
110
111
if (found_mem64)
112
pci_write_config_dword(dev, (bar+=4), 0x00000000);
113
114
pr_debug("size=0x%x, address=0x%x\n",
115
~bar_size + 1, *upper_limit);
116
}
117
}
118
119
/* Initialize the interrupt number. */
120
121
static void __init
122
pciauto_setup_irq(struct pci_controller* pci_ctrl,struct pci_dev *dev,int devfn)
123
{
124
u8 pin;
125
int irq = 0;
126
127
pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
128
129
/* Fix illegal pin numbers. */
130
131
if (pin == 0 || pin > 4)
132
pin = 1;
133
134
if (pci_ctrl->map_irq)
135
irq = pci_ctrl->map_irq(dev, PCI_SLOT(devfn), pin);
136
137
if (irq == -1)
138
irq = 0;
139
140
pr_debug("PCI Autoconfig: Interrupt %d, pin %d\n", irq, pin);
141
142
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
143
}
144
145
146
static void __init
147
pciauto_prescan_setup_bridge(struct pci_dev *dev, int current_bus,
148
int sub_bus, int *iosave, int *memsave)
149
{
150
/* Configure bus number registers */
151
pci_write_config_byte(dev, PCI_PRIMARY_BUS, current_bus);
152
pci_write_config_byte(dev, PCI_SECONDARY_BUS, sub_bus + 1);
153
pci_write_config_byte(dev, PCI_SUBORDINATE_BUS, 0xff);
154
155
/* Round memory allocator to 1MB boundary */
156
pciauto_upper_memspc &= ~(0x100000 - 1);
157
*memsave = pciauto_upper_memspc;
158
159
/* Round I/O allocator to 4KB boundary */
160
pciauto_upper_iospc &= ~(0x1000 - 1);
161
*iosave = pciauto_upper_iospc;
162
163
/* Set up memory and I/O filter limits, assume 32-bit I/O space */
164
pci_write_config_word(dev, PCI_MEMORY_LIMIT,
165
((pciauto_upper_memspc - 1) & 0xfff00000) >> 16);
166
pci_write_config_byte(dev, PCI_IO_LIMIT,
167
((pciauto_upper_iospc - 1) & 0x0000f000) >> 8);
168
pci_write_config_word(dev, PCI_IO_LIMIT_UPPER16,
169
((pciauto_upper_iospc - 1) & 0xffff0000) >> 16);
170
}
171
172
static void __init
173
pciauto_postscan_setup_bridge(struct pci_dev *dev, int current_bus, int sub_bus,
174
int *iosave, int *memsave)
175
{
176
int cmdstat;
177
178
/* Configure bus number registers */
179
pci_write_config_byte(dev, PCI_SUBORDINATE_BUS, sub_bus);
180
181
/*
182
* Round memory allocator to 1MB boundary.
183
* If no space used, allocate minimum.
184
*/
185
pciauto_upper_memspc &= ~(0x100000 - 1);
186
if (*memsave == pciauto_upper_memspc)
187
pciauto_upper_memspc -= 0x00100000;
188
189
pci_write_config_word(dev, PCI_MEMORY_BASE, pciauto_upper_memspc >> 16);
190
191
/* Allocate 1MB for pre-fretch */
192
pci_write_config_word(dev, PCI_PREF_MEMORY_LIMIT,
193
((pciauto_upper_memspc - 1) & 0xfff00000) >> 16);
194
195
pciauto_upper_memspc -= 0x100000;
196
197
pci_write_config_word(dev, PCI_PREF_MEMORY_BASE,
198
pciauto_upper_memspc >> 16);
199
200
/* Round I/O allocator to 4KB boundary */
201
pciauto_upper_iospc &= ~(0x1000 - 1);
202
if (*iosave == pciauto_upper_iospc)
203
pciauto_upper_iospc -= 0x1000;
204
205
pci_write_config_byte(dev, PCI_IO_BASE,
206
(pciauto_upper_iospc & 0x0000f000) >> 8);
207
pci_write_config_word(dev, PCI_IO_BASE_UPPER16,
208
pciauto_upper_iospc >> 16);
209
210
/* Enable memory and I/O accesses, enable bus master */
211
pci_read_config_dword(dev, PCI_COMMAND, &cmdstat);
212
pci_write_config_dword(dev, PCI_COMMAND,
213
cmdstat |
214
PCI_COMMAND_IO |
215
PCI_COMMAND_MEMORY |
216
PCI_COMMAND_MASTER);
217
}
218
219
/*
220
* Scan the current PCI bus.
221
*/
222
223
224
int __init pciauto_bus_scan(struct pci_controller *pci_ctrl, int current_bus)
225
{
226
int sub_bus, pci_devfn, pci_class, cmdstat;
227
unsigned short vid;
228
unsigned char header_type;
229
struct pci_dev *dev = &pciauto_dev;
230
bool found_multi = false;
231
232
pciauto_dev.bus = &pciauto_bus;
233
pciauto_dev.sysdata = pci_ctrl;
234
pciauto_bus.ops = pci_ctrl->ops;
235
236
/*
237
* Fetch our I/O and memory space upper boundaries used
238
* to allocated base addresses on this pci_controller.
239
*/
240
241
if (current_bus == pci_ctrl->first_busno)
242
{
243
pciauto_upper_iospc = pci_ctrl->io_resource.end + 1;
244
pciauto_upper_memspc = pci_ctrl->mem_resources[0].end + 1;
245
}
246
247
sub_bus = current_bus;
248
249
for (pci_devfn = 0; pci_devfn < 0xff; pci_devfn++)
250
{
251
/* Skip our host bridge */
252
if ((current_bus == pci_ctrl->first_busno) && (pci_devfn == 0))
253
continue;
254
255
if (PCI_FUNC(pci_devfn) && !found_multi)
256
continue;
257
258
pciauto_bus.number = current_bus;
259
pciauto_dev.devfn = pci_devfn;
260
261
/* If config space read fails from this device, move on */
262
if (pci_read_config_byte(dev, PCI_HEADER_TYPE, &header_type))
263
continue;
264
265
if (!PCI_FUNC(pci_devfn))
266
found_multi = FIELD_GET(PCI_HEADER_TYPE_MFD, header_type);
267
pci_read_config_word(dev, PCI_VENDOR_ID, &vid);
268
269
if (vid == 0xffff || vid == 0x0000) {
270
found_multi = false;
271
continue;
272
}
273
274
pci_read_config_dword(dev, PCI_CLASS_REVISION, &pci_class);
275
276
if ((pci_class >> 16) == PCI_CLASS_BRIDGE_PCI) {
277
278
int iosave, memsave;
279
280
pr_debug("PCI Autoconfig: Found P2P bridge, device %d\n",
281
PCI_SLOT(pci_devfn));
282
283
/* Allocate PCI I/O and/or memory space */
284
pciauto_setup_bars(dev, PCI_BASE_ADDRESS_1);
285
286
pciauto_prescan_setup_bridge(dev, current_bus, sub_bus,
287
&iosave, &memsave);
288
sub_bus = pciauto_bus_scan(pci_ctrl, sub_bus+1);
289
pciauto_postscan_setup_bridge(dev, current_bus, sub_bus,
290
&iosave, &memsave);
291
pciauto_bus.number = current_bus;
292
293
continue;
294
295
}
296
297
/*
298
* Found a peripheral, enable some standard
299
* settings
300
*/
301
302
pci_read_config_dword(dev, PCI_COMMAND, &cmdstat);
303
pci_write_config_dword(dev, PCI_COMMAND,
304
cmdstat |
305
PCI_COMMAND_IO |
306
PCI_COMMAND_MEMORY |
307
PCI_COMMAND_MASTER);
308
pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x80);
309
310
/* Allocate PCI I/O and/or memory space */
311
pr_debug("PCI Autoconfig: Found Bus %d, Device %d, Function %d\n",
312
current_bus, PCI_SLOT(pci_devfn), PCI_FUNC(pci_devfn));
313
314
pciauto_setup_bars(dev, PCI_BASE_ADDRESS_5);
315
pciauto_setup_irq(pci_ctrl, dev, pci_devfn);
316
}
317
return sub_bus;
318
}
319
320