pci: Add helper for implementing memory-mapped config space accesses

This sort of pattern for implementing memory-mapped PCI config space
accesses appears in U-Boot twice already, and a third user is coming up.
So add helper functions to avoid code duplication, similar to how Linux
has pci_generic_config_write and pci_generic_config_read.

Signed-off-by: Tuomas Tynkkynen <tuomas.tynkkynen@iki.fi>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
This commit is contained in:
Tuomas Tynkkynen 2017-09-19 23:18:03 +03:00 committed by Tom Rini
parent a4d72869f8
commit badb99220a
2 changed files with 109 additions and 0 deletions

View file

@ -518,6 +518,64 @@ int pci_auto_config_devices(struct udevice *bus)
return sub_bus;
}
int pci_generic_mmap_write_config(
struct udevice *bus,
int (*addr_f)(struct udevice *bus, pci_dev_t bdf, uint offset, void **addrp),
pci_dev_t bdf,
uint offset,
ulong value,
enum pci_size_t size)
{
void *address;
if (addr_f(bus, bdf, offset, &address) < 0)
return 0;
switch (size) {
case PCI_SIZE_8:
writeb(value, address);
return 0;
case PCI_SIZE_16:
writew(value, address);
return 0;
case PCI_SIZE_32:
writel(value, address);
return 0;
default:
return -EINVAL;
}
}
int pci_generic_mmap_read_config(
struct udevice *bus,
int (*addr_f)(struct udevice *bus, pci_dev_t bdf, uint offset, void **addrp),
pci_dev_t bdf,
uint offset,
ulong *valuep,
enum pci_size_t size)
{
void *address;
if (addr_f(bus, bdf, offset, &address) < 0) {
*valuep = pci_get_ff(size);
return 0;
}
switch (size) {
case PCI_SIZE_8:
*valuep = readb(address);
return 0;
case PCI_SIZE_16:
*valuep = readw(address);
return 0;
case PCI_SIZE_32:
*valuep = readl(address);
return 0;
default:
return -EINVAL;
}
}
int dm_pci_hose_probe_bus(struct udevice *bus)
{
int sub_bus;

View file

@ -1086,6 +1086,57 @@ int pci_read_config32(pci_dev_t pcidev, int offset, u32 *valuep);
int pci_read_config16(pci_dev_t pcidev, int offset, u16 *valuep);
int pci_read_config8(pci_dev_t pcidev, int offset, u8 *valuep);
/**
* pci_generic_mmap_write_config() - Generic helper for writing to
* memory-mapped PCI configuration space.
* @bus: Pointer to the PCI bus
* @addr_f: Callback for calculating the config space address
* @bdf: Identifies the PCI device to access
* @offset: The offset into the device's configuration space
* @value: The value to write
* @size: Indicates the size of access to perform
*
* Write the value @value of size @size from offset @offset within the
* configuration space of the device identified by the bus, device & function
* numbers in @bdf on the PCI bus @bus. The callback function @addr_f is
* responsible for calculating the CPU address of the respective configuration
* space offset.
*
* Return: 0 on success, else -EINVAL
*/
int pci_generic_mmap_write_config(
struct udevice *bus,
int (*addr_f)(struct udevice *bus, pci_dev_t bdf, uint offset, void **addrp),
pci_dev_t bdf,
uint offset,
ulong value,
enum pci_size_t size);
/**
* pci_generic_mmap_read_config() - Generic helper for reading from
* memory-mapped PCI configuration space.
* @bus: Pointer to the PCI bus
* @addr_f: Callback for calculating the config space address
* @bdf: Identifies the PCI device to access
* @offset: The offset into the device's configuration space
* @valuep: A pointer at which to store the read value
* @size: Indicates the size of access to perform
*
* Read a value of size @size from offset @offset within the configuration
* space of the device identified by the bus, device & function numbers in @bdf
* on the PCI bus @bus. The callback function @addr_f is responsible for
* calculating the CPU address of the respective configuration space offset.
*
* Return: 0 on success, else -EINVAL
*/
int pci_generic_mmap_read_config(
struct udevice *bus,
int (*addr_f)(struct udevice *bus, pci_dev_t bdf, uint offset, void **addrp),
pci_dev_t bdf,
uint offset,
ulong *valuep,
enum pci_size_t size);
#ifdef CONFIG_DM_PCI_COMPAT
/* Compatibility with old naming */
static inline int pci_write_config_dword(pci_dev_t pcidev, int offset,