These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / pci / host / pcie-designware.c
index 2e9f84f..02a7452 100644 (file)
 #define PORT_LINK_MODE_1_LANES         (0x1 << 16)
 #define PORT_LINK_MODE_2_LANES         (0x3 << 16)
 #define PORT_LINK_MODE_4_LANES         (0x7 << 16)
+#define PORT_LINK_MODE_8_LANES         (0xf << 16)
 
 #define PCIE_LINK_WIDTH_SPEED_CONTROL  0x80C
 #define PORT_LOGIC_SPEED_CHANGE                (0x1 << 17)
-#define PORT_LOGIC_LINK_WIDTH_MASK     (0x1ff << 8)
+#define PORT_LOGIC_LINK_WIDTH_MASK     (0x1f << 8)
 #define PORT_LOGIC_LINK_WIDTH_1_LANES  (0x1 << 8)
 #define PORT_LOGIC_LINK_WIDTH_2_LANES  (0x2 << 8)
 #define PORT_LOGIC_LINK_WIDTH_4_LANES  (0x4 << 8)
+#define PORT_LOGIC_LINK_WIDTH_8_LANES  (0x8 << 8)
 
 #define PCIE_MSI_ADDR_LO               0x820
 #define PCIE_MSI_ADDR_HI               0x824
 #define PCIE_ATU_FUNC(x)               (((x) & 0x7) << 16)
 #define PCIE_ATU_UPPER_TARGET          0x91C
 
-static struct hw_pci dw_pci;
+static struct pci_ops dw_pcie_ops;
 
-static unsigned long global_io_offset;
-
-static inline struct pcie_port *sys_to_pcie(struct pci_sys_data *sys)
-{
-       BUG_ON(!sys->private_data);
-
-       return sys->private_data;
-}
-
-int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32 *val)
+int dw_pcie_cfg_read(void __iomem *addr, int size, u32 *val)
 {
-       *val = readl(addr);
+       if ((uintptr_t)addr & (size - 1)) {
+               *val = 0;
+               return PCIBIOS_BAD_REGISTER_NUMBER;
+       }
 
-       if (size == 1)
-               *val = (*val >> (8 * (where & 3))) & 0xff;
+       if (size == 4)
+               *val = readl(addr);
        else if (size == 2)
-               *val = (*val >> (8 * (where & 3))) & 0xffff;
-       else if (size != 4)
+               *val = readw(addr);
+       else if (size == 1)
+               *val = readb(addr);
+       else {
+               *val = 0;
                return PCIBIOS_BAD_REGISTER_NUMBER;
+       }
 
        return PCIBIOS_SUCCESSFUL;
 }
 
-int dw_pcie_cfg_write(void __iomem *addr, int where, int size, u32 val)
+int dw_pcie_cfg_write(void __iomem *addr, int size, u32 val)
 {
+       if ((uintptr_t)addr & (size - 1))
+               return PCIBIOS_BAD_REGISTER_NUMBER;
+
        if (size == 4)
                writel(val, addr);
        else if (size == 2)
-               writew(val, addr + (where & 2));
+               writew(val, addr);
        else if (size == 1)
-               writeb(val, addr + (where & 3));
+               writeb(val, addr);
        else
                return PCIBIOS_BAD_REGISTER_NUMBER;
 
@@ -130,8 +133,7 @@ static int dw_pcie_rd_own_conf(struct pcie_port *pp, int where, int size,
        if (pp->ops->rd_own_conf)
                ret = pp->ops->rd_own_conf(pp, where, size, val);
        else
-               ret = dw_pcie_cfg_read(pp->dbi_base + (where & ~0x3), where,
-                               size, val);
+               ret = dw_pcie_cfg_read(pp->dbi_base + where, size, val);
 
        return ret;
 }
@@ -144,12 +146,26 @@ static int dw_pcie_wr_own_conf(struct pcie_port *pp, int where, int size,
        if (pp->ops->wr_own_conf)
                ret = pp->ops->wr_own_conf(pp, where, size, val);
        else
-               ret = dw_pcie_cfg_write(pp->dbi_base + (where & ~0x3), where,
-                               size, val);
+               ret = dw_pcie_cfg_write(pp->dbi_base + where, size, val);
 
        return ret;
 }
 
+static void dw_pcie_prog_outbound_atu(struct pcie_port *pp, int index,
+               int type, u64 cpu_addr, u64 pci_addr, u32 size)
+{
+       dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | index,
+                         PCIE_ATU_VIEWPORT);
+       dw_pcie_writel_rc(pp, lower_32_bits(cpu_addr), PCIE_ATU_LOWER_BASE);
+       dw_pcie_writel_rc(pp, upper_32_bits(cpu_addr), PCIE_ATU_UPPER_BASE);
+       dw_pcie_writel_rc(pp, lower_32_bits(cpu_addr + size - 1),
+                         PCIE_ATU_LIMIT);
+       dw_pcie_writel_rc(pp, lower_32_bits(pci_addr), PCIE_ATU_LOWER_TARGET);
+       dw_pcie_writel_rc(pp, upper_32_bits(pci_addr), PCIE_ATU_UPPER_TARGET);
+       dw_pcie_writel_rc(pp, type, PCIE_ATU_CR1);
+       dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2);
+}
+
 static struct irq_chip dw_msi_irq_chip = {
        .name = "PCI-MSI",
        .irq_enable = pci_msi_unmask_irq,
@@ -188,12 +204,16 @@ irqreturn_t dw_handle_msi_irq(struct pcie_port *pp)
 
 void dw_pcie_msi_init(struct pcie_port *pp)
 {
+       u64 msi_target;
+
        pp->msi_data = __get_free_pages(GFP_KERNEL, 0);
+       msi_target = virt_to_phys((void *)pp->msi_data);
 
        /* program the msi_data */
        dw_pcie_wr_own_conf(pp, PCIE_MSI_ADDR_LO, 4,
-                       virt_to_phys((void *)pp->msi_data));
-       dw_pcie_wr_own_conf(pp, PCIE_MSI_ADDR_HI, 4, 0);
+                           (u32)(msi_target & 0xffffffff));
+       dw_pcie_wr_own_conf(pp, PCIE_MSI_ADDR_HI, 4,
+                           (u32)(msi_target >> 32 & 0xffffffff));
 }
 
 static void dw_pcie_msi_clear_irq(struct pcie_port *pp, int irq)
@@ -238,7 +258,7 @@ static void dw_pcie_msi_set_irq(struct pcie_port *pp, int irq)
 static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos)
 {
        int irq, pos0, i;
-       struct pcie_port *pp = sys_to_pcie(desc->dev->bus->sysdata);
+       struct pcie_port *pp = (struct pcie_port *) msi_desc_to_pci_sysdata(desc);
 
        pos0 = bitmap_find_free_region(pp->msi_irq_in_use, MAX_MSI_IRQS,
                                       order_base_2(no_irqs));
@@ -269,6 +289,9 @@ static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos)
        }
 
        *pos = pos0;
+       desc->nvec_used = no_irqs;
+       desc->msi_attrib.multiple = order_base_2(no_irqs);
+
        return irq;
 
 no_valid_irq:
@@ -276,12 +299,32 @@ no_valid_irq:
        return -ENOSPC;
 }
 
+static void dw_msi_setup_msg(struct pcie_port *pp, unsigned int irq, u32 pos)
+{
+       struct msi_msg msg;
+       u64 msi_target;
+
+       if (pp->ops->get_msi_addr)
+               msi_target = pp->ops->get_msi_addr(pp);
+       else
+               msi_target = virt_to_phys((void *)pp->msi_data);
+
+       msg.address_lo = (u32)(msi_target & 0xffffffff);
+       msg.address_hi = (u32)(msi_target >> 32 & 0xffffffff);
+
+       if (pp->ops->get_msi_data)
+               msg.data = pp->ops->get_msi_data(pp, pos);
+       else
+               msg.data = pos;
+
+       pci_write_msi_msg(irq, &msg);
+}
+
 static int dw_msi_setup_irq(struct msi_controller *chip, struct pci_dev *pdev,
                        struct msi_desc *desc)
 {
        int irq, pos;
-       struct msi_msg msg;
-       struct pcie_port *pp = sys_to_pcie(pdev->bus->sysdata);
+       struct pcie_port *pp = pdev->bus->sysdata;
 
        if (desc->msi_attrib.is_msix)
                return -EINVAL;
@@ -290,33 +333,50 @@ static int dw_msi_setup_irq(struct msi_controller *chip, struct pci_dev *pdev,
        if (irq < 0)
                return irq;
 
-       if (pp->ops->get_msi_addr)
-               msg.address_lo = pp->ops->get_msi_addr(pp);
-       else
-               msg.address_lo = virt_to_phys((void *)pp->msi_data);
-       msg.address_hi = 0x0;
+       dw_msi_setup_msg(pp, irq, pos);
 
-       if (pp->ops->get_msi_data)
-               msg.data = pp->ops->get_msi_data(pp, pos);
-       else
-               msg.data = pos;
+       return 0;
+}
 
-       pci_write_msi_msg(irq, &msg);
+static int dw_msi_setup_irqs(struct msi_controller *chip, struct pci_dev *pdev,
+                            int nvec, int type)
+{
+#ifdef CONFIG_PCI_MSI
+       int irq, pos;
+       struct msi_desc *desc;
+       struct pcie_port *pp = pdev->bus->sysdata;
+
+       /* MSI-X interrupts are not supported */
+       if (type == PCI_CAP_ID_MSIX)
+               return -EINVAL;
+
+       WARN_ON(!list_is_singular(&pdev->dev.msi_list));
+       desc = list_entry(pdev->dev.msi_list.next, struct msi_desc, list);
+
+       irq = assign_irq(nvec, desc, &pos);
+       if (irq < 0)
+               return irq;
+
+       dw_msi_setup_msg(pp, irq, pos);
 
        return 0;
+#else
+       return -EINVAL;
+#endif
 }
 
 static void dw_msi_teardown_irq(struct msi_controller *chip, unsigned int irq)
 {
        struct irq_data *data = irq_get_irq_data(irq);
-       struct msi_desc *msi = irq_data_get_msi(data);
-       struct pcie_port *pp = sys_to_pcie(msi->dev->bus->sysdata);
+       struct msi_desc *msi = irq_data_get_msi_desc(data);
+       struct pcie_port *pp = (struct pcie_port *) msi_desc_to_pci_sysdata(msi);
 
        clear_irq_range(pp, irq, 1, data->hwirq);
 }
 
 static struct msi_controller dw_pcie_msi_chip = {
        .setup_irq = dw_msi_setup_irq,
+       .setup_irqs = dw_msi_setup_irqs,
        .teardown_irq = dw_msi_teardown_irq,
 };
 
@@ -333,7 +393,6 @@ static int dw_pcie_msi_map(struct irq_domain *domain, unsigned int irq,
 {
        irq_set_chip_and_handler(irq, &dw_msi_irq_chip, handle_simple_irq);
        irq_set_chip_data(irq, domain->host_data);
-       set_irq_flags(irq, IRQF_VALID);
 
        return 0;
 }
@@ -346,18 +405,12 @@ int dw_pcie_host_init(struct pcie_port *pp)
 {
        struct device_node *np = pp->dev->of_node;
        struct platform_device *pdev = to_platform_device(pp->dev);
-       struct of_pci_range range;
-       struct of_pci_range_parser parser;
+       struct pci_bus *bus, *child;
        struct resource *cfg_res;
-       u32 val, na, ns;
-       const __be32 *addrp;
-       int i, index, ret;
-
-       /* Find the address cell size and the number of cells in order to get
-        * the untranslated address.
-        */
-       of_property_read_u32(np, "#address-cells", &na);
-       ns = of_n_size_cells(np);
+       u32 val;
+       int i, ret;
+       LIST_HEAD(res);
+       struct resource_entry *win;
 
        cfg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config");
        if (cfg_res) {
@@ -365,88 +418,60 @@ int dw_pcie_host_init(struct pcie_port *pp)
                pp->cfg1_size = resource_size(cfg_res)/2;
                pp->cfg0_base = cfg_res->start;
                pp->cfg1_base = cfg_res->start + pp->cfg0_size;
-
-               /* Find the untranslated configuration space address */
-               index = of_property_match_string(np, "reg-names", "config");
-               addrp = of_get_address(np, index, NULL, NULL);
-               pp->cfg0_mod_base = of_read_number(addrp, ns);
-               pp->cfg1_mod_base = pp->cfg0_mod_base + pp->cfg0_size;
-       } else {
+       } else if (!pp->va_cfg0_base) {
                dev_err(pp->dev, "missing *config* reg space\n");
        }
 
-       if (of_pci_range_parser_init(&parser, np)) {
-               dev_err(pp->dev, "missing ranges property\n");
-               return -EINVAL;
-       }
+       ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &pp->io_base);
+       if (ret)
+               return ret;
 
        /* Get the I/O and memory ranges from DT */
-       for_each_of_pci_range(&parser, &range) {
-               unsigned long restype = range.flags & IORESOURCE_TYPE_BITS;
-
-               if (restype == IORESOURCE_IO) {
-                       of_pci_range_to_resource(&range, np, &pp->io);
-                       pp->io.name = "I/O";
-                       pp->io.start = max_t(resource_size_t,
-                                            PCIBIOS_MIN_IO,
-                                            range.pci_addr + global_io_offset);
-                       pp->io.end = min_t(resource_size_t,
-                                          IO_SPACE_LIMIT,
-                                          range.pci_addr + range.size
-                                          + global_io_offset - 1);
-                       pp->io_size = resource_size(&pp->io);
-                       pp->io_bus_addr = range.pci_addr;
-                       pp->io_base = range.cpu_addr;
-
-                       /* Find the untranslated IO space address */
-                       pp->io_mod_base = of_read_number(parser.range -
-                                                        parser.np + na, ns);
-               }
-               if (restype == IORESOURCE_MEM) {
-                       of_pci_range_to_resource(&range, np, &pp->mem);
-                       pp->mem.name = "MEM";
-                       pp->mem_size = resource_size(&pp->mem);
-                       pp->mem_bus_addr = range.pci_addr;
-
-                       /* Find the untranslated MEM space address */
-                       pp->mem_mod_base = of_read_number(parser.range -
-                                                         parser.np + na, ns);
-               }
-               if (restype == 0) {
-                       of_pci_range_to_resource(&range, np, &pp->cfg);
-                       pp->cfg0_size = resource_size(&pp->cfg)/2;
-                       pp->cfg1_size = resource_size(&pp->cfg)/2;
-                       pp->cfg0_base = pp->cfg.start;
-                       pp->cfg1_base = pp->cfg.start + pp->cfg0_size;
-
-                       /* Find the untranslated configuration space address */
-                       pp->cfg0_mod_base = of_read_number(parser.range -
-                                                          parser.np + na, ns);
-                       pp->cfg1_mod_base = pp->cfg0_mod_base +
-                                           pp->cfg0_size;
+       resource_list_for_each_entry(win, &res) {
+               switch (resource_type(win->res)) {
+               case IORESOURCE_IO:
+                       pp->io = win->res;
+                       pp->io->name = "I/O";
+                       pp->io_size = resource_size(pp->io);
+                       pp->io_bus_addr = pp->io->start - win->offset;
+                       ret = pci_remap_iospace(pp->io, pp->io_base);
+                       if (ret) {
+                               dev_warn(pp->dev, "error %d: failed to map resource %pR\n",
+                                        ret, pp->io);
+                               continue;
+                       }
+                       break;
+               case IORESOURCE_MEM:
+                       pp->mem = win->res;
+                       pp->mem->name = "MEM";
+                       pp->mem_size = resource_size(pp->mem);
+                       pp->mem_bus_addr = pp->mem->start - win->offset;
+                       break;
+               case 0:
+                       pp->cfg = win->res;
+                       pp->cfg0_size = resource_size(pp->cfg)/2;
+                       pp->cfg1_size = resource_size(pp->cfg)/2;
+                       pp->cfg0_base = pp->cfg->start;
+                       pp->cfg1_base = pp->cfg->start + pp->cfg0_size;
+                       break;
+               case IORESOURCE_BUS:
+                       pp->busn = win->res;
+                       break;
+               default:
+                       continue;
                }
        }
 
-       ret = of_pci_parse_bus_range(np, &pp->busn);
-       if (ret < 0) {
-               pp->busn.name = np->name;
-               pp->busn.start = 0;
-               pp->busn.end = 0xff;
-               pp->busn.flags = IORESOURCE_BUS;
-               dev_dbg(pp->dev, "failed to parse bus-range property: %d, using default %pR\n",
-                       ret, &pp->busn);
-       }
-
        if (!pp->dbi_base) {
-               pp->dbi_base = devm_ioremap(pp->dev, pp->cfg.start,
-                                       resource_size(&pp->cfg));
+               pp->dbi_base = devm_ioremap(pp->dev, pp->cfg->start,
+                                       resource_size(pp->cfg));
                if (!pp->dbi_base) {
                        dev_err(pp->dev, "error with ioremap\n");
                        return -ENOMEM;
                }
        }
 
-       pp->mem_base = pp->mem.start;
+       pp->mem_base = pp->mem->start;
 
        if (!pp->va_cfg0_base) {
                pp->va_cfg0_base = devm_ioremap(pp->dev, pp->cfg0_base,
@@ -466,10 +491,9 @@ int dw_pcie_host_init(struct pcie_port *pp)
                }
        }
 
-       if (of_property_read_u32(np, "num-lanes", &pp->lanes)) {
-               dev_err(pp->dev, "Failed to parse the number of lanes\n");
-               return -EINVAL;
-       }
+       ret = of_property_read_u32(np, "num-lanes", &pp->lanes);
+       if (ret)
+               pp->lanes = 0;
 
        if (IS_ENABLED(CONFIG_PCI_MSI)) {
                if (!pp->ops->msi_host_init) {
@@ -493,6 +517,11 @@ int dw_pcie_host_init(struct pcie_port *pp)
        if (pp->ops->host_init)
                pp->ops->host_init(pp);
 
+       if (!pp->ops->rd_other_conf)
+               dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX1,
+                                         PCIE_ATU_TYPE_MEM, pp->mem_base,
+                                         pp->mem_bus_addr, pp->mem_size);
+
        dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0);
 
        /* program correct class for RC */
@@ -502,128 +531,103 @@ int dw_pcie_host_init(struct pcie_port *pp)
        val |= PORT_LOGIC_SPEED_CHANGE;
        dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val);
 
-#ifdef CONFIG_PCI_MSI
-       dw_pcie_msi_chip.dev = pp->dev;
-       dw_pci.msi_ctrl = &dw_pcie_msi_chip;
-#endif
-
-       dw_pci.nr_controllers = 1;
-       dw_pci.private_data = (void **)&pp;
-
-       pci_common_init_dev(pp->dev, &dw_pci);
+       pp->root_bus_nr = pp->busn->start;
+       if (IS_ENABLED(CONFIG_PCI_MSI)) {
+               bus = pci_scan_root_bus_msi(pp->dev, pp->root_bus_nr,
+                                           &dw_pcie_ops, pp, &res,
+                                           &dw_pcie_msi_chip);
+               dw_pcie_msi_chip.dev = pp->dev;
+       } else
+               bus = pci_scan_root_bus(pp->dev, pp->root_bus_nr, &dw_pcie_ops,
+                                       pp, &res);
+       if (!bus)
+               return -ENOMEM;
 
-       return 0;
-}
+       if (pp->ops->scan_bus)
+               pp->ops->scan_bus(pp);
 
-static void dw_pcie_prog_viewport_cfg0(struct pcie_port *pp, u32 busdev)
-{
-       /* Program viewport 0 : OUTBOUND : CFG0 */
-       dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX0,
-                         PCIE_ATU_VIEWPORT);
-       dw_pcie_writel_rc(pp, pp->cfg0_mod_base, PCIE_ATU_LOWER_BASE);
-       dw_pcie_writel_rc(pp, (pp->cfg0_mod_base >> 32), PCIE_ATU_UPPER_BASE);
-       dw_pcie_writel_rc(pp, pp->cfg0_mod_base + pp->cfg0_size - 1,
-                         PCIE_ATU_LIMIT);
-       dw_pcie_writel_rc(pp, busdev, PCIE_ATU_LOWER_TARGET);
-       dw_pcie_writel_rc(pp, 0, PCIE_ATU_UPPER_TARGET);
-       dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_CFG0, PCIE_ATU_CR1);
-       dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2);
-}
+#ifdef CONFIG_ARM
+       /* support old dtbs that incorrectly describe IRQs */
+       pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
+#endif
 
-static void dw_pcie_prog_viewport_cfg1(struct pcie_port *pp, u32 busdev)
-{
-       /* Program viewport 1 : OUTBOUND : CFG1 */
-       dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX1,
-                         PCIE_ATU_VIEWPORT);
-       dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_CFG1, PCIE_ATU_CR1);
-       dw_pcie_writel_rc(pp, pp->cfg1_mod_base, PCIE_ATU_LOWER_BASE);
-       dw_pcie_writel_rc(pp, (pp->cfg1_mod_base >> 32), PCIE_ATU_UPPER_BASE);
-       dw_pcie_writel_rc(pp, pp->cfg1_mod_base + pp->cfg1_size - 1,
-                         PCIE_ATU_LIMIT);
-       dw_pcie_writel_rc(pp, busdev, PCIE_ATU_LOWER_TARGET);
-       dw_pcie_writel_rc(pp, 0, PCIE_ATU_UPPER_TARGET);
-       dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2);
-}
+       if (!pci_has_flag(PCI_PROBE_ONLY)) {
+               pci_bus_size_bridges(bus);
+               pci_bus_assign_resources(bus);
 
-static void dw_pcie_prog_viewport_mem_outbound(struct pcie_port *pp)
-{
-       /* Program viewport 0 : OUTBOUND : MEM */
-       dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX0,
-                         PCIE_ATU_VIEWPORT);
-       dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_MEM, PCIE_ATU_CR1);
-       dw_pcie_writel_rc(pp, pp->mem_mod_base, PCIE_ATU_LOWER_BASE);
-       dw_pcie_writel_rc(pp, (pp->mem_mod_base >> 32), PCIE_ATU_UPPER_BASE);
-       dw_pcie_writel_rc(pp, pp->mem_mod_base + pp->mem_size - 1,
-                         PCIE_ATU_LIMIT);
-       dw_pcie_writel_rc(pp, pp->mem_bus_addr, PCIE_ATU_LOWER_TARGET);
-       dw_pcie_writel_rc(pp, upper_32_bits(pp->mem_bus_addr),
-                         PCIE_ATU_UPPER_TARGET);
-       dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2);
-}
+               list_for_each_entry(child, &bus->children, node)
+                       pcie_bus_configure_settings(child);
+       }
 
-static void dw_pcie_prog_viewport_io_outbound(struct pcie_port *pp)
-{
-       /* Program viewport 1 : OUTBOUND : IO */
-       dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX1,
-                         PCIE_ATU_VIEWPORT);
-       dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_IO, PCIE_ATU_CR1);
-       dw_pcie_writel_rc(pp, pp->io_mod_base, PCIE_ATU_LOWER_BASE);
-       dw_pcie_writel_rc(pp, (pp->io_mod_base >> 32), PCIE_ATU_UPPER_BASE);
-       dw_pcie_writel_rc(pp, pp->io_mod_base + pp->io_size - 1,
-                         PCIE_ATU_LIMIT);
-       dw_pcie_writel_rc(pp, pp->io_bus_addr, PCIE_ATU_LOWER_TARGET);
-       dw_pcie_writel_rc(pp, upper_32_bits(pp->io_bus_addr),
-                         PCIE_ATU_UPPER_TARGET);
-       dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2);
+       pci_bus_add_devices(bus);
+       return 0;
 }
 
 static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
                u32 devfn, int where, int size, u32 *val)
 {
-       int ret = PCIBIOS_SUCCESSFUL;
-       u32 address, busdev;
+       int ret, type;
+       u32 busdev, cfg_size;
+       u64 cpu_addr;
+       void __iomem *va_cfg_base;
 
        busdev = PCIE_ATU_BUS(bus->number) | PCIE_ATU_DEV(PCI_SLOT(devfn)) |
                 PCIE_ATU_FUNC(PCI_FUNC(devfn));
-       address = where & ~0x3;
 
        if (bus->parent->number == pp->root_bus_nr) {
-               dw_pcie_prog_viewport_cfg0(pp, busdev);
-               ret = dw_pcie_cfg_read(pp->va_cfg0_base + address, where, size,
-                               val);
-               dw_pcie_prog_viewport_mem_outbound(pp);
+               type = PCIE_ATU_TYPE_CFG0;
+               cpu_addr = pp->cfg0_base;
+               cfg_size = pp->cfg0_size;
+               va_cfg_base = pp->va_cfg0_base;
        } else {
-               dw_pcie_prog_viewport_cfg1(pp, busdev);
-               ret = dw_pcie_cfg_read(pp->va_cfg1_base + address, where, size,
-                               val);
-               dw_pcie_prog_viewport_io_outbound(pp);
+               type = PCIE_ATU_TYPE_CFG1;
+               cpu_addr = pp->cfg1_base;
+               cfg_size = pp->cfg1_size;
+               va_cfg_base = pp->va_cfg1_base;
        }
 
+       dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
+                                 type, cpu_addr,
+                                 busdev, cfg_size);
+       ret = dw_pcie_cfg_read(va_cfg_base + where, size, val);
+       dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
+                                 PCIE_ATU_TYPE_IO, pp->io_base,
+                                 pp->io_bus_addr, pp->io_size);
+
        return ret;
 }
 
 static int dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
                u32 devfn, int where, int size, u32 val)
 {
-       int ret = PCIBIOS_SUCCESSFUL;
-       u32 address, busdev;
+       int ret, type;
+       u32 busdev, cfg_size;
+       u64 cpu_addr;
+       void __iomem *va_cfg_base;
 
        busdev = PCIE_ATU_BUS(bus->number) | PCIE_ATU_DEV(PCI_SLOT(devfn)) |
                 PCIE_ATU_FUNC(PCI_FUNC(devfn));
-       address = where & ~0x3;
 
        if (bus->parent->number == pp->root_bus_nr) {
-               dw_pcie_prog_viewport_cfg0(pp, busdev);
-               ret = dw_pcie_cfg_write(pp->va_cfg0_base + address, where, size,
-                               val);
-               dw_pcie_prog_viewport_mem_outbound(pp);
+               type = PCIE_ATU_TYPE_CFG0;
+               cpu_addr = pp->cfg0_base;
+               cfg_size = pp->cfg0_size;
+               va_cfg_base = pp->va_cfg0_base;
        } else {
-               dw_pcie_prog_viewport_cfg1(pp, busdev);
-               ret = dw_pcie_cfg_write(pp->va_cfg1_base + address, where, size,
-                               val);
-               dw_pcie_prog_viewport_io_outbound(pp);
+               type = PCIE_ATU_TYPE_CFG1;
+               cpu_addr = pp->cfg1_base;
+               cfg_size = pp->cfg1_size;
+               va_cfg_base = pp->va_cfg1_base;
        }
 
+       dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
+                                 type, cpu_addr,
+                                 busdev, cfg_size);
+       ret = dw_pcie_cfg_write(va_cfg_base + where, size, val);
+       dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
+                                 PCIE_ATU_TYPE_IO, pp->io_base,
+                                 pp->io_bus_addr, pp->io_size);
+
        return ret;
 }
 
@@ -653,7 +657,7 @@ static int dw_pcie_valid_config(struct pcie_port *pp,
 static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
                        int size, u32 *val)
 {
-       struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+       struct pcie_port *pp = bus->sysdata;
        int ret;
 
        if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) {
@@ -677,7 +681,7 @@ static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
 static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
                        int where, int size, u32 val)
 {
-       struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+       struct pcie_port *pp = bus->sysdata;
        int ret;
 
        if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0)
@@ -701,64 +705,6 @@ static struct pci_ops dw_pcie_ops = {
        .write = dw_pcie_wr_conf,
 };
 
-static int dw_pcie_setup(int nr, struct pci_sys_data *sys)
-{
-       struct pcie_port *pp;
-
-       pp = sys_to_pcie(sys);
-
-       if (global_io_offset < SZ_1M && pp->io_size > 0) {
-               sys->io_offset = global_io_offset - pp->io_bus_addr;
-               pci_ioremap_io(global_io_offset, pp->io_base);
-               global_io_offset += SZ_64K;
-               pci_add_resource_offset(&sys->resources, &pp->io,
-                                       sys->io_offset);
-       }
-
-       sys->mem_offset = pp->mem.start - pp->mem_bus_addr;
-       pci_add_resource_offset(&sys->resources, &pp->mem, sys->mem_offset);
-       pci_add_resource(&sys->resources, &pp->busn);
-
-       return 1;
-}
-
-static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys)
-{
-       struct pci_bus *bus;
-       struct pcie_port *pp = sys_to_pcie(sys);
-
-       pp->root_bus_nr = sys->busnr;
-       bus = pci_create_root_bus(pp->dev, sys->busnr,
-                                 &dw_pcie_ops, sys, &sys->resources);
-       if (!bus)
-               return NULL;
-
-       pci_scan_child_bus(bus);
-
-       if (bus && pp->ops->scan_bus)
-               pp->ops->scan_bus(pp);
-
-       return bus;
-}
-
-static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-{
-       struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
-       int irq;
-
-       irq = of_irq_parse_and_map_pci(dev, slot, pin);
-       if (!irq)
-               irq = pp->irq;
-
-       return irq;
-}
-
-static struct hw_pci dw_pci = {
-       .setup          = dw_pcie_setup,
-       .scan           = dw_pcie_scan_bus,
-       .map_irq        = dw_pcie_map_irq,
-};
-
 void dw_pcie_setup_rc(struct pcie_port *pp)
 {
        u32 val;
@@ -778,6 +724,12 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
        case 4:
                val |= PORT_LINK_MODE_4_LANES;
                break;
+       case 8:
+               val |= PORT_LINK_MODE_8_LANES;
+               break;
+       default:
+               dev_err(pp->dev, "num-lanes %u: invalid value\n", pp->lanes);
+               return;
        }
        dw_pcie_writel_rc(pp, val, PCIE_PORT_LINK_CONTROL);
 
@@ -794,6 +746,9 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
        case 4:
                val |= PORT_LOGIC_LINK_WIDTH_4_LANES;
                break;
+       case 8:
+               val |= PORT_LOGIC_LINK_WIDTH_8_LANES;
+               break;
        }
        dw_pcie_writel_rc(pp, val, PCIE_LINK_WIDTH_SPEED_CONTROL);