xen/arm: Implement pci access functions

Implement generic pci access functions to read/write the configuration
space.

Signed-off-by: Rahul Singh <rahul.singh@arm.com>
Reviewed-by: Bertrand Marquis <bertrand.marquis@arm.com>
Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>
This commit is contained in:
Rahul Singh authored and Stefano Stabellini committed 2021-10-07 12:47:25 -07:00
1 parent 1da6a07be7
commit a095542b68
3 files changed
+77

No files matched your search

+57
View File
@@ -16,6 +16,7 @@
#include <asm/io.h>
#define INVALID_VALUE (~0U)
#define PCI_ERR_VALUE(len) GENMASK(0, len * 8)
int pci_generic_config_read(struct pci_host_bridge *bridge, pci_sbdf_t sbdf,
uint32_t reg, uint32_t len, uint32_t *value)
@@ -72,6 +73,62 @@ int pci_generic_config_write(struct pci_host_bridge *bridge, pci_sbdf_t sbdf,
return 0;
}
static uint32_t pci_config_read(pci_sbdf_t sbdf, unsigned int reg,
unsigned int len)
{
uint32_t val = PCI_ERR_VALUE(len);
struct pci_host_bridge *bridge = pci_find_host_bridge(sbdf.seg, sbdf.bus);
if ( unlikely(!bridge) )
return val;
if ( unlikely(!bridge->ops->read) )
return val;
bridge->ops->read(bridge, sbdf, reg, len, &val);
return val;
}
static void pci_config_write(pci_sbdf_t sbdf, unsigned int reg,
unsigned int len, uint32_t val)
{
struct pci_host_bridge *bridge = pci_find_host_bridge(sbdf.seg, sbdf.bus);
if ( unlikely(!bridge) )
return;
if ( unlikely(!bridge->ops->write) )
return;
bridge->ops->write(bridge, sbdf, reg, len, val);
}
/*
* Wrappers for all PCI configuration access functions.
*/
#define PCI_OP_WRITE(size, type) \
void pci_conf_write##size(pci_sbdf_t sbdf, \
unsigned int reg, type val) \
{ \
pci_config_write(sbdf, reg, size / 8, val); \
}
#define PCI_OP_READ(size, type) \
type pci_conf_read##size(pci_sbdf_t sbdf, \
unsigned int reg) \
{ \
return pci_config_read(sbdf, reg, size / 8); \
}
PCI_OP_READ(8, uint8_t)
PCI_OP_READ(16, uint16_t)
PCI_OP_READ(32, uint32_t)
PCI_OP_WRITE(8, uint8_t)
PCI_OP_WRITE(16, uint16_t)
PCI_OP_WRITE(32, uint32_t)
/*
* Local variables:
* mode: C
+19
View File
@@ -236,6 +236,25 @@ err_exit:
return err;
}
/*
* This function will lookup an hostbridge based on the segment and bus
* number.
*/
struct pci_host_bridge *pci_find_host_bridge(uint16_t segment, uint8_t bus)
{
struct pci_host_bridge *bridge;
list_for_each_entry( bridge, &pci_host_bridges, node )
{
if ( bridge->segment != segment )
continue;
if ( (bus < bridge->cfg->busn_start) || (bus > bridge->cfg->busn_end) )
continue;
return bridge;
}
return NULL;
}
/*
* Local variables:
* mode: C
+1
View File
@@ -81,6 +81,7 @@ int pci_generic_config_write(struct pci_host_bridge *bridge, pci_sbdf_t sbdf,
uint32_t reg, uint32_t len, uint32_t value);
void __iomem *pci_ecam_map_bus(struct pci_host_bridge *bridge,
pci_sbdf_t sbdf, uint32_t where);
struct pci_host_bridge *pci_find_host_bridge(uint16_t segment, uint8_t bus);
static always_inline bool is_pci_passthrough_enabled(void)
{
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.