~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/xtensa/lib/pci-auto.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 <zankel@tensilica.com, cez@zankel.net>
 10  *
 11  * Based on work from Matt Porter <mporter@mvista.com>
 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 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php