From: Andrey Smirnov <andrew.smirnov@gmail.com>
To: barebox@lists.infradead.org
Cc: Andrey Smirnov <andrew.smirnov@gmail.com>
Subject: [PATCH v2 51/65] PCI: dwc: Split pcie-designware.c into host and core files
Date: Sun, 16 Dec 2018 21:19:11 -0800 [thread overview]
Message-ID: <20181217051925.17582-52-andrew.smirnov@gmail.com> (raw)
In-Reply-To: <20181217051925.17582-1-andrew.smirnov@gmail.com>
Port of a Linux commit feb85d9b1c47ea8dbcae559ff127b433fdb245b7
Split pcie-designware.c into pcie-designware-host.c that contains the host
specific parts of the driver and pcie-designware.c that contains the parts
used by both host driver and endpoint driver.
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
drivers/pci/Makefile | 2 +-
drivers/pci/pcie-designware-host.c | 412 +++++++++++++++++++++++++++++
drivers/pci/pcie-designware.c | 386 +--------------------------
drivers/pci/pcie-designware.h | 5 +-
4 files changed, 422 insertions(+), 383 deletions(-)
create mode 100644 drivers/pci/pcie-designware-host.c
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index ce5d0e2c8..562304c65 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -9,5 +9,5 @@ CPPFLAGS += $(ccflags-y)
obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o pci-mvebu-phy.o
obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o
-obj-$(CONFIG_PCIE_DW) += pcie-designware.o
+obj-$(CONFIG_PCIE_DW) += pcie-designware.o pcie-designware-host.o
obj-$(CONFIG_PCI_IMX6) += pci-imx6.o
diff --git a/drivers/pci/pcie-designware-host.c b/drivers/pci/pcie-designware-host.c
new file mode 100644
index 000000000..30bed9444
--- /dev/null
+++ b/drivers/pci/pcie-designware-host.c
@@ -0,0 +1,412 @@
+/*
+ * Synopsys Designware PCIe host controller driver
+ *
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * Author: Jingoo Han <jg1.han@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+
+#include <common.h>
+#include <clock.h>
+#include <malloc.h>
+#include <io.h>
+#include <init.h>
+#include <asm/mmu.h>
+
+#include <linux/clk.h>
+#include <linux/kernel.h>
+#include <of_address.h>
+#include <of_pci.h>
+#include <linux/pci.h>
+#include <linux/phy/phy.h>
+#include <linux/reset.h>
+#include <linux/sizes.h>
+
+#include "pcie-designware.h"
+
+#include <abort.h>
+
+static struct pci_ops dw_pcie_ops;
+static unsigned long global_io_offset;
+
+static int dw_pcie_rd_own_conf(struct pcie_port *pp, int where, int size,
+ u32 *val)
+{
+ struct dw_pcie *pci;
+
+ if (pp->ops->rd_own_conf)
+ return pp->ops->rd_own_conf(pp, where, size, val);
+
+ pci = to_dw_pcie_from_pp(pp);
+ return dw_pcie_read(pci->dbi_base + where, size, val);
+}
+
+static int dw_pcie_wr_own_conf(struct pcie_port *pp, int where, int size,
+ u32 val)
+{
+ struct dw_pcie *pci;
+
+ if (pp->ops->wr_own_conf)
+ return pp->ops->wr_own_conf(pp, where, size, val);
+
+ pci = to_dw_pcie_from_pp(pp);
+ return dw_pcie_write(pci->dbi_base + where, size, val);
+}
+
+static inline struct pcie_port *host_to_pcie(struct pci_controller *host)
+{
+ return container_of(host, struct pcie_port, pci);
+}
+
+static void dw_pcie_set_local_bus_nr(struct pci_controller *host, int busno)
+{
+ struct pcie_port *pp = host_to_pcie(host);
+
+ pp->root_bus_nr = busno;
+}
+
+int __init dw_pcie_host_init(struct pcie_port *pp)
+{
+ struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+ struct device_d *dev = pci->dev;
+ struct device_node *np = dev->device_node;
+ struct of_pci_range range;
+ struct of_pci_range_parser parser;
+ struct resource *cfg_res;
+ u32 na, ns;
+ const __be32 *addrp;
+ int 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);
+
+ cfg_res = dev_get_resource_by_name(dev, IORESOURCE_MEM, "config");
+ if (cfg_res) {
+ pp->cfg0_size = resource_size(cfg_res) / 2;
+ 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 {
+ dev_err(dev, "missing *config* reg space\n");
+ }
+
+ if (of_pci_range_parser_init(&parser, np)) {
+ dev_err(dev, "missing ranges property\n");
+ return -EINVAL;
+ }
+
+ /* 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 = range.pci_addr + global_io_offset;
+ pp->io.end = 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;
+ }
+ }
+
+ if (!pci->dbi_base)
+ pci->dbi_base = (void __force *)pp->cfg.start;
+
+ pp->mem_base = pp->mem.start;
+
+ if (!pp->va_cfg0_base)
+ pp->va_cfg0_base = (void __force *)(u32)pp->cfg0_base;
+
+ if (!pp->va_cfg1_base)
+ pp->va_cfg1_base = (void __force *)(u32)pp->cfg1_base;
+
+ ret = of_property_read_u32(np, "num-viewport", &pci->num_viewport);
+ if (ret)
+ pci->num_viewport = 2;
+
+ if (pp->ops->host_init)
+ pp->ops->host_init(pp);
+
+ pp->pci.parent = dev;
+ pp->pci.pci_ops = &dw_pcie_ops;
+ pp->pci.set_busno = dw_pcie_set_local_bus_nr;
+ pp->pci.mem_resource = &pp->mem;
+ pp->pci.io_resource = &pp->io;
+
+ register_pci_controller(&pp->pci);
+
+ 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, type;
+ u32 address, busdev, cfg_size;
+ u64 cpu_addr;
+ void __iomem *va_cfg_base;
+ struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+
+ if (pp->ops->rd_other_conf)
+ return pp->ops->rd_other_conf(pp, bus, devfn,
+ where, size, val);
+
+ busdev = PCIE_ATU_BUS(bus->number) | PCIE_ATU_DEV(PCI_SLOT(devfn)) |
+ PCIE_ATU_FUNC(PCI_FUNC(devfn));
+ address = where & ~0x3;
+
+ if (bus->primary == pp->root_bus_nr) {
+ type = PCIE_ATU_TYPE_CFG0;
+ cpu_addr = pp->cfg0_mod_base;
+ cfg_size = pp->cfg0_size;
+ va_cfg_base = pp->va_cfg0_base;
+ } else {
+ type = PCIE_ATU_TYPE_CFG1;
+ cpu_addr = pp->cfg1_mod_base;
+ cfg_size = pp->cfg1_size;
+ va_cfg_base = pp->va_cfg1_base;
+ }
+
+ dw_pcie_prog_outbound_atu(pci, PCIE_ATU_REGION_INDEX1,
+ type, cpu_addr,
+ busdev, cfg_size);
+ ret = dw_pcie_read(va_cfg_base + where, size, val);
+ if (pci->num_viewport <= 2)
+ dw_pcie_prog_outbound_atu(pci, PCIE_ATU_REGION_INDEX1,
+ PCIE_ATU_TYPE_IO, pp->io_mod_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, type;
+ u32 busdev, cfg_size;
+ u64 cpu_addr;
+ void __iomem *va_cfg_base;
+ struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+
+ if (pp->ops->wr_other_conf)
+ return pp->ops->wr_other_conf(pp, bus, devfn,
+ where, size, val);
+
+ busdev = PCIE_ATU_BUS(bus->number) | PCIE_ATU_DEV(PCI_SLOT(devfn)) |
+ PCIE_ATU_FUNC(PCI_FUNC(devfn));
+
+ if (bus->primary == pp->root_bus_nr) {
+ type = PCIE_ATU_TYPE_CFG0;
+ cpu_addr = pp->cfg0_mod_base;
+ cfg_size = pp->cfg0_size;
+ va_cfg_base = pp->va_cfg0_base;
+ } else {
+ type = PCIE_ATU_TYPE_CFG1;
+ cpu_addr = pp->cfg1_mod_base;
+ cfg_size = pp->cfg1_size;
+ va_cfg_base = pp->va_cfg1_base;
+ }
+
+ dw_pcie_prog_outbound_atu(pci, PCIE_ATU_REGION_INDEX1,
+ type, cpu_addr,
+ busdev, cfg_size);
+ ret = dw_pcie_write(va_cfg_base + where, size, val);
+ if (pci->num_viewport <= 2)
+ dw_pcie_prog_outbound_atu(pci, PCIE_ATU_REGION_INDEX1,
+ PCIE_ATU_TYPE_IO, pp->io_mod_base,
+ pp->io_bus_addr, pp->io_size);
+
+ return ret;
+}
+
+static int dw_pcie_valid_device(struct pcie_port *pp, struct pci_bus *bus,
+ int dev)
+{
+ struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+
+ /* If there is no link, then there is no device */
+ if (bus->number != pp->root_bus_nr) {
+ if (!dw_pcie_link_up(pci))
+ return 0;
+ }
+
+ /* access only one slot on each root port */
+ if (bus->number == pp->root_bus_nr && dev > 0)
+ return 0;
+
+ /*
+ * do not read more than one device on the bus directly attached
+ * to RC's (Virtual Bridge's) DS side.
+ */
+ if (bus->primary == pp->root_bus_nr && dev > 0)
+ return 0;
+
+ return 1;
+}
+
+static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
+ int size, u32 *val)
+{
+ struct pcie_port *pp = host_to_pcie(bus->host);
+ int ret;
+
+ *val = 0xffffffff;
+
+ if (!dw_pcie_valid_device(pp, bus, PCI_SLOT(devfn)))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ data_abort_mask();
+
+ if (bus->number == pp->root_bus_nr)
+ ret = dw_pcie_rd_own_conf(pp, where, size, val);
+ else
+ ret = dw_pcie_rd_other_conf(pp, bus, devfn,
+ where, size, val);
+
+ if (data_abort_unmask())
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ return ret;
+}
+
+static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
+ int where, int size, u32 val)
+{
+ struct pcie_port *pp = host_to_pcie(bus->host);
+ int ret;
+
+ if (!dw_pcie_valid_device(pp, bus, PCI_SLOT(devfn)))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ data_abort_mask();
+
+ if (bus->number == pp->root_bus_nr)
+ ret = dw_pcie_wr_own_conf(pp, where, size, val);
+ else
+ ret = dw_pcie_wr_other_conf(pp, bus, devfn,
+ where, size, val);
+
+ if (data_abort_unmask())
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ return ret;
+}
+
+static int dw_pcie_res_start(struct pci_bus *bus, resource_size_t res_addr)
+{
+ return res_addr;
+}
+
+static struct pci_ops dw_pcie_ops = {
+ .read = dw_pcie_rd_conf,
+ .write = dw_pcie_wr_conf,
+ .res_start = dw_pcie_res_start,
+};
+
+static u8 dw_pcie_iatu_unroll_enabled(struct dw_pcie *pci)
+{
+ u32 val;
+
+ val = dw_pcie_readl_dbi(pci, PCIE_ATU_VIEWPORT);
+ if (val == 0xffffffff)
+ return 1;
+
+ return 0;
+}
+
+void dw_pcie_setup_rc(struct pcie_port *pp)
+{
+ u32 val;
+ struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+
+ dw_pcie_setup(pci);
+
+ /* setup RC BARs */
+ dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, 0x00000004);
+ dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_1, 0x00000000);
+
+ /* setup bus numbers */
+ val = dw_pcie_readl_dbi(pci, PCI_PRIMARY_BUS);
+ val &= 0xff000000;
+ val |= 0x00010100;
+ dw_pcie_writel_dbi(pci, PCI_PRIMARY_BUS, val);
+
+ /* setup command register */
+ val = dw_pcie_readl_dbi(pci, PCI_COMMAND);
+ val &= 0xffff0000;
+ val |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
+ PCI_COMMAND_MASTER | PCI_COMMAND_SERR;
+ dw_pcie_writel_dbi(pci, PCI_COMMAND, val);
+
+ /*
+ * If the platform provides ->rd_other_conf, it means the platform
+ * uses its own address translation component rather than ATU, so
+ * we should not program the ATU here.
+ */
+ if (!pp->ops->rd_other_conf) {
+ /* get iATU unroll support */
+ pci->iatu_unroll_enabled = dw_pcie_iatu_unroll_enabled(pci);
+ dev_dbg(pci->dev, "iATU unroll: %s\n",
+ pci->iatu_unroll_enabled ? "enabled" : "disabled");
+
+ dw_pcie_prog_outbound_atu(pci, PCIE_ATU_REGION_INDEX0,
+ PCIE_ATU_TYPE_MEM, pp->mem_mod_base,
+ pp->mem_bus_addr, pp->mem_size);
+ if (pci->num_viewport > 2)
+ dw_pcie_prog_outbound_atu(pci, PCIE_ATU_REGION_INDEX2,
+ PCIE_ATU_TYPE_IO, pp->io_base,
+ pp->io_bus_addr, pp->io_size);
+ }
+
+ dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0);
+
+ /* program correct class for RC */
+ dw_pcie_wr_own_conf(pp, PCI_CLASS_DEVICE, 2, PCI_CLASS_BRIDGE_PCI);
+
+ dw_pcie_rd_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, &val);
+ val |= PORT_LOGIC_SPEED_CHANGE;
+ dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val);
+}
\ No newline at end of file
diff --git a/drivers/pci/pcie-designware.c b/drivers/pci/pcie-designware.c
index f5a77ae15..6687fff8b 100644
--- a/drivers/pci/pcie-designware.c
+++ b/drivers/pci/pcie-designware.c
@@ -30,8 +30,6 @@
#include "pcie-designware.h"
-static unsigned long global_io_offset;
-
int dw_pcie_read(void __iomem *addr, int size, u32 *val)
{
if ((uintptr_t)addr & (size - 1)) {
@@ -101,35 +99,9 @@ static void dw_pcie_writel_unroll(struct dw_pcie *pci, u32 index,
dw_pcie_writel_dbi(pci, offset + reg, val);
}
-#include <abort.h>
-
-static int dw_pcie_rd_own_conf(struct pcie_port *pp, int where, int size,
- u32 *val)
-{
- struct dw_pcie *pci;
-
- if (pp->ops->rd_own_conf)
- return pp->ops->rd_own_conf(pp, where, size, val);
-
- pci = to_dw_pcie_from_pp(pp);
- return dw_pcie_read(pci->dbi_base + where, size, val);
-}
-
-static int dw_pcie_wr_own_conf(struct pcie_port *pp, int where, int size,
- u32 val)
-{
- struct dw_pcie *pci;
-
- if (pp->ops->wr_own_conf)
- return pp->ops->wr_own_conf(pp, where, size, val);
-
- pci = to_dw_pcie_from_pp(pp);
- return dw_pcie_write(pci->dbi_base + where, size, val);
-}
-
-static void dw_pcie_prog_outbound_atu(struct dw_pcie *pci, int index,
- int type, u64 cpu_addr, u64 pci_addr,
- u32 size)
+void dw_pcie_prog_outbound_atu(struct dw_pcie *pci, int index,
+ int type, u64 cpu_addr, u64 pci_addr,
+ u32 size)
{
u32 retries, val;
@@ -214,313 +186,11 @@ int dw_pcie_link_up(struct dw_pcie *pci)
!(val & PCIE_PHY_DEBUG_R1_LINK_IN_TRAINING));
}
-static inline struct pcie_port *host_to_pcie(struct pci_controller *host)
-{
- return container_of(host, struct pcie_port, pci);
-}
-
-static void dw_pcie_set_local_bus_nr(struct pci_controller *host, int busno)
-{
- struct pcie_port *pp = host_to_pcie(host);
-
- pp->root_bus_nr = busno;
-}
-
-static struct pci_ops dw_pcie_ops;
-
-static u8 dw_pcie_iatu_unroll_enabled(struct dw_pcie *pci)
-{
- u32 val;
-
- val = dw_pcie_readl_dbi(pci, PCIE_ATU_VIEWPORT);
- if (val == 0xffffffff)
- return 1;
-
- return 0;
-}
-
-
-int __init dw_pcie_host_init(struct pcie_port *pp)
+void dw_pcie_setup(struct dw_pcie *pci)
{
- struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
- struct device_d *dev = pci->dev;
- struct device_node *np = dev->device_node;
- struct of_pci_range range;
- struct of_pci_range_parser parser;
- struct resource *cfg_res;
- u32 na, ns;
- const __be32 *addrp;
- int 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);
-
- cfg_res = dev_get_resource_by_name(dev, IORESOURCE_MEM, "config");
- if (cfg_res) {
- pp->cfg0_size = resource_size(cfg_res) / 2;
- 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 {
- dev_err(dev, "missing *config* reg space\n");
- }
-
- if (of_pci_range_parser_init(&parser, np)) {
- dev_err(dev, "missing ranges property\n");
- return -EINVAL;
- }
-
- /* 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 = range.pci_addr + global_io_offset;
- pp->io.end = 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;
- }
- }
-
- if (!pci->dbi_base)
- pci->dbi_base = (void __force *)pp->cfg.start;
-
- pp->mem_base = pp->mem.start;
-
- if (!pp->va_cfg0_base)
- pp->va_cfg0_base = (void __force *)(u32)pp->cfg0_base;
-
- if (!pp->va_cfg1_base)
- pp->va_cfg1_base = (void __force *)(u32)pp->cfg1_base;
-
- ret = of_property_read_u32(np, "num-viewport", &pci->num_viewport);
- if (ret)
- pci->num_viewport = 2;
-
- if (pp->ops->host_init)
- pp->ops->host_init(pp);
-
- pp->pci.parent = dev;
- pp->pci.pci_ops = &dw_pcie_ops;
- pp->pci.set_busno = dw_pcie_set_local_bus_nr;
- pp->pci.mem_resource = &pp->mem;
- pp->pci.io_resource = &pp->io;
-
- register_pci_controller(&pp->pci);
-
- 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, type;
- u32 address, busdev, cfg_size;
- u64 cpu_addr;
- void __iomem *va_cfg_base;
- struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
-
- if (pp->ops->rd_other_conf)
- return pp->ops->rd_other_conf(pp, bus, devfn,
- where, size, val);
-
- busdev = PCIE_ATU_BUS(bus->number) | PCIE_ATU_DEV(PCI_SLOT(devfn)) |
- PCIE_ATU_FUNC(PCI_FUNC(devfn));
- address = where & ~0x3;
-
- if (bus->primary == pp->root_bus_nr) {
- type = PCIE_ATU_TYPE_CFG0;
- cpu_addr = pp->cfg0_mod_base;
- cfg_size = pp->cfg0_size;
- va_cfg_base = pp->va_cfg0_base;
- } else {
- type = PCIE_ATU_TYPE_CFG1;
- cpu_addr = pp->cfg1_mod_base;
- cfg_size = pp->cfg1_size;
- va_cfg_base = pp->va_cfg1_base;
- }
-
- dw_pcie_prog_outbound_atu(pci, PCIE_ATU_REGION_INDEX1,
- type, cpu_addr,
- busdev, cfg_size);
- ret = dw_pcie_read(va_cfg_base + where, size, val);
- if (pci->num_viewport <= 2)
- dw_pcie_prog_outbound_atu(pci, PCIE_ATU_REGION_INDEX1,
- PCIE_ATU_TYPE_IO, pp->io_mod_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, type;
- u32 busdev, cfg_size;
- u64 cpu_addr;
- void __iomem *va_cfg_base;
- struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
-
- if (pp->ops->wr_other_conf)
- return pp->ops->wr_other_conf(pp, bus, devfn,
- where, size, val);
-
- busdev = PCIE_ATU_BUS(bus->number) | PCIE_ATU_DEV(PCI_SLOT(devfn)) |
- PCIE_ATU_FUNC(PCI_FUNC(devfn));
-
- if (bus->primary == pp->root_bus_nr) {
- type = PCIE_ATU_TYPE_CFG0;
- cpu_addr = pp->cfg0_mod_base;
- cfg_size = pp->cfg0_size;
- va_cfg_base = pp->va_cfg0_base;
- } else {
- type = PCIE_ATU_TYPE_CFG1;
- cpu_addr = pp->cfg1_mod_base;
- cfg_size = pp->cfg1_size;
- va_cfg_base = pp->va_cfg1_base;
- }
-
- dw_pcie_prog_outbound_atu(pci, PCIE_ATU_REGION_INDEX1,
- type, cpu_addr,
- busdev, cfg_size);
- ret = dw_pcie_write(va_cfg_base + where, size, val);
- if (pci->num_viewport <= 2)
- dw_pcie_prog_outbound_atu(pci, PCIE_ATU_REGION_INDEX1,
- PCIE_ATU_TYPE_IO, pp->io_mod_base,
- pp->io_bus_addr, pp->io_size);
-
- return ret;
-}
-
-static int dw_pcie_valid_device(struct pcie_port *pp, struct pci_bus *bus,
- int dev)
-{
- struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
-
- /* If there is no link, then there is no device */
- if (bus->number != pp->root_bus_nr) {
- if (!dw_pcie_link_up(pci))
- return 0;
- }
-
- /* access only one slot on each root port */
- if (bus->number == pp->root_bus_nr && dev > 0)
- return 0;
-
- /*
- * do not read more than one device on the bus directly attached
- * to RC's (Virtual Bridge's) DS side.
- */
- if (bus->primary == pp->root_bus_nr && dev > 0)
- return 0;
-
- return 1;
-}
-
-static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
- int size, u32 *val)
-{
- struct pcie_port *pp = host_to_pcie(bus->host);
- int ret;
-
- *val = 0xffffffff;
-
- if (!dw_pcie_valid_device(pp, bus, PCI_SLOT(devfn)))
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- data_abort_mask();
-
- if (bus->number == pp->root_bus_nr)
- ret = dw_pcie_rd_own_conf(pp, where, size, val);
- else
- ret = dw_pcie_rd_other_conf(pp, bus, devfn,
- where, size, val);
-
- if (data_abort_unmask())
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- return ret;
-}
-
-static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
- int where, int size, u32 val)
-{
- struct pcie_port *pp = host_to_pcie(bus->host);
int ret;
-
- if (!dw_pcie_valid_device(pp, bus, PCI_SLOT(devfn)))
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- data_abort_mask();
-
- if (bus->number == pp->root_bus_nr)
- ret = dw_pcie_wr_own_conf(pp, where, size, val);
- else
- ret = dw_pcie_wr_other_conf(pp, bus, devfn,
- where, size, val);
-
- if (data_abort_unmask())
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- return ret;
-}
-
-static int dw_pcie_res_start(struct pci_bus *bus, resource_size_t res_addr)
-{
- return res_addr;
-}
-
-static struct pci_ops dw_pcie_ops = {
- .read = dw_pcie_rd_conf,
- .write = dw_pcie_wr_conf,
- .res_start = dw_pcie_res_start,
-};
-
-void dw_pcie_setup_rc(struct pcie_port *pp)
-{
- int ret;
- u32 lanes;
u32 val;
- struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+ u32 lanes;
struct device_d *dev = pci->dev;
struct device_node *np = dev->device_node;
@@ -562,52 +232,6 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
break;
}
dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, val);
-
- /* setup RC BARs */
- dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, 0x00000004);
- dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_1, 0x00000000);
-
- /* setup bus numbers */
- val = dw_pcie_readl_dbi(pci, PCI_PRIMARY_BUS);
- val &= 0xff000000;
- val |= 0x00010100;
- dw_pcie_writel_dbi(pci, PCI_PRIMARY_BUS, val);
-
- /* setup command register */
- val = dw_pcie_readl_dbi(pci, PCI_COMMAND);
- val &= 0xffff0000;
- val |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
- PCI_COMMAND_MASTER | PCI_COMMAND_SERR;
- dw_pcie_writel_dbi(pci, PCI_COMMAND, val);
-
- /*
- * If the platform provides ->rd_other_conf, it means the platform
- * uses its own address translation component rather than ATU, so
- * we should not program the ATU here.
- */
- if (!pp->ops->rd_other_conf) {
- /* get iATU unroll support */
- pci->iatu_unroll_enabled = dw_pcie_iatu_unroll_enabled(pci);
- dev_dbg(pci->dev, "iATU unroll: %s\n",
- pci->iatu_unroll_enabled ? "enabled" : "disabled");
-
- dw_pcie_prog_outbound_atu(pci, PCIE_ATU_REGION_INDEX0,
- PCIE_ATU_TYPE_MEM, pp->mem_mod_base,
- pp->mem_bus_addr, pp->mem_size);
- if (pci->num_viewport > 2)
- dw_pcie_prog_outbound_atu(pci, PCIE_ATU_REGION_INDEX2,
- PCIE_ATU_TYPE_IO, pp->io_base,
- pp->io_bus_addr, pp->io_size);
- }
-
- dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0);
-
- /* program correct class for RC */
- dw_pcie_wr_own_conf(pp, PCI_CLASS_DEVICE, 2, PCI_CLASS_BRIDGE_PCI);
-
- dw_pcie_rd_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, &val);
- val |= PORT_LOGIC_SPEED_CHANGE;
- dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val);
}
MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>");
diff --git a/drivers/pci/pcie-designware.h b/drivers/pci/pcie-designware.h
index 06d8c769c..97c8b0b3c 100644
--- a/drivers/pci/pcie-designware.h
+++ b/drivers/pci/pcie-designware.h
@@ -159,5 +159,8 @@ u32 dw_pcie_readl_dbi(struct dw_pcie *pci, u32 reg);
void dw_pcie_writel_dbi(struct dw_pcie *pci, u32 reg, u32 val);
int dw_pcie_link_up(struct dw_pcie *pci);
int dw_pcie_wait_for_link(struct dw_pcie *pci);
-
+void dw_pcie_prog_outbound_atu(struct dw_pcie *pci, int index,
+ int type, u64 cpu_addr, u64 pci_addr,
+ u32 size);
+void dw_pcie_setup(struct dw_pcie *pci);
#endif /* _PCIE_DESIGNWARE_H */
--
2.19.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
next prev parent reply other threads:[~2018-12-17 5:21 UTC|newest]
Thread overview: 68+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-12-17 5:18 [PATCH v2 00/65] PCI i.MX6/DesignWare sync up with 4.20-rc1 Andrey Smirnov
2018-12-17 5:18 ` [PATCH v2 01/65] PCI: desginware: Remove bogus prototypes Andrey Smirnov
2018-12-17 5:18 ` [PATCH v2 02/65] PCI: designware: Consolidate outbound iATU programming functions Andrey Smirnov
2018-12-17 5:18 ` [PATCH v2 03/65] PCI: designware: Use iATU0 for cfg and IO, iATU1 for MEM Andrey Smirnov
2018-12-17 5:18 ` [PATCH v2 04/65] PCI: designware: Fix PORT_LOGIC_LINK_WIDTH_MASK Andrey Smirnov
2018-12-17 5:18 ` [PATCH v2 05/65] PCI: designware: Use exact access size in dw_pcie_cfg_read() Andrey Smirnov
2018-12-17 5:18 ` [PATCH v2 06/65] PCI: designware: Simplify dw_pcie_cfg_read/write() interfaces Andrey Smirnov
2018-12-17 5:18 ` [PATCH v2 07/65] PCI: designware: Require config accesses to be naturally aligned Andrey Smirnov
2018-12-17 5:18 ` [PATCH v2 08/65] PCI: designware: Make "num-lanes" an optional DT property Andrey Smirnov
2018-12-17 5:18 ` [PATCH v2 09/65] PCI: designware: Ensure ATU is enabled before IO/conf space accesses Andrey Smirnov
2018-12-17 5:18 ` [PATCH v2 10/65] PCI: designware: Simplify control flow Andrey Smirnov
2018-12-17 5:18 ` [PATCH v2 11/65] PCI: designware: Make config accessor override checking symmetric Andrey Smirnov
2018-12-17 5:18 ` [PATCH v2 12/65] PCI: designware: Explain why we don't program ATU for some platforms Andrey Smirnov
2018-12-17 5:18 ` [PATCH v2 13/65] PCI: imx6: Move link up check into imx6_pcie_wait_for_link() Andrey Smirnov
2018-12-17 5:18 ` [PATCH v2 14/65] PCI: designware: Add generic dw_pcie_wait_for_link() Andrey Smirnov
2018-12-17 5:18 ` [PATCH v2 15/65] PCI: designware: Add default link up check if sub-driver doesn't override Andrey Smirnov
2018-12-17 5:18 ` [PATCH v2 16/65] PCI: designware: Move Root Complex setup code to dw_pcie_setup_rc() Andrey Smirnov
2018-12-17 5:18 ` [PATCH v2 17/65] PCI: designware: Remove incorrect RC memory base/limit configuration Andrey Smirnov
2018-12-17 5:18 ` [PATCH v2 18/65] PCI: designware: Return data directly from dw_pcie_readl_rc() Andrey Smirnov
2018-12-17 5:18 ` [PATCH v2 19/65] PCI: designware: Move link wait definitions to .c file Andrey Smirnov
2018-12-17 5:18 ` [PATCH v2 20/65] PCI: designware: Wait for iATU enable Andrey Smirnov
2018-12-17 5:18 ` [PATCH v2 21/65] PCI: designware: Add iATU Unroll feature Andrey Smirnov
2018-12-17 5:18 ` [PATCH v2 22/65] PCI: designware: Check LTSSM training bit before deciding link is up Andrey Smirnov
2018-12-17 5:18 ` [PATCH v2 23/65] PCI: designware: Keep viewport fixed for IO transaction if num_viewport > 2 Andrey Smirnov
2018-12-17 5:18 ` [PATCH v2 24/65] PCI: designware: Exchange viewport of `MEMORYs' and `CFGs/IOs' Andrey Smirnov
2018-12-17 5:18 ` [PATCH v2 25/65] PCI: designware: Rename dw_pcie_valid_config() to dw_pcie_valid_device() Andrey Smirnov
2018-12-17 5:18 ` [PATCH v2 26/65] PCI: designware: Simplify dw_pcie_readl_unroll(), dw_pcie_writel_unroll() Andrey Smirnov
2018-12-17 5:18 ` [PATCH v2 27/65] PCI: designware: Simplify pcie_host_ops.readl_rc() and .writel_rc() interfaces Andrey Smirnov
2018-12-17 5:18 ` [PATCH v2 28/65] PCI: designware: Swap order of dw_pcie_writel_rc() reg/val arguments Andrey Smirnov
2018-12-17 5:18 ` [PATCH v2 29/65] PCI: designware: Export dw_pcie_readl_rc(), dw_pcie_writel_rc() Andrey Smirnov
2018-12-17 5:18 ` [PATCH v2 30/65] PCI: designware: Uninline register accessors Andrey Smirnov
2018-12-17 5:18 ` [PATCH v2 31/65] PCI: designware: Swap order of dw_pcie_writel_unroll() reg/val arguments Andrey Smirnov
2018-12-17 5:18 ` [PATCH v2 32/65] PCI: designware: Check for iATU unroll only on platforms that use ATU Andrey Smirnov
2018-12-17 5:18 ` [PATCH v2 33/65] PCI: dwc: designware: Move register defines to designware header file Andrey Smirnov
2018-12-17 5:18 ` [PATCH v2 34/65] PCI: dwc: all: Rename cfg_read/cfg_write to read/write Andrey Smirnov
2018-12-17 5:18 ` [PATCH v2 35/65] PCI: dwc: designware: Get device pointer at the start of dw_pcie_host_init() Andrey Smirnov
2018-12-17 5:18 ` [PATCH v2 36/65] PCI: imx6: Add local struct device pointers Andrey Smirnov
2018-12-17 5:18 ` [PATCH v2 37/65] PCI: imx6: Removed unused struct imx6_pcie.mem_base Andrey Smirnov
2018-12-17 5:18 ` [PATCH v2 38/65] PCI: imx6: Pass struct imx6_pcie to PHY accessors Andrey Smirnov
2018-12-17 5:18 ` [PATCH v2 39/65] PCI: imx6: Pass device-specific struct to internal functions Andrey Smirnov
2018-12-17 5:19 ` [PATCH v2 40/65] PCI: imx6: Use generic DesignWare accessors Andrey Smirnov
2018-12-17 5:19 ` [PATCH v2 41/65] PCI: imx6: Reorder struct imx6_pcie Andrey Smirnov
2018-12-17 5:19 ` [PATCH v2 42/65] PCI: imx6: Port error messages for imx6_pcie_deassert_core_reset() Andrey Smirnov
2018-12-17 5:19 ` [PATCH v2 43/65] PCI: imx6: Remove unused return values Andrey Smirnov
2018-12-17 5:19 ` [PATCH v2 44/65] PCI: imx6: Factor out ref clock enable Andrey Smirnov
2018-12-17 5:19 ` [PATCH v2 45/65] PCI: imx6: Add DT property for link gen, default to Gen1 Andrey Smirnov
2018-12-17 5:19 ` [PATCH v2 46/65] PCI: imx6: Remove redundant "Link never came up" message Andrey Smirnov
2018-12-17 5:19 ` [PATCH v2 47/65] PCI: imx6: Remove LTSSM disable workaround Andrey Smirnov
2018-12-17 5:19 ` [PATCH v2 48/65] PCI: dwc: all: Split struct pcie_port into host-only and core structures Andrey Smirnov
2018-12-17 5:19 ` [PATCH v2 49/65] PCI: dwc: designware: Parse "num-lanes" property in dw_pcie_setup_rc() Andrey Smirnov
2018-12-17 5:19 ` [PATCH v2 50/65] PCI: dwc: designware: Fix style errors in pcie-designware.c Andrey Smirnov
2018-12-17 5:19 ` Andrey Smirnov [this message]
2018-12-17 5:19 ` [PATCH v2 52/65] PCI: dwc: all: Modify dbi accessors to take dbi_base as argument Andrey Smirnov
2018-12-17 5:19 ` [PATCH v2 53/65] PCI: dwc: all: Modify dbi accessors to access data of 4/2/1 bytes Andrey Smirnov
2018-12-17 5:19 ` [PATCH v2 54/65] PCI: dwc: designware: Move _unroll configurations to a separate function Andrey Smirnov
2018-12-17 5:19 ` [PATCH v2 55/65] PCI: dwc: designware: Test PCIE_ATU_ENABLE bit specifically Andrey Smirnov
2018-12-17 5:19 ` [PATCH v2 56/65] PCI: dwc: designware: Make dw_pcie_prog_*_atu_unroll() static Andrey Smirnov
2018-12-17 5:19 ` [PATCH v2 57/65] PCI: Fix typos and whitespace errors Andrey Smirnov
2018-12-17 5:19 ` [PATCH v2 58/65] PCI: Add SPDX GPL-2.0 to replace GPL v2 boilerplate Andrey Smirnov
2018-12-17 5:19 ` [PATCH v2 59/65] PCI: dwc: Replace lower into upper case characters Andrey Smirnov
2018-12-17 5:19 ` [PATCH v2 60/65] PCI: dwc: designware: Handle ->host_init() failures Andrey Smirnov
2018-12-17 5:19 ` [PATCH v2 61/65] PCI: dwc: Add accessors for write permission of DBI Andrey Smirnov
2018-12-17 5:19 ` [PATCH v2 62/65] PCI: dwc: Enable write permission for Class Code, Interrupt Pin updates Andrey Smirnov
2018-12-17 5:19 ` [PATCH v2 63/65] PCI: dwc: Fix enumeration end when reaching root subordinate Andrey Smirnov
2018-12-17 5:19 ` [PATCH v2 64/65] PCI: dwc: Small computation improvement Andrey Smirnov
2018-12-17 5:19 ` [PATCH v2 65/65] PCI: dwc: Constify dw_pcie_host_ops structures Andrey Smirnov
2019-01-07 22:55 ` [PATCH v2 00/65] PCI i.MX6/DesignWare sync up with 4.20-rc1 Andrey Smirnov
2019-01-08 15:31 ` Sascha Hauer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20181217051925.17582-52-andrew.smirnov@gmail.com \
--to=andrew.smirnov@gmail.com \
--cc=barebox@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox