* [PATCH 01/12] PCI: dwc: Don't hard-code DBI/ATU offset
2019-11-27 11:20 [PATCH 00/12] Designware PCIe updates and Layerscape support Sascha Hauer
@ 2019-11-27 11:20 ` Sascha Hauer
2019-11-27 11:20 ` [PATCH 02/12] PCI: dwc: Make use of IS_ALIGNED() Sascha Hauer
` (10 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Sascha Hauer @ 2019-11-27 11:20 UTC (permalink / raw)
To: Barebox List
Port of Linux commit 6d6b05e3d5337f645a411cdf72f1a083e495acb8
The DWC PCIe core contains various separate register spaces: DBI, DBI2,
ATU, DMA, etc. The relationship between the addresses of these register
spaces is entirely determined by the implementation of the IP block, not
by the IP block design itself. Hence, the DWC driver must not make
assumptions that one register space can be accessed at a fixed offset from
any other register space. To avoid such assumptions, introduce an
explicit/separate register pointer for the ATU register space. In
particular, the current assumption is not valid for NVIDIA's T194 SoC.
The ATU register space is only used on systems that require unrolled ATU
access. This property is detected at run-time for host controllers, and
when this is detected, this patch provides a default value for atu_base
that matches the previous assumption re: register layout. An alternative
would be to update all drivers for HW that requires unrolled access to
explicitly set atu_base. However, it's hard to tell which drivers would
require atu_base to be set. The unrolled property is not detected for
endpoint systems, and so any endpoint driver that requires unrolled access
must explicitly set the iatu_unroll_enabled flag (none do at present), and
so a check is added to require the driver to also set atu_base while at
it.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Acked-by: Gustavo Pimentel <gustavo.pimentel@synopsys.com>
Acked-by: Vidya Sagar <vidyas@nvidia.com>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
drivers/pci/pcie-designware-host.c | 3 +++
drivers/pci/pcie-designware.c | 4 ++--
drivers/pci/pcie-designware.h | 22 +++++++++++++++++++++-
3 files changed, 26 insertions(+), 3 deletions(-)
diff --git a/drivers/pci/pcie-designware-host.c b/drivers/pci/pcie-designware-host.c
index 7a95b2a092..f3d7c59a60 100644
--- a/drivers/pci/pcie-designware-host.c
+++ b/drivers/pci/pcie-designware-host.c
@@ -386,6 +386,9 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
dev_dbg(pci->dev, "iATU unroll: %s\n",
pci->iatu_unroll_enabled ? "enabled" : "disabled");
+ if (pci->iatu_unroll_enabled && !pci->atu_base)
+ pci->atu_base = pci->dbi_base + DEFAULT_DBI_ATU_OFFSET;
+
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);
diff --git a/drivers/pci/pcie-designware.c b/drivers/pci/pcie-designware.c
index c6d19559f4..4fe99b1ffb 100644
--- a/drivers/pci/pcie-designware.c
+++ b/drivers/pci/pcie-designware.c
@@ -100,7 +100,7 @@ static u32 dw_pcie_readl_ob_unroll(struct dw_pcie *pci, u32 index, u32 reg)
{
u32 offset = PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(index);
- return dw_pcie_readl_dbi(pci, offset + reg);
+ return dw_pcie_readl_atu(pci, offset + reg);
}
static void dw_pcie_writel_ob_unroll(struct dw_pcie *pci, u32 index,
@@ -108,7 +108,7 @@ static void dw_pcie_writel_ob_unroll(struct dw_pcie *pci, u32 index,
{
u32 offset = PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(index);
- dw_pcie_writel_dbi(pci, offset + reg, val);
+ dw_pcie_writel_atu(pci, offset + reg, val);
}
static void dw_pcie_prog_outbound_atu_unroll(struct dw_pcie *pci, int index,
diff --git a/drivers/pci/pcie-designware.h b/drivers/pci/pcie-designware.h
index 058a0acbb2..f989ef2bd9 100644
--- a/drivers/pci/pcie-designware.h
+++ b/drivers/pci/pcie-designware.h
@@ -74,8 +74,16 @@
#define PCIE_ATU_UNR_LOWER_TARGET 0x14
#define PCIE_ATU_UNR_UPPER_TARGET 0x18
+/*
+ * The default address offset between dbi_base and atu_base. Root controller
+ * drivers are not required to initialize atu_base if the offset matches this
+ * default; the driver core automatically derives atu_base from dbi_base using
+ * this offset, if atu_base not set.
+ */
+#define DEFAULT_DBI_ATU_OFFSET (0x3 << 20)
+
/* Register address builder */
-#define PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(region) ((0x3 << 20) | (region << 9))
+#define PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(region) ((region) << 9)
/* PCIe Port Logic registers */
#define PLR_OFFSET 0x700
@@ -144,6 +152,8 @@ struct dw_pcie_ops {
struct dw_pcie {
struct device_d *dev;
void __iomem *dbi_base;
+ /* Used when iatu_unroll_enabled is true */
+ void __iomem *atu_base;
u32 num_viewport;
u8 iatu_unroll_enabled;
struct pcie_port pp;
@@ -178,6 +188,16 @@ static inline u32 dw_pcie_readl_dbi(struct dw_pcie *pci, u32 reg)
return __dw_pcie_readl_dbi(pci, pci->dbi_base, reg, 0x4);
}
+static inline void dw_pcie_writel_atu(struct dw_pcie *pci, u32 reg, u32 val)
+{
+ __dw_pcie_writel_dbi(pci, pci->atu_base, reg, 0x4, val);
+}
+
+static inline u32 dw_pcie_readl_atu(struct dw_pcie *pci, u32 reg)
+{
+ return __dw_pcie_readl_dbi(pci, pci->atu_base, reg, 0x4);
+}
+
static inline void dw_pcie_dbi_ro_wr_en(struct dw_pcie *pci)
{
u32 reg;
--
2.24.0
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 02/12] PCI: dwc: Make use of IS_ALIGNED()
2019-11-27 11:20 [PATCH 00/12] Designware PCIe updates and Layerscape support Sascha Hauer
2019-11-27 11:20 ` [PATCH 01/12] PCI: dwc: Don't hard-code DBI/ATU offset Sascha Hauer
@ 2019-11-27 11:20 ` Sascha Hauer
2019-11-27 11:20 ` [PATCH 03/12] PCI: dwc: Add dw_pcie_disable_atu() Sascha Hauer
` (9 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Sascha Hauer @ 2019-11-27 11:20 UTC (permalink / raw)
To: Barebox List
Port of Linux commit 4f8bbd2f8e7c4f3112506bf7362aed3a5495d51b
Make the intent a bit more clear as well as get rid of explicit
arithmetic by using IS_ALIGNED() to determine if "addr" is aligned to
"size". No functional change intended.
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Acked-by: Gustavo Pimentel <gustavo.pimentel@synopsys.com>
Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Fabio Estevam <fabio.estevam@nxp.com>
Cc: Chris Healy <cphealy@gmail.com>
Cc: Lucas Stach <l.stach@pengutronix.de>
Cc: Leonard Crestez <leonard.crestez@nxp.com>
Cc: "A.s. Dong" <aisheng.dong@nxp.com>
Cc: Richard Zhu <hongxing.zhu@nxp.com>
Cc: linux-imx@nxp.com
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-pci@vger.kernel.org
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
drivers/pci/pcie-designware.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/pci/pcie-designware.c b/drivers/pci/pcie-designware.c
index 4fe99b1ffb..5747704cd5 100644
--- a/drivers/pci/pcie-designware.c
+++ b/drivers/pci/pcie-designware.c
@@ -29,7 +29,7 @@
int dw_pcie_read(void __iomem *addr, int size, u32 *val)
{
- if ((uintptr_t)addr & (size - 1)) {
+ if (!IS_ALIGNED((uintptr_t)addr, size)) {
*val = 0;
return PCIBIOS_BAD_REGISTER_NUMBER;
}
@@ -50,7 +50,7 @@ int dw_pcie_read(void __iomem *addr, int size, u32 *val)
int dw_pcie_write(void __iomem *addr, int size, u32 val)
{
- if ((uintptr_t)addr & (size - 1))
+ if (!IS_ALIGNED((uintptr_t)addr, size))
return PCIBIOS_BAD_REGISTER_NUMBER;
if (size == 4)
--
2.24.0
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 03/12] PCI: dwc: Add dw_pcie_disable_atu()
2019-11-27 11:20 [PATCH 00/12] Designware PCIe updates and Layerscape support Sascha Hauer
2019-11-27 11:20 ` [PATCH 01/12] PCI: dwc: Don't hard-code DBI/ATU offset Sascha Hauer
2019-11-27 11:20 ` [PATCH 02/12] PCI: dwc: Make use of IS_ALIGNED() Sascha Hauer
@ 2019-11-27 11:20 ` Sascha Hauer
2019-11-27 11:20 ` [PATCH 04/12] PCI: dwc: Make use of BIT() in constant definitions Sascha Hauer
` (8 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Sascha Hauer @ 2019-11-27 11:20 UTC (permalink / raw)
To: Barebox List
This adds dw_pcie_disable_atu() taken from Linux-5.4. This is needed by
the upcoming Layerscape driver.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
drivers/pci/pcie-designware.c | 20 ++++++++++++++++++++
drivers/pci/pcie-designware.h | 8 ++++++++
2 files changed, 28 insertions(+)
diff --git a/drivers/pci/pcie-designware.c b/drivers/pci/pcie-designware.c
index 5747704cd5..9728964ec9 100644
--- a/drivers/pci/pcie-designware.c
+++ b/drivers/pci/pcie-designware.c
@@ -188,6 +188,26 @@ void dw_pcie_prog_outbound_atu(struct dw_pcie *pci, int index,
dev_err(pci->dev, "Outbound iATU is not being enabled\n");
}
+void dw_pcie_disable_atu(struct dw_pcie *pci, int index,
+ enum dw_pcie_region_type type)
+{
+ int region;
+
+ switch (type) {
+ case DW_PCIE_REGION_INBOUND:
+ region = PCIE_ATU_REGION_INBOUND;
+ break;
+ case DW_PCIE_REGION_OUTBOUND:
+ region = PCIE_ATU_REGION_OUTBOUND;
+ break;
+ default:
+ return;
+ }
+
+ dw_pcie_writel_dbi(pci, PCIE_ATU_VIEWPORT, region | index);
+ dw_pcie_writel_dbi(pci, PCIE_ATU_CR2, (u32)~PCIE_ATU_ENABLE);
+}
+
int dw_pcie_wait_for_link(struct dw_pcie *pci)
{
int retries;
diff --git a/drivers/pci/pcie-designware.h b/drivers/pci/pcie-designware.h
index f989ef2bd9..1659d8f60b 100644
--- a/drivers/pci/pcie-designware.h
+++ b/drivers/pci/pcie-designware.h
@@ -103,6 +103,12 @@
struct pcie_port;
struct dw_pcie;
+enum dw_pcie_region_type {
+ DW_PCIE_REGION_UNKNOWN,
+ DW_PCIE_REGION_INBOUND,
+ DW_PCIE_REGION_OUTBOUND,
+};
+
struct dw_pcie_host_ops {
int (*rd_own_conf)(struct pcie_port *pp, int where, int size, u32 *val);
int (*wr_own_conf)(struct pcie_port *pp, int where, int size, u32 val);
@@ -176,6 +182,8 @@ 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_disable_atu(struct dw_pcie *pci, int index,
+ enum dw_pcie_region_type type);
void dw_pcie_setup(struct dw_pcie *pci);
static inline void dw_pcie_writel_dbi(struct dw_pcie *pci, u32 reg, u32 val)
--
2.24.0
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 04/12] PCI: dwc: Make use of BIT() in constant definitions
2019-11-27 11:20 [PATCH 00/12] Designware PCIe updates and Layerscape support Sascha Hauer
` (2 preceding siblings ...)
2019-11-27 11:20 ` [PATCH 03/12] PCI: dwc: Add dw_pcie_disable_atu() Sascha Hauer
@ 2019-11-27 11:20 ` Sascha Hauer
2019-11-27 11:20 ` [PATCH 05/12] PCI: dwc: Enable iATU unroll for endpoint too Sascha Hauer
` (7 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Sascha Hauer @ 2019-11-27 11:20 UTC (permalink / raw)
To: Barebox List
Port of Linux commit 0e11faa48b07a063289d65363015a3d51ca4c337
Avoid using explicit left shifts and convert various definitions to
use BIT() instead. No functional change intended.
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
[lorenzo.pieralisi@arm.com: fixed PORT_LOGIC_SPEED_CHANGE redefinition]
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Acked-by: Gustavo Pimentel <gustavo.pimentel@synopsys.com>
Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Fabio Estevam <fabio.estevam@nxp.com>
Cc: Chris Healy <cphealy@gmail.com>
Cc: Lucas Stach <l.stach@pengutronix.de>
Cc: Leonard Crestez <leonard.crestez@nxp.com>
Cc: "A.s. Dong" <aisheng.dong@nxp.com>
Cc: Richard Zhu <hongxing.zhu@nxp.com>
Cc: linux-imx@nxp.com
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-pci@vger.kernel.org
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
drivers/pci/pci-imx6.c | 1 -
drivers/pci/pcie-designware.h | 12 ++++++------
2 files changed, 6 insertions(+), 7 deletions(-)
diff --git a/drivers/pci/pci-imx6.c b/drivers/pci/pci-imx6.c
index 85307bad3e..6cbae1e223 100644
--- a/drivers/pci/pci-imx6.c
+++ b/drivers/pci/pci-imx6.c
@@ -112,7 +112,6 @@ struct imx6_pcie {
#define PCIE_PHY_STAT_ACK_LOC 16
#define PCIE_LINK_WIDTH_SPEED_CONTROL 0x80C
-#define PORT_LOGIC_SPEED_CHANGE (0x1 << 17)
/* PHY registers (not memory-mapped) */
#define PCIE_PHY_RX_ASIC_OUT 0x100D
diff --git a/drivers/pci/pcie-designware.h b/drivers/pci/pcie-designware.h
index 1659d8f60b..30bdc0ed6e 100644
--- a/drivers/pci/pcie-designware.h
+++ b/drivers/pci/pcie-designware.h
@@ -27,7 +27,7 @@
#define PORT_LINK_MODE_4_LANES (0x7 << 16)
#define PCIE_LINK_WIDTH_SPEED_CONTROL 0x80C
-#define PORT_LOGIC_SPEED_CHANGE (0x1 << 17)
+#define PORT_LOGIC_SPEED_CHANGE BIT(17)
#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)
@@ -40,8 +40,8 @@
#define PCIE_MSI_INTR0_STATUS 0x830
#define PCIE_ATU_VIEWPORT 0x900
-#define PCIE_ATU_REGION_INBOUND (0x1 << 31)
-#define PCIE_ATU_REGION_OUTBOUND (0x0 << 31)
+#define PCIE_ATU_REGION_INBOUND BIT(31)
+#define PCIE_ATU_REGION_OUTBOUND 0
#define PCIE_ATU_REGION_INDEX2 (0x2 << 0)
#define PCIE_ATU_REGION_INDEX1 (0x1 << 0)
#define PCIE_ATU_REGION_INDEX0 (0x0 << 0)
@@ -51,8 +51,8 @@
#define PCIE_ATU_TYPE_CFG0 (0x4 << 0)
#define PCIE_ATU_TYPE_CFG1 (0x5 << 0)
#define PCIE_ATU_CR2 0x908
-#define PCIE_ATU_ENABLE (0x1 << 31)
-#define PCIE_ATU_BAR_MODE_ENABLE (0x1 << 30)
+#define PCIE_ATU_ENABLE BIT(31)
+#define PCIE_ATU_BAR_MODE_ENABLE BIT(30)
#define PCIE_ATU_LOWER_BASE 0x90C
#define PCIE_ATU_UPPER_BASE 0x910
#define PCIE_ATU_LIMIT 0x914
@@ -92,7 +92,7 @@
#define PCIE_PHY_DEBUG_R1_LINK_IN_TRAINING (0x1 << 29)
#define PCIE_MISC_CONTROL_1_OFF 0x8BC
-#define PCIE_DBI_RO_WR_EN (0x1 << 0)
+#define PCIE_DBI_RO_WR_EN BIT(0)
/* PCIe Port Logic registers */
#define PLR_OFFSET 0x700
--
2.24.0
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 05/12] PCI: dwc: Enable iATU unroll for endpoint too
2019-11-27 11:20 [PATCH 00/12] Designware PCIe updates and Layerscape support Sascha Hauer
` (3 preceding siblings ...)
2019-11-27 11:20 ` [PATCH 04/12] PCI: dwc: Make use of BIT() in constant definitions Sascha Hauer
@ 2019-11-27 11:20 ` Sascha Hauer
2019-11-27 11:20 ` [PATCH 06/12] PCI: dwc: Fix ATU identification for designware version >= 4.80 Sascha Hauer
` (6 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Sascha Hauer @ 2019-11-27 11:20 UTC (permalink / raw)
To: Barebox List
Port of Linux commit a9f4c2d2f99ec85ebc734a5bfb21a2cf93c169ad
iatu_unroll_enabled flag is set only for Designware in host mode.
However iATU unroll can be applicable for endpoint mode too. Set
iatu_unroll_enabled flag in dw_pcie_setup() which is common for
both host mode and endpoint mode.
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
drivers/pci/pcie-designware-host.c | 19 -------------------
drivers/pci/pcie-designware.c | 19 +++++++++++++++++++
2 files changed, 19 insertions(+), 19 deletions(-)
diff --git a/drivers/pci/pcie-designware-host.c b/drivers/pci/pcie-designware-host.c
index f3d7c59a60..b2d46d38f8 100644
--- a/drivers/pci/pcie-designware-host.c
+++ b/drivers/pci/pcie-designware-host.c
@@ -340,17 +340,6 @@ static const struct pci_ops dw_pcie_ops = {
.write = dw_pcie_wr_conf,
};
-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;
@@ -381,14 +370,6 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
* 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");
-
- if (pci->iatu_unroll_enabled && !pci->atu_base)
- pci->atu_base = pci->dbi_base + DEFAULT_DBI_ATU_OFFSET;
-
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);
diff --git a/drivers/pci/pcie-designware.c b/drivers/pci/pcie-designware.c
index 9728964ec9..91aac8dec0 100644
--- a/drivers/pci/pcie-designware.c
+++ b/drivers/pci/pcie-designware.c
@@ -238,6 +238,17 @@ int dw_pcie_link_up(struct dw_pcie *pci)
!(val & PCIE_PHY_DEBUG_R1_LINK_IN_TRAINING));
}
+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(struct dw_pcie *pci)
{
int ret;
@@ -246,6 +257,14 @@ void dw_pcie_setup(struct dw_pcie *pci)
struct device_d *dev = pci->dev;
struct device_node *np = dev->device_node;
+ /* 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");
+
+ if (pci->iatu_unroll_enabled && !pci->atu_base)
+ pci->atu_base = pci->dbi_base + DEFAULT_DBI_ATU_OFFSET;
+
ret = of_property_read_u32(np, "num-lanes", &lanes);
if (ret)
lanes = 0;
--
2.24.0
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 06/12] PCI: dwc: Fix ATU identification for designware version >= 4.80
2019-11-27 11:20 [PATCH 00/12] Designware PCIe updates and Layerscape support Sascha Hauer
` (4 preceding siblings ...)
2019-11-27 11:20 ` [PATCH 05/12] PCI: dwc: Enable iATU unroll for endpoint too Sascha Hauer
@ 2019-11-27 11:20 ` Sascha Hauer
2019-11-27 11:20 ` [PATCH 07/12] PCI: dwc: imx6: Share PHY debug register definitions Sascha Hauer
` (5 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Sascha Hauer @ 2019-11-27 11:20 UTC (permalink / raw)
To: Barebox List
Port of Linux commit 2aadcb0cd39198833fabe1c45084f78686e71a6c
Synopsys designware version >= 4.80 uses a separate register space
for programming ATU. The current code identifies if there exists a
separate register space by accessing the register address of ATUs
in designware version < 4.80. Accessing this address results in
abort in the case of K2G.
Fix it here by adding "version" member to struct dw_pcie. This should be
set by platform specific drivers and designware core will use it to
identify if the platform has a separate ATU space. For platforms which
have not populated the version member, the old method of identification
will still be used.
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
drivers/pci/pcie-designware.c | 14 ++++++++------
drivers/pci/pcie-designware.h | 1 +
2 files changed, 9 insertions(+), 6 deletions(-)
diff --git a/drivers/pci/pcie-designware.c b/drivers/pci/pcie-designware.c
index 91aac8dec0..f9a759b8fd 100644
--- a/drivers/pci/pcie-designware.c
+++ b/drivers/pci/pcie-designware.c
@@ -257,13 +257,15 @@ void dw_pcie_setup(struct dw_pcie *pci)
struct device_d *dev = pci->dev;
struct device_node *np = dev->device_node;
- /* 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");
+ if (pci->version >= 0x480A || (!pci->version &&
+ dw_pcie_iatu_unroll_enabled(pci))) {
+ pci->iatu_unroll_enabled = true;
+ if (!pci->atu_base)
+ pci->atu_base = pci->dbi_base + DEFAULT_DBI_ATU_OFFSET;
+ }
+ dev_dbg(pci->dev, "iATU unroll: %s\n", pci->iatu_unroll_enabled ?
+ "enabled" : "disabled");
- if (pci->iatu_unroll_enabled && !pci->atu_base)
- pci->atu_base = pci->dbi_base + DEFAULT_DBI_ATU_OFFSET;
ret = of_property_read_u32(np, "num-lanes", &lanes);
if (ret)
diff --git a/drivers/pci/pcie-designware.h b/drivers/pci/pcie-designware.h
index 30bdc0ed6e..8cd48a27c1 100644
--- a/drivers/pci/pcie-designware.h
+++ b/drivers/pci/pcie-designware.h
@@ -164,6 +164,7 @@ struct dw_pcie {
u8 iatu_unroll_enabled;
struct pcie_port pp;
const struct dw_pcie_ops *ops;
+ unsigned int version;
};
#define to_dw_pcie_from_pp(port) container_of((port), struct dw_pcie, pp)
--
2.24.0
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 07/12] PCI: dwc: imx6: Share PHY debug register definitions
2019-11-27 11:20 [PATCH 00/12] Designware PCIe updates and Layerscape support Sascha Hauer
` (5 preceding siblings ...)
2019-11-27 11:20 ` [PATCH 06/12] PCI: dwc: Fix ATU identification for designware version >= 4.80 Sascha Hauer
@ 2019-11-27 11:20 ` Sascha Hauer
2019-11-27 11:20 ` [PATCH 08/12] PCI: dwc: Cleanup DBI,ATU read and write APIs Sascha Hauer
` (4 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Sascha Hauer @ 2019-11-27 11:20 UTC (permalink / raw)
To: Barebox List
Port of Linux commit 60ef4b072ba089440531287f72740d94ed1e8dd1
Both pcie-designware.c and pci-imx6.c contain custom definitions for
PHY debug registers R0/R1 and on top of that there's already a
definition for R0 in pcie-designware.h. Move all of the definitions to
pcie-designware.h. No functional change intended.
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Reviewed-by: Lucas Stach <l.stach@pengutronix.de>
Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Chris Healy <cphealy@gmail.com>
Cc: Lucas Stach <l.stach@pengutronix.de>
Cc: linux-kernel@vger.kernel.org
Cc: linux-pci@vger.kernel.org
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
drivers/pci/pci-imx6.c | 10 ++++------
drivers/pci/pcie-designware.c | 6 +++---
drivers/pci/pcie-designware.h | 7 +++++++
3 files changed, 14 insertions(+), 9 deletions(-)
diff --git a/drivers/pci/pci-imx6.c b/drivers/pci/pci-imx6.c
index 6cbae1e223..05df9c0f79 100644
--- a/drivers/pci/pci-imx6.c
+++ b/drivers/pci/pci-imx6.c
@@ -97,8 +97,6 @@ struct imx6_pcie {
#define PCIE_PL_PFLR (PL_OFFSET + 0x08)
#define PCIE_PL_PFLR_LINK_STATE_MASK (0x3f << 16)
#define PCIE_PL_PFLR_FORCE_LINK (1 << 15)
-#define PCIE_PHY_DEBUG_R0 (PL_OFFSET + 0x28)
-#define PCIE_PHY_DEBUG_R1_XMLH_LINK_IN_TRAINING (1 << 29)
#define PCIE_PHY_DEBUG_R1_XMLH_LINK_UP (1 << 4)
#define PCIE_PHY_CTRL (PL_OFFSET + 0x114)
@@ -635,8 +633,8 @@ static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie)
err_reset_phy:
dev_dbg(dev, "PHY DEBUG_R0=0x%08x DEBUG_R1=0x%08x\n",
- dw_pcie_readl_dbi(pci, PCIE_PHY_DEBUG_R0),
- dw_pcie_readl_dbi(pci, PCIE_PHY_DEBUG_R1));
+ dw_pcie_readl_dbi(pci, PCIE_PORT_DEBUG0),
+ dw_pcie_readl_dbi(pci, PCIE_PORT_DEBUG1));
imx6_pcie_reset_phy(imx6_pcie);
return ret;
@@ -658,8 +656,8 @@ static int imx6_pcie_host_init(struct pcie_port *pp)
static int imx6_pcie_link_up(struct dw_pcie *pci)
{
- return dw_pcie_readl_dbi(pci, PCIE_PHY_DEBUG_R1) &
- PCIE_PHY_DEBUG_R1_XMLH_LINK_UP;
+ return dw_pcie_readl_dbi(pci, PCIE_PORT_DEBUG1) &
+ PCIE_PORT_DEBUG1_LINK_UP;
}
static const struct dw_pcie_ops dw_pcie_ops = {
diff --git a/drivers/pci/pcie-designware.c b/drivers/pci/pcie-designware.c
index f9a759b8fd..106c3a017c 100644
--- a/drivers/pci/pcie-designware.c
+++ b/drivers/pci/pcie-designware.c
@@ -233,9 +233,9 @@ int dw_pcie_link_up(struct dw_pcie *pci)
if (pci->ops->link_up)
return pci->ops->link_up(pci);
- val = readl(pci->dbi_base + PCIE_PHY_DEBUG_R1);
- return ((val & PCIE_PHY_DEBUG_R1_LINK_UP) &&
- !(val & PCIE_PHY_DEBUG_R1_LINK_IN_TRAINING));
+ val = readl(pci->dbi_base + PCIE_PORT_DEBUG1);
+ return ((val & PCIE_PORT_DEBUG1_LINK_UP) &&
+ (!(val & PCIE_PORT_DEBUG1_LINK_IN_TRAINING)));
}
static u8 dw_pcie_iatu_unroll_enabled(struct dw_pcie *pci)
diff --git a/drivers/pci/pcie-designware.h b/drivers/pci/pcie-designware.h
index 8cd48a27c1..ebd0d8e16c 100644
--- a/drivers/pci/pcie-designware.h
+++ b/drivers/pci/pcie-designware.h
@@ -26,6 +26,13 @@
#define PORT_LINK_MODE_2_LANES (0x3 << 16)
#define PORT_LINK_MODE_4_LANES (0x7 << 16)
+#define PCIE_PORT_DEBUG0 0x728
+#define PORT_LOGIC_LTSSM_STATE_MASK 0x1f
+#define PORT_LOGIC_LTSSM_STATE_L0 0x11
+#define PCIE_PORT_DEBUG1 0x72C
+#define PCIE_PORT_DEBUG1_LINK_UP BIT(4)
+#define PCIE_PORT_DEBUG1_LINK_IN_TRAINING BIT(29)
+
#define PCIE_LINK_WIDTH_SPEED_CONTROL 0x80C
#define PORT_LOGIC_SPEED_CHANGE BIT(17)
#define PORT_LOGIC_LINK_WIDTH_MASK (0x1f << 8)
--
2.24.0
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 08/12] PCI: dwc: Cleanup DBI,ATU read and write APIs
2019-11-27 11:20 [PATCH 00/12] Designware PCIe updates and Layerscape support Sascha Hauer
` (6 preceding siblings ...)
2019-11-27 11:20 ` [PATCH 07/12] PCI: dwc: imx6: Share PHY debug register definitions Sascha Hauer
@ 2019-11-27 11:20 ` Sascha Hauer
2019-11-27 11:20 ` [PATCH 09/12] PCI: dwc: rename readl/writel_dbi ops to read/write_dbi Sascha Hauer
` (3 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Sascha Hauer @ 2019-11-27 11:20 UTC (permalink / raw)
To: Barebox List
Port of Linux commit 7bc082d7e97009f252bd432de5d476b0bcf3b266
Cleanup DBI read and write APIs by removing leading "__" (underscore)
from their names as there is no reason to have leading underscores
in the first place in the function definition.
Remove dbi/dbi2 base address parameters as the same behaviour can be
obtained through read and write APIs. Since dw_pcie_{readl/writel}_dbi()
APIs can't be used for ATU read/write as ATU base address could be
different from DBI base address, implement ATU read/write APIs using ATU
base address without using dw_pcie_{readl/writel}_dbi() APIs.
Signed-off-by: Vidya Sagar <vidyas@nvidia.com>
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Acked-by: Jingoo Han <jingoohan1@gmail.com>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
drivers/pci/pcie-designware.c | 43 ++++++++++++++++++++++++++++-------
drivers/pci/pcie-designware.h | 17 +++++++-------
2 files changed, 43 insertions(+), 17 deletions(-)
diff --git a/drivers/pci/pcie-designware.c b/drivers/pci/pcie-designware.c
index 106c3a017c..1da0947414 100644
--- a/drivers/pci/pcie-designware.c
+++ b/drivers/pci/pcie-designware.c
@@ -65,37 +65,64 @@ int dw_pcie_write(void __iomem *addr, int size, u32 val)
return PCIBIOS_SUCCESSFUL;
}
-u32 __dw_pcie_readl_dbi(struct dw_pcie *pci, void __iomem *base, u32 reg,
- size_t size)
+u32 dw_pcie_read_dbi(struct dw_pcie *pci, u32 reg, size_t size)
{
int ret;
u32 val;
if (pci->ops->readl_dbi)
- return pci->ops->readl_dbi(pci, base, reg, size);
+ return pci->ops->readl_dbi(pci, pci->dbi_base, reg, size);
- ret = dw_pcie_read(base + reg, size, &val);
+ ret = dw_pcie_read(pci->dbi_base + reg, size, &val);
if (ret)
dev_err(pci->dev, "Read DBI address failed\n");
return val;
}
-void __dw_pcie_writel_dbi(struct dw_pcie *pci, void __iomem *base, u32 reg,
- size_t size, u32 val)
+void dw_pcie_write_dbi(struct dw_pcie *pci, u32 reg, size_t size, u32 val)
{
int ret;
if (pci->ops->writel_dbi) {
- pci->ops->writel_dbi(pci, base, reg, size, val);
+ pci->ops->writel_dbi(pci, pci->dbi_base, reg, size, val);
return;
}
- ret = dw_pcie_write(base + reg, size, val);
+ ret = dw_pcie_write(pci->dbi_base + reg, size, val);
if (ret)
dev_err(pci->dev, "Write DBI address failed\n");
}
+u32 dw_pcie_read_atu(struct dw_pcie *pci, u32 reg, size_t size)
+{
+ int ret;
+ u32 val;
+
+ if (pci->ops->readl_dbi)
+ return pci->ops->readl_dbi(pci, pci->atu_base, reg, size);
+
+ ret = dw_pcie_read(pci->atu_base + reg, size, &val);
+ if (ret)
+ dev_err(pci->dev, "Read ATU address failed\n");
+
+ return val;
+}
+
+void dw_pcie_write_atu(struct dw_pcie *pci, u32 reg, size_t size, u32 val)
+{
+ int ret;
+
+ if (pci->ops->writel_dbi) {
+ pci->ops->writel_dbi(pci, pci->atu_base, reg, size, val);
+ return;
+ }
+
+ ret = dw_pcie_write(pci->atu_base + reg, size, val);
+ if (ret)
+ dev_err(pci->dev, "Write ATU address failed\n");
+}
+
static u32 dw_pcie_readl_ob_unroll(struct dw_pcie *pci, u32 index, u32 reg)
{
u32 offset = PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(index);
diff --git a/drivers/pci/pcie-designware.h b/drivers/pci/pcie-designware.h
index ebd0d8e16c..1ffeaa8d1d 100644
--- a/drivers/pci/pcie-designware.h
+++ b/drivers/pci/pcie-designware.h
@@ -180,11 +180,10 @@ int dw_pcie_read(void __iomem *addr, int size, u32 *val);
int dw_pcie_write(void __iomem *addr, int size, u32 val);
void dw_pcie_setup_rc(struct pcie_port *pp);
int dw_pcie_host_init(struct pcie_port *pp);
-
-u32 __dw_pcie_readl_dbi(struct dw_pcie *pci, void __iomem *addr, u32 reg,
- size_t size);
-void __dw_pcie_writel_dbi(struct dw_pcie *pci, void __iomem *addr, u32 reg,
- size_t size, u32 val);
+u32 dw_pcie_read_dbi(struct dw_pcie *pci, u32 reg, size_t size);
+void dw_pcie_write_dbi(struct dw_pcie *pci, u32 reg, size_t size, u32 val);
+u32 dw_pcie_read_atu(struct dw_pcie *pci, u32 reg, size_t size);
+void dw_pcie_write_atu(struct dw_pcie *pci, u32 reg, size_t size, 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,
@@ -196,22 +195,22 @@ void dw_pcie_setup(struct dw_pcie *pci);
static inline void dw_pcie_writel_dbi(struct dw_pcie *pci, u32 reg, u32 val)
{
- __dw_pcie_writel_dbi(pci, pci->dbi_base, reg, 0x4, val);
+ dw_pcie_write_dbi(pci, reg, 0x4, val);
}
static inline u32 dw_pcie_readl_dbi(struct dw_pcie *pci, u32 reg)
{
- return __dw_pcie_readl_dbi(pci, pci->dbi_base, reg, 0x4);
+ return dw_pcie_read_dbi(pci, reg, 0x4);
}
static inline void dw_pcie_writel_atu(struct dw_pcie *pci, u32 reg, u32 val)
{
- __dw_pcie_writel_dbi(pci, pci->atu_base, reg, 0x4, val);
+ dw_pcie_write_atu(pci, reg, 0x4, val);
}
static inline u32 dw_pcie_readl_atu(struct dw_pcie *pci, u32 reg)
{
- return __dw_pcie_readl_dbi(pci, pci->atu_base, reg, 0x4);
+ return dw_pcie_read_atu(pci, reg, 0x4);
}
static inline void dw_pcie_dbi_ro_wr_en(struct dw_pcie *pci)
--
2.24.0
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 09/12] PCI: dwc: rename readl/writel_dbi ops to read/write_dbi
2019-11-27 11:20 [PATCH 00/12] Designware PCIe updates and Layerscape support Sascha Hauer
` (7 preceding siblings ...)
2019-11-27 11:20 ` [PATCH 08/12] PCI: dwc: Cleanup DBI,ATU read and write APIs Sascha Hauer
@ 2019-11-27 11:20 ` Sascha Hauer
2019-11-27 11:20 ` [PATCH 10/12] PCI: dwc: Sync register definitions with Linux-5.4 Sascha Hauer
` (2 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Sascha Hauer @ 2019-11-27 11:20 UTC (permalink / raw)
To: Barebox List
struct dw_pcie_ops read/writel_dbi functions can read values of any
size, so with readl/writel they are misnamed. Rename them to read/write
which also matches the kernel driver.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
drivers/pci/pcie-designware.c | 16 ++++++++--------
drivers/pci/pcie-designware.h | 8 ++++----
2 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/drivers/pci/pcie-designware.c b/drivers/pci/pcie-designware.c
index 1da0947414..72deeee4ed 100644
--- a/drivers/pci/pcie-designware.c
+++ b/drivers/pci/pcie-designware.c
@@ -70,8 +70,8 @@ u32 dw_pcie_read_dbi(struct dw_pcie *pci, u32 reg, size_t size)
int ret;
u32 val;
- if (pci->ops->readl_dbi)
- return pci->ops->readl_dbi(pci, pci->dbi_base, reg, size);
+ if (pci->ops->read_dbi)
+ return pci->ops->read_dbi(pci, pci->dbi_base, reg, size);
ret = dw_pcie_read(pci->dbi_base + reg, size, &val);
if (ret)
@@ -84,8 +84,8 @@ void dw_pcie_write_dbi(struct dw_pcie *pci, u32 reg, size_t size, u32 val)
{
int ret;
- if (pci->ops->writel_dbi) {
- pci->ops->writel_dbi(pci, pci->dbi_base, reg, size, val);
+ if (pci->ops->write_dbi) {
+ pci->ops->write_dbi(pci, pci->dbi_base, reg, size, val);
return;
}
@@ -99,8 +99,8 @@ u32 dw_pcie_read_atu(struct dw_pcie *pci, u32 reg, size_t size)
int ret;
u32 val;
- if (pci->ops->readl_dbi)
- return pci->ops->readl_dbi(pci, pci->atu_base, reg, size);
+ if (pci->ops->read_dbi)
+ return pci->ops->read_dbi(pci, pci->atu_base, reg, size);
ret = dw_pcie_read(pci->atu_base + reg, size, &val);
if (ret)
@@ -113,8 +113,8 @@ void dw_pcie_write_atu(struct dw_pcie *pci, u32 reg, size_t size, u32 val)
{
int ret;
- if (pci->ops->writel_dbi) {
- pci->ops->writel_dbi(pci, pci->atu_base, reg, size, val);
+ if (pci->ops->write_dbi) {
+ pci->ops->write_dbi(pci, pci->atu_base, reg, size, val);
return;
}
diff --git a/drivers/pci/pcie-designware.h b/drivers/pci/pcie-designware.h
index 1ffeaa8d1d..449c72aeaa 100644
--- a/drivers/pci/pcie-designware.h
+++ b/drivers/pci/pcie-designware.h
@@ -155,10 +155,10 @@ struct pcie_port {
};
struct dw_pcie_ops {
- u32 (*readl_dbi)(struct dw_pcie *pcie, void __iomem *base, u32 reg,
- size_t size);
- void (*writel_dbi)(struct dw_pcie *pcie, void __iomem *base, u32 reg,
- size_t size, u32 val);
+ u32 (*read_dbi)(struct dw_pcie *pcie, void __iomem *base, u32 reg,
+ size_t size);
+ void (*write_dbi)(struct dw_pcie *pcie, void __iomem *base, u32 reg,
+ size_t size, u32 val);
int (*link_up)(struct dw_pcie *pcie);
};
--
2.24.0
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 10/12] PCI: dwc: Sync register definitions with Linux-5.4
2019-11-27 11:20 [PATCH 00/12] Designware PCIe updates and Layerscape support Sascha Hauer
` (8 preceding siblings ...)
2019-11-27 11:20 ` [PATCH 09/12] PCI: dwc: rename readl/writel_dbi ops to read/write_dbi Sascha Hauer
@ 2019-11-27 11:20 ` Sascha Hauer
2019-11-27 11:20 ` [PATCH 11/12] PCI: dwc: Return directly when num-lanes is not found Sascha Hauer
2019-11-27 11:20 ` [PATCH 12/12] PCI: Add layerscape PCIe driver Sascha Hauer
11 siblings, 0 replies; 13+ messages in thread
From: Sascha Hauer @ 2019-11-27 11:20 UTC (permalink / raw)
To: Barebox List
Update the dwc register definitions with Linux-5.4 to make further
syncinf with the Linux driver easier.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
drivers/pci/pcie-designware.h | 85 +++++++++++++++++++++--------------
1 file changed, 51 insertions(+), 34 deletions(-)
diff --git a/drivers/pci/pcie-designware.h b/drivers/pci/pcie-designware.h
index 449c72aeaa..de20654e42 100644
--- a/drivers/pci/pcie-designware.h
+++ b/drivers/pci/pcie-designware.h
@@ -11,6 +11,8 @@
#ifndef _PCIE_DESIGNWARE_H
#define _PCIE_DESIGNWARE_H
+#include <linux/bitfield.h>
+
/* Parameters for the waiting for link up routine */
#define LINK_WAIT_MAX_RETRIES 10
#define LINK_WAIT_USLEEP_MAX 100000
@@ -19,12 +21,14 @@
#define LINK_WAIT_MAX_IATU_RETRIES 5
#define LINK_WAIT_IATU_MAX 10000
-/* Synopsis specific PCIE configuration registers */
+/* Synopsys-specific PCIe configuration registers */
#define PCIE_PORT_LINK_CONTROL 0x710
-#define PORT_LINK_MODE_MASK (0x3f << 16)
-#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_MASK GENMASK(21, 16)
+#define PORT_LINK_MODE(n) FIELD_PREP(PORT_LINK_MODE_MASK, n)
+#define PORT_LINK_MODE_1_LANES PORT_LINK_MODE(0x1)
+#define PORT_LINK_MODE_2_LANES PORT_LINK_MODE(0x3)
+#define PORT_LINK_MODE_4_LANES PORT_LINK_MODE(0x7)
+#define PORT_LINK_MODE_8_LANES PORT_LINK_MODE(0xf)
#define PCIE_PORT_DEBUG0 0x728
#define PORT_LOGIC_LTSSM_STATE_MASK 0x1f
@@ -35,10 +39,12 @@
#define PCIE_LINK_WIDTH_SPEED_CONTROL 0x80C
#define PORT_LOGIC_SPEED_CHANGE BIT(17)
-#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_MASK GENMASK(12, 8)
+#define PORT_LOGIC_LINK_WIDTH(n) FIELD_PREP(PORT_LOGIC_LINK_WIDTH_MASK, n)
+#define PORT_LOGIC_LINK_WIDTH_1_LANES PORT_LOGIC_LINK_WIDTH(0x1)
+#define PORT_LOGIC_LINK_WIDTH_2_LANES PORT_LOGIC_LINK_WIDTH(0x2)
+#define PORT_LOGIC_LINK_WIDTH_4_LANES PORT_LOGIC_LINK_WIDTH(0x4)
+#define PORT_LOGIC_LINK_WIDTH_8_LANES PORT_LOGIC_LINK_WIDTH(0x8)
#define PCIE_MSI_ADDR_LO 0x820
#define PCIE_MSI_ADDR_HI 0x824
@@ -49,14 +55,14 @@
#define PCIE_ATU_VIEWPORT 0x900
#define PCIE_ATU_REGION_INBOUND BIT(31)
#define PCIE_ATU_REGION_OUTBOUND 0
-#define PCIE_ATU_REGION_INDEX2 (0x2 << 0)
-#define PCIE_ATU_REGION_INDEX1 (0x1 << 0)
-#define PCIE_ATU_REGION_INDEX0 (0x0 << 0)
+#define PCIE_ATU_REGION_INDEX2 0x2
+#define PCIE_ATU_REGION_INDEX1 0x1
+#define PCIE_ATU_REGION_INDEX0 0x0
#define PCIE_ATU_CR1 0x904
-#define PCIE_ATU_TYPE_MEM (0x0 << 0)
-#define PCIE_ATU_TYPE_IO (0x2 << 0)
-#define PCIE_ATU_TYPE_CFG0 (0x4 << 0)
-#define PCIE_ATU_TYPE_CFG1 (0x5 << 0)
+#define PCIE_ATU_TYPE_MEM 0x0
+#define PCIE_ATU_TYPE_IO 0x2
+#define PCIE_ATU_TYPE_CFG0 0x4
+#define PCIE_ATU_TYPE_CFG1 0x5
#define PCIE_ATU_CR2 0x908
#define PCIE_ATU_ENABLE BIT(31)
#define PCIE_ATU_BAR_MODE_ENABLE BIT(30)
@@ -64,19 +70,31 @@
#define PCIE_ATU_UPPER_BASE 0x910
#define PCIE_ATU_LIMIT 0x914
#define PCIE_ATU_LOWER_TARGET 0x918
-#define PCIE_ATU_BUS(x) (((x) & 0xff) << 24)
-#define PCIE_ATU_DEV(x) (((x) & 0x1f) << 19)
-#define PCIE_ATU_FUNC(x) (((x) & 0x7) << 16)
+#define PCIE_ATU_BUS(x) FIELD_PREP(GENMASK(31, 24), x)
+#define PCIE_ATU_DEV(x) FIELD_PREP(GENMASK(23, 19), x)
+#define PCIE_ATU_FUNC(x) FIELD_PREP(GENMASK(18, 16), x)
#define PCIE_ATU_UPPER_TARGET 0x91C
+#define PCIE_MISC_CONTROL_1_OFF 0x8BC
+#define PCIE_DBI_RO_WR_EN BIT(0)
+
+#define PCIE_PL_CHK_REG_CONTROL_STATUS 0xB20
+#define PCIE_PL_CHK_REG_CHK_REG_START BIT(0)
+#define PCIE_PL_CHK_REG_CHK_REG_CONTINUOUS BIT(1)
+#define PCIE_PL_CHK_REG_CHK_REG_COMPARISON_ERROR BIT(16)
+#define PCIE_PL_CHK_REG_CHK_REG_LOGIC_ERROR BIT(17)
+#define PCIE_PL_CHK_REG_CHK_REG_COMPLETE BIT(18)
+
+#define PCIE_PL_CHK_REG_ERR_ADDR 0xB28
+
/*
* iATU Unroll-specific register definitions
* From 4.80 core version the address translation will be made by unroll
*/
#define PCIE_ATU_UNR_REGION_CTRL1 0x00
#define PCIE_ATU_UNR_REGION_CTRL2 0x04
-#define PCIE_ATU_UNR_LOWER_BASE 0x08
-#define PCIE_ATU_UNR_UPPER_BASE 0x0C
+#define PCIE_ATU_UNR_LOWER_BASE 0x08
+#define PCIE_ATU_UNR_UPPER_BASE 0x0C
#define PCIE_ATU_UNR_LIMIT 0x10
#define PCIE_ATU_UNR_LOWER_TARGET 0x14
#define PCIE_ATU_UNR_UPPER_TARGET 0x18
@@ -90,22 +108,21 @@
#define DEFAULT_DBI_ATU_OFFSET (0x3 << 20)
/* Register address builder */
-#define PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(region) ((region) << 9)
+#define PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(region) \
+ ((region) << 9)
-/* PCIe Port Logic registers */
-#define PLR_OFFSET 0x700
-#define PCIE_PHY_DEBUG_R1 (PLR_OFFSET + 0x2c)
-#define PCIE_PHY_DEBUG_R1_LINK_UP (0x1 << 4)
-#define PCIE_PHY_DEBUG_R1_LINK_IN_TRAINING (0x1 << 29)
+#define PCIE_GET_ATU_INB_UNR_REG_OFFSET(region) \
+ (((region) << 9) | BIT(8))
-#define PCIE_MISC_CONTROL_1_OFF 0x8BC
-#define PCIE_DBI_RO_WR_EN BIT(0)
+#define MAX_MSI_IRQS 256
+#define MAX_MSI_IRQS_PER_CTRL 32
+#define MAX_MSI_CTRLS (MAX_MSI_IRQS / MAX_MSI_IRQS_PER_CTRL)
+#define MSI_REG_CTRL_BLOCK_SIZE 12
+#define MSI_DEF_NUM_VECTORS 32
-/* PCIe Port Logic registers */
-#define PLR_OFFSET 0x700
-#define PCIE_PHY_DEBUG_R1 (PLR_OFFSET + 0x2c)
-#define PCIE_PHY_DEBUG_R1_LINK_UP (0x1 << 4)
-#define PCIE_PHY_DEBUG_R1_LINK_IN_TRAINING (0x1 << 29)
+/* Maximum number of inbound/outbound iATUs */
+#define MAX_IATU_IN 256
+#define MAX_IATU_OUT 256
struct pcie_port;
struct dw_pcie;
--
2.24.0
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 11/12] PCI: dwc: Return directly when num-lanes is not found
2019-11-27 11:20 [PATCH 00/12] Designware PCIe updates and Layerscape support Sascha Hauer
` (9 preceding siblings ...)
2019-11-27 11:20 ` [PATCH 10/12] PCI: dwc: Sync register definitions with Linux-5.4 Sascha Hauer
@ 2019-11-27 11:20 ` Sascha Hauer
2019-11-27 11:20 ` [PATCH 12/12] PCI: Add layerscape PCIe driver Sascha Hauer
11 siblings, 0 replies; 13+ messages in thread
From: Sascha Hauer @ 2019-11-27 11:20 UTC (permalink / raw)
To: Barebox List
Port of Linux commit 66de33f09fd97201847de7e1e2ec8a117242e1d6
The num-lanes is optional since it is not needed on some platforms
that bring up the link in firmware.
The link programming is based on the num-lanes properties (which is
optional); if it is not present code must return instead of fiddling
with the lanes value to print an error message.
Signed-off-by: Hou Zhiqiang <Zhiqiang.Hou@nxp.com>
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Reviewed-by: Andrew Murray <andrew.murray@arm.com>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
drivers/pci/pcie-designware.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/pci/pcie-designware.c b/drivers/pci/pcie-designware.c
index 72deeee4ed..e2007dba6d 100644
--- a/drivers/pci/pcie-designware.c
+++ b/drivers/pci/pcie-designware.c
@@ -295,8 +295,10 @@ void dw_pcie_setup(struct dw_pcie *pci)
ret = of_property_read_u32(np, "num-lanes", &lanes);
- if (ret)
- lanes = 0;
+ if (ret) {
+ dev_dbg(pci->dev, "property num-lanes isn't found\n");
+ return;
+ }
/* Set the number of lanes */
val = dw_pcie_readl_dbi(pci, PCIE_PORT_LINK_CONTROL);
--
2.24.0
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 12/12] PCI: Add layerscape PCIe driver
2019-11-27 11:20 [PATCH 00/12] Designware PCIe updates and Layerscape support Sascha Hauer
` (10 preceding siblings ...)
2019-11-27 11:20 ` [PATCH 11/12] PCI: dwc: Return directly when num-lanes is not found Sascha Hauer
@ 2019-11-27 11:20 ` Sascha Hauer
11 siblings, 0 replies; 13+ messages in thread
From: Sascha Hauer @ 2019-11-27 11:20 UTC (permalink / raw)
To: Barebox List
This adds support for the designware based PCIe controller found on
Layerscape SoCs. The driver is based on Linux-5.4. The device tree
fixups have been taken from U-Boot 2019.10.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
arch/arm/Kconfig | 1 +
drivers/pci/Kconfig | 7 +
drivers/pci/Makefile | 1 +
drivers/pci/pci-layerscape.c | 484 +++++++++++++++++++++++++++++++++++
4 files changed, 493 insertions(+)
create mode 100644 drivers/pci/pci-layerscape.c
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 9589a6a511..a4a4e03a56 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -106,6 +106,7 @@ config ARCH_LAYERSCAPE
select COMMON_CLK
select CLKDEV_LOOKUP
select COMMON_CLK_OF_PROVIDER
+ select HW_HAS_PCI
config ARCH_MVEBU
bool "Marvell EBU platforms"
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 44a89d005f..025c418f2b 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -47,6 +47,13 @@ config PCI_IMX6
select OF_PCI
select PCI
+config PCI_LAYERSCAPE
+ bool "Freescale Layerscape PCIe controller"
+ depends on ARCH_LAYERSCAPE
+ select PCIE_DW
+ select OF_PCI
+ select PCI
+
endmenu
endif
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 562304c65d..3ca6708657 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -11,3 +11,4 @@ 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 pcie-designware-host.o
obj-$(CONFIG_PCI_IMX6) += pci-imx6.o
+obj-$(CONFIG_PCI_LAYERSCAPE) += pci-layerscape.o
diff --git a/drivers/pci/pci-layerscape.c b/drivers/pci/pci-layerscape.c
new file mode 100644
index 0000000000..ccdc025c2e
--- /dev/null
+++ b/drivers/pci/pci-layerscape.c
@@ -0,0 +1,484 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PCIe host controller driver for Freescale Layerscape SoCs
+ *
+ * Copyright (C) 2014 Freescale Semiconductor.
+ *
+ * Author: Minghuan Lian <Minghuan.Lian@freescale.com>
+ */
+
+#include <common.h>
+#include <clock.h>
+#include <abort.h>
+#include <malloc.h>
+#include <io.h>
+#include <init.h>
+#include <gpio.h>
+#include <asm/mmu.h>
+#include <of_gpio.h>
+#include <of_device.h>
+#include <linux/clk.h>
+#include <linux/kernel.h>
+#include <of_address.h>
+#include <of_pci.h>
+#include <regmap.h>
+#include <mfd/syscon.h>
+#include <linux/pci.h>
+#include <linux/phy/phy.h>
+#include <linux/reset.h>
+#include <linux/sizes.h>
+
+#include "pcie-designware.h"
+
+/* PEX1/2 Misc Ports Status Register */
+#define SCFG_PEXMSCPORTSR(pex_idx) (0x94 + (pex_idx) * 4)
+#define LTSSM_STATE_SHIFT 20
+#define LTSSM_STATE_MASK 0x3f
+#define LTSSM_PCIE_L0 0x11 /* L0 state */
+
+/* PEX Internal Configuration Registers */
+#define PCIE_STRFMR1 0x71c /* Symbol Timer & Filter Mask Register1 */
+#define PCIE_ABSERR 0x8d0 /* Bridge Slave Error Response Register */
+#define PCIE_ABSERR_SETTING 0x9401 /* Forward error of non-posted request */
+
+#define PCIE_IATU_NUM 6
+
+#define PCIE_LUT_UDR(n) (0x800 + (n) * 8)
+#define PCIE_LUT_ENABLE (1 << 31)
+#define PCIE_LUT_LDR(n) (0x804 + (n) * 8)
+
+struct ls_pcie_drvdata {
+ u32 lut_offset;
+ u32 ltssm_shift;
+ u32 lut_dbg;
+ int pex_stream_id_start;
+ int pex_stream_id_end;
+ const struct dw_pcie_host_ops *ops;
+ const struct dw_pcie_ops *dw_pcie_ops;
+};
+
+struct ls_pcie {
+ struct dw_pcie pci;
+ void __iomem *lut;
+ struct regmap *scfg;
+ const char *compatible;
+ const struct ls_pcie_drvdata *drvdata;
+ int index;
+ int next_lut_index;
+};
+
+static struct ls_pcie *to_ls_pcie(struct dw_pcie *pci)
+{
+ return container_of(pci, struct ls_pcie, pci);
+}
+
+static u32 lut_readl(struct ls_pcie *pcie, unsigned int offset)
+{
+ return in_be32(pcie->lut + offset);
+}
+
+static void lut_writel(struct ls_pcie *pcie, unsigned int value,
+ unsigned int offset)
+{
+ out_be32(pcie->lut + offset, value);
+}
+
+static int ls_pcie_next_streamid(struct ls_pcie *pcie)
+{
+ static int next_stream_id;
+ int first = pcie->drvdata->pex_stream_id_start;
+ int last = pcie->drvdata->pex_stream_id_end;
+ int current = next_stream_id + first;
+
+ if (current > last)
+ return -EINVAL;
+
+ next_stream_id++;
+
+ return current;
+}
+
+#define PCIE_LUT_ENTRY_COUNT 32
+
+static int ls_pcie_next_lut_index(struct ls_pcie *pcie)
+{
+ if (pcie->next_lut_index < PCIE_LUT_ENTRY_COUNT)
+ return pcie->next_lut_index++;
+ else
+ return -ENOSPC; /* LUT is full */
+}
+
+static void ls_pcie_lut_set_mapping(struct ls_pcie *pcie, int index, u32 devid,
+ u32 stream_id)
+{
+ /* leave mask as all zeroes, want to match all bits */
+ lut_writel(pcie, devid << 16, PCIE_LUT_UDR(index));
+ lut_writel(pcie, stream_id | PCIE_LUT_ENABLE, PCIE_LUT_LDR(index));
+}
+
+static bool ls_pcie_is_bridge(struct ls_pcie *pcie)
+{
+ struct dw_pcie *pci = &pcie->pci;
+ u32 header_type;
+
+ header_type = ioread8(pci->dbi_base + PCI_HEADER_TYPE);
+ header_type &= 0x7f;
+
+ return header_type == PCI_HEADER_TYPE_BRIDGE;
+}
+
+/* Clear multi-function bit */
+static void ls_pcie_clear_multifunction(struct ls_pcie *pcie)
+{
+ struct dw_pcie *pci = &pcie->pci;
+
+ iowrite8(PCI_HEADER_TYPE_BRIDGE, pci->dbi_base + PCI_HEADER_TYPE);
+}
+
+/* Drop MSG TLP except for Vendor MSG */
+static void ls_pcie_drop_msg_tlp(struct ls_pcie *pcie)
+{
+ u32 val;
+ struct dw_pcie *pci = &pcie->pci;
+
+ val = ioread32(pci->dbi_base + PCIE_STRFMR1);
+ val &= 0xDFFFFFFF;
+ iowrite32(val, pci->dbi_base + PCIE_STRFMR1);
+}
+
+static void ls_pcie_disable_outbound_atus(struct ls_pcie *pcie)
+{
+ int i;
+
+ for (i = 0; i < PCIE_IATU_NUM; i++)
+ dw_pcie_disable_atu(&pcie->pci, i, DW_PCIE_REGION_OUTBOUND);
+}
+
+static int ls1021_pcie_link_up(struct dw_pcie *pci)
+{
+ u32 state;
+ struct ls_pcie *pcie = to_ls_pcie(pci);
+
+ if (!pcie->scfg)
+ return 0;
+
+ regmap_read(pcie->scfg, SCFG_PEXMSCPORTSR(pcie->index), &state);
+ state = (state >> LTSSM_STATE_SHIFT) & LTSSM_STATE_MASK;
+
+ if (state < LTSSM_PCIE_L0)
+ return 0;
+
+ return 1;
+}
+
+static int ls_pcie_link_up(struct dw_pcie *pci)
+{
+ struct ls_pcie *pcie = to_ls_pcie(pci);
+ u32 state;
+
+ state = (ioread32(pcie->lut + pcie->drvdata->lut_dbg) >>
+ pcie->drvdata->ltssm_shift) &
+ LTSSM_STATE_MASK;
+
+ if (state < LTSSM_PCIE_L0)
+ return 0;
+
+ return 1;
+}
+
+/* Forward error response of outbound non-posted requests */
+static void ls_pcie_fix_error_response(struct ls_pcie *pcie)
+{
+ struct dw_pcie *pci = &pcie->pci;
+
+ iowrite32(PCIE_ABSERR_SETTING, pci->dbi_base + PCIE_ABSERR);
+}
+
+static int ls_pcie_host_init(struct pcie_port *pp)
+{
+ struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+ struct ls_pcie *pcie = to_ls_pcie(pci);
+
+ /*
+ * Disable outbound windows configured by the bootloader to avoid
+ * one transaction hitting multiple outbound windows.
+ * dw_pcie_setup_rc() will reconfigure the outbound windows.
+ */
+ ls_pcie_disable_outbound_atus(pcie);
+ ls_pcie_fix_error_response(pcie);
+
+ dw_pcie_dbi_ro_wr_en(pci);
+ ls_pcie_clear_multifunction(pcie);
+ dw_pcie_dbi_ro_wr_dis(pci);
+
+ ls_pcie_drop_msg_tlp(pcie);
+
+ dw_pcie_setup_rc(pp);
+
+ return 0;
+}
+
+static int ls1021_pcie_host_init(struct pcie_port *pp)
+{
+ struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+ struct ls_pcie *pcie = to_ls_pcie(pci);
+ struct device_d *dev = pci->dev;
+ u32 index[2];
+ int ret;
+
+ pcie->scfg = syscon_regmap_lookup_by_phandle(dev->device_node,
+ "fsl,pcie-scfg");
+ if (IS_ERR(pcie->scfg)) {
+ ret = PTR_ERR(pcie->scfg);
+ dev_err(dev, "No syscfg phandle specified\n");
+ pcie->scfg = NULL;
+ return ret;
+ }
+
+ if (of_property_read_u32_array(dev->device_node,
+ "fsl,pcie-scfg", index, 2)) {
+ pcie->scfg = NULL;
+ return -EINVAL;
+ }
+ pcie->index = index[1];
+
+ return ls_pcie_host_init(pp);
+}
+
+static const struct dw_pcie_host_ops ls1021_pcie_host_ops = {
+ .host_init = ls1021_pcie_host_init,
+};
+
+static const struct dw_pcie_host_ops ls_pcie_host_ops = {
+ .host_init = ls_pcie_host_init,
+};
+
+static const struct dw_pcie_ops dw_ls1021_pcie_ops = {
+ .link_up = ls1021_pcie_link_up,
+};
+
+static const struct dw_pcie_ops dw_ls_pcie_ops = {
+ .link_up = ls_pcie_link_up,
+};
+
+static const struct ls_pcie_drvdata ls1021_drvdata = {
+ .ops = &ls1021_pcie_host_ops,
+ .dw_pcie_ops = &dw_ls1021_pcie_ops,
+};
+
+static const struct ls_pcie_drvdata ls1043_drvdata = {
+ .lut_offset = 0x10000,
+ .ltssm_shift = 24,
+ .lut_dbg = 0x7fc,
+ .pex_stream_id_start = 11,
+ .pex_stream_id_end = 26,
+ .ops = &ls_pcie_host_ops,
+ .dw_pcie_ops = &dw_ls_pcie_ops,
+};
+
+static const struct ls_pcie_drvdata ls1046_drvdata = {
+ .lut_offset = 0x80000,
+ .ltssm_shift = 24,
+ .lut_dbg = 0x407fc,
+ .pex_stream_id_start = 11,
+ .pex_stream_id_end = 26,
+ .ops = &ls_pcie_host_ops,
+ .dw_pcie_ops = &dw_ls_pcie_ops,
+};
+
+static const struct ls_pcie_drvdata ls2080_drvdata = {
+ .lut_offset = 0x80000,
+ .ltssm_shift = 0,
+ .lut_dbg = 0x7fc,
+ .pex_stream_id_start = 7,
+ .pex_stream_id_end = 22,
+ .ops = &ls_pcie_host_ops,
+ .dw_pcie_ops = &dw_ls_pcie_ops,
+};
+
+static const struct ls_pcie_drvdata ls2088_drvdata = {
+ .lut_offset = 0x80000,
+ .ltssm_shift = 0,
+ .lut_dbg = 0x407fc,
+ .pex_stream_id_start = 7,
+ .pex_stream_id_end = 18,
+ .ops = &ls_pcie_host_ops,
+ .dw_pcie_ops = &dw_ls_pcie_ops,
+};
+
+static const struct of_device_id ls_pcie_of_match[] = {
+ { .compatible = "fsl,ls1012a-pcie", .data = &ls1046_drvdata },
+ { .compatible = "fsl,ls1021a-pcie", .data = &ls1021_drvdata },
+ { .compatible = "fsl,ls1043a-pcie", .data = &ls1043_drvdata },
+ { .compatible = "fsl,ls1046a-pcie", .data = &ls1046_drvdata },
+ { .compatible = "fsl,ls2080a-pcie", .data = &ls2080_drvdata },
+ { .compatible = "fsl,ls2085a-pcie", .data = &ls2080_drvdata },
+ { .compatible = "fsl,ls2088a-pcie", .data = &ls2088_drvdata },
+ { .compatible = "fsl,ls1088a-pcie", .data = &ls2088_drvdata },
+ { },
+};
+
+static int __init ls_add_pcie_port(struct ls_pcie *pcie)
+{
+ struct dw_pcie *pci = &pcie->pci;
+ struct pcie_port *pp = &pci->pp;
+ struct device_d *dev = pci->dev;
+ int ret;
+
+ pp->ops = pcie->drvdata->ops;
+
+ ret = dw_pcie_host_init(pp);
+ if (ret) {
+ dev_err(dev, "failed to initialize host\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int ls_pcie_of_fixup(struct device_node *root, void *ctx)
+{
+ struct ls_pcie *pcie = ctx;
+ struct device_d *dev = pcie->pci.dev;
+ struct device_node *np;
+ char *name;
+ u32 *arr, phandle;
+ int nluts;
+ int ret, i;
+ u32 devid, stream_id;
+
+ name = of_get_reproducible_name(dev->device_node);
+
+ np = root;
+ do {
+ np = of_find_node_by_reproducible_name(np, name);
+ if (!np)
+ return -ENODEV;
+ } while (!of_device_is_compatible(np, pcie->compatible));
+
+ nluts = pcie->next_lut_index;
+
+ ret = of_property_read_u32(np, "msi-parent", &phandle);
+ if (ret) {
+ dev_err(pcie->pci.dev, "Unable to get \"msi-parent\" phandle\n");
+ return ret;
+ }
+
+ arr = xmalloc(nluts * sizeof(u32) * 4);
+
+ for (i = 0; i < nluts; i++) {
+ u32 udr = lut_readl(pcie, PCIE_LUT_UDR(i));
+ u32 ldr = lut_readl(pcie, PCIE_LUT_LDR(i));
+
+ if (!(ldr & PCIE_LUT_ENABLE))
+ break;
+
+ devid = udr >> 16;
+ stream_id = ldr & 0x7fff;
+
+ arr[i * 4] = devid;
+ arr[i * 4 + 1] = phandle;
+ arr[i * 4 + 2] = stream_id;
+ arr[i * 4 + 3] = 1;
+ }
+
+ /*
+ * An msi-map is a property to be added to the pci controller
+ * node. It is a table, where each entry consists of 4 fields
+ * e.g.:
+ *
+ * msi-map = <[devid] [phandle-to-msi-ctrl] [stream-id] [count]
+ * [devid] [phandle-to-msi-ctrl] [stream-id] [count]>;
+ */
+
+ ret = of_property_write_u32_array(np, "msi-map", arr, nluts * 4);
+ if (ret)
+ goto out;
+
+ of_device_enable(np);
+
+ ret = 0;
+
+out:
+ free(arr);
+ return ret;
+}
+
+static int __init ls_pcie_probe(struct device_d *dev)
+{
+ struct dw_pcie *pci;
+ struct ls_pcie *pcie;
+ struct resource *dbi_base;
+ const struct of_device_id *match;
+ int ret;
+
+ pcie = xzalloc(sizeof(*pcie));
+ if (!pcie)
+ return -ENOMEM;
+
+ pci = &pcie->pci;
+
+ match = of_match_device(dev->driver->of_compatible, dev);
+ if (!match)
+ return -ENODEV;
+
+ pcie->drvdata = match->data;
+ pcie->compatible = match->compatible;
+
+ pci->dev = dev;
+ pci->ops = pcie->drvdata->dw_pcie_ops;
+
+ dbi_base = dev_request_mem_resource(dev, 0);
+ if (IS_ERR(dbi_base))
+ return PTR_ERR(dbi_base);
+
+ pci->dbi_base = IOMEM(dbi_base->start);
+
+ pcie->lut = pci->dbi_base + pcie->drvdata->lut_offset;
+
+ if (!ls_pcie_is_bridge(pcie))
+ return -ENODEV;
+
+ dev->priv = pcie;
+
+ ret = ls_add_pcie_port(pcie);
+ if (ret < 0)
+ return ret;
+
+ of_register_fixup(ls_pcie_of_fixup, pcie);
+
+ return 0;
+}
+
+static struct driver_d ls_pcie_driver = {
+ .name = "layerscape-pcie",
+ .of_compatible = DRV_OF_COMPAT(ls_pcie_of_match),
+ .probe = ls_pcie_probe,
+};
+device_platform_driver(ls_pcie_driver);
+
+static void ls_pcie_fixup(struct pci_dev *pcidev)
+{
+ struct pci_bus *bus = pcidev->bus, *p;
+ struct pci_controller *host = bus->host;
+ struct pcie_port *pp = container_of(host, struct pcie_port, pci);
+ struct dw_pcie *dwpcie = container_of(pp, struct dw_pcie, pp);
+ struct ls_pcie *lspcie = container_of(dwpcie, struct ls_pcie, pci);
+ int stream_id, index;
+ int base_bus_num = 0;
+
+ stream_id = ls_pcie_next_streamid(lspcie);
+ index = ls_pcie_next_lut_index(lspcie);
+
+ p = pcidev->bus;
+ while (p) {
+ base_bus_num = p->number;
+ p = p->parent_bus;
+ }
+
+ ls_pcie_lut_set_mapping(lspcie, index,
+ (pcidev->bus->number - base_bus_num) << 8 | pcidev->devfn,
+ stream_id);
+}
+
+DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, ls_pcie_fixup);
--
2.24.0
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 13+ messages in thread