drivers/pci: remove legacy PCI implementation

This has been subsumed by the new implementation in drivers/pcie.
We remove the legacy subsystem, related tests, shell module, and
outdated documentation/config references.

Signed-off-by: Charles E. Youse <charles.youse@intel.com>
This commit is contained in:
Charles E. Youse 2019-08-23 09:45:41 -07:00 committed by Anas Nashif
commit 4a166f4913
16 changed files with 0 additions and 3004 deletions

View file

@ -137,7 +137,6 @@
/drivers/led/ @Mani-Sadhasivam /drivers/led/ @Mani-Sadhasivam
/drivers/led_strip/ @mbolivar /drivers/led_strip/ @mbolivar
/drivers/modem/ @mike-scott /drivers/modem/ @mike-scott
/drivers/pci/ @gnuless
/drivers/pcie/ @gnuless /drivers/pcie/ @gnuless
/drivers/pinmux/stm32/ @rsalveti @idlethread /drivers/pinmux/stm32/ @rsalveti @idlethread
/drivers/sensor/ @MaureenHelm /drivers/sensor/ @MaureenHelm

View file

@ -20,7 +20,6 @@ add_subdirectory_if_kconfig(ipm)
add_subdirectory_if_kconfig(led) add_subdirectory_if_kconfig(led)
add_subdirectory_if_kconfig(led_strip) add_subdirectory_if_kconfig(led_strip)
add_subdirectory_if_kconfig(modem) add_subdirectory_if_kconfig(modem)
add_subdirectory_if_kconfig(pci)
add_subdirectory_if_kconfig(pcie) add_subdirectory_if_kconfig(pcie)
add_subdirectory_if_kconfig(pinmux) add_subdirectory_if_kconfig(pinmux)
add_subdirectory_if_kconfig(pwm) add_subdirectory_if_kconfig(pwm)

View file

@ -27,8 +27,6 @@ source "drivers/timer/Kconfig"
source "drivers/entropy/Kconfig" source "drivers/entropy/Kconfig"
source "drivers/pci/Kconfig"
source "drivers/pcie/Kconfig" source "drivers/pcie/Kconfig"
source "drivers/gpio/Kconfig" source "drivers/gpio/Kconfig"

View file

@ -1,8 +0,0 @@
# SPDX-License-Identifier: Apache-2.0
zephyr_sources(
pci.c
pci_config.c
pci_interface.c
)
zephyr_sources_ifdef(CONFIG_PCI_SHELL pci_shell.c)

View file

@ -1,38 +0,0 @@
# Kconfig - PCI configuration options
#
# Copyright (c) 2015 Intel Corporation
#
# SPDX-License-Identifier: Apache-2.0
#
menuconfig PCI
bool "PCI Settings"
depends on X86
help
This options enables support of PCI bus for device drivers.
if PCI
config PCI_SHELL
bool "Enable PCI Shell"
depends on SHELL
select PCI_ENUMERATION
help
Enable commands for debugging PCI using the built-in shell.
config PCI_ENUMERATION
bool "Enable PCI device enumeration"
help
This option enables the PCI enumeration for device drivers.
This might be useful to find out which are the PCI settings
of the devices. Once those are known and statically set in
every relevant driver's configuration, it might be wise to
disable this option to remove useless code.
module = PCI
module-str = PCI
source "subsys/logging/Kconfig.template.log_config"
endif # PCI

View file

@ -1,476 +0,0 @@
/*
* Copyright (c) 2013-2014 Wind River Systems, Inc.
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @brief PCI probe and information routines
*
* Module implements routines for PCI bus initialization and query.
*
* USAGE
* To use the driver, the platform must define:
* - Numbers of BUSes:
* - PCI_BUS_NUMBERS;
* - Register addresses:
* - PCI_CTRL_ADDR_REG;
* - PCI_CTRL_DATA_REG;
* - pci_pin2irq() - the routine that converts the PCI interrupt pin
* number to IRQ number.
*
* About scanning the PCI buses:
* At every new usage of this API, the code should call pci_bus_scan_init().
* It should own a struct pci_dev_info, filled in with the parameters it is
* interested to look for: class and/or vendor_id/device_id.
*
* Then it can loop on pci_bus_scan() providing a pointer on that structure.
* Such function can be called as long as it returns 1. At every successful
* return of pci_bus_scan() it means the provided structure pointer will have
* been updated with the current scan result which the code might be interested
* in. On pci_bus_scan() returning 0, the code should discard the result and
* stop calling pci_bus_scan(). If it wants to retrieve the result, it will
* have to restart the procedure all over again.
*
* EXAMPLE
* struct pci_dev_info info = {
* .class_type = PCI_CLASS_COMM_CTLR
* };
*
* pci_bus_scan_init();
*
* while (pci_bus_scan(&info)) {
* ...
* do something with "info" which holds a valid result, i.e. some
* device information matching the PCI class PCI_CLASS_COMM_CTLR
* ...
* }
*
* INTERNALS
* The whole logic runs around a structure: struct lookup_data, which exists
* on one instantiation called 'lookup'.
* Such structure is used for 2 distinct roles:
* - to match devices the caller is looking for
* - to loop on PCI bus, devices, function and BARs
*
* The search criteria are the class and/or the vendor_id/device_id of a PCI
* device. The caller first initializes the lookup structure by calling
* pci_bus_scan_init(), which will reset the search criteria as well as the
* loop parameters to 0. At the very first subsequent call of pci_bus_scan()
* the lookup structure will store the search criteria. Then the loop starts.
* For each bus it will run through each device on which it will loop on each
* function and BARs, as long as the criteria does not match or until it hit
* the limit of bus/dev/functions to scan.
*
* On a successful match, it will stop the loop, fill in the caller's
* pci_dev_info structure with the found device information, and return 1.
* Hopefully, the lookup structure still remembers where it stopped and the
* original search criteria. Thus, when the caller asks to scan again for
* a possible result next, the loop will restart where it stopped.
* That will work as long as there are relevant results found.
*/
#include <kernel.h>
#include <arch/cpu.h>
#include <sys/printk.h>
#include <toolchain.h>
#include <linker/sections.h>
#include <soc.h>
#include <pci/pci_mgr.h>
#include <pci/pci.h>
#ifdef CONFIG_PCI_ENUMERATION
/* NOTE. These parameters may need to be configurable */
#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_FUNC PCI_MAX_FUNCTIONS /* maximum functions to scan */
#define LSPCI_MAX_REG 64 /* maximum device registers to read */
/* Base Address Register configuration fields */
#define BAR_SPACE(x) ((x) & 0x00000001)
#define BAR_TYPE(x) ((x) & 0x00000006)
#define BAR_TYPE_32BIT 0
#define BAR_TYPE_64BIT 4
#define BAR_PREFETCH(x) (((x) >> 3) & 0x00000001)
#define BAR_ADDR(x) (((x) >> 4) & 0x0fffffff)
#define BAR_IO_MASK(x) ((x) & ~0x3)
#define BAR_MEM_MASK(x) ((x) & ~0xf)
struct lookup_data {
struct pci_dev_info info;
u32_t bus:9;
u32_t dev:6;
u32_t func:4;
u32_t baridx:3;
u32_t barofs:3;
u32_t unused:7;
u8_t buses;
};
static struct lookup_data __noinit lookup;
/**
* @brief Return the configuration for the specified BAR
*
* @return 0 if BAR is implemented, -1 if not.
*/
static int pci_bar_config_get(union pci_addr_reg pci_ctrl_addr, u32_t *config)
{
u32_t old_value;
/* save the current setting */
pci_read(DEFAULT_PCI_CONTROLLER, pci_ctrl_addr,
sizeof(old_value), &old_value);
/* write to the BAR to see how large it is */
pci_write(DEFAULT_PCI_CONTROLLER, pci_ctrl_addr,
sizeof(u32_t), 0xffffffff);
pci_read(DEFAULT_PCI_CONTROLLER, pci_ctrl_addr,
sizeof(*config), config);
/* put back the old configuration */
pci_write(DEFAULT_PCI_CONTROLLER, pci_ctrl_addr,
sizeof(old_value), old_value);
/* check if this BAR is implemented */
if (*config != 0xffffffff && *config != 0U) {
return 0;
}
/* BAR not supported */
return -1;
}
/**
* @brief Retrieve the I/O address and IRQ of the specified BAR
*
* @return -1 on error, 0 if 32 bit BAR retrieved or 1 if 64 bit BAR retrieved
*
* NOTE: Routine does not set up parameters for 64 bit BARS, they are ignored.
*/
static int pci_bar_params_get(union pci_addr_reg pci_ctrl_addr,
struct pci_dev_info *dev_info,
int max_bars)
{
u32_t bar_value;
u32_t bar_config;
u32_t bar_hival;
u32_t addr;
u32_t mask;
pci_ctrl_addr.field.reg = 4 + lookup.barofs;
pci_read(DEFAULT_PCI_CONTROLLER, pci_ctrl_addr,
sizeof(bar_value), &bar_value);
if (pci_bar_config_get(pci_ctrl_addr, &bar_config) != 0) {
return -1;
}
if (BAR_SPACE(bar_config) == BAR_SPACE_MEM) {
dev_info->mem_type = BAR_SPACE_MEM;
mask = ~0xf;
if (BAR_TYPE(bar_config) == BAR_TYPE_64BIT) {
/* Last BAR register cannot be 64-bit */
if (++lookup.barofs >= max_bars) {
return 1;
}
/* Make sure the address is accessible */
pci_ctrl_addr.field.reg++;
pci_read(DEFAULT_PCI_CONTROLLER, pci_ctrl_addr,
sizeof(bar_hival), &bar_hival);
if (bar_hival) {
return 1; /* Inaccessible memory */
}
}
} else {
dev_info->mem_type = BAR_SPACE_IO;
mask = ~0x3;
}
dev_info->addr = bar_value & mask;
addr = bar_config & mask;
if (addr != 0U) {
/* calculate the size of the BAR memory required */
dev_info->size = 1 << (find_lsb_set(addr) - 1);
}
return 0;
}
static bool pci_read_multifunction(union pci_addr_reg pci_ctrl_addr)
{
u32_t header_type;
pci_ctrl_addr.field.reg = 3;
pci_ctrl_addr.field.offset = 0;
pci_read(DEFAULT_PCI_CONTROLLER, pci_ctrl_addr, sizeof(header_type),
&header_type);
return header_type >> 16 & 0x80;
}
/**
* @brief Scan the specified PCI device for all sub functions
*
* @return 1 if a device has been found, 0 otherwise.
*/
static int pci_dev_scan(union pci_addr_reg pci_ctrl_addr,
struct pci_dev_info *dev_info)
{
static union pci_dev pci_dev_header;
u32_t pci_data;
int max_bars;
bool multi_function;
/* 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;
}
/* Check that PCI is multi a function device */
multi_function = pci_read_multifunction(pci_ctrl_addr);
/* scan all the possible functions for this device */
for (; lookup.func < LSPCI_MAX_FUNC;
lookup.baridx = 0, lookup.barofs = 0, lookup.func++) {
if (lookup.info.function != PCI_FUNCTION_ANY &&
lookup.func != lookup.info.function) {
return 0;
}
/* Skip single function device */
if (lookup.func != 0 && !multi_function) {
break;
}
pci_ctrl_addr.field.func = lookup.func;
if (lookup.func != 0) {
pci_read(DEFAULT_PCI_CONTROLLER, pci_ctrl_addr,
sizeof(pci_data), &pci_data);
if (pci_data == 0xffffffff) {
continue;
}
}
/* get the PCI header from the device */
pci_header_get(DEFAULT_PCI_CONTROLLER,
pci_ctrl_addr, &pci_dev_header);
if (pci_dev_header.field.class == PCI_CLASS_BRIDGE_CTLR &&
pci_dev_header.field.subclass == PCI_SUBCLASS_P2P_BRIDGE) {
lookup.buses++;
}
/*
* Skip a device if its class is specified by the
* caller and does not match
*/
if (lookup.info.class_type &&
pci_dev_header.field.class != lookup.info.class_type) {
continue;
}
if (lookup.info.vendor_id && lookup.info.device_id &&
(lookup.info.vendor_id != pci_dev_header.field.vendor_id ||
lookup.info.device_id != pci_dev_header.field.device_id)) {
continue;
}
/* Get memory and interrupt information */
if ((pci_dev_header.field.hdr_type & 0x7f) == 1) {
max_bars = 2;
} else {
max_bars = PCI_MAX_BARS;
}
for (; lookup.barofs < max_bars;
lookup.baridx++, lookup.barofs++) {
/* Ignore BARs with errors */
if (pci_bar_params_get(pci_ctrl_addr, dev_info,
max_bars) != 0) {
continue;
} else if (lookup.info.bar != PCI_BAR_ANY &&
lookup.baridx != lookup.info.bar) {
continue;
} else {
dev_info->bus = lookup.bus;
dev_info->dev = lookup.dev;
dev_info->vendor_id =
pci_dev_header.field.vendor_id;
dev_info->device_id =
pci_dev_header.field.device_id;
dev_info->class_type =
pci_dev_header.field.class;
dev_info->irq = pci_pin2irq(dev_info->bus,
dev_info->dev,
pci_dev_header.field.interrupt_pin);
dev_info->function = lookup.func;
dev_info->bar = lookup.baridx;
lookup.baridx++;
lookup.barofs++;
if (lookup.barofs >= max_bars) {
lookup.baridx = 0;
lookup.barofs = 0;
lookup.func++;
}
return 1;
}
}
}
return 0;
}
void pci_bus_scan_init(void)
{
lookup.info.class_type = 0;
lookup.info.vendor_id = 0;
lookup.info.device_id = 0;
lookup.info.function = PCI_FUNCTION_ANY;
lookup.info.bar = PCI_BAR_ANY;
lookup.bus = 0;
lookup.dev = 0;
lookup.func = 0;
lookup.baridx = 0;
lookup.barofs = 0;
lookup.buses = LSPCI_MAX_BUS;
}
/**
* @brief Scans PCI bus for devices
*
* The routine scans the PCI bus for the devices on criteria provided in the
* given dev_info at first call. Which criteria can be class and/or
* vendor_id/device_id.
*
* @return 1 on success, 0 otherwise. On success, dev_info is filled in with
* currently found device information
*/
int pci_bus_scan(struct pci_dev_info *dev_info)
{
union pci_addr_reg pci_ctrl_addr;
bool init_from_dev_info =
!lookup.info.class_type &&
!lookup.info.vendor_id &&
!lookup.info.device_id &&
lookup.info.bar == PCI_BAR_ANY &&
lookup.info.function == PCI_FUNCTION_ANY;
if (init_from_dev_info) {
lookup.info.class_type = dev_info->class_type;
lookup.info.vendor_id = dev_info->vendor_id;
lookup.info.device_id = dev_info->device_id;
lookup.info.function = dev_info->function;
lookup.info.bar = dev_info->bar;
}
/* initialise the PCI controller address register value */
pci_ctrl_addr.value = 0;
if (lookup.info.function != PCI_FUNCTION_ANY) {
lookup.func = lookup.info.function;
}
/* run through the buses and devices */
for (; lookup.bus < lookup.buses; lookup.bus++) {
for (; lookup.dev < LSPCI_MAX_DEV; lookup.dev++) {
if (lookup.bus == 0 && lookup.dev == 0) {
continue;
}
pci_ctrl_addr.field.bus = lookup.bus;
pci_ctrl_addr.field.device = lookup.dev;
if (pci_dev_scan(pci_ctrl_addr, dev_info)) {
return 1;
}
if (lookup.info.function != PCI_FUNCTION_ANY) {
lookup.func = lookup.info.function;
} else {
lookup.func = 0;
}
}
lookup.dev = 0;
}
return 0;
}
#endif /* CONFIG_PCI_ENUMERATION */
static void pci_set_command_bits(struct pci_dev_info *dev_info, u32_t bits)
{
union pci_addr_reg pci_ctrl_addr;
u32_t pci_data;
pci_ctrl_addr.value = 0;
pci_ctrl_addr.field.func = dev_info->function;
pci_ctrl_addr.field.bus = dev_info->bus;
pci_ctrl_addr.field.device = dev_info->dev;
pci_ctrl_addr.field.reg = 1;
pci_read(DEFAULT_PCI_CONTROLLER, pci_ctrl_addr,
sizeof(u16_t), &pci_data);
pci_data = pci_data | bits;
pci_write(DEFAULT_PCI_CONTROLLER, pci_ctrl_addr,
sizeof(u16_t), pci_data);
}
void pci_enable_regs(struct pci_dev_info *dev_info)
{
pci_set_command_bits(dev_info, PCI_CMD_MEM_ENABLE);
}
void pci_enable_bus_master(struct pci_dev_info *dev_info)
{
pci_set_command_bits(dev_info, PCI_CMD_MASTER_ENABLE);
}
#ifdef CONFIG_PCI_LOG_LEVEL_DBG
/**
*
* @brief Show PCI device
*
* Shows the PCI device found provided as parameter.
*
* @return N/A
*/
void pci_show(struct pci_dev_info *dev_info)
{
printk("%x:%x.%x %X:%X class: 0x%X, %u, %s, "
"addrs: 0x%X-0x%X, IRQ %d\n",
dev_info->bus,
dev_info->dev,
dev_info->function,
dev_info->vendor_id,
dev_info->device_id,
dev_info->class_type,
dev_info->bar,
(dev_info->mem_type == BAR_SPACE_MEM) ? "MEM" : "I/O",
(u32_t)dev_info->addr,
(u32_t)(dev_info->addr + dev_info->size - 1),
dev_info->irq);
}
#endif /* CONFIG_PCI_LOG_LEVEL_DBG */

View file

@ -1,283 +0,0 @@
/*
* Copyright (c) 2009-2010, 2013-2014 Wind River Systems, Inc.
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @brief PCI bus support
*
*
* This module implements the PCI config space access functions
*
*/
#include <kernel.h>
#include <arch/cpu.h>
#include <pci/pci_mgr.h>
#include <string.h>
/**
*
* @brief Write a 32bit data to pci reg in offset
*
* @param bus_no Bus number.
* @param device_no Device number
* @param func_no Function number
* @param offset Offset into the configuration space.
* @param data Data written to the offset.
*
* @return N/A
*/
void pci_config_out_long(u32_t bus_no, u32_t device_no, u32_t func_no,
u32_t offset, u32_t data)
{
union pci_addr_reg pci_addr;
/* create the PCI address we're going to access */
pci_addr.field.bus = bus_no;
pci_addr.field.device = device_no;
pci_addr.field.func = func_no;
pci_addr.field.reg = offset / 4U;
pci_addr.field.offset = 0;
/* write to the PCI controller */
pci_write(DEFAULT_PCI_CONTROLLER, pci_addr, sizeof(u32_t), data);
}
/**
*
* @brief Write a 16bit data to pci reg in offset
*
* @param bus_no Bus number.
* @param device_no Device number.
* @param func_no Function number.
* @param offset Offset into the configuration space.
* @param data Data written to the offset.
*
* @return N/A
*/
void pci_config_out_word(u32_t bus_no, u32_t device_no, u32_t func_no,
u32_t offset, u16_t data)
{
union pci_addr_reg pci_addr;
/* create the PCI address we're going to access */
pci_addr.field.bus = bus_no;
pci_addr.field.device = device_no;
pci_addr.field.func = func_no;
pci_addr.field.reg = offset / 4U;
pci_addr.field.offset = offset & 2;
/* write to the PCI controller */
pci_write(DEFAULT_PCI_CONTROLLER, pci_addr, sizeof(u16_t), data);
}
/**
*
* @brief Write a 8bit data to pci reg in offset
*
* @param bus_no Bus number.
* @param device_no Device number.
* @param func_no Function number.
* @param offset Offset into the configuration space.
* @param data Data written to the offset.
*
* @return N/A
*/
void pci_config_out_byte(u32_t bus_no, u32_t device_no, u32_t func_no,
u32_t offset, u8_t data)
{
union pci_addr_reg pci_addr;
/* create the PCI address we're going to access */
pci_addr.field.bus = bus_no;
pci_addr.field.device = device_no;
pci_addr.field.func = func_no;
pci_addr.field.reg = offset / 4U;
pci_addr.field.offset = offset % 4;
/* write to the PCI controller */
pci_write(DEFAULT_PCI_CONTROLLER, pci_addr, sizeof(u8_t), data);
}
/**
*
* @brief Read a 32bit data from pci reg in offset
*
* @param bus_no Bus number.
* @param device_no Device number.
* @param func_no Function number.
* @param offset Offset into the configuration space.
* @param data Data read from the offset.
*
* @return N/A
*
*/
void pci_config_in_long(u32_t bus_no, u32_t device_no, u32_t func_no,
u32_t offset, u32_t *data)
{
union pci_addr_reg pci_addr;
/* create the PCI address we're going to access */
pci_addr.field.bus = bus_no;
pci_addr.field.device = device_no;
pci_addr.field.func = func_no;
pci_addr.field.reg = offset / 4U;
pci_addr.field.offset = 0;
/* read from the PCI controller */
pci_read(DEFAULT_PCI_CONTROLLER, pci_addr, sizeof(u32_t), data);
}
/**
*
* @brief Read in a 16bit data from a pci reg in offset
*
* @param bus_no Bus number.
* @param device_no Device number.
* @param func_no Function number.
* @param offset Offset into the configuration space.
* @param data Data read from the offset.
*
* @return N/A
*
*/
void pci_config_in_word(u32_t bus_no, u32_t device_no, u32_t func_no,
u32_t offset, u16_t *data)
{
union pci_addr_reg pci_addr;
u32_t pci_data;
/* create the PCI address we're going to access */
pci_addr.field.bus = bus_no;
pci_addr.field.device = device_no;
pci_addr.field.func = func_no;
pci_addr.field.reg = offset / 4U;
pci_addr.field.offset = offset & 2;
/* read from the PCI controller */
pci_read(DEFAULT_PCI_CONTROLLER, pci_addr, sizeof(u16_t), &pci_data);
/* return the data */
*data = (u16_t)pci_data;
}
/**
*
* @brief Read in a 8bit data from a pci reg in offset
*
* @param bus_no Bus number.
* @param device_no Device number.
* @param func_no Function number.
* @param offset Offset into the configuration space.
* @param data Data read from the offset.
*
* @return N/A
*
*/
void pci_config_in_byte(u32_t bus_no, u32_t device_no, u32_t func_no,
u32_t offset, u8_t *data)
{
union pci_addr_reg pci_addr;
u32_t pci_data;
/* create the PCI address we're going to access */
pci_addr.field.bus = bus_no;
pci_addr.field.device = device_no;
pci_addr.field.func = func_no;
pci_addr.field.reg = offset / 4U;
pci_addr.field.offset = offset % 4;
/* read from the PCI controller */
pci_read(DEFAULT_PCI_CONTROLLER, pci_addr, sizeof(u8_t), &pci_data);
/* return the data */
*data = (u8_t)pci_data;
}
/**
*
* @brief Find extended capability in ECP linked list
*
* This routine searches for an extended capability in the linked list of
* capabilities in config space. If found, the offset of the first byte
* of the capability of interest in config space is returned via pOffset.
*
* @param ext_cap_find_id Extended capabilities ID to search for.
* @param bus PCI bus number.
* @param device PCI device number.
* @param function PCI function number.
* @param p_offset Returned config space offset.
*
* @return 0 if Extended Capability found, -1 otherwise
*
*/
int pci_config_ext_cap_ptr_find(u8_t ext_cap_find_id, u32_t bus,
u32_t device, u32_t function,
u8_t *p_offset)
{
u16_t tmp_stat;
u8_t tmp_offset;
u8_t cap_offset = 0x00;
u8_t cap_id = 0x00;
/* Check to see if the device has any extended capabilities */
pci_config_in_word(bus, device, function, PCI_CFG_STATUS, &tmp_stat);
if ((tmp_stat & PCI_STATUS_NEW_CAP) == 0U) {
return -1;
}
/* Get the initial ECP offset and make longword aligned */
pci_config_in_byte(bus, device, function, PCI_CFG_CAP_PTR, &cap_offset);
cap_offset &= ~0x02;
/* Bounds check the ECP offset */
if (cap_offset < 0x40) {
return -1;
}
/* Look for the specified Extended Cap item in the linked list */
while (cap_offset != 0x00) {
/* Get the Capability ID and check */
pci_config_in_byte(bus, device, function, (int)cap_offset, &cap_id);
if (cap_id == ext_cap_find_id) {
*p_offset = cap_offset;
return 0;
}
/* Get the offset to the next New Capabilities item */
tmp_offset = cap_offset + (u8_t)0x01;
pci_config_in_byte(bus, device, function, (int)tmp_offset, &cap_offset);
}
return -1;
}

View file

@ -1,400 +0,0 @@
/*
* Copyright (c) 2009-2011, 2013-2014 Wind River Systems, Inc.
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @brief PCI bus support
*
*
* This module implements the PCI H/W access functions.
*/
#include <kernel.h>
#include <arch/cpu.h>
#include <pci/pci_mgr.h>
#include <string.h>
#include <soc.h>
#if (PCI_CTRL_ADDR_REG == 0)
#error "PCI_CTRL_ADDR_REG cannot be zero"
#endif
#if (PCI_CTRL_DATA_REG == 0)
#error "PCI_CTRL_DATA_REG cannot be zero"
#endif
/**
*
* @brief Read a PCI controller register
*
* @param reg PCI register to read
* @param data where to put the data
* @param size size of the data to read (8/16/32 bits)
*
* This routine reads the specified register from the PCI controller and
* places the data into the provided buffer.
*
* @return N/A
*
*/
static void pci_ctrl_read(u32_t reg, u32_t *data, u32_t size)
{
/* read based on the size requested */
switch (size) {
/* long (32 bits) */
case SYS_PCI_ACCESS_32BIT:
*data = sys_in32(reg);
break;
/* word (16 bits) */
case SYS_PCI_ACCESS_16BIT:
*data = sys_in16(reg);
break;
/* byte (8 bits) */
case SYS_PCI_ACCESS_8BIT:
*data = sys_in8(reg);
break;
}
}
/**
*
* @brief Write a PCI controller register
*
* @param reg PCI register to write
* @param data data to write
* @param size size of the data to write (8/16/32 bits)
*
* This routine writes the provided data to the specified register in the PCI
* controller.
*
* @return N/A
*
*/
static void pci_ctrl_write(u32_t reg, u32_t data, u32_t size)
{
/* write based on the size requested */
switch (size) {
/* long (32 bits) */
case SYS_PCI_ACCESS_32BIT:
sys_out32(data, reg);
break;
/* word (16 bits) */
case SYS_PCI_ACCESS_16BIT:
sys_out16(data, reg);
break;
/* byte (8 bits) */
case SYS_PCI_ACCESS_8BIT:
sys_out8(data, reg);
break;
}
}
/**
*
* @brief Read the PCI controller data register
*
* @param controller controller number
* @param offset is the offset within the data region
* @param data is the returned data
* @param size is the size of the data to read
*
* This routine reads the data register of the specified PCI controller.
*
* @return 0 or -1
*
*/
static int pci_ctrl_data_read(u32_t controller, u32_t offset,
u32_t *data, u32_t size)
{
/* we only support one controller */
if (controller != DEFAULT_PCI_CONTROLLER) {
return (-1);
}
pci_ctrl_read(PCI_CTRL_DATA_REG + offset, data, size);
return 0;
}
/**
*
* @brief Write the PCI controller data register
*
* @param controller the controller number
* @param offset is the offset within the address register
* @param data is the data to write
* @param size is the size of the data
*
* This routine writes the provided data to the data register of the
* specified PCI controller.
*
* @return 0 or -1
*
*/
static int pci_ctrl_data_write(u32_t controller, u32_t offset,
u32_t data, u32_t size)
{
/* we only support one controller */
if (controller != DEFAULT_PCI_CONTROLLER) {
return (-1);
}
pci_ctrl_write(PCI_CTRL_DATA_REG + offset, data, size);
return 0;
}
/**
*
* @brief Write the PCI controller address register
*
* @param controller is the controller number
* @param offset is the offset within the address register
* @param data is the data to write
* @param size is the size of the data
*
* This routine writes the provided data to the address register of the
* specified PCI controller.
*
* @return 0 or -1
*
*/
static int pci_ctrl_addr_write(u32_t controller, u32_t offset,
u32_t data, u32_t size)
{
/* we only support one controller */
if (controller != DEFAULT_PCI_CONTROLLER) {
return (-1);
}
pci_ctrl_write(PCI_CTRL_ADDR_REG + offset, data, size);
return 0;
}
/**
*
* @brief Read a PCI register from a device
*
* This routine reads data from a PCI device's configuration space. The
* device and register to read is specified by the address parameter ("addr")
* and must be set appropriately by the caller. The address is defined by
* the structure type pci_addr_t and contains the following members:
*
* bus: PCI bus number (0-255)
* device: PCI device number (0-31)
* func: device function number (0-7)
* reg: device 32-bit register number to read (0-63)
* offset: offset within 32-bit register to read (0-3)
*
* The size parameter specifies the number of bytes to read from the PCI
* configuration space, valid values are 1, 2, and 4 bytes. A 32-bit value
* is always returned but it will contain only the number of bytes specified
* by the size parameter.
*
* If multiple PCI controllers are present in the system, the controller id
* can be specified in the "controller" parameter. If only one controller
* is present, the id DEFAULT_PCI_CONTROLLER can be used to denote this
* controller.
*
* Example:
*
* union pci_addr_reg addr;
* u32_t status;
*
* addr.field.bus = 0; /@ PCI bus zero @/
* addr.field.device = 1; /@ PCI device one @/
* addr.field.func = 0; /@ PCI function zero @/
* addr.field.reg = 4; /@ PCI register 4 @/
* addr.field.offset = 0; /@ PCI register offset @/
*
* pci_read (DEFAULT_PCI_CONTROLLER, addr, sizeof(u16_t), &status);
*
*
* NOTE:
* Reading of PCI data must be performed as an atomic operation. It is up to
* the caller to enforce this.
*
* @param controller is the PCI controller number to use
* @param addr is the PCI address to read
* @param size is the size of the data in bytes
* @param data is a pointer to the data read from the device
*
* @return N/A
*
*/
void pci_read(u32_t controller, union pci_addr_reg addr,
u32_t size, u32_t *data)
{
u32_t access_size;
u32_t access_offset;
/* validate the access size */
switch (size) {
case 1:
access_size = SYS_PCI_ACCESS_8BIT;
access_offset = addr.field.offset;
break;
case 2:
access_size = SYS_PCI_ACCESS_16BIT;
access_offset = addr.field.offset;
break;
case 4:
default:
access_size = SYS_PCI_ACCESS_32BIT;
access_offset = 0U;
break;
}
/* ensure enable has been set */
addr.field.enable = 1;
/* clear the offset for the address register */
addr.field.offset = 0;
/* read the data from the PCI controller */
pci_ctrl_addr_write(
controller, PCI_NO_OFFSET, addr.value, SYS_PCI_ACCESS_32BIT);
pci_ctrl_data_read(controller, access_offset, data, access_size);
}
/**
*
* @brief Write a to a PCI register
*
* This routine writes data to a PCI device's configuration space. The
* device and register to write is specified by the address parameter ("addr")
* and must be set appropriately by the caller. The address is defined by
* the structure type pci_addr_t and contains the following members:
*
* bus: PCI bus number (0-255)
* device: PCI device number (0-31)
* func: device function number (0-7)
* reg: device register number to read (0-63)
* offset: offset within 32-bit register to write (0-3)
*
* The size parameter specifies the number of bytes to write to the PCI
* configuration space, valid values are 1, 2, and 4 bytes. A 32-bit value
* is always provided but only the number of bytes specified by the size
* parameter will be written to the device.
*
* If multiple PCI controllers are present in the system, the controller id
* can be specified in the "controller" parameter. If only one controller
* is present, the id DEFAULT_PCI_CONTROLLER can be used to denote this
* controller.
*
* Example:
*
* pci_addr_t addr;
* u32_t bar0 = 0xE0000000;
*
* addr.field.bus = 0; /@ PCI bus zero @/
* addr.field.device = 1; /@ PCI device one @/
* addr.field.func = 0; /@ PCI function zero @/
* addr.field.reg = 16; /@ PCI register 16 @/
* addr.field.offset = 0; /@ PCI register offset @/
*
* pci_write (DEFAULT_PCI_CONTROLLER, addr, sizeof(u32_t), bar0);
*
* NOTE:
* Writing of PCI data must be performed as an atomic operation. It is up to
* the caller to enforce this.
*
* @param controller is the PCI controller to use
* @param addr is the PCI address to read
* @param size is the size in bytes to write
* @param data is the data to write
*
* @return N/A
*
*/
void pci_write(u32_t controller, union pci_addr_reg addr,
u32_t size, u32_t data)
{
u32_t access_size;
u32_t access_offset;
/* validate the access size */
switch (size) {
case 1:
access_size = SYS_PCI_ACCESS_8BIT;
access_offset = addr.field.offset;
break;
case 2:
access_size = SYS_PCI_ACCESS_16BIT;
access_offset = addr.field.offset;
break;
case 4:
default:
access_size = SYS_PCI_ACCESS_32BIT;
access_offset = 0U;
break;
}
/* ensure enable has been set */
addr.field.enable = 1;
/* clear the offset for the address register */
addr.field.offset = 0;
/* write the data to the PCI controller */
pci_ctrl_addr_write(
controller, PCI_NO_OFFSET, addr.value, SYS_PCI_ACCESS_32BIT);
pci_ctrl_data_write(controller, access_offset, data, access_size);
}
/**
*
* @brief Get the PCI header for a device
*
* This routine reads the PCI header for the specified device and puts the
* result in the supplied header structure.
*
* @return N/A
*/
void pci_header_get(u32_t controller,
union pci_addr_reg pci_ctrl_addr,
union pci_dev *pci_dev_header)
{
u32_t i;
/* clear out the header */
(void)memset(pci_dev_header, 0, sizeof(*pci_dev_header));
/* fill in the PCI header from the device */
for (i = 0U; i < PCI_HEADER_WORDS; i++) {
pci_ctrl_addr.field.reg = i;
pci_read(controller,
pci_ctrl_addr,
sizeof(u32_t),
&pci_dev_header->words.word[i]);
}
}

View file

@ -1,61 +0,0 @@
/*
* Copyright (c) 2018 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <shell/shell.h>
#include <init.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <logging/log.h>
#include <pci/pci.h>
#define LOG_LEVEL CONFIG_LOG_DEFAULT_LEVEL
LOG_MODULE_REGISTER(lspci_shell);
static void list_devices(const struct shell *shell,
struct pci_dev_info *dev_info)
{
shell_fprintf(shell, SHELL_NORMAL,
"%x:%x.%x %X:%X class: 0x%X, %u, %s, "
"addrs: 0x%X-0x%X, IRQ %d\n",
dev_info->bus,
dev_info->dev,
dev_info->function,
dev_info->vendor_id,
dev_info->device_id,
dev_info->class_type,
dev_info->bar,
(dev_info->mem_type == BAR_SPACE_MEM) ? "MEM" : "I/O",
(u32_t)dev_info->addr,
(u32_t)(dev_info->addr + dev_info->size - 1),
dev_info->irq);
}
static int cmd_lspci(const struct shell *shell, size_t argc, char **argv)
{
struct pci_dev_info info = {
.function = PCI_FUNCTION_ANY,
.bar = PCI_BAR_ANY,
};
pci_bus_scan_init();
while (pci_bus_scan(&info)) {
list_devices(shell, &info);
info.class_type = 0;
info.vendor_id = 0;
info.device_id = 0;
info.function = PCI_FUNCTION_ANY;
info.bar = PCI_BAR_ANY;
}
return 0;
}
SHELL_CMD_REGISTER(lspci, NULL, "List PCI devices", cmd_lspci);

View file

@ -1,78 +0,0 @@
/*
* 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
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_LOG_LEVEL_DBG
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_ */

File diff suppressed because it is too large Load diff

View file

@ -20,7 +20,6 @@ config TEST
config TEST_SHELL config TEST_SHELL
bool "Enable various shells for testing" bool "Enable various shells for testing"
select GPIO_SHELL if GPIO select GPIO_SHELL if GPIO
select PCI_SHELL if PCI
help help
Enable various platform and driver related shells for testing. Enable various platform and driver related shells for testing.

View file

@ -1,8 +0,0 @@
# SPDX-License-Identifier: Apache-2.0
cmake_minimum_required(VERSION 3.13.1)
include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE)
project(pci_enum)
FILE(GLOB app_sources src/*.c)
target_sources(app PRIVATE ${app_sources})

View file

@ -1,3 +0,0 @@
CONFIG_PCI=y
CONFIG_PCI_ENUMERATION=y
CONFIG_ZTEST=y

View file

@ -1,34 +0,0 @@
/* pci_enum.c - PCI Enumeration print-out application */
/*
* Copyright (c) 2015 Intel Corporation.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <ztest.h>
#include <pci/pci.h>
static void pci_enumerate(void)
{
struct pci_dev_info info = {
.function = PCI_FUNCTION_ANY,
.bar = PCI_BAR_ANY,
};
pci_bus_scan_init();
while (pci_bus_scan(&info)) {
pci_show(&info);
info.class_type = 0;
info.vendor_id = 0;
info.device_id = 0;
info.function = PCI_FUNCTION_ANY;
info.bar = PCI_BAR_ANY;
}
}
void test_main(void)
{
ztest_test_suite(pci_test, ztest_unit_test(pci_enumerate));
ztest_run_test_suite(pci_test);
}

View file

@ -1,4 +0,0 @@
tests:
peripheral.pci:
depends_on: pci
tags: drivers pci