pci: Add support for filtering by function
This will be useful for PCI based drivers to integrate fully within the device driver model, where they will have to provide the function they are found. Change-Id: I7d64a4c6727cee52cbcb743c859cda43ac1a853b Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
This commit is contained in:
parent
507decb731
commit
ff39559146
5 changed files with 48 additions and 15 deletions
|
@ -65,6 +65,7 @@ the 'ia32_pci' platform.
|
||||||
/* Generic definitions */
|
/* Generic definitions */
|
||||||
#define CONFIG_UART_PCI_VENDOR_ID 0x8086
|
#define CONFIG_UART_PCI_VENDOR_ID 0x8086
|
||||||
#define CONFIG_UART_PCI_DEVICE_ID 0x0936
|
#define CONFIG_UART_PCI_DEVICE_ID 0x0936
|
||||||
|
#define CONFIG_UART_PCI_FUNCTION PCI_FUNCTION_ANY
|
||||||
#define CONFIG_UART_PCI_BAR 0
|
#define CONFIG_UART_PCI_BAR 0
|
||||||
#define CONFIG_UART_BAUDRATE COM1_BAUD_RATE
|
#define CONFIG_UART_BAUDRATE COM1_BAUD_RATE
|
||||||
|
|
||||||
|
|
|
@ -110,6 +110,7 @@ static int ia32_pci_init(struct device *arg)
|
||||||
#ifdef CONFIG_PCI_DEBUG
|
#ifdef CONFIG_PCI_DEBUG
|
||||||
/* Rescan PCI and display the list of PCI attached devices */
|
/* Rescan PCI and display the list of PCI attached devices */
|
||||||
struct pci_dev_info info = {
|
struct pci_dev_info info = {
|
||||||
|
.function = PCI_FUNCTION_ANY,
|
||||||
.bar = PCI_BAR_ANY,
|
.bar = PCI_BAR_ANY,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -120,6 +121,7 @@ static int ia32_pci_init(struct device *arg)
|
||||||
info.class = 0;
|
info.class = 0;
|
||||||
info.vendor_id = 0;
|
info.vendor_id = 0;
|
||||||
info.device_id = 0;
|
info.device_id = 0;
|
||||||
|
info.function = PCI_FUNCTION_ANY;
|
||||||
info.bar = PCI_BAR_ANY;
|
info.bar = PCI_BAR_ANY;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_PCI_DEBUG */
|
#endif /* CONFIG_PCI_DEBUG */
|
||||||
|
|
|
@ -129,7 +129,7 @@ restarting from 0.
|
||||||
/* NOTE. These parameters may need to be configurable */
|
/* NOTE. These parameters may need to be configurable */
|
||||||
#define LSPCI_MAX_BUS PCI_BUS_NUMBERS /* maximum number of buses to scan */
|
#define LSPCI_MAX_BUS PCI_BUS_NUMBERS /* maximum number of buses to scan */
|
||||||
#define LSPCI_MAX_DEV 32 /* maximum number of devices to scan */
|
#define LSPCI_MAX_DEV 32 /* maximum number of devices to scan */
|
||||||
#define LSPCI_MAX_FUNC 8 /* maximum device functions to scan */
|
#define LSPCI_MAX_FUNC PCI_MAX_FUNCTIONS /* maximum functions to scan */
|
||||||
#define LSPCI_MAX_REG 64 /* maximum device registers to read */
|
#define LSPCI_MAX_REG 64 /* maximum device registers to read */
|
||||||
|
|
||||||
/* Base Address Register configuration fields */
|
/* Base Address Register configuration fields */
|
||||||
|
@ -279,21 +279,36 @@ static inline int pci_dev_scan(union pci_addr_reg pci_ctrl_addr,
|
||||||
uint32_t pci_data;
|
uint32_t pci_data;
|
||||||
int max_bars;
|
int max_bars;
|
||||||
|
|
||||||
|
/* verify first if there is a valid device at this point */
|
||||||
|
pci_ctrl_addr.field.func = 0;
|
||||||
|
|
||||||
|
pci_read(DEFAULT_PCI_CONTROLLER,
|
||||||
|
pci_ctrl_addr,
|
||||||
|
sizeof(pci_data),
|
||||||
|
&pci_data);
|
||||||
|
|
||||||
|
if (pci_data == 0xffffffff) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* scan all the possible functions for this device */
|
/* scan all the possible functions for this device */
|
||||||
for (; lookup.func < LSPCI_MAX_FUNC; lookup.bar = 0, lookup.func++) {
|
for (; lookup.func < LSPCI_MAX_FUNC; lookup.bar = 0, lookup.func++) {
|
||||||
|
if (lookup.info.function != PCI_FUNCTION_ANY &&
|
||||||
|
lookup.func != lookup.info.function) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
pci_ctrl_addr.field.func = lookup.func;
|
pci_ctrl_addr.field.func = lookup.func;
|
||||||
|
|
||||||
pci_read(DEFAULT_PCI_CONTROLLER,
|
if (lookup.func != 0) {
|
||||||
pci_ctrl_addr,
|
pci_read(DEFAULT_PCI_CONTROLLER,
|
||||||
sizeof(pci_data),
|
pci_ctrl_addr,
|
||||||
&pci_data);
|
sizeof(pci_data),
|
||||||
|
&pci_data);
|
||||||
|
|
||||||
if (pci_data == 0xffffffff) {
|
if (pci_data == 0xffffffff) {
|
||||||
if (lookup.func == 0) {
|
continue;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get the PCI header from the device */
|
/* get the PCI header from the device */
|
||||||
|
@ -367,6 +382,7 @@ void pci_bus_scan_init(void)
|
||||||
lookup.info.class = 0;
|
lookup.info.class = 0;
|
||||||
lookup.info.vendor_id = 0;
|
lookup.info.vendor_id = 0;
|
||||||
lookup.info.device_id = 0;
|
lookup.info.device_id = 0;
|
||||||
|
lookup.info.function = PCI_FUNCTION_ANY;
|
||||||
lookup.info.bar = PCI_BAR_ANY;
|
lookup.info.bar = PCI_BAR_ANY;
|
||||||
lookup.bus = 0;
|
lookup.bus = 0;
|
||||||
lookup.dev = 0;
|
lookup.dev = 0;
|
||||||
|
@ -395,10 +411,12 @@ int pci_bus_scan(struct pci_dev_info *dev_info)
|
||||||
if (!lookup.info.class &&
|
if (!lookup.info.class &&
|
||||||
!lookup.info.vendor_id &&
|
!lookup.info.vendor_id &&
|
||||||
!lookup.info.device_id &&
|
!lookup.info.device_id &&
|
||||||
lookup.info.bar == PCI_BAR_ANY) {
|
lookup.info.bar == PCI_BAR_ANY &&
|
||||||
|
lookup.info.function == PCI_FUNCTION_ANY) {
|
||||||
lookup.info.class = dev_info->class;
|
lookup.info.class = dev_info->class;
|
||||||
lookup.info.vendor_id = dev_info->vendor_id;
|
lookup.info.vendor_id = dev_info->vendor_id;
|
||||||
lookup.info.device_id = dev_info->device_id;
|
lookup.info.device_id = dev_info->device_id;
|
||||||
|
lookup.info.function = dev_info->function;
|
||||||
lookup.info.bar = dev_info->bar;
|
lookup.info.bar = dev_info->bar;
|
||||||
|
|
||||||
if (class_bd[lookup.info.class].set) {
|
if (class_bd[lookup.info.class].set) {
|
||||||
|
@ -411,16 +429,25 @@ int pci_bus_scan(struct pci_dev_info *dev_info)
|
||||||
pci_ctrl_addr.value = 0;
|
pci_ctrl_addr.value = 0;
|
||||||
pci_ctrl_addr.field.enable = 1;
|
pci_ctrl_addr.field.enable = 1;
|
||||||
|
|
||||||
|
if (lookup.info.function != PCI_FUNCTION_ANY) {
|
||||||
|
lookup.func = lookup.info.function;
|
||||||
|
}
|
||||||
|
|
||||||
/* run through the buses and devices */
|
/* run through the buses and devices */
|
||||||
for (; lookup.bus < LSPCI_MAX_BUS; lookup.bus++) {
|
for (; lookup.bus < LSPCI_MAX_BUS; lookup.bus++) {
|
||||||
for (; (lookup.dev < LSPCI_MAX_DEV);
|
for (; (lookup.dev < LSPCI_MAX_DEV); lookup.dev++) {
|
||||||
lookup.func = 0, lookup.dev++) {
|
|
||||||
pci_ctrl_addr.field.bus = lookup.bus;
|
pci_ctrl_addr.field.bus = lookup.bus;
|
||||||
pci_ctrl_addr.field.device = lookup.dev;
|
pci_ctrl_addr.field.device = lookup.dev;
|
||||||
|
|
||||||
if (pci_dev_scan(pci_ctrl_addr, dev_info)) {
|
if (pci_dev_scan(pci_ctrl_addr, dev_info)) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lookup.info.function != PCI_FUNCTION_ANY) {
|
||||||
|
lookup.func = lookup.info.function;
|
||||||
|
} else {
|
||||||
|
lookup.func = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -226,6 +226,7 @@ static inline void ns16550_pci_uart_scan(void)
|
||||||
.class = PCI_CLASS_COMM_CTLR,
|
.class = PCI_CLASS_COMM_CTLR,
|
||||||
.vendor_id = CONFIG_UART_PCI_VENDOR_ID,
|
.vendor_id = CONFIG_UART_PCI_VENDOR_ID,
|
||||||
.device_id = CONFIG_UART_PCI_DEVICE_ID,
|
.device_id = CONFIG_UART_PCI_DEVICE_ID,
|
||||||
|
.function = CONFIG_UART_PCI_FUNCTION,
|
||||||
.bar = CONFIG_UART_PCI_BAR,
|
.bar = CONFIG_UART_PCI_BAR,
|
||||||
};
|
};
|
||||||
int i;
|
int i;
|
||||||
|
|
|
@ -41,6 +41,9 @@ Module declares routines of PCI bus initialization and query
|
||||||
#define BAR_SPACE_MEM 0
|
#define BAR_SPACE_MEM 0
|
||||||
#define BAR_SPACE_IO 1
|
#define BAR_SPACE_IO 1
|
||||||
|
|
||||||
|
#define PCI_MAX_FUNCTIONS 8
|
||||||
|
#define PCI_FUNCTION_ANY PCI_MAX_FUNCTIONS
|
||||||
|
|
||||||
#define PCI_MAX_BARS 6
|
#define PCI_MAX_BARS 6
|
||||||
#define PCI_BAR_ANY PCI_MAX_BARS
|
#define PCI_BAR_ANY PCI_MAX_BARS
|
||||||
|
|
||||||
|
@ -52,9 +55,8 @@ struct pci_dev_info {
|
||||||
int irq;
|
int irq;
|
||||||
uint16_t mem_type:1; /* memory type: BAR_SPACE_MEM/BAR_SPACE_IO */
|
uint16_t mem_type:1; /* memory type: BAR_SPACE_MEM/BAR_SPACE_IO */
|
||||||
uint16_t class:8;
|
uint16_t class:8;
|
||||||
uint16_t function:3;
|
uint16_t function:4;
|
||||||
uint16_t bar:3;
|
uint16_t bar:3;
|
||||||
uint16_t unused:1;
|
|
||||||
uint16_t vendor_id;
|
uint16_t vendor_id;
|
||||||
uint16_t device_id;
|
uint16_t device_id;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue