diff options
Diffstat (limited to 'drivers/pci/controller/pcie-rcar.c')
-rw-r--r-- | drivers/pci/controller/pcie-rcar.c | 92 |
1 files changed, 42 insertions, 50 deletions
diff --git a/drivers/pci/controller/pcie-rcar.c b/drivers/pci/controller/pcie-rcar.c index f6a669a9af41..759c6542c5c8 100644 --- a/drivers/pci/controller/pcie-rcar.c +++ b/drivers/pci/controller/pcie-rcar.c @@ -30,8 +30,6 @@ #include <linux/pm_runtime.h> #include <linux/slab.h> -#include "../pci.h" - #define PCIECAR 0x000010 #define PCIECCTLR 0x000018 #define CONFIG_SEND_ENABLE BIT(31) @@ -93,8 +91,11 @@ #define LINK_SPEED_2_5GTS (1 << 16) #define LINK_SPEED_5_0GTS (2 << 16) #define MACCTLR 0x011058 +#define MACCTLR_NFTS_MASK GENMASK(23, 16) /* The name is from SH7786 */ #define SPEED_CHANGE BIT(24) #define SCRAMBLE_DISABLE BIT(27) +#define LTSMDIS BIT(31) +#define MACCTLR_INIT_VAL (LTSMDIS | MACCTLR_NFTS_MASK) #define PMSR 0x01105c #define MACS2R 0x011078 #define MACCGSPSETR 0x011084 @@ -615,6 +616,8 @@ static int rcar_pcie_hw_init(struct rcar_pcie *pcie) if (IS_ENABLED(CONFIG_PCI_MSI)) rcar_pci_write_reg(pcie, 0x801f0000, PCIEMSITXR); + rcar_pci_write_reg(pcie, MACCTLR_INIT_VAL, MACCTLR); + /* Finish initialization - establish a PCI Express link */ rcar_pci_write_reg(pcie, CFINIT, PCIETCTLR); @@ -1014,40 +1017,43 @@ err_irq1: } static int rcar_pcie_inbound_ranges(struct rcar_pcie *pcie, - struct of_pci_range *range, + struct resource_entry *entry, int *index) { - u64 restype = range->flags; - u64 cpu_addr = range->cpu_addr; - u64 cpu_end = range->cpu_addr + range->size; - u64 pci_addr = range->pci_addr; + u64 restype = entry->res->flags; + u64 cpu_addr = entry->res->start; + u64 cpu_end = entry->res->end; + u64 pci_addr = entry->res->start - entry->offset; u32 flags = LAM_64BIT | LAR_ENABLE; u64 mask; - u64 size; + u64 size = resource_size(entry->res); int idx = *index; if (restype & IORESOURCE_PREFETCH) flags |= LAM_PREFETCH; - /* - * If the size of the range is larger than the alignment of the start - * address, we have to use multiple entries to perform the mapping. - */ - if (cpu_addr > 0) { - unsigned long nr_zeros = __ffs64(cpu_addr); - u64 alignment = 1ULL << nr_zeros; + while (cpu_addr < cpu_end) { + if (idx >= MAX_NR_INBOUND_MAPS - 1) { + dev_err(pcie->dev, "Failed to map inbound regions!\n"); + return -EINVAL; + } + /* + * If the size of the range is larger than the alignment of + * the start address, we have to use multiple entries to + * perform the mapping. + */ + if (cpu_addr > 0) { + unsigned long nr_zeros = __ffs64(cpu_addr); + u64 alignment = 1ULL << nr_zeros; - size = min(range->size, alignment); - } else { - size = range->size; - } - /* Hardware supports max 4GiB inbound region */ - size = min(size, 1ULL << 32); + size = min(size, alignment); + } + /* Hardware supports max 4GiB inbound region */ + size = min(size, 1ULL << 32); - mask = roundup_pow_of_two(size) - 1; - mask &= ~0xf; + mask = roundup_pow_of_two(size) - 1; + mask &= ~0xf; - while (cpu_addr < cpu_end) { /* * Set up 64-bit inbound regions as the range parser doesn't * distinguish between 32 and 64-bit types. @@ -1067,41 +1073,25 @@ static int rcar_pcie_inbound_ranges(struct rcar_pcie *pcie, pci_addr += size; cpu_addr += size; idx += 2; - - if (idx > MAX_NR_INBOUND_MAPS) { - dev_err(pcie->dev, "Failed to map inbound regions!\n"); - return -EINVAL; - } } *index = idx; return 0; } -static int rcar_pcie_parse_map_dma_ranges(struct rcar_pcie *pcie, - struct device_node *np) +static int rcar_pcie_parse_map_dma_ranges(struct rcar_pcie *pcie) { - struct of_pci_range range; - struct of_pci_range_parser parser; - int index = 0; - int err; - - if (of_pci_dma_range_parser_init(&parser, np)) - return -EINVAL; - - /* Get the dma-ranges from DT */ - for_each_of_pci_range(&parser, &range) { - u64 end = range.cpu_addr + range.size - 1; - - dev_dbg(pcie->dev, "0x%08x 0x%016llx..0x%016llx -> 0x%016llx\n", - range.flags, range.cpu_addr, end, range.pci_addr); + struct pci_host_bridge *bridge = pci_host_bridge_from_priv(pcie); + struct resource_entry *entry; + int index = 0, err = 0; - err = rcar_pcie_inbound_ranges(pcie, &range, &index); + resource_list_for_each_entry(entry, &bridge->dma_ranges) { + err = rcar_pcie_inbound_ranges(pcie, entry, &index); if (err) - return err; + break; } - return 0; + return err; } static const struct of_device_id rcar_pcie_of_match[] = { @@ -1138,7 +1128,8 @@ static int rcar_pcie_probe(struct platform_device *pdev) pcie->dev = dev; platform_set_drvdata(pdev, pcie); - err = pci_parse_request_of_pci_ranges(dev, &pcie->resources, NULL); + err = pci_parse_request_of_pci_ranges(dev, &pcie->resources, + &bridge->dma_ranges, NULL); if (err) goto err_free_bridge; @@ -1161,7 +1152,7 @@ static int rcar_pcie_probe(struct platform_device *pdev) goto err_unmap_msi_irqs; } - err = rcar_pcie_parse_map_dma_ranges(pcie, dev->of_node); + err = rcar_pcie_parse_map_dma_ranges(pcie); if (err) goto err_clk_disable; @@ -1237,6 +1228,7 @@ static int rcar_pcie_resume_noirq(struct device *dev) return 0; /* Re-establish the PCIe link */ + rcar_pci_write_reg(pcie, MACCTLR_INIT_VAL, MACCTLR); rcar_pci_write_reg(pcie, CFINIT, PCIETCTLR); return rcar_pcie_wait_for_dl(pcie); } |