Message ID | 20170919201808.11433-2-tuomas.tynkkynen@iki.fi |
---|---|
State | Accepted |
Commit | badb99220a42f88bc823c884e487657bfe734a4d |
Delegated to: | Tom Rini |
Headers | show |
Series | Board for QEMU's '-machine virt' on ARM | expand |
Hi Tuomas, On Wed, Sep 20, 2017 at 4:18 AM, Tuomas Tynkkynen <tuomas.tynkkynen@iki.fi> wrote: > 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> > --- > drivers/pci/pci-uclass.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++ > include/pci.h | 51 ++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 109 insertions(+) > > diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c > index 86df141d60..5a24eb6428 100644 > --- a/drivers/pci/pci-uclass.c > +++ b/drivers/pci/pci-uclass.c > @@ -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; > diff --git a/include/pci.h b/include/pci.h > index c8ef997d0d..7adc04301c 100644 > --- a/include/pci.h > +++ b/include/pci.h > @@ -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. nits: suggest adding one blank line here. > + * @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. nits: suggest adding one blank line here. > + * @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, > -- Other than above nits: Reviewed-by: Bin Meng <bmeng.cn@gmail.com> Regards, Bin
On Tue, Sep 19, 2017 at 11:18:03PM +0300, Tuomas Tynkkynen wrote: > 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> Applied to u-boot/master, thanks!
diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c index 86df141d60..5a24eb6428 100644 --- a/drivers/pci/pci-uclass.c +++ b/drivers/pci/pci-uclass.c @@ -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; diff --git a/include/pci.h b/include/pci.h index c8ef997d0d..7adc04301c 100644 --- a/include/pci.h +++ b/include/pci.h @@ -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,
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> --- drivers/pci/pci-uclass.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++ include/pci.h | 51 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+)