On 7 December 2015 at 04:14, Bin Meng <bmeng...@gmail.com> wrote: > Hi Simon, > > On Mon, Nov 30, 2015 at 4:18 AM, Simon Glass <s...@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 <s...@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...@gmail.com>
Fix these and: Applied to u-boot-dm/next. > > Regards, > Bin _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot