[U-Boot] [PATCH v2 18/26] dm: pci: Add driver model API functions for address mapping
Simon Glass
sjg at chromium.org
Mon Dec 14 04:46:13 CET 2015
On 7 December 2015 at 04:14, Bin Meng <bmeng.cn at gmail.com> wrote:
> Hi Simon,
>
> On Mon, Nov 30, 2015 at 4:18 AM, Simon Glass <sjg at chromium.org> wrote:
>> At present the PCI address map functions use the old API. Add new functions
>> for this so that drivers can be converted.
>>
>> Signed-off-by: Simon Glass <sjg at chromium.org>
>> ---
>>
>> Changes in v2:
>> - Add missing code in dm_pci_phys_to_bus()
>> - Rename _dm_pci_hose_bus_to_phys() to _dm_pci_bus_to_phys()
>>
>> drivers/pci/pci-uclass.c | 136 +++++++++++++++++++++++++++++++++++++++++++++++
>> include/pci.h | 59 ++++++++++++++++++++
>> 2 files changed, 195 insertions(+)
>>
>> diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c
>> index 7a886f2..80e234b 100644
>> --- a/drivers/pci/pci-uclass.c
>> +++ b/drivers/pci/pci-uclass.c
>> @@ -11,6 +11,7 @@
>> #include <fdtdec.h>
>> #include <inttypes.h>
>> #include <pci.h>
>> +#include <asm/io.h>
>> #include <dm/lists.h>
>> #include <dm/root.h>
>> #include <dm/device-internal.h>
>> @@ -1068,6 +1069,141 @@ u32 dm_pci_read_bar32(struct udevice *dev, int barnum)
>> return addr & PCI_BASE_ADDRESS_MEM_MASK;
>> }
>>
>> +static int _dm_pci_bus_to_phys(struct udevice *ctlr,
>> + pci_addr_t bus_addr, unsigned long flags,
>> + unsigned long skip_mask, phys_addr_t *pa)
>
> nits: the indention of the above 2 lines looks wrong.
>
>> +{
>> + struct pci_controller *hose = dev_get_uclass_priv(ctlr);
>> + struct pci_region *res;
>> + int i;
>> +
>> + for (i = 0; i < hose->region_count; i++) {
>> + res = &hose->regions[i];
>> +
>> + if (((res->flags ^ flags) & PCI_REGION_TYPE) != 0)
>> + continue;
>> +
>> + if (res->flags & skip_mask)
>> + continue;
>> +
>> + if (bus_addr >= res->bus_start &&
>> + (bus_addr - res->bus_start) < res->size) {
>> + *pa = (bus_addr - res->bus_start + res->phys_start);
>> + return 0;
>> + }
>> + }
>> +
>> + return 1;
>> +}
>> +
>> +phys_addr_t dm_pci_bus_to_phys(struct udevice *dev, pci_addr_t bus_addr,
>> + unsigned long flags)
>> +{
>> + phys_addr_t phys_addr = 0;
>> + struct udevice *ctlr;
>> + int ret;
>> +
>> + /* The root controller has the region information */
>> + ctlr = pci_get_controller(dev);
>> +
>> + /*
>> + * if PCI_REGION_MEM is set we do a two pass search with preference
>> + * on matches that don't have PCI_REGION_SYS_MEMORY set
>> + */
>> + if ((flags & PCI_REGION_TYPE) == PCI_REGION_MEM) {
>> + ret = _dm_pci_bus_to_phys(ctlr, bus_addr,
>> + flags, PCI_REGION_SYS_MEMORY,
>> + &phys_addr);
>
> nits: the indention of the above 2 lines looks wrong.
>
>> + if (!ret)
>> + return phys_addr;
>> + }
>> +
>> + ret = _dm_pci_bus_to_phys(ctlr, bus_addr, flags, 0, &phys_addr);
>> +
>> + if (ret)
>> + puts("pci_hose_bus_to_phys: invalid physical address\n");
>> +
>> + return phys_addr;
>> +}
>> +
>> +int _dm_pci_phys_to_bus(struct udevice *dev, phys_addr_t phys_addr,
>> + unsigned long flags, unsigned long skip_mask,
>> + pci_addr_t *ba)
>> +{
>> + struct pci_region *res;
>> + struct udevice *ctlr;
>> + pci_addr_t bus_addr;
>> + int i;
>> + struct pci_controller *hose;
>> +
>> + /* The root controller has the region information */
>> + ctlr = pci_get_controller(dev);
>> + hose = dev_get_uclass_priv(ctlr);
>> +
>> + for (i = 0; i < hose->region_count; i++) {
>> + res = &hose->regions[i];
>> +
>> + if (((res->flags ^ flags) & PCI_REGION_TYPE) != 0)
>> + continue;
>> +
>> + if (res->flags & skip_mask)
>> + continue;
>> +
>> + bus_addr = phys_addr - res->phys_start + res->bus_start;
>> +
>> + if (bus_addr >= res->bus_start &&
>> + (bus_addr - res->bus_start) < res->size) {
>> + *ba = bus_addr;
>> + return 0;
>> + }
>> + }
>> +
>> + return 1;
>> +}
>> +
>> +pci_addr_t dm_pci_phys_to_bus(struct udevice *dev, phys_addr_t phys_addr,
>> + unsigned long flags)
>> +{
>> + pci_addr_t bus_addr = 0;
>> + int ret;
>> +
>> + /*
>> + * if PCI_REGION_MEM is set we do a two pass search with preference
>> + * on matches that don't have PCI_REGION_SYS_MEMORY set
>> + */
>> + if ((flags & PCI_REGION_TYPE) == PCI_REGION_MEM) {
>> + ret = _dm_pci_phys_to_bus(dev, phys_addr, flags,
>> + PCI_REGION_SYS_MEMORY, &bus_addr);
>> + if (!ret)
>> + return bus_addr;
>> + }
>> +
>> + ret = _dm_pci_phys_to_bus(dev, phys_addr, flags, 0, &bus_addr);
>> +
>> + if (ret)
>> + puts("pci_hose_phys_to_bus: invalid physical address\n");
>> +
>> + return bus_addr;
>> +}
>> +
>> +void *dm_pci_map_bar(struct udevice *dev, int bar, int flags)
>> +{
>> + pci_addr_t pci_bus_addr;
>> + u32 bar_response;
>> +
>> + /* read BAR address */
>> + dm_pci_read_config32(dev, bar, &bar_response);
>> + pci_bus_addr = (pci_addr_t)(bar_response & ~0xf);
>> +
>> + /*
>> + * Pass "0" as the length argument to pci_bus_to_virt. The arg
>> + * isn't actualy used on any platform because u-boot assumes a static
>> + * linear mapping. In the future, this could read the BAR size
>> + * and pass that as the size if needed.
>> + */
>> + return dm_pci_bus_to_virt(dev, pci_bus_addr, flags, 0, MAP_NOCACHE);
>> +}
>> +
>> UCLASS_DRIVER(pci) = {
>> .id = UCLASS_PCI,
>> .name = "pci",
>> diff --git a/include/pci.h b/include/pci.h
>> index dcbe978..2be49be 100644
>> --- a/include/pci.h
>> +++ b/include/pci.h
>> @@ -1176,6 +1176,65 @@ int pci_get_regions(struct udevice *dev, struct pci_region **iop,
>> u32 dm_pci_read_bar32(struct udevice *dev, int barnum);
>>
>> /**
>> + * dm_pci_bus_to_phys() - convert a PCI bus address to a physical address
>> + *
>> + * @dev: Device containing the PCI address
>> + * @addr: PCI address to convert
>> + * @flags: Flags for the region type (PCI_REGION_...)
>> + * @return physical address corresponding to that PCI bus address
>> + */
>> +phys_addr_t dm_pci_bus_to_phys(struct udevice *dev, pci_addr_t addr,
>> + unsigned long flags);
>> +
>> +/**
>> + * dm_pci_phys_to_bus() - convert a physical address to a PCI bus address
>> + *
>> + * @dev: Device containing the bus address
>> + * @addr: Physical address to convert
>> + * @flags: Flags for the region type (PCI_REGION_...)
>> + * @return PCI bus address corresponding to that physical address
>> + */
>> +pci_addr_t dm_pci_phys_to_bus(struct udevice *dev, phys_addr_t addr,
>> + unsigned long flags);
>> +
>> +/**
>> + * dm_pci_map_bar() - get a physical address associated with a BAR region
>
> It should be virtual address, not physical address.
>
>> + *
>> + * Looks up a base address register and finds the physical memory address
>> + * that corresponds to it
>> + *
>> + * @dev: Device to check
>> + * @bar: Bar number to read (numbered from 0)
>> + * @flags: Flags for the region type (PCI_REGION_...)
>> + * @return: pointer to the physical address to use
>
> virtual address.
>
>> + */
>> +void *dm_pci_map_bar(struct udevice *dev, int bar, int flags);
>> +
>> +#define dm_pci_virt_to_bus(dev, addr, flags) \
>> + dm_pci_phys_to_bus(dev, (virt_to_phys(addr)), (flags))
>> +#define dm_pci_bus_to_virt(dev, addr, flags, len, map_flags) \
>> + map_physmem(dm_pci_bus_to_phys(dev, (addr), (flags)), \
>> + (len), (map_flags))
>> +
>> +#define dm_pci_phys_to_mem(dev, addr) \
>> + dm_pci_phys_to_bus((dev), (addr), PCI_REGION_MEM)
>> +#define dm_pci_mem_to_phys(dev, addr) \
>> + dm_pci_bus_to_phys((dev), (addr), PCI_REGION_MEM)
>> +#define dm_pci_phys_to_io(dev, addr) \
>> + dm_pci_phys_to_bus((dev), (addr), PCI_REGION_IO)
>> +#define dm_pci_io_to_phys(dev, addr) \
>> + dm_pci_bus_to_phys((dev), (addr), PCI_REGION_IO)
>> +
>> +#define dm_pci_virt_to_mem(dev, addr) \
>> + dm_pci_virt_to_bus((dev), (addr), PCI_REGION_MEM)
>> +#define dm_pci_mem_to_virt(dev, addr, len, map_flags) \
>> + dm_pci_bus_to_virt((dev), (addr), PCI_REGION_MEM, (len), (map_flags))
>> +#define dm_pci_virt_to_io(dev, addr) \
>> + dm_dm_pci_virt_to_bus((dev), (addr), PCI_REGION_IO)
>> +#define dm_pci_io_to_virt(dev, addr, len, map_flags) \
>> + dm_dm_pci_bus_to_virt((dev), (addr), PCI_REGION_IO, (len), (map_flags))
>> +
>> +/**
>> * dm_pci_find_device() - find a device by vendor/device ID
>> *
>> * @vendor: Vendor ID
>> --
>
> Other than above nits,
>
> Reviewed-by: Bin Meng <bmeng.cn at gmail.com>
Fix these and:
Applied to u-boot-dm/next.
>
> Regards,
> Bin
More information about the U-Boot
mailing list