zephyr/include/drivers/pci/pci.h

79 lines
1.6 KiB
C
Raw Normal View History

/*
* Copyright (c) 2013-2014 Wind River Systems, Inc.
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @brief PCI probe and information routines
*
* Module declares routines of PCI bus initialization and query
*/
#ifndef ZEPHYR_INCLUDE_DRIVERS_PCI_PCI_H_
#define ZEPHYR_INCLUDE_DRIVERS_PCI_PCI_H_
#ifdef __cplusplus
extern "C" {
#endif
#define BAR_SPACE_MEM 0
#define BAR_SPACE_IO 1
#define PCI_MAX_FUNCTIONS 8
#define PCI_FUNCTION_ANY PCI_MAX_FUNCTIONS
#define PCI_MAX_BARS 6
#define PCI_BAR_ANY PCI_MAX_BARS
/* PCI device information */
struct pci_dev_info {
u32_t addr; /* I/O or memory region address */
u32_t size; /* memory region size */
int irq;
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;
u16_t vendor_id;
u16_t device_id;
};
#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);
#else
#define pci_bus_scan_init(void) { ; }
static inline int pci_bus_scan(struct pci_dev_info *dev_info)
{
return 1;
}
#endif /* CONFIG_PCI_ENUMERATION */
void pci_enable_regs(struct pci_dev_info *dev_info);
void pci_enable_bus_master(struct pci_dev_info *dev_info);
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);
#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);
#else
#define pci_show(__unused__) { ; }
#endif
#ifdef __cplusplus
}
#endif
#endif /* ZEPHYR_INCLUDE_DRIVERS_PCI_PCI_H_ */