diff options
Diffstat (limited to 'drivers/pci/controller/pcie-iproc.c')
-rw-r--r-- | drivers/pci/controller/pcie-iproc.c | 106 |
1 files changed, 43 insertions, 63 deletions
diff --git a/drivers/pci/controller/pcie-iproc.c b/drivers/pci/controller/pcie-iproc.c index 2d457bfdaf66..0a468c73bae3 100644 --- a/drivers/pci/controller/pcie-iproc.c +++ b/drivers/pci/controller/pcie-iproc.c @@ -1122,15 +1122,16 @@ static int iproc_pcie_ib_write(struct iproc_pcie *pcie, int region_idx, } static int iproc_pcie_setup_ib(struct iproc_pcie *pcie, - struct of_pci_range *range, + struct resource_entry *entry, enum iproc_pcie_ib_map_type type) { struct device *dev = pcie->dev; struct iproc_pcie_ib *ib = &pcie->ib; int ret; unsigned int region_idx, size_idx; - u64 axi_addr = range->cpu_addr, pci_addr = range->pci_addr; - resource_size_t size = range->size; + u64 axi_addr = entry->res->start; + u64 pci_addr = entry->res->start - entry->offset; + resource_size_t size = resource_size(entry->res); /* iterate through all IARR mapping regions */ for (region_idx = 0; region_idx < ib->nr_regions; region_idx++) { @@ -1182,67 +1183,46 @@ err_ib: return ret; } -static int iproc_pcie_add_dma_range(struct device *dev, - struct list_head *resources, - struct of_pci_range *range) +static int iproc_pcie_map_dma_ranges(struct iproc_pcie *pcie) { - struct resource *res; - struct resource_entry *entry, *tmp; - struct list_head *head = resources; - - res = devm_kzalloc(dev, sizeof(struct resource), GFP_KERNEL); - if (!res) - return -ENOMEM; + struct pci_host_bridge *host = pci_host_bridge_from_priv(pcie); + struct resource_entry *entry; + int ret = 0; - resource_list_for_each_entry(tmp, resources) { - if (tmp->res->start < range->cpu_addr) - head = &tmp->node; + resource_list_for_each_entry(entry, &host->dma_ranges) { + /* Each range entry corresponds to an inbound mapping region */ + ret = iproc_pcie_setup_ib(pcie, entry, IPROC_PCIE_IB_MAP_MEM); + if (ret) + break; } - res->start = range->cpu_addr; - res->end = res->start + range->size - 1; - - entry = resource_list_create_entry(res, 0); - if (!entry) - return -ENOMEM; - - entry->offset = res->start - range->cpu_addr; - resource_list_add(entry, head); - - return 0; + return ret; } -static int iproc_pcie_map_dma_ranges(struct iproc_pcie *pcie) +static void iproc_pcie_invalidate_mapping(struct iproc_pcie *pcie) { - struct pci_host_bridge *host = pci_host_bridge_from_priv(pcie); - struct of_pci_range range; - struct of_pci_range_parser parser; - int ret; - LIST_HEAD(resources); + struct iproc_pcie_ib *ib = &pcie->ib; + struct iproc_pcie_ob *ob = &pcie->ob; + int idx; - /* Get the dma-ranges from DT */ - ret = of_pci_dma_range_parser_init(&parser, pcie->dev->of_node); - if (ret) - return ret; + if (pcie->ep_is_internal) + return; - for_each_of_pci_range(&parser, &range) { - ret = iproc_pcie_add_dma_range(pcie->dev, - &resources, - &range); - if (ret) - goto out; - /* Each range entry corresponds to an inbound mapping region */ - ret = iproc_pcie_setup_ib(pcie, &range, IPROC_PCIE_IB_MAP_MEM); - if (ret) - goto out; + if (pcie->need_ob_cfg) { + /* iterate through all OARR mapping regions */ + for (idx = ob->nr_windows - 1; idx >= 0; idx--) { + iproc_pcie_write_reg(pcie, + MAP_REG(IPROC_PCIE_OARR0, idx), 0); + } } - list_splice_init(&resources, &host->dma_ranges); - - return 0; -out: - pci_free_resource_list(&resources); - return ret; + if (pcie->need_ib_cfg) { + /* iterate through all IARR mapping regions */ + for (idx = 0; idx < ib->nr_regions; idx++) { + iproc_pcie_write_reg(pcie, + MAP_REG(IPROC_PCIE_IARR0, idx), 0); + } + } } static int iproce_pcie_get_msi(struct iproc_pcie *pcie, @@ -1276,13 +1256,16 @@ static int iproce_pcie_get_msi(struct iproc_pcie *pcie, static int iproc_pcie_paxb_v2_msi_steer(struct iproc_pcie *pcie, u64 msi_addr) { int ret; - struct of_pci_range range; + struct resource_entry entry; - memset(&range, 0, sizeof(range)); - range.size = SZ_32K; - range.pci_addr = range.cpu_addr = msi_addr & ~(range.size - 1); + memset(&entry, 0, sizeof(entry)); + entry.res = &entry.__res; - ret = iproc_pcie_setup_ib(pcie, &range, IPROC_PCIE_IB_MAP_IO); + msi_addr &= ~(SZ_32K - 1); + entry.res->start = msi_addr; + entry.res->end = msi_addr + SZ_32K - 1; + + ret = iproc_pcie_setup_ib(pcie, &entry, IPROC_PCIE_IB_MAP_IO); return ret; } @@ -1498,10 +1481,6 @@ int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res) return ret; } - ret = devm_request_pci_bus_resources(dev, res); - if (ret) - return ret; - ret = phy_init(pcie->phy); if (ret) { dev_err(dev, "unable to initialize PCIe PHY\n"); @@ -1517,6 +1496,8 @@ int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res) iproc_pcie_perst_ctrl(pcie, true); iproc_pcie_perst_ctrl(pcie, false); + iproc_pcie_invalidate_mapping(pcie); + if (pcie->need_ob_cfg) { ret = iproc_pcie_map_ranges(pcie, res); if (ret) { @@ -1543,7 +1524,6 @@ int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res) if (iproc_pcie_msi_enable(pcie)) dev_info(dev, "not using iProc MSI\n"); - list_splice_init(res, &host->windows); host->busnr = 0; host->dev.parent = dev; host->ops = &iproc_pcie_ops; |