2015-04-10 16:44:37 -07:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2013-2014 Wind River Systems, Inc.
|
|
|
|
*
|
2015-10-06 11:00:37 -05:00
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
2015-04-10 16:44:37 -07:00
|
|
|
*
|
2015-10-06 11:00:37 -05:00
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
2015-04-10 16:44:37 -07:00
|
|
|
*
|
2015-10-06 11:00:37 -05:00
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
2015-04-10 16:44:37 -07:00
|
|
|
*/
|
|
|
|
|
2015-12-04 10:09:39 -05:00
|
|
|
/**
|
|
|
|
* @file
|
|
|
|
* @brief PCI probe and information routines
|
|
|
|
*
|
2015-10-20 09:42:33 -07:00
|
|
|
* Module declares routines of PCI bus initialization and query
|
2015-07-01 17:22:39 -04:00
|
|
|
*/
|
2015-04-10 16:44:37 -07:00
|
|
|
|
|
|
|
#ifndef _PCI_H_
|
|
|
|
#define _PCI_H_
|
|
|
|
|
|
|
|
#define BAR_SPACE_MEM 0
|
|
|
|
#define BAR_SPACE_IO 1
|
|
|
|
|
2015-08-21 12:52:25 +03:00
|
|
|
#define PCI_MAX_FUNCTIONS 8
|
|
|
|
#define PCI_FUNCTION_ANY PCI_MAX_FUNCTIONS
|
|
|
|
|
2015-05-25 17:26:33 -04:00
|
|
|
#define PCI_MAX_BARS 6
|
|
|
|
#define PCI_BAR_ANY PCI_MAX_BARS
|
|
|
|
|
2015-04-10 16:44:37 -07:00
|
|
|
/* PCI device information */
|
|
|
|
|
|
|
|
struct pci_dev_info {
|
|
|
|
uint32_t addr; /* I/O or memory region address */
|
|
|
|
uint32_t size; /* memory region size */
|
|
|
|
int irq;
|
2015-08-21 12:53:40 +03:00
|
|
|
|
|
|
|
uint32_t bus:8;
|
|
|
|
uint32_t dev:5;
|
|
|
|
uint32_t function:4;
|
|
|
|
uint32_t mem_type:1; /* memory type: BAR_SPACE_MEM/BAR_SPACE_IO */
|
2015-12-29 16:34:58 -06:00
|
|
|
uint32_t class_type:8;
|
2015-08-21 12:53:40 +03:00
|
|
|
uint32_t bar:3;
|
|
|
|
uint32_t _reserved:3;
|
|
|
|
|
2015-04-10 16:44:37 -07:00
|
|
|
uint16_t vendor_id;
|
|
|
|
uint16_t device_id;
|
|
|
|
};
|
|
|
|
|
2015-08-25 19:16:07 +03:00
|
|
|
#ifdef CONFIG_PCI_ENUMERATION
|
pci: Provide a simpler yet powerful PCI enumeration API
This fixes many issues around PCI enumeration from old API:
- a static internal table was fed with scanning results, thus eating
memory, and worse: due to the limit of its size, scanning for new
classes was impossible unless growing statically the size of this
table --> more memory eaten! Not to mention PCI enumeration is done
once at boot time for driver initialization and that's all, so this
table is hanging around for nothing afterwards.
- one needs first to scan a class, then maybe he will be able to find
his device via pci_dev_find. Where all could be done at once.
- pci_dev_find was not trustworthy due again to the internal table. Now
if the device is not found, one will know it really went through all
the possbilities.
- still let the possibility for hard-coded BARs value on driver side
(thus no PCI scan required). However this is greatly advised not to do
so as BARs might change over a firmware/BIOS update.
Comparison:
old pci_dev_scan: could only filter out via class mask.
new pci_dev_scan: can filter out via a class, a vendor and device ID
(it could easily do the same for Function and BAR index as these are
usually fixed and informed through datasheet)
old pci_dev_scan: was limited in its findings by the size of the
internal result table.
new pci_dev_scan: can proceed through all the buses and devices every
time (there are optimizations to avoid useless work of course)
old results did not tell about the function or BAR index.
new one tells, and the structure has not bloated.
old internal code: was storing a big table of results
new internal code: is only storing a small lookup structure and an
array of Bus:Dev pairs for each PCI class for optimizations purpose.
(though, if needed, we could disable this through some #ifdef)
Usage:
- Have a local struct dev_info
- Fill it with what you want to look for, currently: only class and
vendor_id/device_id. Function and BAR index could be added if needed.
- Call pci_bus_scan_init(): this will reset the internal lookup
structure.
- Call pci_dev_scan(<a pointer to your dev_info>): at first call, the
internal lookup structure will pick up the informations from dev_info
and will try to find out what has been requested. It will return 1 on
success, or 0. On 1, your dev_info structure will be updated with the
found informations. If more devices can be found against the same
lookup informations, just call again pci_dev_scan(<a pointer to your
dev_info>) as long as it returns 1. When 0 is hit, it will mean you
found all.
Change-Id: Ibc2a16c4485ee3fed7ef4946af0ece032ae406e4
Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
2015-05-20 14:30:35 +03:00
|
|
|
extern void pci_bus_scan_init(void);
|
|
|
|
extern int pci_bus_scan(struct pci_dev_info *dev_info);
|
2015-08-25 19:16:07 +03:00
|
|
|
#else
|
2015-10-14 13:34:31 -07:00
|
|
|
#define pci_bus_scan_init(void) { ; }
|
2015-08-25 19:16:07 +03:00
|
|
|
static inline int pci_bus_scan(struct pci_dev_info *dev_info)
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
#endif /* CONFIG_PCI_ENUMERATION */
|
|
|
|
|
2015-08-21 12:53:40 +03:00
|
|
|
void pci_enable_regs(struct pci_dev_info *dev_info);
|
2015-10-14 21:22:54 -07:00
|
|
|
void pci_enable_bus_master(struct pci_dev_info *dev_info);
|
2015-10-01 14:40:23 -04:00
|
|
|
int pci_legacy_bridge_detect(struct pci_dev_info *dev_info);
|
|
|
|
void pci_legacy_bridge_configure(struct pci_dev_info *dev_info,
|
|
|
|
int io_block_num,
|
|
|
|
int pci_interrupt_pin,
|
|
|
|
int irq_number);
|
2015-04-10 16:44:37 -07:00
|
|
|
|
2015-05-27 13:08:34 -04:00
|
|
|
#ifdef CONFIG_PCI_DEBUG
|
pci: Provide a simpler yet powerful PCI enumeration API
This fixes many issues around PCI enumeration from old API:
- a static internal table was fed with scanning results, thus eating
memory, and worse: due to the limit of its size, scanning for new
classes was impossible unless growing statically the size of this
table --> more memory eaten! Not to mention PCI enumeration is done
once at boot time for driver initialization and that's all, so this
table is hanging around for nothing afterwards.
- one needs first to scan a class, then maybe he will be able to find
his device via pci_dev_find. Where all could be done at once.
- pci_dev_find was not trustworthy due again to the internal table. Now
if the device is not found, one will know it really went through all
the possbilities.
- still let the possibility for hard-coded BARs value on driver side
(thus no PCI scan required). However this is greatly advised not to do
so as BARs might change over a firmware/BIOS update.
Comparison:
old pci_dev_scan: could only filter out via class mask.
new pci_dev_scan: can filter out via a class, a vendor and device ID
(it could easily do the same for Function and BAR index as these are
usually fixed and informed through datasheet)
old pci_dev_scan: was limited in its findings by the size of the
internal result table.
new pci_dev_scan: can proceed through all the buses and devices every
time (there are optimizations to avoid useless work of course)
old results did not tell about the function or BAR index.
new one tells, and the structure has not bloated.
old internal code: was storing a big table of results
new internal code: is only storing a small lookup structure and an
array of Bus:Dev pairs for each PCI class for optimizations purpose.
(though, if needed, we could disable this through some #ifdef)
Usage:
- Have a local struct dev_info
- Fill it with what you want to look for, currently: only class and
vendor_id/device_id. Function and BAR index could be added if needed.
- Call pci_bus_scan_init(): this will reset the internal lookup
structure.
- Call pci_dev_scan(<a pointer to your dev_info>): at first call, the
internal lookup structure will pick up the informations from dev_info
and will try to find out what has been requested. It will return 1 on
success, or 0. On 1, your dev_info structure will be updated with the
found informations. If more devices can be found against the same
lookup informations, just call again pci_dev_scan(<a pointer to your
dev_info>) as long as it returns 1. When 0 is hit, it will mean you
found all.
Change-Id: Ibc2a16c4485ee3fed7ef4946af0ece032ae406e4
Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
2015-05-20 14:30:35 +03:00
|
|
|
extern void pci_show(struct pci_dev_info *dev_info);
|
2015-08-25 21:45:14 +03:00
|
|
|
#else
|
2015-10-14 13:34:31 -07:00
|
|
|
#define pci_show(__unused__) { ; }
|
2015-05-27 13:08:34 -04:00
|
|
|
#endif
|
2015-04-10 16:44:37 -07:00
|
|
|
|
|
|
|
#endif /* _PCI_H_ */
|