diff mbox

[U-Boot,v2,18/26] dm: pci: Add driver model API functions for address mapping

Message ID 1448828291-12660-19-git-send-email-sjg@chromium.org
State Accepted
Delegated to: Simon Glass
Headers show

Commit Message

Simon Glass Nov. 29, 2015, 8:18 p.m. UTC
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@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(+)

Comments

Bin Meng Dec. 7, 2015, 11:14 a.m. UTC | #1
Hi Simon,

On Mon, Nov 30, 2015 at 4:18 AM, Simon Glass <sjg@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@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@gmail.com>

Regards,
Bin
Simon Glass Dec. 14, 2015, 3:46 a.m. UTC | #2
On 7 December 2015 at 04:14, Bin Meng <bmeng.cn@gmail.com> wrote:
> Hi Simon,
>
> On Mon, Nov 30, 2015 at 4:18 AM, Simon Glass <sjg@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@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@gmail.com>

Fix these and:

Applied to u-boot-dm/next.

>
> Regards,
> Bin
diff mbox

Patch

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)
+{
+	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);
+		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
+ *
+ * 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
+ */
+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