2015-04-11 07:44:37 +08:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2013-2014 Wind River Systems, Inc.
|
|
|
|
*
|
2017-01-19 09:01:01 +08:00
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
2015-04-11 07:44:37 +08:00
|
|
|
*/
|
|
|
|
|
2015-12-04 23:09:39 +08:00
|
|
|
/**
|
|
|
|
* @file
|
|
|
|
* @brief PCI probe and information routines
|
|
|
|
*
|
2015-10-21 00:42:33 +08:00
|
|
|
* Module declares routines of PCI bus initialization and query
|
2015-07-02 05:22:39 +08:00
|
|
|
*/
|
2015-04-11 07:44:37 +08:00
|
|
|
|
2018-09-15 01:43:44 +08:00
|
|
|
#ifndef ZEPHYR_INCLUDE_DRIVERS_PCI_PCI_H_
|
|
|
|
#define ZEPHYR_INCLUDE_DRIVERS_PCI_PCI_H_
|
2015-04-11 07:44:37 +08:00
|
|
|
|
2016-01-23 01:38:49 +08:00
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
|
2015-04-11 07:44:37 +08:00
|
|
|
#define BAR_SPACE_MEM 0
|
|
|
|
#define BAR_SPACE_IO 1
|
|
|
|
|
2015-08-21 17:52:25 +08:00
|
|
|
#define PCI_MAX_FUNCTIONS 8
|
|
|
|
#define PCI_FUNCTION_ANY PCI_MAX_FUNCTIONS
|
|
|
|
|
2015-05-26 05:26:33 +08:00
|
|
|
#define PCI_MAX_BARS 6
|
|
|
|
#define PCI_BAR_ANY PCI_MAX_BARS
|
|
|
|
|
2015-04-11 07:44:37 +08:00
|
|
|
/* PCI device information */
|
|
|
|
|
|
|
|
struct pci_dev_info {
|
2017-04-21 23:55:34 +08:00
|
|
|
u32_t addr; /* I/O or memory region address */
|
|
|
|
u32_t size; /* memory region size */
|
2015-04-11 07:44:37 +08:00
|
|
|
int irq;
|
2015-08-21 17:53:40 +08:00
|
|
|
|
2017-04-21 23:55:34 +08:00
|
|
|
u32_t bus:8;
|
|
|
|
u32_t dev:5;
|
|
|
|
u32_t function:4;
|
|
|
|
u32_t mem_type:1; /* memory type: BAR_SPACE_MEM/BAR_SPACE_IO */
|
|
|
|
u32_t class_type:8;
|
|
|
|
u32_t bar:3;
|
|
|
|
u32_t _reserved:3;
|
2015-08-21 17:53:40 +08:00
|
|
|
|
2017-04-21 23:55:34 +08:00
|
|
|
u16_t vendor_id;
|
|
|
|
u16_t device_id;
|
2015-04-11 07:44:37 +08:00
|
|
|
};
|
|
|
|
|
2015-08-26 00:16:07 +08: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 19:30:35 +08:00
|
|
|
extern void pci_bus_scan_init(void);
|
|
|
|
extern int pci_bus_scan(struct pci_dev_info *dev_info);
|
2015-08-26 00:16:07 +08:00
|
|
|
#else
|
2015-10-15 04:34:31 +08:00
|
|
|
#define pci_bus_scan_init(void) { ; }
|
2015-08-26 00:16:07 +08:00
|
|
|
static inline int pci_bus_scan(struct pci_dev_info *dev_info)
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
#endif /* CONFIG_PCI_ENUMERATION */
|
|
|
|
|
2015-08-21 17:53:40 +08:00
|
|
|
void pci_enable_regs(struct pci_dev_info *dev_info);
|
2015-10-15 12:22:54 +08:00
|
|
|
void pci_enable_bus_master(struct pci_dev_info *dev_info);
|
2015-10-02 02:40:23 +08: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-11 07:44:37 +08:00
|
|
|
|
2015-05-28 01:08:34 +08: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 19:30:35 +08:00
|
|
|
extern void pci_show(struct pci_dev_info *dev_info);
|
2015-08-26 02:45:14 +08:00
|
|
|
#else
|
2015-10-15 04:34:31 +08:00
|
|
|
#define pci_show(__unused__) { ; }
|
2015-05-28 01:08:34 +08:00
|
|
|
#endif
|
2015-04-11 07:44:37 +08:00
|
|
|
|
2016-01-23 01:38:49 +08:00
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2018-09-15 01:43:44 +08:00
|
|
|
#endif /* ZEPHYR_INCLUDE_DRIVERS_PCI_PCI_H_ */
|