All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/5] PCI: MediaTek: Add support for new generation host controller
@ 2017-07-27  2:58 ` honghui.zhang
  0 siblings, 0 replies; 80+ messages in thread
From: honghui.zhang @ 2017-07-27  2:58 UTC (permalink / raw)
  To: bhelgaas, robh, robh+dt, matthias.bgg, linux-arm-kernel,
	linux-mediatek, linux-pci, linux-kernel, devicetree,
	yingjoe.chen, eddie.huang, ryder.lee
  Cc: honghui.zhang, hongkun.cao, youlin.pei, yong.wu, yt.shen,
	sean.wang, xinping.qian

From: Honghui Zhang <honghui.zhang@mediatek.com>

MediaTek's PCIe host controller has two generation HWs, the new
generation HW has two root ports, it shares most probing flow with the
legacy controller. But the read/write config space logical is different
from the lagacy controller.
This patchset abstract the common probing flow, and add support for the
new generation controller.

Changes since v1:
 - Fix build warnings in arm arch.
 - Using SoC specific compatible instead of generic compatible.
 - Add devicetree binding example for mt7622.
 - Unified the register define names with PCIE_ prefix.
 - Cleanup some un-necessary condition determine when starup port.
 - minor code cleanups.

Ryder Lee (5):
  PCI: mediatek: Add a structure to abstract the controller generations
  PCI: mediatek: switch to use platform_get_resource_byname()
  dt-bindings: PCI: rename and cleanup MediaTek binding text
  PCI: mediatek: Add new generation controller support
  dt-bindings: PCI: add support for new generation controller

 .../bindings/pci/mediatek,mt7623-pcie.txt          | 130 -----
 .../devicetree/bindings/pci/mediatek-pcie.txt      | 283 ++++++++++
 drivers/pci/host/Kconfig                           |   5 +-
 drivers/pci/host/pcie-mediatek.c                   | 588 +++++++++++++++++++--
 4 files changed, 829 insertions(+), 177 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/pci/mediatek,mt7623-pcie.txt
 create mode 100644 Documentation/devicetree/bindings/pci/mediatek-pcie.txt

-- 
2.6.4

^ permalink raw reply	[flat|nested] 80+ messages in thread

* [PATCH v2 0/5] PCI: MediaTek: Add support for new generation host controller
@ 2017-07-27  2:58 ` honghui.zhang
  0 siblings, 0 replies; 80+ messages in thread
From: honghui.zhang @ 2017-07-27  2:58 UTC (permalink / raw)
  To: bhelgaas, robh, robh+dt, matthias.bgg, linux-arm-kernel,
	linux-mediatek, linux-pci, linux-kernel, devicetree,
	yingjoe.chen, eddie.huang, ryder.lee
  Cc: honghui.zhang, hongkun.cao, youlin.pei, yong.wu, yt.shen,
	sean.wang, xinping.qian

From: Honghui Zhang <honghui.zhang@mediatek.com>

MediaTek's PCIe host controller has two generation HWs, the new
generation HW has two root ports, it shares most probing flow with the
legacy controller. But the read/write config space logical is different
from the lagacy controller.
This patchset abstract the common probing flow, and add support for the
new generation controller.

Changes since v1:
 - Fix build warnings in arm arch.
 - Using SoC specific compatible instead of generic compatible.
 - Add devicetree binding example for mt7622.
 - Unified the register define names with PCIE_ prefix.
 - Cleanup some un-necessary condition determine when starup port.
 - minor code cleanups.

Ryder Lee (5):
  PCI: mediatek: Add a structure to abstract the controller generations
  PCI: mediatek: switch to use platform_get_resource_byname()
  dt-bindings: PCI: rename and cleanup MediaTek binding text
  PCI: mediatek: Add new generation controller support
  dt-bindings: PCI: add support for new generation controller

 .../bindings/pci/mediatek,mt7623-pcie.txt          | 130 -----
 .../devicetree/bindings/pci/mediatek-pcie.txt      | 283 ++++++++++
 drivers/pci/host/Kconfig                           |   5 +-
 drivers/pci/host/pcie-mediatek.c                   | 588 +++++++++++++++++++--
 4 files changed, 829 insertions(+), 177 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/pci/mediatek,mt7623-pcie.txt
 create mode 100644 Documentation/devicetree/bindings/pci/mediatek-pcie.txt

-- 
2.6.4

^ permalink raw reply	[flat|nested] 80+ messages in thread

* [PATCH v2 0/5] PCI: MediaTek: Add support for new generation host controller
@ 2017-07-27  2:58 ` honghui.zhang
  0 siblings, 0 replies; 80+ messages in thread
From: honghui.zhang @ 2017-07-27  2:58 UTC (permalink / raw)
  To: bhelgaas, robh, robh+dt, matthias.bgg, linux-arm-kernel,
	linux-mediatek, linux-pci, linux-kernel, devicetree,
	yingjoe.chen, eddie.huang, ryder.lee
  Cc: youlin.pei, hongkun.cao, sean.wang, xinping.qian, honghui.zhang,
	yt.shen, yong.wu

From: Honghui Zhang <honghui.zhang@mediatek.com>

MediaTek's PCIe host controller has two generation HWs, the new
generation HW has two root ports, it shares most probing flow with the
legacy controller. But the read/write config space logical is different
from the lagacy controller.
This patchset abstract the common probing flow, and add support for the
new generation controller.

Changes since v1:
 - Fix build warnings in arm arch.
 - Using SoC specific compatible instead of generic compatible.
 - Add devicetree binding example for mt7622.
 - Unified the register define names with PCIE_ prefix.
 - Cleanup some un-necessary condition determine when starup port.
 - minor code cleanups.

Ryder Lee (5):
  PCI: mediatek: Add a structure to abstract the controller generations
  PCI: mediatek: switch to use platform_get_resource_byname()
  dt-bindings: PCI: rename and cleanup MediaTek binding text
  PCI: mediatek: Add new generation controller support
  dt-bindings: PCI: add support for new generation controller

 .../bindings/pci/mediatek,mt7623-pcie.txt          | 130 -----
 .../devicetree/bindings/pci/mediatek-pcie.txt      | 283 ++++++++++
 drivers/pci/host/Kconfig                           |   5 +-
 drivers/pci/host/pcie-mediatek.c                   | 588 +++++++++++++++++++--
 4 files changed, 829 insertions(+), 177 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/pci/mediatek,mt7623-pcie.txt
 create mode 100644 Documentation/devicetree/bindings/pci/mediatek-pcie.txt

-- 
2.6.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 80+ messages in thread

* [PATCH v2 0/5] PCI: MediaTek: Add support for new generation host controller
@ 2017-07-27  2:58 ` honghui.zhang
  0 siblings, 0 replies; 80+ messages in thread
From: honghui.zhang at mediatek.com @ 2017-07-27  2:58 UTC (permalink / raw)
  To: linux-arm-kernel

From: Honghui Zhang <honghui.zhang@mediatek.com>

MediaTek's PCIe host controller has two generation HWs, the new
generation HW has two root ports, it shares most probing flow with the
legacy controller. But the read/write config space logical is different
from the lagacy controller.
This patchset abstract the common probing flow, and add support for the
new generation controller.

Changes since v1:
 - Fix build warnings in arm arch.
 - Using SoC specific compatible instead of generic compatible.
 - Add devicetree binding example for mt7622.
 - Unified the register define names with PCIE_ prefix.
 - Cleanup some un-necessary condition determine when starup port.
 - minor code cleanups.

Ryder Lee (5):
  PCI: mediatek: Add a structure to abstract the controller generations
  PCI: mediatek: switch to use platform_get_resource_byname()
  dt-bindings: PCI: rename and cleanup MediaTek binding text
  PCI: mediatek: Add new generation controller support
  dt-bindings: PCI: add support for new generation controller

 .../bindings/pci/mediatek,mt7623-pcie.txt          | 130 -----
 .../devicetree/bindings/pci/mediatek-pcie.txt      | 283 ++++++++++
 drivers/pci/host/Kconfig                           |   5 +-
 drivers/pci/host/pcie-mediatek.c                   | 588 +++++++++++++++++++--
 4 files changed, 829 insertions(+), 177 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/pci/mediatek,mt7623-pcie.txt
 create mode 100644 Documentation/devicetree/bindings/pci/mediatek-pcie.txt

-- 
2.6.4

^ permalink raw reply	[flat|nested] 80+ messages in thread

* [PATCH v2 1/5] PCI: mediatek: Add a structure to abstract the controller generations
  2017-07-27  2:58 ` honghui.zhang
  (?)
@ 2017-07-27  2:58   ` honghui.zhang
  -1 siblings, 0 replies; 80+ messages in thread
From: honghui.zhang @ 2017-07-27  2:58 UTC (permalink / raw)
  To: bhelgaas, robh, robh+dt, matthias.bgg, linux-arm-kernel,
	linux-mediatek, linux-pci, linux-kernel, devicetree,
	yingjoe.chen, eddie.huang, ryder.lee
  Cc: honghui.zhang, hongkun.cao, youlin.pei, yong.wu, yt.shen,
	sean.wang, xinping.qian

From: Ryder Lee <ryder.lee@mediatek.com>

Introduce a structure "mtk_pcie_soc" to abstract the differences between
controller generations, and the .startup() hook is used to encapsulate
some SoC-dependent related setting. In doing so, the common code which
will be reused by future chips.

In addition, we change the approaches to waiting Gen2 training by using
readl_poll_timeout() calls.

Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
Signed-off-by: Honghui Zhang <honghui.zhang@mediatek.com>
---
 drivers/pci/host/pcie-mediatek.c | 81 +++++++++++++++++++++++-----------------
 1 file changed, 47 insertions(+), 34 deletions(-)

diff --git a/drivers/pci/host/pcie-mediatek.c b/drivers/pci/host/pcie-mediatek.c
index 5a9d858..7f952a4 100644
--- a/drivers/pci/host/pcie-mediatek.c
+++ b/drivers/pci/host/pcie-mediatek.c
@@ -16,6 +16,7 @@
 
 #include <linux/clk.h>
 #include <linux/delay.h>
+#include <linux/iopoll.h>
 #include <linux/kernel.h>
 #include <linux/of_address.h>
 #include <linux/of_pci.h>
@@ -63,6 +64,18 @@
 #define PCIE_FC_CREDIT_MASK	(GENMASK(31, 31) | GENMASK(28, 16))
 #define PCIE_FC_CREDIT_VAL(x)	((x) << 16)
 
+struct mtk_pcie_port;
+
+/**
+ * struct mtk_pcie_soc - differentiate between host generations
+ * @ops: pointer to configuration access functions
+ * @startup: pointer to controller setting functions
+ */
+struct mtk_pcie_soc {
+	struct pci_ops *ops;
+	int (*startup)(struct mtk_pcie_port *port);
+};
+
 /**
  * struct mtk_pcie_port - PCIe port information
  * @base: IO mapped register base
@@ -96,6 +109,7 @@ struct mtk_pcie_port {
  * @busn: bus range
  * @offset: IO / Memory offset
  * @ports: pointer to PCIe port information
+ * @soc: pointer to SoC-dependent operations
  */
 struct mtk_pcie {
 	struct device *dev;
@@ -111,13 +125,9 @@ struct mtk_pcie {
 		resource_size_t io;
 	} offset;
 	struct list_head ports;
+	const struct mtk_pcie_soc *soc;
 };
 
-static inline bool mtk_pcie_link_up(struct mtk_pcie_port *port)
-{
-	return !!(readl(port->base + PCIE_LINK_STATUS) & PCIE_PORT_LINKUP);
-}
-
 static void mtk_pcie_subsys_powerdown(struct mtk_pcie *pcie)
 {
 	struct device *dev = pcie->dev;
@@ -171,12 +181,30 @@ static struct pci_ops mtk_pcie_ops = {
 	.write = pci_generic_config_write,
 };
 
-static void mtk_pcie_configure_rc(struct mtk_pcie_port *port)
+static int mtk_pcie_startup_ports(struct mtk_pcie_port *port)
 {
 	struct mtk_pcie *pcie = port->pcie;
 	u32 func = PCI_FUNC(port->index << 3);
 	u32 slot = PCI_SLOT(port->index << 3);
 	u32 val;
+	int err;
+
+	/* assert port PERST_N */
+	val = readl(pcie->base + PCIE_SYS_CFG);
+	val |= PCIE_PORT_PERST(port->index);
+	writel(val, pcie->base + PCIE_SYS_CFG);
+
+	/* de-assert port PERST_N */
+	val = readl(pcie->base + PCIE_SYS_CFG);
+	val &= ~PCIE_PORT_PERST(port->index);
+	writel(val, pcie->base + PCIE_SYS_CFG);
+
+	/* 100ms timeout value should be enough for Gen1/2 training */
+	err = readl_poll_timeout(port->base + PCIE_LINK_STATUS, val,
+				 !!(val & PCIE_PORT_LINKUP), 20,
+				 100 * USEC_PER_MSEC);
+	if (err)
+		return -ETIMEDOUT;
 
 	/* enable interrupt */
 	val = readl(pcie->base + PCIE_INT_ENABLE);
@@ -209,30 +237,14 @@ static void mtk_pcie_configure_rc(struct mtk_pcie_port *port)
 	writel(PCIE_CONF_ADDR(PCIE_FTS_NUM, func, slot, 0),
 	       pcie->base + PCIE_CFG_ADDR);
 	writel(val, pcie->base + PCIE_CFG_DATA);
-}
 
-static void mtk_pcie_assert_ports(struct mtk_pcie_port *port)
-{
-	struct mtk_pcie *pcie = port->pcie;
-	u32 val;
-
-	/* assert port PERST_N */
-	val = readl(pcie->base + PCIE_SYS_CFG);
-	val |= PCIE_PORT_PERST(port->index);
-	writel(val, pcie->base + PCIE_SYS_CFG);
-
-	/* de-assert port PERST_N */
-	val = readl(pcie->base + PCIE_SYS_CFG);
-	val &= ~PCIE_PORT_PERST(port->index);
-	writel(val, pcie->base + PCIE_SYS_CFG);
-
-	/* PCIe v2.0 need at least 100ms delay to train from Gen1 to Gen2 */
-	msleep(100);
+	return 0;
 }
 
 static void mtk_pcie_enable_ports(struct mtk_pcie_port *port)
 {
-	struct device *dev = port->pcie->dev;
+	struct mtk_pcie *pcie = port->pcie;
+	struct device *dev = pcie->dev;
 	int err;
 
 	err = clk_prepare_enable(port->sys_ck);
@@ -250,13 +262,8 @@ static void mtk_pcie_enable_ports(struct mtk_pcie_port *port)
 		goto err_phy_on;
 	}
 
-	mtk_pcie_assert_ports(port);
-
-	/* if link up, then setup root port configuration space */
-	if (mtk_pcie_link_up(port)) {
-		mtk_pcie_configure_rc(port);
+	if (!pcie->soc->startup(port))
 		return;
-	}
 
 	dev_info(dev, "Port%d link down\n", port->index);
 
@@ -480,7 +487,7 @@ static int mtk_pcie_register_host(struct pci_host_bridge *host)
 
 	host->busnr = pcie->busn.start;
 	host->dev.parent = pcie->dev;
-	host->ops = &mtk_pcie_ops;
+	host->ops = pcie->soc->ops;
 	host->map_irq = of_irq_parse_and_map_pci;
 	host->swizzle_irq = pci_common_swizzle;
 
@@ -513,6 +520,7 @@ static int mtk_pcie_probe(struct platform_device *pdev)
 	pcie = pci_host_bridge_priv(host);
 
 	pcie->dev = dev;
+	pcie->soc = of_device_get_match_data(dev);
 	platform_set_drvdata(pdev, pcie);
 	INIT_LIST_HEAD(&pcie->ports);
 
@@ -537,9 +545,14 @@ static int mtk_pcie_probe(struct platform_device *pdev)
 	return err;
 }
 
+static struct mtk_pcie_soc mtk_pcie_soc_v1 = {
+	.ops = &mtk_pcie_ops,
+	.startup = mtk_pcie_startup_ports,
+};
+
 static const struct of_device_id mtk_pcie_ids[] = {
-	{ .compatible = "mediatek,mt7623-pcie"},
-	{ .compatible = "mediatek,mt2701-pcie"},
+	{ .compatible = "mediatek,mt2701-pcie", .data = &mtk_pcie_soc_v1 },
+	{ .compatible = "mediatek,mt7623-pcie", .data = &mtk_pcie_soc_v1 },
 	{},
 };
 
-- 
2.6.4

^ permalink raw reply related	[flat|nested] 80+ messages in thread

* [PATCH v2 1/5] PCI: mediatek: Add a structure to abstract the controller generations
@ 2017-07-27  2:58   ` honghui.zhang
  0 siblings, 0 replies; 80+ messages in thread
From: honghui.zhang @ 2017-07-27  2:58 UTC (permalink / raw)
  To: bhelgaas, robh, robh+dt, matthias.bgg, linux-arm-kernel,
	linux-mediatek, linux-pci, linux-kernel, devicetree,
	yingjoe.chen, eddie.huang, ryder.lee
  Cc: honghui.zhang, hongkun.cao, youlin.pei, yong.wu, yt.shen,
	sean.wang, xinping.qian

From: Ryder Lee <ryder.lee@mediatek.com>

Introduce a structure "mtk_pcie_soc" to abstract the differences between
controller generations, and the .startup() hook is used to encapsulate
some SoC-dependent related setting. In doing so, the common code which
will be reused by future chips.

In addition, we change the approaches to waiting Gen2 training by using
readl_poll_timeout() calls.

Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
Signed-off-by: Honghui Zhang <honghui.zhang@mediatek.com>
---
 drivers/pci/host/pcie-mediatek.c | 81 +++++++++++++++++++++++-----------------
 1 file changed, 47 insertions(+), 34 deletions(-)

diff --git a/drivers/pci/host/pcie-mediatek.c b/drivers/pci/host/pcie-mediatek.c
index 5a9d858..7f952a4 100644
--- a/drivers/pci/host/pcie-mediatek.c
+++ b/drivers/pci/host/pcie-mediatek.c
@@ -16,6 +16,7 @@
 
 #include <linux/clk.h>
 #include <linux/delay.h>
+#include <linux/iopoll.h>
 #include <linux/kernel.h>
 #include <linux/of_address.h>
 #include <linux/of_pci.h>
@@ -63,6 +64,18 @@
 #define PCIE_FC_CREDIT_MASK	(GENMASK(31, 31) | GENMASK(28, 16))
 #define PCIE_FC_CREDIT_VAL(x)	((x) << 16)
 
+struct mtk_pcie_port;
+
+/**
+ * struct mtk_pcie_soc - differentiate between host generations
+ * @ops: pointer to configuration access functions
+ * @startup: pointer to controller setting functions
+ */
+struct mtk_pcie_soc {
+	struct pci_ops *ops;
+	int (*startup)(struct mtk_pcie_port *port);
+};
+
 /**
  * struct mtk_pcie_port - PCIe port information
  * @base: IO mapped register base
@@ -96,6 +109,7 @@ struct mtk_pcie_port {
  * @busn: bus range
  * @offset: IO / Memory offset
  * @ports: pointer to PCIe port information
+ * @soc: pointer to SoC-dependent operations
  */
 struct mtk_pcie {
 	struct device *dev;
@@ -111,13 +125,9 @@ struct mtk_pcie {
 		resource_size_t io;
 	} offset;
 	struct list_head ports;
+	const struct mtk_pcie_soc *soc;
 };
 
-static inline bool mtk_pcie_link_up(struct mtk_pcie_port *port)
-{
-	return !!(readl(port->base + PCIE_LINK_STATUS) & PCIE_PORT_LINKUP);
-}
-
 static void mtk_pcie_subsys_powerdown(struct mtk_pcie *pcie)
 {
 	struct device *dev = pcie->dev;
@@ -171,12 +181,30 @@ static struct pci_ops mtk_pcie_ops = {
 	.write = pci_generic_config_write,
 };
 
-static void mtk_pcie_configure_rc(struct mtk_pcie_port *port)
+static int mtk_pcie_startup_ports(struct mtk_pcie_port *port)
 {
 	struct mtk_pcie *pcie = port->pcie;
 	u32 func = PCI_FUNC(port->index << 3);
 	u32 slot = PCI_SLOT(port->index << 3);
 	u32 val;
+	int err;
+
+	/* assert port PERST_N */
+	val = readl(pcie->base + PCIE_SYS_CFG);
+	val |= PCIE_PORT_PERST(port->index);
+	writel(val, pcie->base + PCIE_SYS_CFG);
+
+	/* de-assert port PERST_N */
+	val = readl(pcie->base + PCIE_SYS_CFG);
+	val &= ~PCIE_PORT_PERST(port->index);
+	writel(val, pcie->base + PCIE_SYS_CFG);
+
+	/* 100ms timeout value should be enough for Gen1/2 training */
+	err = readl_poll_timeout(port->base + PCIE_LINK_STATUS, val,
+				 !!(val & PCIE_PORT_LINKUP), 20,
+				 100 * USEC_PER_MSEC);
+	if (err)
+		return -ETIMEDOUT;
 
 	/* enable interrupt */
 	val = readl(pcie->base + PCIE_INT_ENABLE);
@@ -209,30 +237,14 @@ static void mtk_pcie_configure_rc(struct mtk_pcie_port *port)
 	writel(PCIE_CONF_ADDR(PCIE_FTS_NUM, func, slot, 0),
 	       pcie->base + PCIE_CFG_ADDR);
 	writel(val, pcie->base + PCIE_CFG_DATA);
-}
 
-static void mtk_pcie_assert_ports(struct mtk_pcie_port *port)
-{
-	struct mtk_pcie *pcie = port->pcie;
-	u32 val;
-
-	/* assert port PERST_N */
-	val = readl(pcie->base + PCIE_SYS_CFG);
-	val |= PCIE_PORT_PERST(port->index);
-	writel(val, pcie->base + PCIE_SYS_CFG);
-
-	/* de-assert port PERST_N */
-	val = readl(pcie->base + PCIE_SYS_CFG);
-	val &= ~PCIE_PORT_PERST(port->index);
-	writel(val, pcie->base + PCIE_SYS_CFG);
-
-	/* PCIe v2.0 need at least 100ms delay to train from Gen1 to Gen2 */
-	msleep(100);
+	return 0;
 }
 
 static void mtk_pcie_enable_ports(struct mtk_pcie_port *port)
 {
-	struct device *dev = port->pcie->dev;
+	struct mtk_pcie *pcie = port->pcie;
+	struct device *dev = pcie->dev;
 	int err;
 
 	err = clk_prepare_enable(port->sys_ck);
@@ -250,13 +262,8 @@ static void mtk_pcie_enable_ports(struct mtk_pcie_port *port)
 		goto err_phy_on;
 	}
 
-	mtk_pcie_assert_ports(port);
-
-	/* if link up, then setup root port configuration space */
-	if (mtk_pcie_link_up(port)) {
-		mtk_pcie_configure_rc(port);
+	if (!pcie->soc->startup(port))
 		return;
-	}
 
 	dev_info(dev, "Port%d link down\n", port->index);
 
@@ -480,7 +487,7 @@ static int mtk_pcie_register_host(struct pci_host_bridge *host)
 
 	host->busnr = pcie->busn.start;
 	host->dev.parent = pcie->dev;
-	host->ops = &mtk_pcie_ops;
+	host->ops = pcie->soc->ops;
 	host->map_irq = of_irq_parse_and_map_pci;
 	host->swizzle_irq = pci_common_swizzle;
 
@@ -513,6 +520,7 @@ static int mtk_pcie_probe(struct platform_device *pdev)
 	pcie = pci_host_bridge_priv(host);
 
 	pcie->dev = dev;
+	pcie->soc = of_device_get_match_data(dev);
 	platform_set_drvdata(pdev, pcie);
 	INIT_LIST_HEAD(&pcie->ports);
 
@@ -537,9 +545,14 @@ static int mtk_pcie_probe(struct platform_device *pdev)
 	return err;
 }
 
+static struct mtk_pcie_soc mtk_pcie_soc_v1 = {
+	.ops = &mtk_pcie_ops,
+	.startup = mtk_pcie_startup_ports,
+};
+
 static const struct of_device_id mtk_pcie_ids[] = {
-	{ .compatible = "mediatek,mt7623-pcie"},
-	{ .compatible = "mediatek,mt2701-pcie"},
+	{ .compatible = "mediatek,mt2701-pcie", .data = &mtk_pcie_soc_v1 },
+	{ .compatible = "mediatek,mt7623-pcie", .data = &mtk_pcie_soc_v1 },
 	{},
 };
 
-- 
2.6.4

^ permalink raw reply related	[flat|nested] 80+ messages in thread

* [PATCH v2 1/5] PCI: mediatek: Add a structure to abstract the controller generations
@ 2017-07-27  2:58   ` honghui.zhang
  0 siblings, 0 replies; 80+ messages in thread
From: honghui.zhang at mediatek.com @ 2017-07-27  2:58 UTC (permalink / raw)
  To: linux-arm-kernel

From: Ryder Lee <ryder.lee@mediatek.com>

Introduce a structure "mtk_pcie_soc" to abstract the differences between
controller generations, and the .startup() hook is used to encapsulate
some SoC-dependent related setting. In doing so, the common code which
will be reused by future chips.

In addition, we change the approaches to waiting Gen2 training by using
readl_poll_timeout() calls.

Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
Signed-off-by: Honghui Zhang <honghui.zhang@mediatek.com>
---
 drivers/pci/host/pcie-mediatek.c | 81 +++++++++++++++++++++++-----------------
 1 file changed, 47 insertions(+), 34 deletions(-)

diff --git a/drivers/pci/host/pcie-mediatek.c b/drivers/pci/host/pcie-mediatek.c
index 5a9d858..7f952a4 100644
--- a/drivers/pci/host/pcie-mediatek.c
+++ b/drivers/pci/host/pcie-mediatek.c
@@ -16,6 +16,7 @@
 
 #include <linux/clk.h>
 #include <linux/delay.h>
+#include <linux/iopoll.h>
 #include <linux/kernel.h>
 #include <linux/of_address.h>
 #include <linux/of_pci.h>
@@ -63,6 +64,18 @@
 #define PCIE_FC_CREDIT_MASK	(GENMASK(31, 31) | GENMASK(28, 16))
 #define PCIE_FC_CREDIT_VAL(x)	((x) << 16)
 
+struct mtk_pcie_port;
+
+/**
+ * struct mtk_pcie_soc - differentiate between host generations
+ * @ops: pointer to configuration access functions
+ * @startup: pointer to controller setting functions
+ */
+struct mtk_pcie_soc {
+	struct pci_ops *ops;
+	int (*startup)(struct mtk_pcie_port *port);
+};
+
 /**
  * struct mtk_pcie_port - PCIe port information
  * @base: IO mapped register base
@@ -96,6 +109,7 @@ struct mtk_pcie_port {
  * @busn: bus range
  * @offset: IO / Memory offset
  * @ports: pointer to PCIe port information
+ * @soc: pointer to SoC-dependent operations
  */
 struct mtk_pcie {
 	struct device *dev;
@@ -111,13 +125,9 @@ struct mtk_pcie {
 		resource_size_t io;
 	} offset;
 	struct list_head ports;
+	const struct mtk_pcie_soc *soc;
 };
 
-static inline bool mtk_pcie_link_up(struct mtk_pcie_port *port)
-{
-	return !!(readl(port->base + PCIE_LINK_STATUS) & PCIE_PORT_LINKUP);
-}
-
 static void mtk_pcie_subsys_powerdown(struct mtk_pcie *pcie)
 {
 	struct device *dev = pcie->dev;
@@ -171,12 +181,30 @@ static struct pci_ops mtk_pcie_ops = {
 	.write = pci_generic_config_write,
 };
 
-static void mtk_pcie_configure_rc(struct mtk_pcie_port *port)
+static int mtk_pcie_startup_ports(struct mtk_pcie_port *port)
 {
 	struct mtk_pcie *pcie = port->pcie;
 	u32 func = PCI_FUNC(port->index << 3);
 	u32 slot = PCI_SLOT(port->index << 3);
 	u32 val;
+	int err;
+
+	/* assert port PERST_N */
+	val = readl(pcie->base + PCIE_SYS_CFG);
+	val |= PCIE_PORT_PERST(port->index);
+	writel(val, pcie->base + PCIE_SYS_CFG);
+
+	/* de-assert port PERST_N */
+	val = readl(pcie->base + PCIE_SYS_CFG);
+	val &= ~PCIE_PORT_PERST(port->index);
+	writel(val, pcie->base + PCIE_SYS_CFG);
+
+	/* 100ms timeout value should be enough for Gen1/2 training */
+	err = readl_poll_timeout(port->base + PCIE_LINK_STATUS, val,
+				 !!(val & PCIE_PORT_LINKUP), 20,
+				 100 * USEC_PER_MSEC);
+	if (err)
+		return -ETIMEDOUT;
 
 	/* enable interrupt */
 	val = readl(pcie->base + PCIE_INT_ENABLE);
@@ -209,30 +237,14 @@ static void mtk_pcie_configure_rc(struct mtk_pcie_port *port)
 	writel(PCIE_CONF_ADDR(PCIE_FTS_NUM, func, slot, 0),
 	       pcie->base + PCIE_CFG_ADDR);
 	writel(val, pcie->base + PCIE_CFG_DATA);
-}
 
-static void mtk_pcie_assert_ports(struct mtk_pcie_port *port)
-{
-	struct mtk_pcie *pcie = port->pcie;
-	u32 val;
-
-	/* assert port PERST_N */
-	val = readl(pcie->base + PCIE_SYS_CFG);
-	val |= PCIE_PORT_PERST(port->index);
-	writel(val, pcie->base + PCIE_SYS_CFG);
-
-	/* de-assert port PERST_N */
-	val = readl(pcie->base + PCIE_SYS_CFG);
-	val &= ~PCIE_PORT_PERST(port->index);
-	writel(val, pcie->base + PCIE_SYS_CFG);
-
-	/* PCIe v2.0 need at least 100ms delay to train from Gen1 to Gen2 */
-	msleep(100);
+	return 0;
 }
 
 static void mtk_pcie_enable_ports(struct mtk_pcie_port *port)
 {
-	struct device *dev = port->pcie->dev;
+	struct mtk_pcie *pcie = port->pcie;
+	struct device *dev = pcie->dev;
 	int err;
 
 	err = clk_prepare_enable(port->sys_ck);
@@ -250,13 +262,8 @@ static void mtk_pcie_enable_ports(struct mtk_pcie_port *port)
 		goto err_phy_on;
 	}
 
-	mtk_pcie_assert_ports(port);
-
-	/* if link up, then setup root port configuration space */
-	if (mtk_pcie_link_up(port)) {
-		mtk_pcie_configure_rc(port);
+	if (!pcie->soc->startup(port))
 		return;
-	}
 
 	dev_info(dev, "Port%d link down\n", port->index);
 
@@ -480,7 +487,7 @@ static int mtk_pcie_register_host(struct pci_host_bridge *host)
 
 	host->busnr = pcie->busn.start;
 	host->dev.parent = pcie->dev;
-	host->ops = &mtk_pcie_ops;
+	host->ops = pcie->soc->ops;
 	host->map_irq = of_irq_parse_and_map_pci;
 	host->swizzle_irq = pci_common_swizzle;
 
@@ -513,6 +520,7 @@ static int mtk_pcie_probe(struct platform_device *pdev)
 	pcie = pci_host_bridge_priv(host);
 
 	pcie->dev = dev;
+	pcie->soc = of_device_get_match_data(dev);
 	platform_set_drvdata(pdev, pcie);
 	INIT_LIST_HEAD(&pcie->ports);
 
@@ -537,9 +545,14 @@ static int mtk_pcie_probe(struct platform_device *pdev)
 	return err;
 }
 
+static struct mtk_pcie_soc mtk_pcie_soc_v1 = {
+	.ops = &mtk_pcie_ops,
+	.startup = mtk_pcie_startup_ports,
+};
+
 static const struct of_device_id mtk_pcie_ids[] = {
-	{ .compatible = "mediatek,mt7623-pcie"},
-	{ .compatible = "mediatek,mt2701-pcie"},
+	{ .compatible = "mediatek,mt2701-pcie", .data = &mtk_pcie_soc_v1 },
+	{ .compatible = "mediatek,mt7623-pcie", .data = &mtk_pcie_soc_v1 },
 	{},
 };
 
-- 
2.6.4

^ permalink raw reply related	[flat|nested] 80+ messages in thread

* [PATCH v2 2/5] PCI: mediatek: switch to use platform_get_resource_byname()
  2017-07-27  2:58 ` honghui.zhang
  (?)
@ 2017-07-27  2:58   ` honghui.zhang
  -1 siblings, 0 replies; 80+ messages in thread
From: honghui.zhang @ 2017-07-27  2:58 UTC (permalink / raw)
  To: bhelgaas, robh, robh+dt, matthias.bgg, linux-arm-kernel,
	linux-mediatek, linux-pci, linux-kernel, devicetree,
	yingjoe.chen, eddie.huang, ryder.lee
  Cc: honghui.zhang, hongkun.cao, youlin.pei, yong.wu, yt.shen,
	sean.wang, xinping.qian

From: Ryder Lee <ryder.lee@mediatek.com>

This is a transitional patch. We currently use platfarm_get_resource() for
retrieving the IOMEM resources, but there might be some chips don't have
subsys/shared registers part, which depends on platform design, and these
will be introduced in further patches.

Switch this function to use the platform_get_resource_byname() so that the
binding can be agnostic of the resource order.

Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
---
 drivers/pci/host/pcie-mediatek.c | 17 ++++++++++-------
 1 file changed, 10 insertions(+), 7 deletions(-)

diff --git a/drivers/pci/host/pcie-mediatek.c b/drivers/pci/host/pcie-mediatek.c
index 7f952a4..f8e2f68 100644
--- a/drivers/pci/host/pcie-mediatek.c
+++ b/drivers/pci/host/pcie-mediatek.c
@@ -295,7 +295,8 @@ static int mtk_pcie_parse_ports(struct mtk_pcie *pcie,
 		return err;
 	}
 
-	regs = platform_get_resource(pdev, IORESOURCE_MEM, index + 1);
+	snprintf(name, sizeof(name), "port%d", index);
+	regs = platform_get_resource_byname(pdev, IORESOURCE_MEM, name);
 	port->base = devm_ioremap_resource(dev, regs);
 	if (IS_ERR(port->base)) {
 		dev_err(dev, "failed to map port%d base\n", index);
@@ -336,12 +337,14 @@ static int mtk_pcie_subsys_powerup(struct mtk_pcie *pcie)
 	struct resource *regs;
 	int err;
 
-	/* get shared registers */
-	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	pcie->base = devm_ioremap_resource(dev, regs);
-	if (IS_ERR(pcie->base)) {
-		dev_err(dev, "failed to map shared register\n");
-		return PTR_ERR(pcie->base);
+	/* get shared registers, which are optional */
+	regs = platform_get_resource_byname(pdev, IORESOURCE_MEM, "subsys");
+	if (regs) {
+		pcie->base = devm_ioremap_resource(dev, regs);
+		if (IS_ERR(pcie->base)) {
+			dev_err(dev, "failed to map shared register\n");
+			return PTR_ERR(pcie->base);
+		}
 	}
 
 	pcie->free_ck = devm_clk_get(dev, "free_ck");
-- 
2.6.4

^ permalink raw reply related	[flat|nested] 80+ messages in thread

* [PATCH v2 2/5] PCI: mediatek: switch to use platform_get_resource_byname()
@ 2017-07-27  2:58   ` honghui.zhang
  0 siblings, 0 replies; 80+ messages in thread
From: honghui.zhang @ 2017-07-27  2:58 UTC (permalink / raw)
  To: bhelgaas, robh, robh+dt, matthias.bgg, linux-arm-kernel,
	linux-mediatek, linux-pci, linux-kernel, devicetree,
	yingjoe.chen, eddie.huang, ryder.lee
  Cc: honghui.zhang, hongkun.cao, youlin.pei, yong.wu, yt.shen,
	sean.wang, xinping.qian

From: Ryder Lee <ryder.lee@mediatek.com>

This is a transitional patch. We currently use platfarm_get_resource() for
retrieving the IOMEM resources, but there might be some chips don't have
subsys/shared registers part, which depends on platform design, and these
will be introduced in further patches.

Switch this function to use the platform_get_resource_byname() so that the
binding can be agnostic of the resource order.

Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
---
 drivers/pci/host/pcie-mediatek.c | 17 ++++++++++-------
 1 file changed, 10 insertions(+), 7 deletions(-)

diff --git a/drivers/pci/host/pcie-mediatek.c b/drivers/pci/host/pcie-mediatek.c
index 7f952a4..f8e2f68 100644
--- a/drivers/pci/host/pcie-mediatek.c
+++ b/drivers/pci/host/pcie-mediatek.c
@@ -295,7 +295,8 @@ static int mtk_pcie_parse_ports(struct mtk_pcie *pcie,
 		return err;
 	}
 
-	regs = platform_get_resource(pdev, IORESOURCE_MEM, index + 1);
+	snprintf(name, sizeof(name), "port%d", index);
+	regs = platform_get_resource_byname(pdev, IORESOURCE_MEM, name);
 	port->base = devm_ioremap_resource(dev, regs);
 	if (IS_ERR(port->base)) {
 		dev_err(dev, "failed to map port%d base\n", index);
@@ -336,12 +337,14 @@ static int mtk_pcie_subsys_powerup(struct mtk_pcie *pcie)
 	struct resource *regs;
 	int err;
 
-	/* get shared registers */
-	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	pcie->base = devm_ioremap_resource(dev, regs);
-	if (IS_ERR(pcie->base)) {
-		dev_err(dev, "failed to map shared register\n");
-		return PTR_ERR(pcie->base);
+	/* get shared registers, which are optional */
+	regs = platform_get_resource_byname(pdev, IORESOURCE_MEM, "subsys");
+	if (regs) {
+		pcie->base = devm_ioremap_resource(dev, regs);
+		if (IS_ERR(pcie->base)) {
+			dev_err(dev, "failed to map shared register\n");
+			return PTR_ERR(pcie->base);
+		}
 	}
 
 	pcie->free_ck = devm_clk_get(dev, "free_ck");
-- 
2.6.4

^ permalink raw reply related	[flat|nested] 80+ messages in thread

* [PATCH v2 2/5] PCI: mediatek: switch to use platform_get_resource_byname()
@ 2017-07-27  2:58   ` honghui.zhang
  0 siblings, 0 replies; 80+ messages in thread
From: honghui.zhang at mediatek.com @ 2017-07-27  2:58 UTC (permalink / raw)
  To: linux-arm-kernel

From: Ryder Lee <ryder.lee@mediatek.com>

This is a transitional patch. We currently use platfarm_get_resource() for
retrieving the IOMEM resources, but there might be some chips don't have
subsys/shared registers part, which depends on platform design, and these
will be introduced in further patches.

Switch this function to use the platform_get_resource_byname() so that the
binding can be agnostic of the resource order.

Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
---
 drivers/pci/host/pcie-mediatek.c | 17 ++++++++++-------
 1 file changed, 10 insertions(+), 7 deletions(-)

diff --git a/drivers/pci/host/pcie-mediatek.c b/drivers/pci/host/pcie-mediatek.c
index 7f952a4..f8e2f68 100644
--- a/drivers/pci/host/pcie-mediatek.c
+++ b/drivers/pci/host/pcie-mediatek.c
@@ -295,7 +295,8 @@ static int mtk_pcie_parse_ports(struct mtk_pcie *pcie,
 		return err;
 	}
 
-	regs = platform_get_resource(pdev, IORESOURCE_MEM, index + 1);
+	snprintf(name, sizeof(name), "port%d", index);
+	regs = platform_get_resource_byname(pdev, IORESOURCE_MEM, name);
 	port->base = devm_ioremap_resource(dev, regs);
 	if (IS_ERR(port->base)) {
 		dev_err(dev, "failed to map port%d base\n", index);
@@ -336,12 +337,14 @@ static int mtk_pcie_subsys_powerup(struct mtk_pcie *pcie)
 	struct resource *regs;
 	int err;
 
-	/* get shared registers */
-	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	pcie->base = devm_ioremap_resource(dev, regs);
-	if (IS_ERR(pcie->base)) {
-		dev_err(dev, "failed to map shared register\n");
-		return PTR_ERR(pcie->base);
+	/* get shared registers, which are optional */
+	regs = platform_get_resource_byname(pdev, IORESOURCE_MEM, "subsys");
+	if (regs) {
+		pcie->base = devm_ioremap_resource(dev, regs);
+		if (IS_ERR(pcie->base)) {
+			dev_err(dev, "failed to map shared register\n");
+			return PTR_ERR(pcie->base);
+		}
 	}
 
 	pcie->free_ck = devm_clk_get(dev, "free_ck");
-- 
2.6.4

^ permalink raw reply related	[flat|nested] 80+ messages in thread

* [PATCH v2 3/5] dt-bindings: PCI: rename and cleanup MediaTek binding text
  2017-07-27  2:58 ` honghui.zhang
  (?)
  (?)
@ 2017-07-27  2:58   ` honghui.zhang
  -1 siblings, 0 replies; 80+ messages in thread
From: honghui.zhang @ 2017-07-27  2:58 UTC (permalink / raw)
  To: bhelgaas, robh, robh+dt, matthias.bgg, linux-arm-kernel,
	linux-mediatek, linux-pci, linux-kernel, devicetree,
	yingjoe.chen, eddie.huang, ryder.lee
  Cc: honghui.zhang, hongkun.cao, youlin.pei, yong.wu, yt.shen,
	sean.wang, xinping.qian

From: Ryder Lee <ryder.lee@mediatek.com>

In order to accommodate other SoC generations, this patch updates filename
to make it more generic, regroups specific properties by SoCs, and removes
redundant descriptions.

Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
---
 ...{mediatek,mt7623-pcie.txt => mediatek-pcie.txt} | 29 +++++++++++-----------
 1 file changed, 14 insertions(+), 15 deletions(-)
 rename Documentation/devicetree/bindings/pci/{mediatek,mt7623-pcie.txt => mediatek-pcie.txt} (91%)

diff --git a/Documentation/devicetree/bindings/pci/mediatek,mt7623-pcie.txt b/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
similarity index 91%
rename from Documentation/devicetree/bindings/pci/mediatek,mt7623-pcie.txt
rename to Documentation/devicetree/bindings/pci/mediatek-pcie.txt
index fe80dda..a968f25 100644
--- a/Documentation/devicetree/bindings/pci/mediatek,mt7623-pcie.txt
+++ b/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
@@ -1,18 +1,13 @@
-MediaTek Gen2 PCIe controller which is available on MT7623 series SoCs
-
-PCIe subsys supports single root complex (RC) with 3 Root Ports. Each root
-ports supports a Gen2 1-lane Link and has PIPE interface to PHY.
+MediaTek Gen2 PCIe controller
 
 Required properties:
-- compatible: Should contain "mediatek,mt7623-pcie".
+- compatible: Should contain one of the following string:
+	"mediatek,mt2701-pcie"
+	"mediatek,mt7623-pcie"
 - device_type: Must be "pci"
 - reg: Base addresses and lengths of the PCIe controller.
 - #address-cells: Address representation for root ports (must be 3)
 - #size-cells: Size representation for root ports (must be 2)
-- #interrupt-cells: Size representation for interrupts (must be 1)
-- interrupt-map-mask and interrupt-map: Standard PCI IRQ mapping properties
-  Please refer to the standard PCI bus binding document for a more detailed
-  explanation.
 - clocks: Must contain an entry for each entry in clock-names.
   See ../clocks/clock-bindings.txt for details.
 - clock-names: Must include the following entries:
@@ -20,12 +15,6 @@ Required properties:
   - sys_ck0 :for clock of Port0
   - sys_ck1 :for clock of Port1
   - sys_ck2 :for clock of Port2
-- resets: Must contain an entry for each entry in reset-names.
-  See ../reset/reset.txt for details.
-- reset-names: Must include the following entries:
-  - pcie-rst0 :port0 reset
-  - pcie-rst1 :port1 reset
-  - pcie-rst2 :port2 reset
 - phys: List of PHY specifiers (used by generic PHY framework).
 - phy-names : Must be "pcie-phy0", "pcie-phy1", "pcie-phyN".. based on the
   number of PHYs as specified in *phys* property.
@@ -34,6 +23,16 @@ Required properties:
 - bus-range: Range of bus numbers associated with this controller.
 - ranges: Ranges for the PCI memory and I/O regions.
 
+Required properties for MT7623/MT2701:
+- #interrupt-cells: Size representation for interrupts (must be 1)
+- interrupt-map-mask and interrupt-map: Standard PCI IRQ mapping properties
+  Please refer to the standard PCI bus binding document for a more detailed
+  explanation.
+- resets: Must contain an entry for each entry in reset-names.
+  See ../reset/reset.txt for details.
+- reset-names: Must be "pcie-rst0", "pcie-rst1", "pcie-rstN".. based on the
+  number of root ports.
+
 In addition, the device tree node must have sub-nodes describing each
 PCIe port interface, having the following mandatory properties:
 
-- 
2.6.4

^ permalink raw reply related	[flat|nested] 80+ messages in thread

* [PATCH v2 3/5] dt-bindings: PCI: rename and cleanup MediaTek binding text
@ 2017-07-27  2:58   ` honghui.zhang
  0 siblings, 0 replies; 80+ messages in thread
From: honghui.zhang @ 2017-07-27  2:58 UTC (permalink / raw)
  To: bhelgaas, robh, robh+dt, matthias.bgg, linux-arm-kernel,
	linux-mediatek, linux-pci, linux-kernel, devicetree,
	yingjoe.chen, eddie.huang, ryder.lee
  Cc: honghui.zhang, hongkun.cao, youlin.pei, yong.wu, yt.shen,
	sean.wang, xinping.qian

From: Ryder Lee <ryder.lee@mediatek.com>

In order to accommodate other SoC generations, this patch updates filename
to make it more generic, regroups specific properties by SoCs, and removes
redundant descriptions.

Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
---
 ...{mediatek,mt7623-pcie.txt => mediatek-pcie.txt} | 29 +++++++++++-----------
 1 file changed, 14 insertions(+), 15 deletions(-)
 rename Documentation/devicetree/bindings/pci/{mediatek,mt7623-pcie.txt => mediatek-pcie.txt} (91%)

diff --git a/Documentation/devicetree/bindings/pci/mediatek,mt7623-pcie.txt b/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
similarity index 91%
rename from Documentation/devicetree/bindings/pci/mediatek,mt7623-pcie.txt
rename to Documentation/devicetree/bindings/pci/mediatek-pcie.txt
index fe80dda..a968f25 100644
--- a/Documentation/devicetree/bindings/pci/mediatek,mt7623-pcie.txt
+++ b/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
@@ -1,18 +1,13 @@
-MediaTek Gen2 PCIe controller which is available on MT7623 series SoCs
-
-PCIe subsys supports single root complex (RC) with 3 Root Ports. Each root
-ports supports a Gen2 1-lane Link and has PIPE interface to PHY.
+MediaTek Gen2 PCIe controller
 
 Required properties:
-- compatible: Should contain "mediatek,mt7623-pcie".
+- compatible: Should contain one of the following string:
+	"mediatek,mt2701-pcie"
+	"mediatek,mt7623-pcie"
 - device_type: Must be "pci"
 - reg: Base addresses and lengths of the PCIe controller.
 - #address-cells: Address representation for root ports (must be 3)
 - #size-cells: Size representation for root ports (must be 2)
-- #interrupt-cells: Size representation for interrupts (must be 1)
-- interrupt-map-mask and interrupt-map: Standard PCI IRQ mapping properties
-  Please refer to the standard PCI bus binding document for a more detailed
-  explanation.
 - clocks: Must contain an entry for each entry in clock-names.
   See ../clocks/clock-bindings.txt for details.
 - clock-names: Must include the following entries:
@@ -20,12 +15,6 @@ Required properties:
   - sys_ck0 :for clock of Port0
   - sys_ck1 :for clock of Port1
   - sys_ck2 :for clock of Port2
-- resets: Must contain an entry for each entry in reset-names.
-  See ../reset/reset.txt for details.
-- reset-names: Must include the following entries:
-  - pcie-rst0 :port0 reset
-  - pcie-rst1 :port1 reset
-  - pcie-rst2 :port2 reset
 - phys: List of PHY specifiers (used by generic PHY framework).
 - phy-names : Must be "pcie-phy0", "pcie-phy1", "pcie-phyN".. based on the
   number of PHYs as specified in *phys* property.
@@ -34,6 +23,16 @@ Required properties:
 - bus-range: Range of bus numbers associated with this controller.
 - ranges: Ranges for the PCI memory and I/O regions.
 
+Required properties for MT7623/MT2701:
+- #interrupt-cells: Size representation for interrupts (must be 1)
+- interrupt-map-mask and interrupt-map: Standard PCI IRQ mapping properties
+  Please refer to the standard PCI bus binding document for a more detailed
+  explanation.
+- resets: Must contain an entry for each entry in reset-names.
+  See ../reset/reset.txt for details.
+- reset-names: Must be "pcie-rst0", "pcie-rst1", "pcie-rstN".. based on the
+  number of root ports.
+
 In addition, the device tree node must have sub-nodes describing each
 PCIe port interface, having the following mandatory properties:
 
-- 
2.6.4

^ permalink raw reply related	[flat|nested] 80+ messages in thread

* [PATCH v2 3/5] dt-bindings: PCI: rename and cleanup MediaTek binding text
@ 2017-07-27  2:58   ` honghui.zhang
  0 siblings, 0 replies; 80+ messages in thread
From: honghui.zhang @ 2017-07-27  2:58 UTC (permalink / raw)
  To: bhelgaas, robh, robh+dt, matthias.bgg, linux-arm-kernel,
	linux-mediatek, linux-pci, linux-kernel, devicetree,
	yingjoe.chen, eddie.huang, ryder.lee
  Cc: youlin.pei, hongkun.cao, sean.wang, xinping.qian, honghui.zhang,
	yt.shen, yong.wu

From: Ryder Lee <ryder.lee@mediatek.com>

In order to accommodate other SoC generations, this patch updates filename
to make it more generic, regroups specific properties by SoCs, and removes
redundant descriptions.

Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
---
 ...{mediatek,mt7623-pcie.txt => mediatek-pcie.txt} | 29 +++++++++++-----------
 1 file changed, 14 insertions(+), 15 deletions(-)
 rename Documentation/devicetree/bindings/pci/{mediatek,mt7623-pcie.txt => mediatek-pcie.txt} (91%)

diff --git a/Documentation/devicetree/bindings/pci/mediatek,mt7623-pcie.txt b/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
similarity index 91%
rename from Documentation/devicetree/bindings/pci/mediatek,mt7623-pcie.txt
rename to Documentation/devicetree/bindings/pci/mediatek-pcie.txt
index fe80dda..a968f25 100644
--- a/Documentation/devicetree/bindings/pci/mediatek,mt7623-pcie.txt
+++ b/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
@@ -1,18 +1,13 @@
-MediaTek Gen2 PCIe controller which is available on MT7623 series SoCs
-
-PCIe subsys supports single root complex (RC) with 3 Root Ports. Each root
-ports supports a Gen2 1-lane Link and has PIPE interface to PHY.
+MediaTek Gen2 PCIe controller
 
 Required properties:
-- compatible: Should contain "mediatek,mt7623-pcie".
+- compatible: Should contain one of the following string:
+	"mediatek,mt2701-pcie"
+	"mediatek,mt7623-pcie"
 - device_type: Must be "pci"
 - reg: Base addresses and lengths of the PCIe controller.
 - #address-cells: Address representation for root ports (must be 3)
 - #size-cells: Size representation for root ports (must be 2)
-- #interrupt-cells: Size representation for interrupts (must be 1)
-- interrupt-map-mask and interrupt-map: Standard PCI IRQ mapping properties
-  Please refer to the standard PCI bus binding document for a more detailed
-  explanation.
 - clocks: Must contain an entry for each entry in clock-names.
   See ../clocks/clock-bindings.txt for details.
 - clock-names: Must include the following entries:
@@ -20,12 +15,6 @@ Required properties:
   - sys_ck0 :for clock of Port0
   - sys_ck1 :for clock of Port1
   - sys_ck2 :for clock of Port2
-- resets: Must contain an entry for each entry in reset-names.
-  See ../reset/reset.txt for details.
-- reset-names: Must include the following entries:
-  - pcie-rst0 :port0 reset
-  - pcie-rst1 :port1 reset
-  - pcie-rst2 :port2 reset
 - phys: List of PHY specifiers (used by generic PHY framework).
 - phy-names : Must be "pcie-phy0", "pcie-phy1", "pcie-phyN".. based on the
   number of PHYs as specified in *phys* property.
@@ -34,6 +23,16 @@ Required properties:
 - bus-range: Range of bus numbers associated with this controller.
 - ranges: Ranges for the PCI memory and I/O regions.
 
+Required properties for MT7623/MT2701:
+- #interrupt-cells: Size representation for interrupts (must be 1)
+- interrupt-map-mask and interrupt-map: Standard PCI IRQ mapping properties
+  Please refer to the standard PCI bus binding document for a more detailed
+  explanation.
+- resets: Must contain an entry for each entry in reset-names.
+  See ../reset/reset.txt for details.
+- reset-names: Must be "pcie-rst0", "pcie-rst1", "pcie-rstN".. based on the
+  number of root ports.
+
 In addition, the device tree node must have sub-nodes describing each
 PCIe port interface, having the following mandatory properties:
 
-- 
2.6.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 80+ messages in thread

* [PATCH v2 3/5] dt-bindings: PCI: rename and cleanup MediaTek binding text
@ 2017-07-27  2:58   ` honghui.zhang
  0 siblings, 0 replies; 80+ messages in thread
From: honghui.zhang at mediatek.com @ 2017-07-27  2:58 UTC (permalink / raw)
  To: linux-arm-kernel

From: Ryder Lee <ryder.lee@mediatek.com>

In order to accommodate other SoC generations, this patch updates filename
to make it more generic, regroups specific properties by SoCs, and removes
redundant descriptions.

Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
---
 ...{mediatek,mt7623-pcie.txt => mediatek-pcie.txt} | 29 +++++++++++-----------
 1 file changed, 14 insertions(+), 15 deletions(-)
 rename Documentation/devicetree/bindings/pci/{mediatek,mt7623-pcie.txt => mediatek-pcie.txt} (91%)

diff --git a/Documentation/devicetree/bindings/pci/mediatek,mt7623-pcie.txt b/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
similarity index 91%
rename from Documentation/devicetree/bindings/pci/mediatek,mt7623-pcie.txt
rename to Documentation/devicetree/bindings/pci/mediatek-pcie.txt
index fe80dda..a968f25 100644
--- a/Documentation/devicetree/bindings/pci/mediatek,mt7623-pcie.txt
+++ b/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
@@ -1,18 +1,13 @@
-MediaTek Gen2 PCIe controller which is available on MT7623 series SoCs
-
-PCIe subsys supports single root complex (RC) with 3 Root Ports. Each root
-ports supports a Gen2 1-lane Link and has PIPE interface to PHY.
+MediaTek Gen2 PCIe controller
 
 Required properties:
-- compatible: Should contain "mediatek,mt7623-pcie".
+- compatible: Should contain one of the following string:
+	"mediatek,mt2701-pcie"
+	"mediatek,mt7623-pcie"
 - device_type: Must be "pci"
 - reg: Base addresses and lengths of the PCIe controller.
 - #address-cells: Address representation for root ports (must be 3)
 - #size-cells: Size representation for root ports (must be 2)
-- #interrupt-cells: Size representation for interrupts (must be 1)
-- interrupt-map-mask and interrupt-map: Standard PCI IRQ mapping properties
-  Please refer to the standard PCI bus binding document for a more detailed
-  explanation.
 - clocks: Must contain an entry for each entry in clock-names.
   See ../clocks/clock-bindings.txt for details.
 - clock-names: Must include the following entries:
@@ -20,12 +15,6 @@ Required properties:
   - sys_ck0 :for clock of Port0
   - sys_ck1 :for clock of Port1
   - sys_ck2 :for clock of Port2
-- resets: Must contain an entry for each entry in reset-names.
-  See ../reset/reset.txt for details.
-- reset-names: Must include the following entries:
-  - pcie-rst0 :port0 reset
-  - pcie-rst1 :port1 reset
-  - pcie-rst2 :port2 reset
 - phys: List of PHY specifiers (used by generic PHY framework).
 - phy-names : Must be "pcie-phy0", "pcie-phy1", "pcie-phyN".. based on the
   number of PHYs as specified in *phys* property.
@@ -34,6 +23,16 @@ Required properties:
 - bus-range: Range of bus numbers associated with this controller.
 - ranges: Ranges for the PCI memory and I/O regions.
 
+Required properties for MT7623/MT2701:
+- #interrupt-cells: Size representation for interrupts (must be 1)
+- interrupt-map-mask and interrupt-map: Standard PCI IRQ mapping properties
+  Please refer to the standard PCI bus binding document for a more detailed
+  explanation.
+- resets: Must contain an entry for each entry in reset-names.
+  See ../reset/reset.txt for details.
+- reset-names: Must be "pcie-rst0", "pcie-rst1", "pcie-rstN".. based on the
+  number of root ports.
+
 In addition, the device tree node must have sub-nodes describing each
 PCIe port interface, having the following mandatory properties:
 
-- 
2.6.4

^ permalink raw reply related	[flat|nested] 80+ messages in thread

* [PATCH v2 4/5] PCI: mediatek: Add new generation controller support
  2017-07-27  2:58 ` honghui.zhang
  (?)
@ 2017-07-27  2:58   ` honghui.zhang
  -1 siblings, 0 replies; 80+ messages in thread
From: honghui.zhang @ 2017-07-27  2:58 UTC (permalink / raw)
  To: bhelgaas, robh, robh+dt, matthias.bgg, linux-arm-kernel,
	linux-mediatek, linux-pci, linux-kernel, devicetree,
	yingjoe.chen, eddie.huang, ryder.lee
  Cc: honghui.zhang, hongkun.cao, youlin.pei, yong.wu, yt.shen,
	sean.wang, xinping.qian

From: Ryder Lee <ryder.lee@mediatek.com>

Add support for new Gen2 controller which has two root ports and shares
the probing flow with legacy controller. Currently this IP block can be
found on MT7622/MT2712.

Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
Signed-off-by: Honghui Zhang <honghui.zhang@mediatek.com>
---
 drivers/pci/host/Kconfig         |   5 +-
 drivers/pci/host/pcie-mediatek.c | 490 ++++++++++++++++++++++++++++++++++++++-
 2 files changed, 489 insertions(+), 6 deletions(-)

diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
index 89d61c2..5b1ae9f 100644
--- a/drivers/pci/host/Kconfig
+++ b/drivers/pci/host/Kconfig
@@ -182,14 +182,13 @@ config PCIE_ROCKCHIP
 
 config PCIE_MEDIATEK
 	bool "MediaTek PCIe controller"
-	depends on ARM && (ARCH_MEDIATEK || COMPILE_TEST)
+	depends on (ARM || ARM64) && (ARCH_MEDIATEK || COMPILE_TEST)
 	depends on OF
 	depends on PCI
 	select PCIEPORTBUS
 	help
 	  Say Y here if you want to enable PCIe controller support on
-	  MT7623 series SoCs.  There is one single root complex with 3 root
-	  ports available.  Each port supports Gen2 lane x1.
+	  MediaTek SoCs.
 
 config PCIE_TANGO_SMP8759
 	bool "Tango SMP8759 PCIe controller (DANGEROUS)"
diff --git a/drivers/pci/host/pcie-mediatek.c b/drivers/pci/host/pcie-mediatek.c
index f8e2f68..5fe92ff 100644
--- a/drivers/pci/host/pcie-mediatek.c
+++ b/drivers/pci/host/pcie-mediatek.c
@@ -3,6 +3,7 @@
  *
  * Copyright (c) 2017 MediaTek Inc.
  * Author: Ryder Lee <ryder.lee@mediatek.com>
+ *	   Honghui Zhang <honghui.zhang@mediatek.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
@@ -17,6 +18,8 @@
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/iopoll.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
 #include <linux/kernel.h>
 #include <linux/of_address.h>
 #include <linux/of_pci.h>
@@ -64,16 +67,77 @@
 #define PCIE_FC_CREDIT_MASK	(GENMASK(31, 31) | GENMASK(28, 16))
 #define PCIE_FC_CREDIT_VAL(x)	((x) << 16)
 
+/* PCIe V2 share registers */
+#define PCIE_SYS_CFG_V2		0x0
+#define PCIE_CSR_LTSSM_EN(x)	BIT(0 + (x) * 8)
+#define PCIE_CSR_ASPM_L1_EN(x)	BIT(1 + (x) * 8)
+
+/* PCIe V2 per-port registers */
+#define PCIE_INT_MASK		0x420
+#define INTX_MASK		GENMASK(19, 16)
+#define INTX_SHIFT		16
+#define INTX_NUM		4
+#define PCIE_INT_STATUS		0x424
+
+#define PCIE_AHB_TRANS_BASE0_L	0x438
+#define PCIE_AHB_TRANS_BASE0_H	0x43c
+#define AHB2PCIE_BASEL(x)	((x) & GENMASK(31, 0))
+#define AHB2PCIE_BASEH(x)	(((u64)(x) >> 32) & GENMASK(31, 0))
+#define AHB2PCIE_SIZE(x)	((x) & GENMASK(4, 0))
+#define PCIE_AXI_WINDOW0	0x448
+#define WIN_ENABLE		BIT(7)
+
+/* PCIe V2 Configuration Transaction Header */
+#define PCIE_CFG_HEADER0	0x460
+#define PCIE_CFG_HEADER1	0x464
+#define PCIE_CFG_HEADER2	0x468
+#define PCIE_CFG_WDATA		0x470
+#define PCIE_APP_TLP_REQ	0x488
+#define PCIE_CFG_RDATA		0x48c
+#define APP_CFG_REQ		BIT(0)
+#define APP_CPL_STATUS		GENMASK(7, 5)
+
+#define CFG_WRRD_TYPE_0		4
+#define CFG_WR_FMT		2
+#define CFG_RD_FMT		0
+
+#define CFG_DW0_LENGTH(length)	((length) & GENMASK(9, 0))
+#define CFG_DW0_TYPE(type)	(((type) << 24) & GENMASK(28, 24))
+#define CFG_DW0_FMT(fmt)	(((fmt) << 29) & GENMASK(31, 29))
+#define CFG_DW2_REGN(regn)	((regn) & GENMASK(11, 2))
+#define CFG_DW2_FUN(fun)	(((fun) << 16) & GENMASK(18, 16))
+#define CFG_DW2_DEV(dev)	(((dev) << 19) & GENMASK(23, 19))
+#define CFG_DW2_BUS(bus)	(((bus) << 24) & GENMASK(31, 24))
+#define CFG_HEADER_DW0(type, fmt) \
+	(CFG_DW0_LENGTH(1) | CFG_DW0_TYPE(type) | CFG_DW0_FMT(fmt))
+#define CFG_HEADER_DW1(where, size) \
+	(GENMASK(((size) - 1), 0) << ((where) & 0x3))
+#define CFG_HEADER_DW2(regn, fun, dev, bus) \
+	(CFG_DW2_REGN(regn) | CFG_DW2_FUN(fun) | \
+	CFG_DW2_DEV(dev) | CFG_DW2_BUS(bus))
+
+#define PCIE_RST_CTRL		0x510
+#define PCIE_PHY_RSTB		BIT(0)
+#define PCIE_PIPE_SRSTB		BIT(1)
+#define PCIE_MAC_SRSTB		BIT(2)
+#define PCIE_CRSTB		BIT(3)
+#define PCIE_PERSTB		BIT(8)
+#define PCI_LINKDOWN_RST_EN	GENMASK(15, 13)
+#define PCIE_LINK_STATUS_V2	0x804
+#define PCIE_PORT_LINKUP_V2	BIT(10)
+
 struct mtk_pcie_port;
 
 /**
  * struct mtk_pcie_soc - differentiate between host generations
  * @ops: pointer to configuration access functions
  * @startup: pointer to controller setting functions
+ * @setup_irq: pointer to initialize irq functions
  */
 struct mtk_pcie_soc {
 	struct pci_ops *ops;
 	int (*startup)(struct mtk_pcie_port *port);
+	int (*setup_irq)(struct mtk_pcie_port *port, struct device_node *node);
 };
 
 /**
@@ -82,10 +146,18 @@ struct mtk_pcie_soc {
  * @list: port list
  * @pcie: pointer to PCIe host info
  * @reset: pointer to port reset control
- * @sys_ck: pointer to bus clock
+ * @sys_ck: pointer to transaction/data link layer clock
+ * @ahb_ck: pinter to AHB slave interface operating clock for CSR access
+ *          and RC initiated MMIO access
+ * @axi_ck: pointer to application layer MMIO channel operating clock
+ * @aux_ck: pointer to pe2_mac_bridge and pe2_mac_core operating clock
+ *          when pcie_mac_ck/pcie_pipe_ck is turned off
+ * @obff_ck: pointer to OBFF functional block operating clock
+ * @pipe_ck: pointer to LTSSM and phy/mac layer operating clock
  * @phy: pointer to phy control block
  * @lane: lane count
  * @index: port index
+ * @irq_domain: legacy intx irq domain
  */
 struct mtk_pcie_port {
 	void __iomem *base;
@@ -93,9 +165,15 @@ struct mtk_pcie_port {
 	struct mtk_pcie *pcie;
 	struct reset_control *reset;
 	struct clk *sys_ck;
+	struct clk *ahb_ck;
+	struct clk *axi_ck;
+	struct clk *aux_ck;
+	struct clk *obff_ck;
+	struct clk *pipe_ck;
 	struct phy *phy;
 	u32 lane;
 	u32 index;
+	struct irq_domain *irq_domain;
 };
 
 /**
@@ -156,6 +234,12 @@ static void mtk_pcie_put_resources(struct mtk_pcie *pcie)
 
 	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
 		phy_power_off(port->phy);
+		phy_exit(port->phy);
+		clk_disable_unprepare(port->pipe_ck);
+		clk_disable_unprepare(port->obff_ck);
+		clk_disable_unprepare(port->axi_ck);
+		clk_disable_unprepare(port->aux_ck);
+		clk_disable_unprepare(port->ahb_ck);
 		clk_disable_unprepare(port->sys_ck);
 		mtk_pcie_port_free(port);
 	}
@@ -163,6 +247,298 @@ static void mtk_pcie_put_resources(struct mtk_pcie *pcie)
 	mtk_pcie_subsys_powerdown(pcie);
 }
 
+static int mtk_pcie_check_cfg_cpld(struct mtk_pcie_port *port)
+{
+	u32 val;
+	int err;
+
+	err = readl_poll_timeout_atomic(port->base + PCIE_APP_TLP_REQ, val,
+					!(val & APP_CFG_REQ), 10,
+					100 * USEC_PER_MSEC);
+	if (err)
+		return PCIBIOS_SET_FAILED;
+
+	if (readl(port->base + PCIE_APP_TLP_REQ) & APP_CPL_STATUS)
+		return PCIBIOS_SET_FAILED;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int mtk_pcie_hw_rd_cfg(struct mtk_pcie_port *port, u32 bus, u32 devfn,
+			      int where, int size, u32 *val)
+{
+	int reg, shift = 8 * (where & 3);
+
+	/* Write PCIe Configuration Transaction Header for cfgrd */
+	writel(CFG_HEADER_DW0(CFG_WRRD_TYPE_0, CFG_RD_FMT),
+	       port->base + PCIE_CFG_HEADER0);
+	writel(CFG_HEADER_DW1(where, size), port->base + PCIE_CFG_HEADER1);
+	writel(CFG_HEADER_DW2(where, PCI_FUNC(devfn), PCI_SLOT(devfn), bus),
+	       port->base + PCIE_CFG_HEADER2);
+
+	/* Triget h/w to transmit Cfgrd TLP */
+	reg = readl(port->base + PCIE_APP_TLP_REQ);
+	writel(reg | APP_CFG_REQ, port->base + PCIE_APP_TLP_REQ);
+
+	/* Check complete condition */
+	if (mtk_pcie_check_cfg_cpld(port))
+		return PCIBIOS_SET_FAILED;
+
+	/* Read cpld payload of Cfgrd */
+	*val = readl(port->base + PCIE_CFG_RDATA);
+
+	switch (size) {
+	case 4:
+		break;
+	case 3:
+		*val = (*val >> shift) & 0xffffff;
+		break;
+	case 2:
+		*val = (*val >> shift) & 0xffff;
+		break;
+	case 1:
+		*val = (*val >> shift) & 0xff;
+		break;
+	default:
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+	}
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int mtk_pcie_hw_wr_cfg(struct mtk_pcie_port *port, u32 bus, u32 devfn,
+			      int where, int size, u32 val)
+{
+	/* Write PCIe Configuration Transaction Header for Cfgwr */
+	writel(CFG_HEADER_DW0(CFG_WRRD_TYPE_0, CFG_WR_FMT),
+	       port->base + PCIE_CFG_HEADER0);
+	writel(CFG_HEADER_DW1(where, size), port->base + PCIE_CFG_HEADER1);
+	writel(CFG_HEADER_DW2(where, PCI_FUNC(devfn), PCI_SLOT(devfn), bus),
+	       port->base + PCIE_CFG_HEADER2);
+
+	/* Write cfgwr data */
+	val = val << 8 * (where & 3);
+	writel(val, port->base + PCIE_CFG_WDATA);
+
+	/* Triget h/w to transmit Cfgwr TLP */
+	val = readl(port->base + PCIE_APP_TLP_REQ);
+	val |= APP_CFG_REQ;
+	writel(val, port->base + PCIE_APP_TLP_REQ);
+
+	/* Check complete condition */
+	return mtk_pcie_check_cfg_cpld(port);
+}
+
+static struct mtk_pcie_port *mtk_pcie_find_port(struct mtk_pcie *pcie,
+						struct pci_bus *bus, int devfn)
+{
+	struct pci_dev *dev;
+	struct pci_bus *pbus;
+	struct mtk_pcie_port *port, *tmp;
+
+	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
+		if (bus->number == 0 && port->index == PCI_SLOT(devfn)) {
+			return port;
+		} else if (bus->number != 0) {
+			pbus = bus;
+			do {
+				dev = pbus->self;
+				if (port->index == PCI_SLOT(dev->devfn))
+					return port;
+				pbus = dev->bus;
+			} while (dev->bus->number != 0);
+		}
+	}
+
+	return NULL;
+}
+
+static int mtk_pcie_config_read(struct pci_bus *bus, unsigned int devfn,
+				int where, int size, u32 *val)
+{
+	struct mtk_pcie_port *port;
+	struct pci_host_bridge *host = pci_find_host_bridge(bus);
+	struct mtk_pcie *pcie = pci_host_bridge_priv(host);
+	u32 bn = bus->number;
+	int ret;
+
+	port = mtk_pcie_find_port(pcie, bus, devfn);
+	if (!port) {
+		*val = ~0;
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	}
+
+	ret = mtk_pcie_hw_rd_cfg(port, bn, devfn, where, size, val);
+	if (ret)
+		*val = ~0;
+
+	return ret;
+}
+
+static int mtk_pcie_config_write(struct pci_bus *bus, unsigned int devfn,
+				 int where, int size, u32 val)
+{
+	u32 bn = bus->number;
+	struct pci_host_bridge *host = pci_find_host_bridge(bus);
+	struct mtk_pcie *pcie = pci_host_bridge_priv(host);
+	struct mtk_pcie_port *port;
+
+	port = mtk_pcie_find_port(pcie, bus, devfn);
+	if (!port)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	return mtk_pcie_hw_wr_cfg(port, bn, devfn, where, size, val);
+}
+
+static struct pci_ops mtk_pcie_ops_v2 = {
+	.read  = mtk_pcie_config_read,
+	.write = mtk_pcie_config_write,
+};
+
+static int mtk_pcie_startup_ports_v2(struct mtk_pcie_port *port)
+{
+	struct mtk_pcie *pcie = port->pcie;
+	struct resource *mem = &pcie->mem;
+	u32 val;
+	size_t size;
+	int err;
+
+	/* mt7622 platforms need to enable LTSSM and ASPM from PCIe subsys */
+	if (pcie->base) {
+		val = readl(pcie->base + PCIE_SYS_CFG_V2);
+		val |= PCIE_CSR_LTSSM_EN(port->index) |
+		       PCIE_CSR_ASPM_L1_EN(port->index);
+		writel(val, pcie->base + PCIE_SYS_CFG_V2);
+	}
+
+	/* Assert all reset signals */
+	writel(0, port->base + PCIE_RST_CTRL);
+
+	/*
+	 * Enable rc internal reset.
+	 * The reset will work when the link is from link up to link down.
+	 */
+	writel(PCI_LINKDOWN_RST_EN, port->base + PCIE_RST_CTRL);
+
+	/* De-assert phy, pe, pipe, mac and configuration reset	*/
+	val = readl(port->base + PCIE_RST_CTRL);
+	val |= PCIE_PHY_RSTB | PCIE_PERSTB | PCIE_PIPE_SRSTB |
+	       PCIE_MAC_SRSTB | PCIE_CRSTB;
+	writel(val, port->base + PCIE_RST_CTRL);
+
+	/* PCIe v2.0 need at least 100ms delay to train from Gen1 to Gen2 */
+	err = readl_poll_timeout(port->base + PCIE_LINK_STATUS_V2, val,
+				 !!(val & PCIE_PORT_LINKUP_V2), 20,
+				 100 * USEC_PER_MSEC);
+	if (err)
+		return -ETIMEDOUT;
+
+	/* Set INTx mask */
+	val = readl(port->base + PCIE_INT_MASK);
+	val &= ~INTX_MASK;
+	writel(val, port->base + PCIE_INT_MASK);
+
+	/* Set AHB to PCIe translation windows */
+	size = mem->end - mem->start;
+	val = AHB2PCIE_BASEL(mem->start) | AHB2PCIE_SIZE(fls(size));
+	writel(val, port->base + PCIE_AHB_TRANS_BASE0_L);
+
+	val = AHB2PCIE_BASEH(mem->start);
+	writel(val, port->base + PCIE_AHB_TRANS_BASE0_H);
+
+	/* Set PCIe to axi translation memory space.*/
+	val = fls(0xffffffff) | WIN_ENABLE;
+	writel(val, port->base + PCIE_AXI_WINDOW0);
+
+	return 0;
+}
+
+static int mtk_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
+			     irq_hw_number_t hwirq)
+{
+	irq_set_chip_and_handler(irq, &dummy_irq_chip, handle_simple_irq);
+	irq_set_chip_data(irq, domain->host_data);
+
+	return 0;
+}
+
+static const struct irq_domain_ops intx_domain_ops = {
+	.map = mtk_pcie_intx_map,
+};
+
+static int mtk_pcie_init_irq_domain(struct mtk_pcie_port *port,
+				    struct device_node *node)
+{
+	struct device *dev = port->pcie->dev;
+	struct device_node *pcie_intc_node;
+
+	/* Setup INTx */
+	pcie_intc_node = of_get_next_child(node, NULL);
+	if (!pcie_intc_node) {
+		dev_err(dev, "No PCIe Intc node found\n");
+		return PTR_ERR(pcie_intc_node);
+	}
+
+	port->irq_domain = irq_domain_add_linear(pcie_intc_node, INTX_NUM,
+						 &intx_domain_ops, port);
+	if (!port->irq_domain) {
+		dev_err(dev, "Failed to get INTx IRQ domain\n");
+		return PTR_ERR(port->irq_domain);
+	}
+
+	return 0;
+}
+
+static irqreturn_t mtk_pcie_intr_handler(int irq, void *data)
+{
+	struct mtk_pcie_port *port = (struct mtk_pcie_port *)data;
+	struct device *dev = port->pcie->dev;
+	unsigned long status;
+	u32 virq;
+	u32 bit = INTX_SHIFT;
+
+	while ((status = readl(port->base + PCIE_INT_STATUS)) & INTX_MASK) {
+		for_each_set_bit_from(bit, &status, INTX_NUM + INTX_SHIFT) {
+			/* Clear the INTx */
+			writel(1 << bit, port->base + PCIE_INT_STATUS);
+			virq = irq_find_mapping(port->irq_domain,
+						bit - INTX_SHIFT);
+			if (virq)
+				generic_handle_irq(virq);
+			else
+				dev_err(dev, "unexpected IRQ, INT%d\n",
+					bit - INTX_SHIFT);
+		}
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int mtk_pcie_setup_irq(struct mtk_pcie_port *port,
+			      struct device_node *node)
+{
+	struct mtk_pcie *pcie = port->pcie;
+	struct device *dev = pcie->dev;
+	struct platform_device *pdev = to_platform_device(dev);
+	int err, irq;
+
+	irq = platform_get_irq(pdev, port->index);
+	err = devm_request_irq(dev, irq, mtk_pcie_intr_handler,
+			       IRQF_SHARED, "mtk-pcie", port);
+	if (err) {
+		dev_err(dev, "unable to request irq %d\n", irq);
+		return err;
+	}
+
+	err = mtk_pcie_init_irq_domain(port, node);
+	if (err) {
+		dev_err(dev, "failed to init pcie lagecy irq domain\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
 static void __iomem *mtk_pcie_map_bus(struct pci_bus *bus,
 				      unsigned int devfn, int where)
 {
@@ -249,13 +625,49 @@ static void mtk_pcie_enable_ports(struct mtk_pcie_port *port)
 
 	err = clk_prepare_enable(port->sys_ck);
 	if (err) {
-		dev_err(dev, "failed to enable port%d clock\n", port->index);
+		dev_err(dev, "failed to enable sys_ck%d\n", port->index);
 		goto err_sys_clk;
 	}
 
+	err = clk_prepare_enable(port->ahb_ck);
+	if (err) {
+		dev_err(dev, "failed to enable ahb_ck%d\n", port->index);
+		goto err_ahb_clk;
+	}
+
+	err = clk_prepare_enable(port->aux_ck);
+	if (err) {
+		dev_err(dev, "failed to enable aux_ck%d\n", port->index);
+		goto err_aux_clk;
+	}
+
+	err = clk_prepare_enable(port->axi_ck);
+	if (err) {
+		dev_err(dev, "failed to enable axi_ck%d\n", port->index);
+		goto err_axi_clk;
+	}
+
+	err = clk_prepare_enable(port->obff_ck);
+	if (err) {
+		dev_err(dev, "failed to enable obff_ck%d\n", port->index);
+		goto err_obff_clk;
+	}
+
+	err = clk_prepare_enable(port->pipe_ck);
+	if (err) {
+		dev_err(dev, "failed to enable pipe_ck%d\n", port->index);
+		goto err_pipe_clk;
+	}
+
 	reset_control_assert(port->reset);
 	reset_control_deassert(port->reset);
 
+	err = phy_init(port->phy);
+	if (err) {
+		dev_err(dev, "failed to initialize port%d phy\n", port->index);
+		goto err_phy_init;
+	}
+
 	err = phy_power_on(port->phy);
 	if (err) {
 		dev_err(dev, "failed to power on port%d phy\n", port->index);
@@ -269,6 +681,18 @@ static void mtk_pcie_enable_ports(struct mtk_pcie_port *port)
 
 	phy_power_off(port->phy);
 err_phy_on:
+	phy_exit(port->phy);
+err_phy_init:
+	clk_disable_unprepare(port->pipe_ck);
+err_pipe_clk:
+	clk_disable_unprepare(port->obff_ck);
+err_obff_clk:
+	clk_disable_unprepare(port->axi_ck);
+err_axi_clk:
+	clk_disable_unprepare(port->aux_ck);
+err_aux_clk:
+	clk_disable_unprepare(port->ahb_ck);
+err_ahb_clk:
 	clk_disable_unprepare(port->sys_ck);
 err_sys_clk:
 	mtk_pcie_port_free(port);
@@ -306,10 +730,56 @@ static int mtk_pcie_parse_ports(struct mtk_pcie *pcie,
 	snprintf(name, sizeof(name), "sys_ck%d", index);
 	port->sys_ck = devm_clk_get(dev, name);
 	if (IS_ERR(port->sys_ck)) {
-		dev_err(dev, "failed to get port%d clock\n", index);
+		dev_err(dev, "failed to get sys_ck%d\n", index);
 		return PTR_ERR(port->sys_ck);
 	}
 
+	/* sys_ck might be divided into the following parts in some chips */
+	snprintf(name, sizeof(name), "ahb_ck%d", index);
+	port->ahb_ck = devm_clk_get(dev, name);
+	if (IS_ERR(port->ahb_ck)) {
+		if (PTR_ERR(port->ahb_ck) == -EPROBE_DEFER)
+			return -EPROBE_DEFER;
+
+		port->ahb_ck = NULL;
+	}
+
+	snprintf(name, sizeof(name), "axi_ck%d", index);
+	port->axi_ck = devm_clk_get(dev, name);
+	if (IS_ERR(port->axi_ck)) {
+		if (PTR_ERR(port->axi_ck) == -EPROBE_DEFER)
+			return -EPROBE_DEFER;
+
+		port->axi_ck = NULL;
+	}
+
+	snprintf(name, sizeof(name), "aux_ck%d", index);
+	port->aux_ck = devm_clk_get(dev, name);
+	if (IS_ERR(port->aux_ck)) {
+		if (PTR_ERR(port->aux_ck) == -EPROBE_DEFER)
+			return -EPROBE_DEFER;
+
+		port->aux_ck = NULL;
+	}
+
+	snprintf(name, sizeof(name), "obff_ck%d", index);
+	port->obff_ck = devm_clk_get(dev, name);
+	if (IS_ERR(port->obff_ck)) {
+		if (PTR_ERR(port->obff_ck) == -EPROBE_DEFER)
+			return -EPROBE_DEFER;
+
+		port->obff_ck = NULL;
+	}
+
+	snprintf(name, sizeof(name), "pipe_ck%d", index);
+	port->pipe_ck = devm_clk_get(dev, name);
+	if (IS_ERR(port->pipe_ck)) {
+		if (PTR_ERR(port->pipe_ck) == -EPROBE_DEFER)
+			return -EPROBE_DEFER;
+
+		port->pipe_ck = NULL;
+	}
+
 	snprintf(name, sizeof(name), "pcie-rst%d", index);
 	port->reset = devm_reset_control_get_optional(dev, name);
 	if (PTR_ERR(port->reset) == -EPROBE_DEFER)
@@ -324,6 +794,12 @@ static int mtk_pcie_parse_ports(struct mtk_pcie *pcie,
 	port->index = index;
 	port->pcie = pcie;
 
+	if (pcie->soc->setup_irq) {
+		err = pcie->soc->setup_irq(port, node);
+		if (err)
+			return err;
+	}
+
 	INIT_LIST_HEAD(&port->list);
 	list_add_tail(&port->list, &pcie->ports);
 
@@ -553,9 +1029,17 @@ static struct mtk_pcie_soc mtk_pcie_soc_v1 = {
 	.startup = mtk_pcie_startup_ports,
 };
 
+static struct mtk_pcie_soc mtk_pcie_soc_v2 = {
+	.ops = &mtk_pcie_ops_v2,
+	.startup = mtk_pcie_startup_ports_v2,
+	.setup_irq = mtk_pcie_setup_irq,
+};
+
 static const struct of_device_id mtk_pcie_ids[] = {
 	{ .compatible = "mediatek,mt2701-pcie", .data = &mtk_pcie_soc_v1 },
 	{ .compatible = "mediatek,mt7623-pcie", .data = &mtk_pcie_soc_v1 },
+	{ .compatible = "mediatek,mt2712-pcie", .data = &mtk_pcie_soc_v2 },
+	{ .compatible = "mediatek,mt7622-pcie", .data = &mtk_pcie_soc_v2 },
 	{},
 };
 
-- 
2.6.4

^ permalink raw reply related	[flat|nested] 80+ messages in thread

* [PATCH v2 4/5] PCI: mediatek: Add new generation controller support
@ 2017-07-27  2:58   ` honghui.zhang
  0 siblings, 0 replies; 80+ messages in thread
From: honghui.zhang @ 2017-07-27  2:58 UTC (permalink / raw)
  To: bhelgaas, robh, robh+dt, matthias.bgg, linux-arm-kernel,
	linux-mediatek, linux-pci, linux-kernel, devicetree,
	yingjoe.chen, eddie.huang, ryder.lee
  Cc: honghui.zhang, hongkun.cao, youlin.pei, yong.wu, yt.shen,
	sean.wang, xinping.qian

From: Ryder Lee <ryder.lee@mediatek.com>

Add support for new Gen2 controller which has two root ports and shares
the probing flow with legacy controller. Currently this IP block can be
found on MT7622/MT2712.

Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
Signed-off-by: Honghui Zhang <honghui.zhang@mediatek.com>
---
 drivers/pci/host/Kconfig         |   5 +-
 drivers/pci/host/pcie-mediatek.c | 490 ++++++++++++++++++++++++++++++++++++++-
 2 files changed, 489 insertions(+), 6 deletions(-)

diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
index 89d61c2..5b1ae9f 100644
--- a/drivers/pci/host/Kconfig
+++ b/drivers/pci/host/Kconfig
@@ -182,14 +182,13 @@ config PCIE_ROCKCHIP
 
 config PCIE_MEDIATEK
 	bool "MediaTek PCIe controller"
-	depends on ARM && (ARCH_MEDIATEK || COMPILE_TEST)
+	depends on (ARM || ARM64) && (ARCH_MEDIATEK || COMPILE_TEST)
 	depends on OF
 	depends on PCI
 	select PCIEPORTBUS
 	help
 	  Say Y here if you want to enable PCIe controller support on
-	  MT7623 series SoCs.  There is one single root complex with 3 root
-	  ports available.  Each port supports Gen2 lane x1.
+	  MediaTek SoCs.
 
 config PCIE_TANGO_SMP8759
 	bool "Tango SMP8759 PCIe controller (DANGEROUS)"
diff --git a/drivers/pci/host/pcie-mediatek.c b/drivers/pci/host/pcie-mediatek.c
index f8e2f68..5fe92ff 100644
--- a/drivers/pci/host/pcie-mediatek.c
+++ b/drivers/pci/host/pcie-mediatek.c
@@ -3,6 +3,7 @@
  *
  * Copyright (c) 2017 MediaTek Inc.
  * Author: Ryder Lee <ryder.lee@mediatek.com>
+ *	   Honghui Zhang <honghui.zhang@mediatek.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
@@ -17,6 +18,8 @@
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/iopoll.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
 #include <linux/kernel.h>
 #include <linux/of_address.h>
 #include <linux/of_pci.h>
@@ -64,16 +67,77 @@
 #define PCIE_FC_CREDIT_MASK	(GENMASK(31, 31) | GENMASK(28, 16))
 #define PCIE_FC_CREDIT_VAL(x)	((x) << 16)
 
+/* PCIe V2 share registers */
+#define PCIE_SYS_CFG_V2		0x0
+#define PCIE_CSR_LTSSM_EN(x)	BIT(0 + (x) * 8)
+#define PCIE_CSR_ASPM_L1_EN(x)	BIT(1 + (x) * 8)
+
+/* PCIe V2 per-port registers */
+#define PCIE_INT_MASK		0x420
+#define INTX_MASK		GENMASK(19, 16)
+#define INTX_SHIFT		16
+#define INTX_NUM		4
+#define PCIE_INT_STATUS		0x424
+
+#define PCIE_AHB_TRANS_BASE0_L	0x438
+#define PCIE_AHB_TRANS_BASE0_H	0x43c
+#define AHB2PCIE_BASEL(x)	((x) & GENMASK(31, 0))
+#define AHB2PCIE_BASEH(x)	(((u64)(x) >> 32) & GENMASK(31, 0))
+#define AHB2PCIE_SIZE(x)	((x) & GENMASK(4, 0))
+#define PCIE_AXI_WINDOW0	0x448
+#define WIN_ENABLE		BIT(7)
+
+/* PCIe V2 Configuration Transaction Header */
+#define PCIE_CFG_HEADER0	0x460
+#define PCIE_CFG_HEADER1	0x464
+#define PCIE_CFG_HEADER2	0x468
+#define PCIE_CFG_WDATA		0x470
+#define PCIE_APP_TLP_REQ	0x488
+#define PCIE_CFG_RDATA		0x48c
+#define APP_CFG_REQ		BIT(0)
+#define APP_CPL_STATUS		GENMASK(7, 5)
+
+#define CFG_WRRD_TYPE_0		4
+#define CFG_WR_FMT		2
+#define CFG_RD_FMT		0
+
+#define CFG_DW0_LENGTH(length)	((length) & GENMASK(9, 0))
+#define CFG_DW0_TYPE(type)	(((type) << 24) & GENMASK(28, 24))
+#define CFG_DW0_FMT(fmt)	(((fmt) << 29) & GENMASK(31, 29))
+#define CFG_DW2_REGN(regn)	((regn) & GENMASK(11, 2))
+#define CFG_DW2_FUN(fun)	(((fun) << 16) & GENMASK(18, 16))
+#define CFG_DW2_DEV(dev)	(((dev) << 19) & GENMASK(23, 19))
+#define CFG_DW2_BUS(bus)	(((bus) << 24) & GENMASK(31, 24))
+#define CFG_HEADER_DW0(type, fmt) \
+	(CFG_DW0_LENGTH(1) | CFG_DW0_TYPE(type) | CFG_DW0_FMT(fmt))
+#define CFG_HEADER_DW1(where, size) \
+	(GENMASK(((size) - 1), 0) << ((where) & 0x3))
+#define CFG_HEADER_DW2(regn, fun, dev, bus) \
+	(CFG_DW2_REGN(regn) | CFG_DW2_FUN(fun) | \
+	CFG_DW2_DEV(dev) | CFG_DW2_BUS(bus))
+
+#define PCIE_RST_CTRL		0x510
+#define PCIE_PHY_RSTB		BIT(0)
+#define PCIE_PIPE_SRSTB		BIT(1)
+#define PCIE_MAC_SRSTB		BIT(2)
+#define PCIE_CRSTB		BIT(3)
+#define PCIE_PERSTB		BIT(8)
+#define PCI_LINKDOWN_RST_EN	GENMASK(15, 13)
+#define PCIE_LINK_STATUS_V2	0x804
+#define PCIE_PORT_LINKUP_V2	BIT(10)
+
 struct mtk_pcie_port;
 
 /**
  * struct mtk_pcie_soc - differentiate between host generations
  * @ops: pointer to configuration access functions
  * @startup: pointer to controller setting functions
+ * @setup_irq: pointer to initialize irq functions
  */
 struct mtk_pcie_soc {
 	struct pci_ops *ops;
 	int (*startup)(struct mtk_pcie_port *port);
+	int (*setup_irq)(struct mtk_pcie_port *port, struct device_node *node);
 };
 
 /**
@@ -82,10 +146,18 @@ struct mtk_pcie_soc {
  * @list: port list
  * @pcie: pointer to PCIe host info
  * @reset: pointer to port reset control
- * @sys_ck: pointer to bus clock
+ * @sys_ck: pointer to transaction/data link layer clock
+ * @ahb_ck: pinter to AHB slave interface operating clock for CSR access
+ *          and RC initiated MMIO access
+ * @axi_ck: pointer to application layer MMIO channel operating clock
+ * @aux_ck: pointer to pe2_mac_bridge and pe2_mac_core operating clock
+ *          when pcie_mac_ck/pcie_pipe_ck is turned off
+ * @obff_ck: pointer to OBFF functional block operating clock
+ * @pipe_ck: pointer to LTSSM and phy/mac layer operating clock
  * @phy: pointer to phy control block
  * @lane: lane count
  * @index: port index
+ * @irq_domain: legacy intx irq domain
  */
 struct mtk_pcie_port {
 	void __iomem *base;
@@ -93,9 +165,15 @@ struct mtk_pcie_port {
 	struct mtk_pcie *pcie;
 	struct reset_control *reset;
 	struct clk *sys_ck;
+	struct clk *ahb_ck;
+	struct clk *axi_ck;
+	struct clk *aux_ck;
+	struct clk *obff_ck;
+	struct clk *pipe_ck;
 	struct phy *phy;
 	u32 lane;
 	u32 index;
+	struct irq_domain *irq_domain;
 };
 
 /**
@@ -156,6 +234,12 @@ static void mtk_pcie_put_resources(struct mtk_pcie *pcie)
 
 	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
 		phy_power_off(port->phy);
+		phy_exit(port->phy);
+		clk_disable_unprepare(port->pipe_ck);
+		clk_disable_unprepare(port->obff_ck);
+		clk_disable_unprepare(port->axi_ck);
+		clk_disable_unprepare(port->aux_ck);
+		clk_disable_unprepare(port->ahb_ck);
 		clk_disable_unprepare(port->sys_ck);
 		mtk_pcie_port_free(port);
 	}
@@ -163,6 +247,298 @@ static void mtk_pcie_put_resources(struct mtk_pcie *pcie)
 	mtk_pcie_subsys_powerdown(pcie);
 }
 
+static int mtk_pcie_check_cfg_cpld(struct mtk_pcie_port *port)
+{
+	u32 val;
+	int err;
+
+	err = readl_poll_timeout_atomic(port->base + PCIE_APP_TLP_REQ, val,
+					!(val & APP_CFG_REQ), 10,
+					100 * USEC_PER_MSEC);
+	if (err)
+		return PCIBIOS_SET_FAILED;
+
+	if (readl(port->base + PCIE_APP_TLP_REQ) & APP_CPL_STATUS)
+		return PCIBIOS_SET_FAILED;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int mtk_pcie_hw_rd_cfg(struct mtk_pcie_port *port, u32 bus, u32 devfn,
+			      int where, int size, u32 *val)
+{
+	int reg, shift = 8 * (where & 3);
+
+	/* Write PCIe Configuration Transaction Header for cfgrd */
+	writel(CFG_HEADER_DW0(CFG_WRRD_TYPE_0, CFG_RD_FMT),
+	       port->base + PCIE_CFG_HEADER0);
+	writel(CFG_HEADER_DW1(where, size), port->base + PCIE_CFG_HEADER1);
+	writel(CFG_HEADER_DW2(where, PCI_FUNC(devfn), PCI_SLOT(devfn), bus),
+	       port->base + PCIE_CFG_HEADER2);
+
+	/* Triget h/w to transmit Cfgrd TLP */
+	reg = readl(port->base + PCIE_APP_TLP_REQ);
+	writel(reg | APP_CFG_REQ, port->base + PCIE_APP_TLP_REQ);
+
+	/* Check complete condition */
+	if (mtk_pcie_check_cfg_cpld(port))
+		return PCIBIOS_SET_FAILED;
+
+	/* Read cpld payload of Cfgrd */
+	*val = readl(port->base + PCIE_CFG_RDATA);
+
+	switch (size) {
+	case 4:
+		break;
+	case 3:
+		*val = (*val >> shift) & 0xffffff;
+		break;
+	case 2:
+		*val = (*val >> shift) & 0xffff;
+		break;
+	case 1:
+		*val = (*val >> shift) & 0xff;
+		break;
+	default:
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+	}
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int mtk_pcie_hw_wr_cfg(struct mtk_pcie_port *port, u32 bus, u32 devfn,
+			      int where, int size, u32 val)
+{
+	/* Write PCIe Configuration Transaction Header for Cfgwr */
+	writel(CFG_HEADER_DW0(CFG_WRRD_TYPE_0, CFG_WR_FMT),
+	       port->base + PCIE_CFG_HEADER0);
+	writel(CFG_HEADER_DW1(where, size), port->base + PCIE_CFG_HEADER1);
+	writel(CFG_HEADER_DW2(where, PCI_FUNC(devfn), PCI_SLOT(devfn), bus),
+	       port->base + PCIE_CFG_HEADER2);
+
+	/* Write cfgwr data */
+	val = val << 8 * (where & 3);
+	writel(val, port->base + PCIE_CFG_WDATA);
+
+	/* Triget h/w to transmit Cfgwr TLP */
+	val = readl(port->base + PCIE_APP_TLP_REQ);
+	val |= APP_CFG_REQ;
+	writel(val, port->base + PCIE_APP_TLP_REQ);
+
+	/* Check complete condition */
+	return mtk_pcie_check_cfg_cpld(port);
+}
+
+static struct mtk_pcie_port *mtk_pcie_find_port(struct mtk_pcie *pcie,
+						struct pci_bus *bus, int devfn)
+{
+	struct pci_dev *dev;
+	struct pci_bus *pbus;
+	struct mtk_pcie_port *port, *tmp;
+
+	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
+		if (bus->number == 0 && port->index == PCI_SLOT(devfn)) {
+			return port;
+		} else if (bus->number != 0) {
+			pbus = bus;
+			do {
+				dev = pbus->self;
+				if (port->index == PCI_SLOT(dev->devfn))
+					return port;
+				pbus = dev->bus;
+			} while (dev->bus->number != 0);
+		}
+	}
+
+	return NULL;
+}
+
+static int mtk_pcie_config_read(struct pci_bus *bus, unsigned int devfn,
+				int where, int size, u32 *val)
+{
+	struct mtk_pcie_port *port;
+	struct pci_host_bridge *host = pci_find_host_bridge(bus);
+	struct mtk_pcie *pcie = pci_host_bridge_priv(host);
+	u32 bn = bus->number;
+	int ret;
+
+	port = mtk_pcie_find_port(pcie, bus, devfn);
+	if (!port) {
+		*val = ~0;
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	}
+
+	ret = mtk_pcie_hw_rd_cfg(port, bn, devfn, where, size, val);
+	if (ret)
+		*val = ~0;
+
+	return ret;
+}
+
+static int mtk_pcie_config_write(struct pci_bus *bus, unsigned int devfn,
+				 int where, int size, u32 val)
+{
+	u32 bn = bus->number;
+	struct pci_host_bridge *host = pci_find_host_bridge(bus);
+	struct mtk_pcie *pcie = pci_host_bridge_priv(host);
+	struct mtk_pcie_port *port;
+
+	port = mtk_pcie_find_port(pcie, bus, devfn);
+	if (!port)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	return mtk_pcie_hw_wr_cfg(port, bn, devfn, where, size, val);
+}
+
+static struct pci_ops mtk_pcie_ops_v2 = {
+	.read  = mtk_pcie_config_read,
+	.write = mtk_pcie_config_write,
+};
+
+static int mtk_pcie_startup_ports_v2(struct mtk_pcie_port *port)
+{
+	struct mtk_pcie *pcie = port->pcie;
+	struct resource *mem = &pcie->mem;
+	u32 val;
+	size_t size;
+	int err;
+
+	/* mt7622 platforms need to enable LTSSM and ASPM from PCIe subsys */
+	if (pcie->base) {
+		val = readl(pcie->base + PCIE_SYS_CFG_V2);
+		val |= PCIE_CSR_LTSSM_EN(port->index) |
+		       PCIE_CSR_ASPM_L1_EN(port->index);
+		writel(val, pcie->base + PCIE_SYS_CFG_V2);
+	}
+
+	/* Assert all reset signals */
+	writel(0, port->base + PCIE_RST_CTRL);
+
+	/*
+	 * Enable rc internal reset.
+	 * The reset will work when the link is from link up to link down.
+	 */
+	writel(PCI_LINKDOWN_RST_EN, port->base + PCIE_RST_CTRL);
+
+	/* De-assert phy, pe, pipe, mac and configuration reset	*/
+	val = readl(port->base + PCIE_RST_CTRL);
+	val |= PCIE_PHY_RSTB | PCIE_PERSTB | PCIE_PIPE_SRSTB |
+	       PCIE_MAC_SRSTB | PCIE_CRSTB;
+	writel(val, port->base + PCIE_RST_CTRL);
+
+	/* PCIe v2.0 need at least 100ms delay to train from Gen1 to Gen2 */
+	err = readl_poll_timeout(port->base + PCIE_LINK_STATUS_V2, val,
+				 !!(val & PCIE_PORT_LINKUP_V2), 20,
+				 100 * USEC_PER_MSEC);
+	if (err)
+		return -ETIMEDOUT;
+
+	/* Set INTx mask */
+	val = readl(port->base + PCIE_INT_MASK);
+	val &= ~INTX_MASK;
+	writel(val, port->base + PCIE_INT_MASK);
+
+	/* Set AHB to PCIe translation windows */
+	size = mem->end - mem->start;
+	val = AHB2PCIE_BASEL(mem->start) | AHB2PCIE_SIZE(fls(size));
+	writel(val, port->base + PCIE_AHB_TRANS_BASE0_L);
+
+	val = AHB2PCIE_BASEH(mem->start);
+	writel(val, port->base + PCIE_AHB_TRANS_BASE0_H);
+
+	/* Set PCIe to axi translation memory space.*/
+	val = fls(0xffffffff) | WIN_ENABLE;
+	writel(val, port->base + PCIE_AXI_WINDOW0);
+
+	return 0;
+}
+
+static int mtk_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
+			     irq_hw_number_t hwirq)
+{
+	irq_set_chip_and_handler(irq, &dummy_irq_chip, handle_simple_irq);
+	irq_set_chip_data(irq, domain->host_data);
+
+	return 0;
+}
+
+static const struct irq_domain_ops intx_domain_ops = {
+	.map = mtk_pcie_intx_map,
+};
+
+static int mtk_pcie_init_irq_domain(struct mtk_pcie_port *port,
+				    struct device_node *node)
+{
+	struct device *dev = port->pcie->dev;
+	struct device_node *pcie_intc_node;
+
+	/* Setup INTx */
+	pcie_intc_node = of_get_next_child(node, NULL);
+	if (!pcie_intc_node) {
+		dev_err(dev, "No PCIe Intc node found\n");
+		return PTR_ERR(pcie_intc_node);
+	}
+
+	port->irq_domain = irq_domain_add_linear(pcie_intc_node, INTX_NUM,
+						 &intx_domain_ops, port);
+	if (!port->irq_domain) {
+		dev_err(dev, "Failed to get INTx IRQ domain\n");
+		return PTR_ERR(port->irq_domain);
+	}
+
+	return 0;
+}
+
+static irqreturn_t mtk_pcie_intr_handler(int irq, void *data)
+{
+	struct mtk_pcie_port *port = (struct mtk_pcie_port *)data;
+	struct device *dev = port->pcie->dev;
+	unsigned long status;
+	u32 virq;
+	u32 bit = INTX_SHIFT;
+
+	while ((status = readl(port->base + PCIE_INT_STATUS)) & INTX_MASK) {
+		for_each_set_bit_from(bit, &status, INTX_NUM + INTX_SHIFT) {
+			/* Clear the INTx */
+			writel(1 << bit, port->base + PCIE_INT_STATUS);
+			virq = irq_find_mapping(port->irq_domain,
+						bit - INTX_SHIFT);
+			if (virq)
+				generic_handle_irq(virq);
+			else
+				dev_err(dev, "unexpected IRQ, INT%d\n",
+					bit - INTX_SHIFT);
+		}
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int mtk_pcie_setup_irq(struct mtk_pcie_port *port,
+			      struct device_node *node)
+{
+	struct mtk_pcie *pcie = port->pcie;
+	struct device *dev = pcie->dev;
+	struct platform_device *pdev = to_platform_device(dev);
+	int err, irq;
+
+	irq = platform_get_irq(pdev, port->index);
+	err = devm_request_irq(dev, irq, mtk_pcie_intr_handler,
+			       IRQF_SHARED, "mtk-pcie", port);
+	if (err) {
+		dev_err(dev, "unable to request irq %d\n", irq);
+		return err;
+	}
+
+	err = mtk_pcie_init_irq_domain(port, node);
+	if (err) {
+		dev_err(dev, "failed to init pcie lagecy irq domain\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
 static void __iomem *mtk_pcie_map_bus(struct pci_bus *bus,
 				      unsigned int devfn, int where)
 {
@@ -249,13 +625,49 @@ static void mtk_pcie_enable_ports(struct mtk_pcie_port *port)
 
 	err = clk_prepare_enable(port->sys_ck);
 	if (err) {
-		dev_err(dev, "failed to enable port%d clock\n", port->index);
+		dev_err(dev, "failed to enable sys_ck%d\n", port->index);
 		goto err_sys_clk;
 	}
 
+	err = clk_prepare_enable(port->ahb_ck);
+	if (err) {
+		dev_err(dev, "failed to enable ahb_ck%d\n", port->index);
+		goto err_ahb_clk;
+	}
+
+	err = clk_prepare_enable(port->aux_ck);
+	if (err) {
+		dev_err(dev, "failed to enable aux_ck%d\n", port->index);
+		goto err_aux_clk;
+	}
+
+	err = clk_prepare_enable(port->axi_ck);
+	if (err) {
+		dev_err(dev, "failed to enable axi_ck%d\n", port->index);
+		goto err_axi_clk;
+	}
+
+	err = clk_prepare_enable(port->obff_ck);
+	if (err) {
+		dev_err(dev, "failed to enable obff_ck%d\n", port->index);
+		goto err_obff_clk;
+	}
+
+	err = clk_prepare_enable(port->pipe_ck);
+	if (err) {
+		dev_err(dev, "failed to enable pipe_ck%d\n", port->index);
+		goto err_pipe_clk;
+	}
+
 	reset_control_assert(port->reset);
 	reset_control_deassert(port->reset);
 
+	err = phy_init(port->phy);
+	if (err) {
+		dev_err(dev, "failed to initialize port%d phy\n", port->index);
+		goto err_phy_init;
+	}
+
 	err = phy_power_on(port->phy);
 	if (err) {
 		dev_err(dev, "failed to power on port%d phy\n", port->index);
@@ -269,6 +681,18 @@ static void mtk_pcie_enable_ports(struct mtk_pcie_port *port)
 
 	phy_power_off(port->phy);
 err_phy_on:
+	phy_exit(port->phy);
+err_phy_init:
+	clk_disable_unprepare(port->pipe_ck);
+err_pipe_clk:
+	clk_disable_unprepare(port->obff_ck);
+err_obff_clk:
+	clk_disable_unprepare(port->axi_ck);
+err_axi_clk:
+	clk_disable_unprepare(port->aux_ck);
+err_aux_clk:
+	clk_disable_unprepare(port->ahb_ck);
+err_ahb_clk:
 	clk_disable_unprepare(port->sys_ck);
 err_sys_clk:
 	mtk_pcie_port_free(port);
@@ -306,10 +730,56 @@ static int mtk_pcie_parse_ports(struct mtk_pcie *pcie,
 	snprintf(name, sizeof(name), "sys_ck%d", index);
 	port->sys_ck = devm_clk_get(dev, name);
 	if (IS_ERR(port->sys_ck)) {
-		dev_err(dev, "failed to get port%d clock\n", index);
+		dev_err(dev, "failed to get sys_ck%d\n", index);
 		return PTR_ERR(port->sys_ck);
 	}
 
+	/* sys_ck might be divided into the following parts in some chips */
+	snprintf(name, sizeof(name), "ahb_ck%d", index);
+	port->ahb_ck = devm_clk_get(dev, name);
+	if (IS_ERR(port->ahb_ck)) {
+		if (PTR_ERR(port->ahb_ck) == -EPROBE_DEFER)
+			return -EPROBE_DEFER;
+
+		port->ahb_ck = NULL;
+	}
+
+	snprintf(name, sizeof(name), "axi_ck%d", index);
+	port->axi_ck = devm_clk_get(dev, name);
+	if (IS_ERR(port->axi_ck)) {
+		if (PTR_ERR(port->axi_ck) == -EPROBE_DEFER)
+			return -EPROBE_DEFER;
+
+		port->axi_ck = NULL;
+	}
+
+	snprintf(name, sizeof(name), "aux_ck%d", index);
+	port->aux_ck = devm_clk_get(dev, name);
+	if (IS_ERR(port->aux_ck)) {
+		if (PTR_ERR(port->aux_ck) == -EPROBE_DEFER)
+			return -EPROBE_DEFER;
+
+		port->aux_ck = NULL;
+	}
+
+	snprintf(name, sizeof(name), "obff_ck%d", index);
+	port->obff_ck = devm_clk_get(dev, name);
+	if (IS_ERR(port->obff_ck)) {
+		if (PTR_ERR(port->obff_ck) == -EPROBE_DEFER)
+			return -EPROBE_DEFER;
+
+		port->obff_ck = NULL;
+	}
+
+	snprintf(name, sizeof(name), "pipe_ck%d", index);
+	port->pipe_ck = devm_clk_get(dev, name);
+	if (IS_ERR(port->pipe_ck)) {
+		if (PTR_ERR(port->pipe_ck) == -EPROBE_DEFER)
+			return -EPROBE_DEFER;
+
+		port->pipe_ck = NULL;
+	}
+
 	snprintf(name, sizeof(name), "pcie-rst%d", index);
 	port->reset = devm_reset_control_get_optional(dev, name);
 	if (PTR_ERR(port->reset) == -EPROBE_DEFER)
@@ -324,6 +794,12 @@ static int mtk_pcie_parse_ports(struct mtk_pcie *pcie,
 	port->index = index;
 	port->pcie = pcie;
 
+	if (pcie->soc->setup_irq) {
+		err = pcie->soc->setup_irq(port, node);
+		if (err)
+			return err;
+	}
+
 	INIT_LIST_HEAD(&port->list);
 	list_add_tail(&port->list, &pcie->ports);
 
@@ -553,9 +1029,17 @@ static struct mtk_pcie_soc mtk_pcie_soc_v1 = {
 	.startup = mtk_pcie_startup_ports,
 };
 
+static struct mtk_pcie_soc mtk_pcie_soc_v2 = {
+	.ops = &mtk_pcie_ops_v2,
+	.startup = mtk_pcie_startup_ports_v2,
+	.setup_irq = mtk_pcie_setup_irq,
+};
+
 static const struct of_device_id mtk_pcie_ids[] = {
 	{ .compatible = "mediatek,mt2701-pcie", .data = &mtk_pcie_soc_v1 },
 	{ .compatible = "mediatek,mt7623-pcie", .data = &mtk_pcie_soc_v1 },
+	{ .compatible = "mediatek,mt2712-pcie", .data = &mtk_pcie_soc_v2 },
+	{ .compatible = "mediatek,mt7622-pcie", .data = &mtk_pcie_soc_v2 },
 	{},
 };
 
-- 
2.6.4

^ permalink raw reply related	[flat|nested] 80+ messages in thread

* [PATCH v2 4/5] PCI: mediatek: Add new generation controller support
@ 2017-07-27  2:58   ` honghui.zhang
  0 siblings, 0 replies; 80+ messages in thread
From: honghui.zhang at mediatek.com @ 2017-07-27  2:58 UTC (permalink / raw)
  To: linux-arm-kernel

From: Ryder Lee <ryder.lee@mediatek.com>

Add support for new Gen2 controller which has two root ports and shares
the probing flow with legacy controller. Currently this IP block can be
found on MT7622/MT2712.

Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
Signed-off-by: Honghui Zhang <honghui.zhang@mediatek.com>
---
 drivers/pci/host/Kconfig         |   5 +-
 drivers/pci/host/pcie-mediatek.c | 490 ++++++++++++++++++++++++++++++++++++++-
 2 files changed, 489 insertions(+), 6 deletions(-)

diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
index 89d61c2..5b1ae9f 100644
--- a/drivers/pci/host/Kconfig
+++ b/drivers/pci/host/Kconfig
@@ -182,14 +182,13 @@ config PCIE_ROCKCHIP
 
 config PCIE_MEDIATEK
 	bool "MediaTek PCIe controller"
-	depends on ARM && (ARCH_MEDIATEK || COMPILE_TEST)
+	depends on (ARM || ARM64) && (ARCH_MEDIATEK || COMPILE_TEST)
 	depends on OF
 	depends on PCI
 	select PCIEPORTBUS
 	help
 	  Say Y here if you want to enable PCIe controller support on
-	  MT7623 series SoCs.  There is one single root complex with 3 root
-	  ports available.  Each port supports Gen2 lane x1.
+	  MediaTek SoCs.
 
 config PCIE_TANGO_SMP8759
 	bool "Tango SMP8759 PCIe controller (DANGEROUS)"
diff --git a/drivers/pci/host/pcie-mediatek.c b/drivers/pci/host/pcie-mediatek.c
index f8e2f68..5fe92ff 100644
--- a/drivers/pci/host/pcie-mediatek.c
+++ b/drivers/pci/host/pcie-mediatek.c
@@ -3,6 +3,7 @@
  *
  * Copyright (c) 2017 MediaTek Inc.
  * Author: Ryder Lee <ryder.lee@mediatek.com>
+ *	   Honghui Zhang <honghui.zhang@mediatek.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
@@ -17,6 +18,8 @@
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/iopoll.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
 #include <linux/kernel.h>
 #include <linux/of_address.h>
 #include <linux/of_pci.h>
@@ -64,16 +67,77 @@
 #define PCIE_FC_CREDIT_MASK	(GENMASK(31, 31) | GENMASK(28, 16))
 #define PCIE_FC_CREDIT_VAL(x)	((x) << 16)
 
+/* PCIe V2 share registers */
+#define PCIE_SYS_CFG_V2		0x0
+#define PCIE_CSR_LTSSM_EN(x)	BIT(0 + (x) * 8)
+#define PCIE_CSR_ASPM_L1_EN(x)	BIT(1 + (x) * 8)
+
+/* PCIe V2 per-port registers */
+#define PCIE_INT_MASK		0x420
+#define INTX_MASK		GENMASK(19, 16)
+#define INTX_SHIFT		16
+#define INTX_NUM		4
+#define PCIE_INT_STATUS		0x424
+
+#define PCIE_AHB_TRANS_BASE0_L	0x438
+#define PCIE_AHB_TRANS_BASE0_H	0x43c
+#define AHB2PCIE_BASEL(x)	((x) & GENMASK(31, 0))
+#define AHB2PCIE_BASEH(x)	(((u64)(x) >> 32) & GENMASK(31, 0))
+#define AHB2PCIE_SIZE(x)	((x) & GENMASK(4, 0))
+#define PCIE_AXI_WINDOW0	0x448
+#define WIN_ENABLE		BIT(7)
+
+/* PCIe V2 Configuration Transaction Header */
+#define PCIE_CFG_HEADER0	0x460
+#define PCIE_CFG_HEADER1	0x464
+#define PCIE_CFG_HEADER2	0x468
+#define PCIE_CFG_WDATA		0x470
+#define PCIE_APP_TLP_REQ	0x488
+#define PCIE_CFG_RDATA		0x48c
+#define APP_CFG_REQ		BIT(0)
+#define APP_CPL_STATUS		GENMASK(7, 5)
+
+#define CFG_WRRD_TYPE_0		4
+#define CFG_WR_FMT		2
+#define CFG_RD_FMT		0
+
+#define CFG_DW0_LENGTH(length)	((length) & GENMASK(9, 0))
+#define CFG_DW0_TYPE(type)	(((type) << 24) & GENMASK(28, 24))
+#define CFG_DW0_FMT(fmt)	(((fmt) << 29) & GENMASK(31, 29))
+#define CFG_DW2_REGN(regn)	((regn) & GENMASK(11, 2))
+#define CFG_DW2_FUN(fun)	(((fun) << 16) & GENMASK(18, 16))
+#define CFG_DW2_DEV(dev)	(((dev) << 19) & GENMASK(23, 19))
+#define CFG_DW2_BUS(bus)	(((bus) << 24) & GENMASK(31, 24))
+#define CFG_HEADER_DW0(type, fmt) \
+	(CFG_DW0_LENGTH(1) | CFG_DW0_TYPE(type) | CFG_DW0_FMT(fmt))
+#define CFG_HEADER_DW1(where, size) \
+	(GENMASK(((size) - 1), 0) << ((where) & 0x3))
+#define CFG_HEADER_DW2(regn, fun, dev, bus) \
+	(CFG_DW2_REGN(regn) | CFG_DW2_FUN(fun) | \
+	CFG_DW2_DEV(dev) | CFG_DW2_BUS(bus))
+
+#define PCIE_RST_CTRL		0x510
+#define PCIE_PHY_RSTB		BIT(0)
+#define PCIE_PIPE_SRSTB		BIT(1)
+#define PCIE_MAC_SRSTB		BIT(2)
+#define PCIE_CRSTB		BIT(3)
+#define PCIE_PERSTB		BIT(8)
+#define PCI_LINKDOWN_RST_EN	GENMASK(15, 13)
+#define PCIE_LINK_STATUS_V2	0x804
+#define PCIE_PORT_LINKUP_V2	BIT(10)
+
 struct mtk_pcie_port;
 
 /**
  * struct mtk_pcie_soc - differentiate between host generations
  * @ops: pointer to configuration access functions
  * @startup: pointer to controller setting functions
+ * @setup_irq: pointer to initialize irq functions
  */
 struct mtk_pcie_soc {
 	struct pci_ops *ops;
 	int (*startup)(struct mtk_pcie_port *port);
+	int (*setup_irq)(struct mtk_pcie_port *port, struct device_node *node);
 };
 
 /**
@@ -82,10 +146,18 @@ struct mtk_pcie_soc {
  * @list: port list
  * @pcie: pointer to PCIe host info
  * @reset: pointer to port reset control
- * @sys_ck: pointer to bus clock
+ * @sys_ck: pointer to transaction/data link layer clock
+ * @ahb_ck: pinter to AHB slave interface operating clock for CSR access
+ *          and RC initiated MMIO access
+ * @axi_ck: pointer to application layer MMIO channel operating clock
+ * @aux_ck: pointer to pe2_mac_bridge and pe2_mac_core operating clock
+ *          when pcie_mac_ck/pcie_pipe_ck is turned off
+ * @obff_ck: pointer to OBFF functional block operating clock
+ * @pipe_ck: pointer to LTSSM and phy/mac layer operating clock
  * @phy: pointer to phy control block
  * @lane: lane count
  * @index: port index
+ * @irq_domain: legacy intx irq domain
  */
 struct mtk_pcie_port {
 	void __iomem *base;
@@ -93,9 +165,15 @@ struct mtk_pcie_port {
 	struct mtk_pcie *pcie;
 	struct reset_control *reset;
 	struct clk *sys_ck;
+	struct clk *ahb_ck;
+	struct clk *axi_ck;
+	struct clk *aux_ck;
+	struct clk *obff_ck;
+	struct clk *pipe_ck;
 	struct phy *phy;
 	u32 lane;
 	u32 index;
+	struct irq_domain *irq_domain;
 };
 
 /**
@@ -156,6 +234,12 @@ static void mtk_pcie_put_resources(struct mtk_pcie *pcie)
 
 	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
 		phy_power_off(port->phy);
+		phy_exit(port->phy);
+		clk_disable_unprepare(port->pipe_ck);
+		clk_disable_unprepare(port->obff_ck);
+		clk_disable_unprepare(port->axi_ck);
+		clk_disable_unprepare(port->aux_ck);
+		clk_disable_unprepare(port->ahb_ck);
 		clk_disable_unprepare(port->sys_ck);
 		mtk_pcie_port_free(port);
 	}
@@ -163,6 +247,298 @@ static void mtk_pcie_put_resources(struct mtk_pcie *pcie)
 	mtk_pcie_subsys_powerdown(pcie);
 }
 
+static int mtk_pcie_check_cfg_cpld(struct mtk_pcie_port *port)
+{
+	u32 val;
+	int err;
+
+	err = readl_poll_timeout_atomic(port->base + PCIE_APP_TLP_REQ, val,
+					!(val & APP_CFG_REQ), 10,
+					100 * USEC_PER_MSEC);
+	if (err)
+		return PCIBIOS_SET_FAILED;
+
+	if (readl(port->base + PCIE_APP_TLP_REQ) & APP_CPL_STATUS)
+		return PCIBIOS_SET_FAILED;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int mtk_pcie_hw_rd_cfg(struct mtk_pcie_port *port, u32 bus, u32 devfn,
+			      int where, int size, u32 *val)
+{
+	int reg, shift = 8 * (where & 3);
+
+	/* Write PCIe Configuration Transaction Header for cfgrd */
+	writel(CFG_HEADER_DW0(CFG_WRRD_TYPE_0, CFG_RD_FMT),
+	       port->base + PCIE_CFG_HEADER0);
+	writel(CFG_HEADER_DW1(where, size), port->base + PCIE_CFG_HEADER1);
+	writel(CFG_HEADER_DW2(where, PCI_FUNC(devfn), PCI_SLOT(devfn), bus),
+	       port->base + PCIE_CFG_HEADER2);
+
+	/* Triget h/w to transmit Cfgrd TLP */
+	reg = readl(port->base + PCIE_APP_TLP_REQ);
+	writel(reg | APP_CFG_REQ, port->base + PCIE_APP_TLP_REQ);
+
+	/* Check complete condition */
+	if (mtk_pcie_check_cfg_cpld(port))
+		return PCIBIOS_SET_FAILED;
+
+	/* Read cpld payload of Cfgrd */
+	*val = readl(port->base + PCIE_CFG_RDATA);
+
+	switch (size) {
+	case 4:
+		break;
+	case 3:
+		*val = (*val >> shift) & 0xffffff;
+		break;
+	case 2:
+		*val = (*val >> shift) & 0xffff;
+		break;
+	case 1:
+		*val = (*val >> shift) & 0xff;
+		break;
+	default:
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+	}
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int mtk_pcie_hw_wr_cfg(struct mtk_pcie_port *port, u32 bus, u32 devfn,
+			      int where, int size, u32 val)
+{
+	/* Write PCIe Configuration Transaction Header for Cfgwr */
+	writel(CFG_HEADER_DW0(CFG_WRRD_TYPE_0, CFG_WR_FMT),
+	       port->base + PCIE_CFG_HEADER0);
+	writel(CFG_HEADER_DW1(where, size), port->base + PCIE_CFG_HEADER1);
+	writel(CFG_HEADER_DW2(where, PCI_FUNC(devfn), PCI_SLOT(devfn), bus),
+	       port->base + PCIE_CFG_HEADER2);
+
+	/* Write cfgwr data */
+	val = val << 8 * (where & 3);
+	writel(val, port->base + PCIE_CFG_WDATA);
+
+	/* Triget h/w to transmit Cfgwr TLP */
+	val = readl(port->base + PCIE_APP_TLP_REQ);
+	val |= APP_CFG_REQ;
+	writel(val, port->base + PCIE_APP_TLP_REQ);
+
+	/* Check complete condition */
+	return mtk_pcie_check_cfg_cpld(port);
+}
+
+static struct mtk_pcie_port *mtk_pcie_find_port(struct mtk_pcie *pcie,
+						struct pci_bus *bus, int devfn)
+{
+	struct pci_dev *dev;
+	struct pci_bus *pbus;
+	struct mtk_pcie_port *port, *tmp;
+
+	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
+		if (bus->number == 0 && port->index == PCI_SLOT(devfn)) {
+			return port;
+		} else if (bus->number != 0) {
+			pbus = bus;
+			do {
+				dev = pbus->self;
+				if (port->index == PCI_SLOT(dev->devfn))
+					return port;
+				pbus = dev->bus;
+			} while (dev->bus->number != 0);
+		}
+	}
+
+	return NULL;
+}
+
+static int mtk_pcie_config_read(struct pci_bus *bus, unsigned int devfn,
+				int where, int size, u32 *val)
+{
+	struct mtk_pcie_port *port;
+	struct pci_host_bridge *host = pci_find_host_bridge(bus);
+	struct mtk_pcie *pcie = pci_host_bridge_priv(host);
+	u32 bn = bus->number;
+	int ret;
+
+	port = mtk_pcie_find_port(pcie, bus, devfn);
+	if (!port) {
+		*val = ~0;
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	}
+
+	ret = mtk_pcie_hw_rd_cfg(port, bn, devfn, where, size, val);
+	if (ret)
+		*val = ~0;
+
+	return ret;
+}
+
+static int mtk_pcie_config_write(struct pci_bus *bus, unsigned int devfn,
+				 int where, int size, u32 val)
+{
+	u32 bn = bus->number;
+	struct pci_host_bridge *host = pci_find_host_bridge(bus);
+	struct mtk_pcie *pcie = pci_host_bridge_priv(host);
+	struct mtk_pcie_port *port;
+
+	port = mtk_pcie_find_port(pcie, bus, devfn);
+	if (!port)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	return mtk_pcie_hw_wr_cfg(port, bn, devfn, where, size, val);
+}
+
+static struct pci_ops mtk_pcie_ops_v2 = {
+	.read  = mtk_pcie_config_read,
+	.write = mtk_pcie_config_write,
+};
+
+static int mtk_pcie_startup_ports_v2(struct mtk_pcie_port *port)
+{
+	struct mtk_pcie *pcie = port->pcie;
+	struct resource *mem = &pcie->mem;
+	u32 val;
+	size_t size;
+	int err;
+
+	/* mt7622 platforms need to enable LTSSM and ASPM from PCIe subsys */
+	if (pcie->base) {
+		val = readl(pcie->base + PCIE_SYS_CFG_V2);
+		val |= PCIE_CSR_LTSSM_EN(port->index) |
+		       PCIE_CSR_ASPM_L1_EN(port->index);
+		writel(val, pcie->base + PCIE_SYS_CFG_V2);
+	}
+
+	/* Assert all reset signals */
+	writel(0, port->base + PCIE_RST_CTRL);
+
+	/*
+	 * Enable rc internal reset.
+	 * The reset will work when the link is from link up to link down.
+	 */
+	writel(PCI_LINKDOWN_RST_EN, port->base + PCIE_RST_CTRL);
+
+	/* De-assert phy, pe, pipe, mac and configuration reset	*/
+	val = readl(port->base + PCIE_RST_CTRL);
+	val |= PCIE_PHY_RSTB | PCIE_PERSTB | PCIE_PIPE_SRSTB |
+	       PCIE_MAC_SRSTB | PCIE_CRSTB;
+	writel(val, port->base + PCIE_RST_CTRL);
+
+	/* PCIe v2.0 need at least 100ms delay to train from Gen1 to Gen2 */
+	err = readl_poll_timeout(port->base + PCIE_LINK_STATUS_V2, val,
+				 !!(val & PCIE_PORT_LINKUP_V2), 20,
+				 100 * USEC_PER_MSEC);
+	if (err)
+		return -ETIMEDOUT;
+
+	/* Set INTx mask */
+	val = readl(port->base + PCIE_INT_MASK);
+	val &= ~INTX_MASK;
+	writel(val, port->base + PCIE_INT_MASK);
+
+	/* Set AHB to PCIe translation windows */
+	size = mem->end - mem->start;
+	val = AHB2PCIE_BASEL(mem->start) | AHB2PCIE_SIZE(fls(size));
+	writel(val, port->base + PCIE_AHB_TRANS_BASE0_L);
+
+	val = AHB2PCIE_BASEH(mem->start);
+	writel(val, port->base + PCIE_AHB_TRANS_BASE0_H);
+
+	/* Set PCIe to axi translation memory space.*/
+	val = fls(0xffffffff) | WIN_ENABLE;
+	writel(val, port->base + PCIE_AXI_WINDOW0);
+
+	return 0;
+}
+
+static int mtk_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
+			     irq_hw_number_t hwirq)
+{
+	irq_set_chip_and_handler(irq, &dummy_irq_chip, handle_simple_irq);
+	irq_set_chip_data(irq, domain->host_data);
+
+	return 0;
+}
+
+static const struct irq_domain_ops intx_domain_ops = {
+	.map = mtk_pcie_intx_map,
+};
+
+static int mtk_pcie_init_irq_domain(struct mtk_pcie_port *port,
+				    struct device_node *node)
+{
+	struct device *dev = port->pcie->dev;
+	struct device_node *pcie_intc_node;
+
+	/* Setup INTx */
+	pcie_intc_node = of_get_next_child(node, NULL);
+	if (!pcie_intc_node) {
+		dev_err(dev, "No PCIe Intc node found\n");
+		return PTR_ERR(pcie_intc_node);
+	}
+
+	port->irq_domain = irq_domain_add_linear(pcie_intc_node, INTX_NUM,
+						 &intx_domain_ops, port);
+	if (!port->irq_domain) {
+		dev_err(dev, "Failed to get INTx IRQ domain\n");
+		return PTR_ERR(port->irq_domain);
+	}
+
+	return 0;
+}
+
+static irqreturn_t mtk_pcie_intr_handler(int irq, void *data)
+{
+	struct mtk_pcie_port *port = (struct mtk_pcie_port *)data;
+	struct device *dev = port->pcie->dev;
+	unsigned long status;
+	u32 virq;
+	u32 bit = INTX_SHIFT;
+
+	while ((status = readl(port->base + PCIE_INT_STATUS)) & INTX_MASK) {
+		for_each_set_bit_from(bit, &status, INTX_NUM + INTX_SHIFT) {
+			/* Clear the INTx */
+			writel(1 << bit, port->base + PCIE_INT_STATUS);
+			virq = irq_find_mapping(port->irq_domain,
+						bit - INTX_SHIFT);
+			if (virq)
+				generic_handle_irq(virq);
+			else
+				dev_err(dev, "unexpected IRQ, INT%d\n",
+					bit - INTX_SHIFT);
+		}
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int mtk_pcie_setup_irq(struct mtk_pcie_port *port,
+			      struct device_node *node)
+{
+	struct mtk_pcie *pcie = port->pcie;
+	struct device *dev = pcie->dev;
+	struct platform_device *pdev = to_platform_device(dev);
+	int err, irq;
+
+	irq = platform_get_irq(pdev, port->index);
+	err = devm_request_irq(dev, irq, mtk_pcie_intr_handler,
+			       IRQF_SHARED, "mtk-pcie", port);
+	if (err) {
+		dev_err(dev, "unable to request irq %d\n", irq);
+		return err;
+	}
+
+	err = mtk_pcie_init_irq_domain(port, node);
+	if (err) {
+		dev_err(dev, "failed to init pcie lagecy irq domain\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
 static void __iomem *mtk_pcie_map_bus(struct pci_bus *bus,
 				      unsigned int devfn, int where)
 {
@@ -249,13 +625,49 @@ static void mtk_pcie_enable_ports(struct mtk_pcie_port *port)
 
 	err = clk_prepare_enable(port->sys_ck);
 	if (err) {
-		dev_err(dev, "failed to enable port%d clock\n", port->index);
+		dev_err(dev, "failed to enable sys_ck%d\n", port->index);
 		goto err_sys_clk;
 	}
 
+	err = clk_prepare_enable(port->ahb_ck);
+	if (err) {
+		dev_err(dev, "failed to enable ahb_ck%d\n", port->index);
+		goto err_ahb_clk;
+	}
+
+	err = clk_prepare_enable(port->aux_ck);
+	if (err) {
+		dev_err(dev, "failed to enable aux_ck%d\n", port->index);
+		goto err_aux_clk;
+	}
+
+	err = clk_prepare_enable(port->axi_ck);
+	if (err) {
+		dev_err(dev, "failed to enable axi_ck%d\n", port->index);
+		goto err_axi_clk;
+	}
+
+	err = clk_prepare_enable(port->obff_ck);
+	if (err) {
+		dev_err(dev, "failed to enable obff_ck%d\n", port->index);
+		goto err_obff_clk;
+	}
+
+	err = clk_prepare_enable(port->pipe_ck);
+	if (err) {
+		dev_err(dev, "failed to enable pipe_ck%d\n", port->index);
+		goto err_pipe_clk;
+	}
+
 	reset_control_assert(port->reset);
 	reset_control_deassert(port->reset);
 
+	err = phy_init(port->phy);
+	if (err) {
+		dev_err(dev, "failed to initialize port%d phy\n", port->index);
+		goto err_phy_init;
+	}
+
 	err = phy_power_on(port->phy);
 	if (err) {
 		dev_err(dev, "failed to power on port%d phy\n", port->index);
@@ -269,6 +681,18 @@ static void mtk_pcie_enable_ports(struct mtk_pcie_port *port)
 
 	phy_power_off(port->phy);
 err_phy_on:
+	phy_exit(port->phy);
+err_phy_init:
+	clk_disable_unprepare(port->pipe_ck);
+err_pipe_clk:
+	clk_disable_unprepare(port->obff_ck);
+err_obff_clk:
+	clk_disable_unprepare(port->axi_ck);
+err_axi_clk:
+	clk_disable_unprepare(port->aux_ck);
+err_aux_clk:
+	clk_disable_unprepare(port->ahb_ck);
+err_ahb_clk:
 	clk_disable_unprepare(port->sys_ck);
 err_sys_clk:
 	mtk_pcie_port_free(port);
@@ -306,10 +730,56 @@ static int mtk_pcie_parse_ports(struct mtk_pcie *pcie,
 	snprintf(name, sizeof(name), "sys_ck%d", index);
 	port->sys_ck = devm_clk_get(dev, name);
 	if (IS_ERR(port->sys_ck)) {
-		dev_err(dev, "failed to get port%d clock\n", index);
+		dev_err(dev, "failed to get sys_ck%d\n", index);
 		return PTR_ERR(port->sys_ck);
 	}
 
+	/* sys_ck might be divided into the following parts in some chips */
+	snprintf(name, sizeof(name), "ahb_ck%d", index);
+	port->ahb_ck = devm_clk_get(dev, name);
+	if (IS_ERR(port->ahb_ck)) {
+		if (PTR_ERR(port->ahb_ck) == -EPROBE_DEFER)
+			return -EPROBE_DEFER;
+
+		port->ahb_ck = NULL;
+	}
+
+	snprintf(name, sizeof(name), "axi_ck%d", index);
+	port->axi_ck = devm_clk_get(dev, name);
+	if (IS_ERR(port->axi_ck)) {
+		if (PTR_ERR(port->axi_ck) == -EPROBE_DEFER)
+			return -EPROBE_DEFER;
+
+		port->axi_ck = NULL;
+	}
+
+	snprintf(name, sizeof(name), "aux_ck%d", index);
+	port->aux_ck = devm_clk_get(dev, name);
+	if (IS_ERR(port->aux_ck)) {
+		if (PTR_ERR(port->aux_ck) == -EPROBE_DEFER)
+			return -EPROBE_DEFER;
+
+		port->aux_ck = NULL;
+	}
+
+	snprintf(name, sizeof(name), "obff_ck%d", index);
+	port->obff_ck = devm_clk_get(dev, name);
+	if (IS_ERR(port->obff_ck)) {
+		if (PTR_ERR(port->obff_ck) == -EPROBE_DEFER)
+			return -EPROBE_DEFER;
+
+		port->obff_ck = NULL;
+	}
+
+	snprintf(name, sizeof(name), "pipe_ck%d", index);
+	port->pipe_ck = devm_clk_get(dev, name);
+	if (IS_ERR(port->pipe_ck)) {
+		if (PTR_ERR(port->pipe_ck) == -EPROBE_DEFER)
+			return -EPROBE_DEFER;
+
+		port->pipe_ck = NULL;
+	}
+
 	snprintf(name, sizeof(name), "pcie-rst%d", index);
 	port->reset = devm_reset_control_get_optional(dev, name);
 	if (PTR_ERR(port->reset) == -EPROBE_DEFER)
@@ -324,6 +794,12 @@ static int mtk_pcie_parse_ports(struct mtk_pcie *pcie,
 	port->index = index;
 	port->pcie = pcie;
 
+	if (pcie->soc->setup_irq) {
+		err = pcie->soc->setup_irq(port, node);
+		if (err)
+			return err;
+	}
+
 	INIT_LIST_HEAD(&port->list);
 	list_add_tail(&port->list, &pcie->ports);
 
@@ -553,9 +1029,17 @@ static struct mtk_pcie_soc mtk_pcie_soc_v1 = {
 	.startup = mtk_pcie_startup_ports,
 };
 
+static struct mtk_pcie_soc mtk_pcie_soc_v2 = {
+	.ops = &mtk_pcie_ops_v2,
+	.startup = mtk_pcie_startup_ports_v2,
+	.setup_irq = mtk_pcie_setup_irq,
+};
+
 static const struct of_device_id mtk_pcie_ids[] = {
 	{ .compatible = "mediatek,mt2701-pcie", .data = &mtk_pcie_soc_v1 },
 	{ .compatible = "mediatek,mt7623-pcie", .data = &mtk_pcie_soc_v1 },
+	{ .compatible = "mediatek,mt2712-pcie", .data = &mtk_pcie_soc_v2 },
+	{ .compatible = "mediatek,mt7622-pcie", .data = &mtk_pcie_soc_v2 },
 	{},
 };
 
-- 
2.6.4

^ permalink raw reply related	[flat|nested] 80+ messages in thread

* [PATCH v2 5/5] dt-bindings: PCI: add support for new generation controller
  2017-07-27  2:58 ` honghui.zhang
  (?)
  (?)
@ 2017-07-27  2:58   ` honghui.zhang
  -1 siblings, 0 replies; 80+ messages in thread
From: honghui.zhang @ 2017-07-27  2:58 UTC (permalink / raw)
  To: bhelgaas, robh, robh+dt, matthias.bgg, linux-arm-kernel,
	linux-mediatek, linux-pci, linux-kernel, devicetree,
	yingjoe.chen, eddie.huang, ryder.lee
  Cc: honghui.zhang, hongkun.cao, youlin.pei, yong.wu, yt.shen,
	sean.wang, xinping.qian

From: Ryder Lee <ryder.lee@mediatek.com>

Add support for MediaTek new generation controller and update related
properities.

Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
Signed-off-by: Honghui Zhang <honghui.zhang@mediatek.com>
---
 .../devicetree/bindings/pci/mediatek-pcie.txt      | 168 ++++++++++++++++++++-
 1 file changed, 161 insertions(+), 7 deletions(-)

diff --git a/Documentation/devicetree/bindings/pci/mediatek-pcie.txt b/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
index a968f25..179329b 100644
--- a/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
+++ b/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
@@ -3,18 +3,31 @@ MediaTek Gen2 PCIe controller
 Required properties:
 - compatible: Should contain one of the following string:
 	"mediatek,mt2701-pcie"
+	"mediatek,mt2712-pcie"
+	"mediatek,mt7622-pcie"
 	"mediatek,mt7623-pcie"
 - device_type: Must be "pci"
-- reg: Base addresses and lengths of the PCIe controller.
+- reg: Base addresses and lengths of the PICe subsys and root ports.
+- reg-names: Names of the above areas to use during resource look-up.
 - #address-cells: Address representation for root ports (must be 3)
 - #size-cells: Size representation for root ports (must be 2)
 - clocks: Must contain an entry for each entry in clock-names.
   See ../clocks/clock-bindings.txt for details.
-- clock-names: Must include the following entries:
-  - free_ck :for reference clock of PCIe subsys
-  - sys_ck0 :for clock of Port0
-  - sys_ck1 :for clock of Port1
-  - sys_ck2 :for clock of Port2
+- clock-names:
+  Mandatory entries:
+   - sys_ckN :transaction layer and data link layer clock
+  Required entries for MT2701/MT7623:
+   - free_ck :for reference clock of PCIe subsys
+  Required entries for MT2712/MT7622:
+   - ahb_ckN :AHB slave interface operating clock for CSR access and RC
+	      initiated MMIO access
+  Required entries for MT7622:
+   - axi_ckN :application layer MMIO channel operating clock
+   - aux_ckN :pe2_mac_bridge and pe2_mac_core operating clock when
+	      pcie_mac_ck/pcie_pipe_ck is turned off
+   - obff_ckN :OBFF functional block operating clock
+   - pipe_ckN :LTSSM and phy/mac layer operating clock
+  where N starting from 0 to the maximum number of root ports.
 - phys: List of PHY specifiers (used by generic PHY framework).
 - phy-names : Must be "pcie-phy0", "pcie-phy1", "pcie-phyN".. based on the
   number of PHYs as specified in *phys* property.
@@ -33,6 +46,10 @@ Required properties for MT7623/MT2701:
 - reset-names: Must be "pcie-rst0", "pcie-rst1", "pcie-rstN".. based on the
   number of root ports.
 
+Required properties for MT2712/MT7622:
+-interrupts: A list of interrupt outputs of the controller, must have one
+	     entry for each PCIe port
+
 In addition, the device tree node must have sub-nodes describing each
 PCIe port interface, having the following mandatory properties:
 
@@ -50,7 +67,7 @@ Required properties:
   property is sufficient.
 - num-lanes: Number of lanes to use for this port.
 
-Examples:
+Examples for MT7623:
 
 	hifsys: syscon@1a000000 {
 		compatible = "mediatek,mt7623-hifsys",
@@ -68,6 +85,7 @@ Examples:
 		      <0 0x1a142000 0 0x1000>, /* Port0 registers */
 		      <0 0x1a143000 0 0x1000>, /* Port1 registers */
 		      <0 0x1a144000 0 0x1000>; /* Port2 registers */
+		reg-names = "subsys", "port0", "port1", "port2";
 		#address-cells = <3>;
 		#size-cells = <2>;
 		#interrupt-cells = <1>;
@@ -127,3 +145,139 @@ Examples:
 			num-lanes = <1>;
 		};
 	};
+
+Examples for MT2712:
+	pcie: pcie@11700000 {
+		compatible = "mediatek,generic-pcie-v2";
+		device_type = "pci";
+		reg = <0 0x11700000 0 0x1000>,
+		      <0 0x112ff000 0 0x1000>;
+		reg-names = "port0", "port1";
+		#address-cells = <3>;
+		#size-cells = <2>;
+		interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&pericfg CLK_PERI_PCIE0>,
+			 <&pericfg CLK_PERI_PCIE1>,
+			 <&topckgen CLK_TOP_PE2_MAC_P0_SEL>,
+			 <&topckgen CLK_TOP_PE2_MAC_P1_SEL>;
+		clock-names = "sys_ck0", "sys_ck1", "ahb_ck0", "ahb_ck1";
+		phys = <&pcie0_phy PHY_TYPE_PCIE>, <&pcie1_phy PHY_TYPE_PCIE>;
+		phy-names = "pcie-phy0", "pcie-phy1";
+		bus-range = <0x00 0xff>;
+		ranges = <0x82000000 0 0x20000000  0x0 0x20000000  0 0x10000000>;
+
+		pcie0: pcie@0,0 {
+			device_type = "pci";
+			reg = <0x0000 0 0 0 0>;
+			#address-cells = <3>;
+			#size-cells = <2>;
+			#interrupt-cells = <1>;
+			ranges;
+			num-lanes = <1>;
+			interrupt-map-mask = <0 0 0 7>;
+			interrupt-map = <0 0 0 1 &pcie_intc0 0>,
+					<0 0 0 2 &pcie_intc0 1>,
+					<0 0 0 3 &pcie_intc0 2>,
+					<0 0 0 4 &pcie_intc0 3>;
+			pcie_intc0: interrupt-controller {
+				interrupt-controller;
+				#address-cells = <0>;
+				#interrupt-cells = <1>;
+			};
+		};
+
+		pcie1: pcie@1,0 {
+			device_type = "pci";
+			reg = <0x0800 0 0 0 0>;
+			#address-cells = <3>;
+			#size-cells = <2>;
+			#interrupt-cells = <1>;
+			ranges;
+			num-lanes = <1>;
+			interrupt-map-mask = <0 0 0 7>;
+			interrupt-map = <0 0 0 1 &pcie_intc1 0>,
+					<0 0 0 2 &pcie_intc1 1>,
+					<0 0 0 3 &pcie_intc1 2>,
+					<0 0 0 4 &pcie_intc1 3>;
+			pcie_intc1: interrupt-controller {
+				interrupt-controller;
+				#address-cells = <0>;
+				#interrupt-cells = <1>;
+			};
+		};
+	};
+
+Examples for MT7622:
+	pcie: pcie@1a140000 {
+		compatible = "mediatek,generic-pcie-v2";
+		device_type = "pci";
+		reg = <0 0x1a140000 0 0x1000>,
+		      <0 0x1a143000 0 0x1000>,
+		      <0 0x1a145000 0 0x1000>;
+		reg-names = "subsys", "port0", "port1";
+		#address-cells = <3>;
+		#size-cells = <2>;
+		interrupts = <GIC_SPI 228 IRQ_TYPE_LEVEL_LOW>,
+			     <GIC_SPI 229 IRQ_TYPE_LEVEL_LOW>;
+		clocks = <&pciesys CLK_PCIE_P0_MAC_EN>,
+			 <&pciesys CLK_PCIE_P1_MAC_EN>,
+			 <&pciesys CLK_PCIE_P0_AHB_EN>,
+			 <&pciesys CLK_PCIE_P1_AHB_EN>,
+			 <&pciesys CLK_PCIE_P0_AUX_EN>,
+			 <&pciesys CLK_PCIE_P1_AUX_EN>,
+			 <&pciesys CLK_PCIE_P0_AXI_EN>,
+			 <&pciesys CLK_PCIE_P1_AXI_EN>,
+			 <&pciesys CLK_PCIE_P0_OBFF_EN>,
+			 <&pciesys CLK_PCIE_P1_OBFF_EN>,
+			 <&pciesys CLK_PCIE_P0_PIPE_EN>,
+			 <&pciesys CLK_PCIE_P1_PIPE_EN>;
+		clock-names = "sys_ck0", "sys_ck1", "ahb_ck0", "ahb_ck1",
+			      "aux_ck0", "aux_ck1", "axi_ck0", "axi_ck1",
+			      "obff_ck0", "obff_ck1", "pipe_ck0", "pipe_ck1";
+		phys = <&pcie0_phy PHY_TYPE_PCIE>, <&pcie1_phy PHY_TYPE_PCIE>;
+		phy-names = "pcie-phy0", "pcie-phy1";
+		power-domains = <&scpsys MT7622_POWER_DOMAIN_HIF0>;
+		bus-range = <0x00 0xff>;
+		ranges = <0x82000000 0 0x20000000  0x0 0x20000000  0 0x10000000>;
+
+		pcie0: pcie@0,0 {
+			device_type = "pci";
+			reg = <0x0000 0 0 0 0>;
+			#address-cells = <3>;
+			#size-cells = <2>;
+			#interrupt-cells = <1>;
+			ranges;
+			num-lanes = <1>;
+			interrupt-map-mask = <0 0 0 7>;
+			interrupt-map = <0 0 0 1 &pcie_intc0 0>,
+					<0 0 0 2 &pcie_intc0 1>,
+					<0 0 0 3 &pcie_intc0 2>,
+					<0 0 0 4 &pcie_intc0 3>;
+			pcie_intc0: interrupt-controller {
+				interrupt-controller;
+				#address-cells = <0>;
+				#interrupt-cells = <1>;
+			};
+		};
+
+		pcie1: pcie@1,0 {
+			device_type = "pci";
+			reg = <0x0800 0 0 0 0>;
+			#address-cells = <3>;
+			#size-cells = <2>;
+			#interrupt-cells = <1>;
+			ranges;
+			num-lanes = <1>;
+			interrupt-map-mask = <0 0 0 7>;
+			interrupt-map = <0 0 0 1 &pcie_intc1 0>,
+					<0 0 0 2 &pcie_intc1 1>,
+					<0 0 0 3 &pcie_intc1 2>,
+					<0 0 0 4 &pcie_intc1 3>;
+			pcie_intc1: interrupt-controller {
+				interrupt-controller;
+				#address-cells = <0>;
+				#interrupt-cells = <1>;
+			};
+		};
+	};
-- 
2.6.4

^ permalink raw reply related	[flat|nested] 80+ messages in thread

* [PATCH v2 5/5] dt-bindings: PCI: add support for new generation controller
@ 2017-07-27  2:58   ` honghui.zhang
  0 siblings, 0 replies; 80+ messages in thread
From: honghui.zhang @ 2017-07-27  2:58 UTC (permalink / raw)
  To: bhelgaas, robh, robh+dt, matthias.bgg, linux-arm-kernel,
	linux-mediatek, linux-pci, linux-kernel, devicetree,
	yingjoe.chen, eddie.huang, ryder.lee
  Cc: honghui.zhang, hongkun.cao, youlin.pei, yong.wu, yt.shen,
	sean.wang, xinping.qian

From: Ryder Lee <ryder.lee@mediatek.com>

Add support for MediaTek new generation controller and update related
properities.

Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
Signed-off-by: Honghui Zhang <honghui.zhang@mediatek.com>
---
 .../devicetree/bindings/pci/mediatek-pcie.txt      | 168 ++++++++++++++++++++-
 1 file changed, 161 insertions(+), 7 deletions(-)

diff --git a/Documentation/devicetree/bindings/pci/mediatek-pcie.txt b/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
index a968f25..179329b 100644
--- a/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
+++ b/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
@@ -3,18 +3,31 @@ MediaTek Gen2 PCIe controller
 Required properties:
 - compatible: Should contain one of the following string:
 	"mediatek,mt2701-pcie"
+	"mediatek,mt2712-pcie"
+	"mediatek,mt7622-pcie"
 	"mediatek,mt7623-pcie"
 - device_type: Must be "pci"
-- reg: Base addresses and lengths of the PCIe controller.
+- reg: Base addresses and lengths of the PICe subsys and root ports.
+- reg-names: Names of the above areas to use during resource look-up.
 - #address-cells: Address representation for root ports (must be 3)
 - #size-cells: Size representation for root ports (must be 2)
 - clocks: Must contain an entry for each entry in clock-names.
   See ../clocks/clock-bindings.txt for details.
-- clock-names: Must include the following entries:
-  - free_ck :for reference clock of PCIe subsys
-  - sys_ck0 :for clock of Port0
-  - sys_ck1 :for clock of Port1
-  - sys_ck2 :for clock of Port2
+- clock-names:
+  Mandatory entries:
+   - sys_ckN :transaction layer and data link layer clock
+  Required entries for MT2701/MT7623:
+   - free_ck :for reference clock of PCIe subsys
+  Required entries for MT2712/MT7622:
+   - ahb_ckN :AHB slave interface operating clock for CSR access and RC
+	      initiated MMIO access
+  Required entries for MT7622:
+   - axi_ckN :application layer MMIO channel operating clock
+   - aux_ckN :pe2_mac_bridge and pe2_mac_core operating clock when
+	      pcie_mac_ck/pcie_pipe_ck is turned off
+   - obff_ckN :OBFF functional block operating clock
+   - pipe_ckN :LTSSM and phy/mac layer operating clock
+  where N starting from 0 to the maximum number of root ports.
 - phys: List of PHY specifiers (used by generic PHY framework).
 - phy-names : Must be "pcie-phy0", "pcie-phy1", "pcie-phyN".. based on the
   number of PHYs as specified in *phys* property.
@@ -33,6 +46,10 @@ Required properties for MT7623/MT2701:
 - reset-names: Must be "pcie-rst0", "pcie-rst1", "pcie-rstN".. based on the
   number of root ports.
 
+Required properties for MT2712/MT7622:
+-interrupts: A list of interrupt outputs of the controller, must have one
+	     entry for each PCIe port
+
 In addition, the device tree node must have sub-nodes describing each
 PCIe port interface, having the following mandatory properties:
 
@@ -50,7 +67,7 @@ Required properties:
   property is sufficient.
 - num-lanes: Number of lanes to use for this port.
 
-Examples:
+Examples for MT7623:
 
 	hifsys: syscon@1a000000 {
 		compatible = "mediatek,mt7623-hifsys",
@@ -68,6 +85,7 @@ Examples:
 		      <0 0x1a142000 0 0x1000>, /* Port0 registers */
 		      <0 0x1a143000 0 0x1000>, /* Port1 registers */
 		      <0 0x1a144000 0 0x1000>; /* Port2 registers */
+		reg-names = "subsys", "port0", "port1", "port2";
 		#address-cells = <3>;
 		#size-cells = <2>;
 		#interrupt-cells = <1>;
@@ -127,3 +145,139 @@ Examples:
 			num-lanes = <1>;
 		};
 	};
+
+Examples for MT2712:
+	pcie: pcie@11700000 {
+		compatible = "mediatek,generic-pcie-v2";
+		device_type = "pci";
+		reg = <0 0x11700000 0 0x1000>,
+		      <0 0x112ff000 0 0x1000>;
+		reg-names = "port0", "port1";
+		#address-cells = <3>;
+		#size-cells = <2>;
+		interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&pericfg CLK_PERI_PCIE0>,
+			 <&pericfg CLK_PERI_PCIE1>,
+			 <&topckgen CLK_TOP_PE2_MAC_P0_SEL>,
+			 <&topckgen CLK_TOP_PE2_MAC_P1_SEL>;
+		clock-names = "sys_ck0", "sys_ck1", "ahb_ck0", "ahb_ck1";
+		phys = <&pcie0_phy PHY_TYPE_PCIE>, <&pcie1_phy PHY_TYPE_PCIE>;
+		phy-names = "pcie-phy0", "pcie-phy1";
+		bus-range = <0x00 0xff>;
+		ranges = <0x82000000 0 0x20000000  0x0 0x20000000  0 0x10000000>;
+
+		pcie0: pcie@0,0 {
+			device_type = "pci";
+			reg = <0x0000 0 0 0 0>;
+			#address-cells = <3>;
+			#size-cells = <2>;
+			#interrupt-cells = <1>;
+			ranges;
+			num-lanes = <1>;
+			interrupt-map-mask = <0 0 0 7>;
+			interrupt-map = <0 0 0 1 &pcie_intc0 0>,
+					<0 0 0 2 &pcie_intc0 1>,
+					<0 0 0 3 &pcie_intc0 2>,
+					<0 0 0 4 &pcie_intc0 3>;
+			pcie_intc0: interrupt-controller {
+				interrupt-controller;
+				#address-cells = <0>;
+				#interrupt-cells = <1>;
+			};
+		};
+
+		pcie1: pcie@1,0 {
+			device_type = "pci";
+			reg = <0x0800 0 0 0 0>;
+			#address-cells = <3>;
+			#size-cells = <2>;
+			#interrupt-cells = <1>;
+			ranges;
+			num-lanes = <1>;
+			interrupt-map-mask = <0 0 0 7>;
+			interrupt-map = <0 0 0 1 &pcie_intc1 0>,
+					<0 0 0 2 &pcie_intc1 1>,
+					<0 0 0 3 &pcie_intc1 2>,
+					<0 0 0 4 &pcie_intc1 3>;
+			pcie_intc1: interrupt-controller {
+				interrupt-controller;
+				#address-cells = <0>;
+				#interrupt-cells = <1>;
+			};
+		};
+	};
+
+Examples for MT7622:
+	pcie: pcie@1a140000 {
+		compatible = "mediatek,generic-pcie-v2";
+		device_type = "pci";
+		reg = <0 0x1a140000 0 0x1000>,
+		      <0 0x1a143000 0 0x1000>,
+		      <0 0x1a145000 0 0x1000>;
+		reg-names = "subsys", "port0", "port1";
+		#address-cells = <3>;
+		#size-cells = <2>;
+		interrupts = <GIC_SPI 228 IRQ_TYPE_LEVEL_LOW>,
+			     <GIC_SPI 229 IRQ_TYPE_LEVEL_LOW>;
+		clocks = <&pciesys CLK_PCIE_P0_MAC_EN>,
+			 <&pciesys CLK_PCIE_P1_MAC_EN>,
+			 <&pciesys CLK_PCIE_P0_AHB_EN>,
+			 <&pciesys CLK_PCIE_P1_AHB_EN>,
+			 <&pciesys CLK_PCIE_P0_AUX_EN>,
+			 <&pciesys CLK_PCIE_P1_AUX_EN>,
+			 <&pciesys CLK_PCIE_P0_AXI_EN>,
+			 <&pciesys CLK_PCIE_P1_AXI_EN>,
+			 <&pciesys CLK_PCIE_P0_OBFF_EN>,
+			 <&pciesys CLK_PCIE_P1_OBFF_EN>,
+			 <&pciesys CLK_PCIE_P0_PIPE_EN>,
+			 <&pciesys CLK_PCIE_P1_PIPE_EN>;
+		clock-names = "sys_ck0", "sys_ck1", "ahb_ck0", "ahb_ck1",
+			      "aux_ck0", "aux_ck1", "axi_ck0", "axi_ck1",
+			      "obff_ck0", "obff_ck1", "pipe_ck0", "pipe_ck1";
+		phys = <&pcie0_phy PHY_TYPE_PCIE>, <&pcie1_phy PHY_TYPE_PCIE>;
+		phy-names = "pcie-phy0", "pcie-phy1";
+		power-domains = <&scpsys MT7622_POWER_DOMAIN_HIF0>;
+		bus-range = <0x00 0xff>;
+		ranges = <0x82000000 0 0x20000000  0x0 0x20000000  0 0x10000000>;
+
+		pcie0: pcie@0,0 {
+			device_type = "pci";
+			reg = <0x0000 0 0 0 0>;
+			#address-cells = <3>;
+			#size-cells = <2>;
+			#interrupt-cells = <1>;
+			ranges;
+			num-lanes = <1>;
+			interrupt-map-mask = <0 0 0 7>;
+			interrupt-map = <0 0 0 1 &pcie_intc0 0>,
+					<0 0 0 2 &pcie_intc0 1>,
+					<0 0 0 3 &pcie_intc0 2>,
+					<0 0 0 4 &pcie_intc0 3>;
+			pcie_intc0: interrupt-controller {
+				interrupt-controller;
+				#address-cells = <0>;
+				#interrupt-cells = <1>;
+			};
+		};
+
+		pcie1: pcie@1,0 {
+			device_type = "pci";
+			reg = <0x0800 0 0 0 0>;
+			#address-cells = <3>;
+			#size-cells = <2>;
+			#interrupt-cells = <1>;
+			ranges;
+			num-lanes = <1>;
+			interrupt-map-mask = <0 0 0 7>;
+			interrupt-map = <0 0 0 1 &pcie_intc1 0>,
+					<0 0 0 2 &pcie_intc1 1>,
+					<0 0 0 3 &pcie_intc1 2>,
+					<0 0 0 4 &pcie_intc1 3>;
+			pcie_intc1: interrupt-controller {
+				interrupt-controller;
+				#address-cells = <0>;
+				#interrupt-cells = <1>;
+			};
+		};
+	};
-- 
2.6.4

^ permalink raw reply related	[flat|nested] 80+ messages in thread

* [PATCH v2 5/5] dt-bindings: PCI: add support for new generation controller
@ 2017-07-27  2:58   ` honghui.zhang
  0 siblings, 0 replies; 80+ messages in thread
From: honghui.zhang @ 2017-07-27  2:58 UTC (permalink / raw)
  To: bhelgaas, robh, robh+dt, matthias.bgg, linux-arm-kernel,
	linux-mediatek, linux-pci, linux-kernel, devicetree,
	yingjoe.chen, eddie.huang, ryder.lee
  Cc: youlin.pei, hongkun.cao, sean.wang, xinping.qian, honghui.zhang,
	yt.shen, yong.wu

From: Ryder Lee <ryder.lee@mediatek.com>

Add support for MediaTek new generation controller and update related
properities.

Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
Signed-off-by: Honghui Zhang <honghui.zhang@mediatek.com>
---
 .../devicetree/bindings/pci/mediatek-pcie.txt      | 168 ++++++++++++++++++++-
 1 file changed, 161 insertions(+), 7 deletions(-)

diff --git a/Documentation/devicetree/bindings/pci/mediatek-pcie.txt b/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
index a968f25..179329b 100644
--- a/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
+++ b/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
@@ -3,18 +3,31 @@ MediaTek Gen2 PCIe controller
 Required properties:
 - compatible: Should contain one of the following string:
 	"mediatek,mt2701-pcie"
+	"mediatek,mt2712-pcie"
+	"mediatek,mt7622-pcie"
 	"mediatek,mt7623-pcie"
 - device_type: Must be "pci"
-- reg: Base addresses and lengths of the PCIe controller.
+- reg: Base addresses and lengths of the PICe subsys and root ports.
+- reg-names: Names of the above areas to use during resource look-up.
 - #address-cells: Address representation for root ports (must be 3)
 - #size-cells: Size representation for root ports (must be 2)
 - clocks: Must contain an entry for each entry in clock-names.
   See ../clocks/clock-bindings.txt for details.
-- clock-names: Must include the following entries:
-  - free_ck :for reference clock of PCIe subsys
-  - sys_ck0 :for clock of Port0
-  - sys_ck1 :for clock of Port1
-  - sys_ck2 :for clock of Port2
+- clock-names:
+  Mandatory entries:
+   - sys_ckN :transaction layer and data link layer clock
+  Required entries for MT2701/MT7623:
+   - free_ck :for reference clock of PCIe subsys
+  Required entries for MT2712/MT7622:
+   - ahb_ckN :AHB slave interface operating clock for CSR access and RC
+	      initiated MMIO access
+  Required entries for MT7622:
+   - axi_ckN :application layer MMIO channel operating clock
+   - aux_ckN :pe2_mac_bridge and pe2_mac_core operating clock when
+	      pcie_mac_ck/pcie_pipe_ck is turned off
+   - obff_ckN :OBFF functional block operating clock
+   - pipe_ckN :LTSSM and phy/mac layer operating clock
+  where N starting from 0 to the maximum number of root ports.
 - phys: List of PHY specifiers (used by generic PHY framework).
 - phy-names : Must be "pcie-phy0", "pcie-phy1", "pcie-phyN".. based on the
   number of PHYs as specified in *phys* property.
@@ -33,6 +46,10 @@ Required properties for MT7623/MT2701:
 - reset-names: Must be "pcie-rst0", "pcie-rst1", "pcie-rstN".. based on the
   number of root ports.
 
+Required properties for MT2712/MT7622:
+-interrupts: A list of interrupt outputs of the controller, must have one
+	     entry for each PCIe port
+
 In addition, the device tree node must have sub-nodes describing each
 PCIe port interface, having the following mandatory properties:
 
@@ -50,7 +67,7 @@ Required properties:
   property is sufficient.
 - num-lanes: Number of lanes to use for this port.
 
-Examples:
+Examples for MT7623:
 
 	hifsys: syscon@1a000000 {
 		compatible = "mediatek,mt7623-hifsys",
@@ -68,6 +85,7 @@ Examples:
 		      <0 0x1a142000 0 0x1000>, /* Port0 registers */
 		      <0 0x1a143000 0 0x1000>, /* Port1 registers */
 		      <0 0x1a144000 0 0x1000>; /* Port2 registers */
+		reg-names = "subsys", "port0", "port1", "port2";
 		#address-cells = <3>;
 		#size-cells = <2>;
 		#interrupt-cells = <1>;
@@ -127,3 +145,139 @@ Examples:
 			num-lanes = <1>;
 		};
 	};
+
+Examples for MT2712:
+	pcie: pcie@11700000 {
+		compatible = "mediatek,generic-pcie-v2";
+		device_type = "pci";
+		reg = <0 0x11700000 0 0x1000>,
+		      <0 0x112ff000 0 0x1000>;
+		reg-names = "port0", "port1";
+		#address-cells = <3>;
+		#size-cells = <2>;
+		interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&pericfg CLK_PERI_PCIE0>,
+			 <&pericfg CLK_PERI_PCIE1>,
+			 <&topckgen CLK_TOP_PE2_MAC_P0_SEL>,
+			 <&topckgen CLK_TOP_PE2_MAC_P1_SEL>;
+		clock-names = "sys_ck0", "sys_ck1", "ahb_ck0", "ahb_ck1";
+		phys = <&pcie0_phy PHY_TYPE_PCIE>, <&pcie1_phy PHY_TYPE_PCIE>;
+		phy-names = "pcie-phy0", "pcie-phy1";
+		bus-range = <0x00 0xff>;
+		ranges = <0x82000000 0 0x20000000  0x0 0x20000000  0 0x10000000>;
+
+		pcie0: pcie@0,0 {
+			device_type = "pci";
+			reg = <0x0000 0 0 0 0>;
+			#address-cells = <3>;
+			#size-cells = <2>;
+			#interrupt-cells = <1>;
+			ranges;
+			num-lanes = <1>;
+			interrupt-map-mask = <0 0 0 7>;
+			interrupt-map = <0 0 0 1 &pcie_intc0 0>,
+					<0 0 0 2 &pcie_intc0 1>,
+					<0 0 0 3 &pcie_intc0 2>,
+					<0 0 0 4 &pcie_intc0 3>;
+			pcie_intc0: interrupt-controller {
+				interrupt-controller;
+				#address-cells = <0>;
+				#interrupt-cells = <1>;
+			};
+		};
+
+		pcie1: pcie@1,0 {
+			device_type = "pci";
+			reg = <0x0800 0 0 0 0>;
+			#address-cells = <3>;
+			#size-cells = <2>;
+			#interrupt-cells = <1>;
+			ranges;
+			num-lanes = <1>;
+			interrupt-map-mask = <0 0 0 7>;
+			interrupt-map = <0 0 0 1 &pcie_intc1 0>,
+					<0 0 0 2 &pcie_intc1 1>,
+					<0 0 0 3 &pcie_intc1 2>,
+					<0 0 0 4 &pcie_intc1 3>;
+			pcie_intc1: interrupt-controller {
+				interrupt-controller;
+				#address-cells = <0>;
+				#interrupt-cells = <1>;
+			};
+		};
+	};
+
+Examples for MT7622:
+	pcie: pcie@1a140000 {
+		compatible = "mediatek,generic-pcie-v2";
+		device_type = "pci";
+		reg = <0 0x1a140000 0 0x1000>,
+		      <0 0x1a143000 0 0x1000>,
+		      <0 0x1a145000 0 0x1000>;
+		reg-names = "subsys", "port0", "port1";
+		#address-cells = <3>;
+		#size-cells = <2>;
+		interrupts = <GIC_SPI 228 IRQ_TYPE_LEVEL_LOW>,
+			     <GIC_SPI 229 IRQ_TYPE_LEVEL_LOW>;
+		clocks = <&pciesys CLK_PCIE_P0_MAC_EN>,
+			 <&pciesys CLK_PCIE_P1_MAC_EN>,
+			 <&pciesys CLK_PCIE_P0_AHB_EN>,
+			 <&pciesys CLK_PCIE_P1_AHB_EN>,
+			 <&pciesys CLK_PCIE_P0_AUX_EN>,
+			 <&pciesys CLK_PCIE_P1_AUX_EN>,
+			 <&pciesys CLK_PCIE_P0_AXI_EN>,
+			 <&pciesys CLK_PCIE_P1_AXI_EN>,
+			 <&pciesys CLK_PCIE_P0_OBFF_EN>,
+			 <&pciesys CLK_PCIE_P1_OBFF_EN>,
+			 <&pciesys CLK_PCIE_P0_PIPE_EN>,
+			 <&pciesys CLK_PCIE_P1_PIPE_EN>;
+		clock-names = "sys_ck0", "sys_ck1", "ahb_ck0", "ahb_ck1",
+			      "aux_ck0", "aux_ck1", "axi_ck0", "axi_ck1",
+			      "obff_ck0", "obff_ck1", "pipe_ck0", "pipe_ck1";
+		phys = <&pcie0_phy PHY_TYPE_PCIE>, <&pcie1_phy PHY_TYPE_PCIE>;
+		phy-names = "pcie-phy0", "pcie-phy1";
+		power-domains = <&scpsys MT7622_POWER_DOMAIN_HIF0>;
+		bus-range = <0x00 0xff>;
+		ranges = <0x82000000 0 0x20000000  0x0 0x20000000  0 0x10000000>;
+
+		pcie0: pcie@0,0 {
+			device_type = "pci";
+			reg = <0x0000 0 0 0 0>;
+			#address-cells = <3>;
+			#size-cells = <2>;
+			#interrupt-cells = <1>;
+			ranges;
+			num-lanes = <1>;
+			interrupt-map-mask = <0 0 0 7>;
+			interrupt-map = <0 0 0 1 &pcie_intc0 0>,
+					<0 0 0 2 &pcie_intc0 1>,
+					<0 0 0 3 &pcie_intc0 2>,
+					<0 0 0 4 &pcie_intc0 3>;
+			pcie_intc0: interrupt-controller {
+				interrupt-controller;
+				#address-cells = <0>;
+				#interrupt-cells = <1>;
+			};
+		};
+
+		pcie1: pcie@1,0 {
+			device_type = "pci";
+			reg = <0x0800 0 0 0 0>;
+			#address-cells = <3>;
+			#size-cells = <2>;
+			#interrupt-cells = <1>;
+			ranges;
+			num-lanes = <1>;
+			interrupt-map-mask = <0 0 0 7>;
+			interrupt-map = <0 0 0 1 &pcie_intc1 0>,
+					<0 0 0 2 &pcie_intc1 1>,
+					<0 0 0 3 &pcie_intc1 2>,
+					<0 0 0 4 &pcie_intc1 3>;
+			pcie_intc1: interrupt-controller {
+				interrupt-controller;
+				#address-cells = <0>;
+				#interrupt-cells = <1>;
+			};
+		};
+	};
-- 
2.6.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 80+ messages in thread

* [PATCH v2 5/5] dt-bindings: PCI: add support for new generation controller
@ 2017-07-27  2:58   ` honghui.zhang
  0 siblings, 0 replies; 80+ messages in thread
From: honghui.zhang at mediatek.com @ 2017-07-27  2:58 UTC (permalink / raw)
  To: linux-arm-kernel

From: Ryder Lee <ryder.lee@mediatek.com>

Add support for MediaTek new generation controller and update related
properities.

Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
Signed-off-by: Honghui Zhang <honghui.zhang@mediatek.com>
---
 .../devicetree/bindings/pci/mediatek-pcie.txt      | 168 ++++++++++++++++++++-
 1 file changed, 161 insertions(+), 7 deletions(-)

diff --git a/Documentation/devicetree/bindings/pci/mediatek-pcie.txt b/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
index a968f25..179329b 100644
--- a/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
+++ b/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
@@ -3,18 +3,31 @@ MediaTek Gen2 PCIe controller
 Required properties:
 - compatible: Should contain one of the following string:
 	"mediatek,mt2701-pcie"
+	"mediatek,mt2712-pcie"
+	"mediatek,mt7622-pcie"
 	"mediatek,mt7623-pcie"
 - device_type: Must be "pci"
-- reg: Base addresses and lengths of the PCIe controller.
+- reg: Base addresses and lengths of the PICe subsys and root ports.
+- reg-names: Names of the above areas to use during resource look-up.
 - #address-cells: Address representation for root ports (must be 3)
 - #size-cells: Size representation for root ports (must be 2)
 - clocks: Must contain an entry for each entry in clock-names.
   See ../clocks/clock-bindings.txt for details.
-- clock-names: Must include the following entries:
-  - free_ck :for reference clock of PCIe subsys
-  - sys_ck0 :for clock of Port0
-  - sys_ck1 :for clock of Port1
-  - sys_ck2 :for clock of Port2
+- clock-names:
+  Mandatory entries:
+   - sys_ckN :transaction layer and data link layer clock
+  Required entries for MT2701/MT7623:
+   - free_ck :for reference clock of PCIe subsys
+  Required entries for MT2712/MT7622:
+   - ahb_ckN :AHB slave interface operating clock for CSR access and RC
+	      initiated MMIO access
+  Required entries for MT7622:
+   - axi_ckN :application layer MMIO channel operating clock
+   - aux_ckN :pe2_mac_bridge and pe2_mac_core operating clock when
+	      pcie_mac_ck/pcie_pipe_ck is turned off
+   - obff_ckN :OBFF functional block operating clock
+   - pipe_ckN :LTSSM and phy/mac layer operating clock
+  where N starting from 0 to the maximum number of root ports.
 - phys: List of PHY specifiers (used by generic PHY framework).
 - phy-names : Must be "pcie-phy0", "pcie-phy1", "pcie-phyN".. based on the
   number of PHYs as specified in *phys* property.
@@ -33,6 +46,10 @@ Required properties for MT7623/MT2701:
 - reset-names: Must be "pcie-rst0", "pcie-rst1", "pcie-rstN".. based on the
   number of root ports.
 
+Required properties for MT2712/MT7622:
+-interrupts: A list of interrupt outputs of the controller, must have one
+	     entry for each PCIe port
+
 In addition, the device tree node must have sub-nodes describing each
 PCIe port interface, having the following mandatory properties:
 
@@ -50,7 +67,7 @@ Required properties:
   property is sufficient.
 - num-lanes: Number of lanes to use for this port.
 
-Examples:
+Examples for MT7623:
 
 	hifsys: syscon at 1a000000 {
 		compatible = "mediatek,mt7623-hifsys",
@@ -68,6 +85,7 @@ Examples:
 		      <0 0x1a142000 0 0x1000>, /* Port0 registers */
 		      <0 0x1a143000 0 0x1000>, /* Port1 registers */
 		      <0 0x1a144000 0 0x1000>; /* Port2 registers */
+		reg-names = "subsys", "port0", "port1", "port2";
 		#address-cells = <3>;
 		#size-cells = <2>;
 		#interrupt-cells = <1>;
@@ -127,3 +145,139 @@ Examples:
 			num-lanes = <1>;
 		};
 	};
+
+Examples for MT2712:
+	pcie: pcie at 11700000 {
+		compatible = "mediatek,generic-pcie-v2";
+		device_type = "pci";
+		reg = <0 0x11700000 0 0x1000>,
+		      <0 0x112ff000 0 0x1000>;
+		reg-names = "port0", "port1";
+		#address-cells = <3>;
+		#size-cells = <2>;
+		interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&pericfg CLK_PERI_PCIE0>,
+			 <&pericfg CLK_PERI_PCIE1>,
+			 <&topckgen CLK_TOP_PE2_MAC_P0_SEL>,
+			 <&topckgen CLK_TOP_PE2_MAC_P1_SEL>;
+		clock-names = "sys_ck0", "sys_ck1", "ahb_ck0", "ahb_ck1";
+		phys = <&pcie0_phy PHY_TYPE_PCIE>, <&pcie1_phy PHY_TYPE_PCIE>;
+		phy-names = "pcie-phy0", "pcie-phy1";
+		bus-range = <0x00 0xff>;
+		ranges = <0x82000000 0 0x20000000  0x0 0x20000000  0 0x10000000>;
+
+		pcie0: pcie at 0,0 {
+			device_type = "pci";
+			reg = <0x0000 0 0 0 0>;
+			#address-cells = <3>;
+			#size-cells = <2>;
+			#interrupt-cells = <1>;
+			ranges;
+			num-lanes = <1>;
+			interrupt-map-mask = <0 0 0 7>;
+			interrupt-map = <0 0 0 1 &pcie_intc0 0>,
+					<0 0 0 2 &pcie_intc0 1>,
+					<0 0 0 3 &pcie_intc0 2>,
+					<0 0 0 4 &pcie_intc0 3>;
+			pcie_intc0: interrupt-controller {
+				interrupt-controller;
+				#address-cells = <0>;
+				#interrupt-cells = <1>;
+			};
+		};
+
+		pcie1: pcie at 1,0 {
+			device_type = "pci";
+			reg = <0x0800 0 0 0 0>;
+			#address-cells = <3>;
+			#size-cells = <2>;
+			#interrupt-cells = <1>;
+			ranges;
+			num-lanes = <1>;
+			interrupt-map-mask = <0 0 0 7>;
+			interrupt-map = <0 0 0 1 &pcie_intc1 0>,
+					<0 0 0 2 &pcie_intc1 1>,
+					<0 0 0 3 &pcie_intc1 2>,
+					<0 0 0 4 &pcie_intc1 3>;
+			pcie_intc1: interrupt-controller {
+				interrupt-controller;
+				#address-cells = <0>;
+				#interrupt-cells = <1>;
+			};
+		};
+	};
+
+Examples for MT7622:
+	pcie: pcie at 1a140000 {
+		compatible = "mediatek,generic-pcie-v2";
+		device_type = "pci";
+		reg = <0 0x1a140000 0 0x1000>,
+		      <0 0x1a143000 0 0x1000>,
+		      <0 0x1a145000 0 0x1000>;
+		reg-names = "subsys", "port0", "port1";
+		#address-cells = <3>;
+		#size-cells = <2>;
+		interrupts = <GIC_SPI 228 IRQ_TYPE_LEVEL_LOW>,
+			     <GIC_SPI 229 IRQ_TYPE_LEVEL_LOW>;
+		clocks = <&pciesys CLK_PCIE_P0_MAC_EN>,
+			 <&pciesys CLK_PCIE_P1_MAC_EN>,
+			 <&pciesys CLK_PCIE_P0_AHB_EN>,
+			 <&pciesys CLK_PCIE_P1_AHB_EN>,
+			 <&pciesys CLK_PCIE_P0_AUX_EN>,
+			 <&pciesys CLK_PCIE_P1_AUX_EN>,
+			 <&pciesys CLK_PCIE_P0_AXI_EN>,
+			 <&pciesys CLK_PCIE_P1_AXI_EN>,
+			 <&pciesys CLK_PCIE_P0_OBFF_EN>,
+			 <&pciesys CLK_PCIE_P1_OBFF_EN>,
+			 <&pciesys CLK_PCIE_P0_PIPE_EN>,
+			 <&pciesys CLK_PCIE_P1_PIPE_EN>;
+		clock-names = "sys_ck0", "sys_ck1", "ahb_ck0", "ahb_ck1",
+			      "aux_ck0", "aux_ck1", "axi_ck0", "axi_ck1",
+			      "obff_ck0", "obff_ck1", "pipe_ck0", "pipe_ck1";
+		phys = <&pcie0_phy PHY_TYPE_PCIE>, <&pcie1_phy PHY_TYPE_PCIE>;
+		phy-names = "pcie-phy0", "pcie-phy1";
+		power-domains = <&scpsys MT7622_POWER_DOMAIN_HIF0>;
+		bus-range = <0x00 0xff>;
+		ranges = <0x82000000 0 0x20000000  0x0 0x20000000  0 0x10000000>;
+
+		pcie0: pcie at 0,0 {
+			device_type = "pci";
+			reg = <0x0000 0 0 0 0>;
+			#address-cells = <3>;
+			#size-cells = <2>;
+			#interrupt-cells = <1>;
+			ranges;
+			num-lanes = <1>;
+			interrupt-map-mask = <0 0 0 7>;
+			interrupt-map = <0 0 0 1 &pcie_intc0 0>,
+					<0 0 0 2 &pcie_intc0 1>,
+					<0 0 0 3 &pcie_intc0 2>,
+					<0 0 0 4 &pcie_intc0 3>;
+			pcie_intc0: interrupt-controller {
+				interrupt-controller;
+				#address-cells = <0>;
+				#interrupt-cells = <1>;
+			};
+		};
+
+		pcie1: pcie at 1,0 {
+			device_type = "pci";
+			reg = <0x0800 0 0 0 0>;
+			#address-cells = <3>;
+			#size-cells = <2>;
+			#interrupt-cells = <1>;
+			ranges;
+			num-lanes = <1>;
+			interrupt-map-mask = <0 0 0 7>;
+			interrupt-map = <0 0 0 1 &pcie_intc1 0>,
+					<0 0 0 2 &pcie_intc1 1>,
+					<0 0 0 3 &pcie_intc1 2>,
+					<0 0 0 4 &pcie_intc1 3>;
+			pcie_intc1: interrupt-controller {
+				interrupt-controller;
+				#address-cells = <0>;
+				#interrupt-cells = <1>;
+			};
+		};
+	};
-- 
2.6.4

^ permalink raw reply related	[flat|nested] 80+ messages in thread

* Re: [PATCH v2 1/5] PCI: mediatek: Add a structure to abstract the controller generations
@ 2017-07-27  3:19     ` Honghui Zhang
  0 siblings, 0 replies; 80+ messages in thread
From: Honghui Zhang @ 2017-07-27  3:19 UTC (permalink / raw)
  To: bhelgaas
  Cc: robh, robh+dt, matthias.bgg, linux-arm-kernel, linux-mediatek,
	linux-pci, linux-kernel, devicetree, yingjoe.chen, eddie.huang,
	ryder.lee, hongkun.cao, youlin.pei, yong.wu, yt.shen, sean.wang,
	xinping.qian

On Thu, 2017-07-27 at 10:58 +0800, honghui.zhang@mediatek.com wrote:
> From: Ryder Lee <ryder.lee@mediatek.com>
> 
> Introduce a structure "mtk_pcie_soc" to abstract the differences between
> controller generations, and the .startup() hook is used to encapsulate
> some SoC-dependent related setting. In doing so, the common code which
> will be reused by future chips.
> 
> In addition, we change the approaches to waiting Gen2 training by using
> readl_poll_timeout() calls.
> 
> Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> Signed-off-by: Honghui Zhang <honghui.zhang@mediatek.com>
> ---
>  drivers/pci/host/pcie-mediatek.c | 81 +++++++++++++++++++++++-----------------
>  1 file changed, 47 insertions(+), 34 deletions(-)
> 
> diff --git a/drivers/pci/host/pcie-mediatek.c b/drivers/pci/host/pcie-mediatek.c
> index 5a9d858..7f952a4 100644
> --- a/drivers/pci/host/pcie-mediatek.c
> +++ b/drivers/pci/host/pcie-mediatek.c
> @@ -16,6 +16,7 @@
>  

Sorry about the disturb, I send the wrong patch for this one.
I will resend the right version for this last patch.

thanks.
>  #include <linux/clk.h>
>  #include <linux/delay.h>
> +#include <linux/iopoll.h>
>  #include <linux/kernel.h>
>  #include <linux/of_address.h>
>  #include <linux/of_pci.h>
> @@ -63,6 +64,18 @@
>  #define PCIE_FC_CREDIT_MASK	(GENMASK(31, 31) | GENMASK(28, 16))
>  #define PCIE_FC_CREDIT_VAL(x)	((x) << 16)
>  
> +struct mtk_pcie_port;
> +
> +/**
> + * struct mtk_pcie_soc - differentiate between host generations
> + * @ops: pointer to configuration access functions
> + * @startup: pointer to controller setting functions
> + */
> +struct mtk_pcie_soc {
> +	struct pci_ops *ops;
> +	int (*startup)(struct mtk_pcie_port *port);
> +};
> +
>  /**
>   * struct mtk_pcie_port - PCIe port information
>   * @base: IO mapped register base
> @@ -96,6 +109,7 @@ struct mtk_pcie_port {
>   * @busn: bus range
>   * @offset: IO / Memory offset
>   * @ports: pointer to PCIe port information
> + * @soc: pointer to SoC-dependent operations
>   */
>  struct mtk_pcie {
>  	struct device *dev;
> @@ -111,13 +125,9 @@ struct mtk_pcie {
>  		resource_size_t io;
>  	} offset;
>  	struct list_head ports;
> +	const struct mtk_pcie_soc *soc;
>  };
>  
> -static inline bool mtk_pcie_link_up(struct mtk_pcie_port *port)
> -{
> -	return !!(readl(port->base + PCIE_LINK_STATUS) & PCIE_PORT_LINKUP);
> -}
> -
>  static void mtk_pcie_subsys_powerdown(struct mtk_pcie *pcie)
>  {
>  	struct device *dev = pcie->dev;
> @@ -171,12 +181,30 @@ static struct pci_ops mtk_pcie_ops = {
>  	.write = pci_generic_config_write,
>  };
>  
> -static void mtk_pcie_configure_rc(struct mtk_pcie_port *port)
> +static int mtk_pcie_startup_ports(struct mtk_pcie_port *port)
>  {
>  	struct mtk_pcie *pcie = port->pcie;
>  	u32 func = PCI_FUNC(port->index << 3);
>  	u32 slot = PCI_SLOT(port->index << 3);
>  	u32 val;
> +	int err;
> +
> +	/* assert port PERST_N */
> +	val = readl(pcie->base + PCIE_SYS_CFG);
> +	val |= PCIE_PORT_PERST(port->index);
> +	writel(val, pcie->base + PCIE_SYS_CFG);
> +
> +	/* de-assert port PERST_N */
> +	val = readl(pcie->base + PCIE_SYS_CFG);
> +	val &= ~PCIE_PORT_PERST(port->index);
> +	writel(val, pcie->base + PCIE_SYS_CFG);
> +
> +	/* 100ms timeout value should be enough for Gen1/2 training */
> +	err = readl_poll_timeout(port->base + PCIE_LINK_STATUS, val,
> +				 !!(val & PCIE_PORT_LINKUP), 20,
> +				 100 * USEC_PER_MSEC);
> +	if (err)
> +		return -ETIMEDOUT;
>  
>  	/* enable interrupt */
>  	val = readl(pcie->base + PCIE_INT_ENABLE);
> @@ -209,30 +237,14 @@ static void mtk_pcie_configure_rc(struct mtk_pcie_port *port)
>  	writel(PCIE_CONF_ADDR(PCIE_FTS_NUM, func, slot, 0),
>  	       pcie->base + PCIE_CFG_ADDR);
>  	writel(val, pcie->base + PCIE_CFG_DATA);
> -}
>  
> -static void mtk_pcie_assert_ports(struct mtk_pcie_port *port)
> -{
> -	struct mtk_pcie *pcie = port->pcie;
> -	u32 val;
> -
> -	/* assert port PERST_N */
> -	val = readl(pcie->base + PCIE_SYS_CFG);
> -	val |= PCIE_PORT_PERST(port->index);
> -	writel(val, pcie->base + PCIE_SYS_CFG);
> -
> -	/* de-assert port PERST_N */
> -	val = readl(pcie->base + PCIE_SYS_CFG);
> -	val &= ~PCIE_PORT_PERST(port->index);
> -	writel(val, pcie->base + PCIE_SYS_CFG);
> -
> -	/* PCIe v2.0 need at least 100ms delay to train from Gen1 to Gen2 */
> -	msleep(100);
> +	return 0;
>  }
>  
>  static void mtk_pcie_enable_ports(struct mtk_pcie_port *port)
>  {
> -	struct device *dev = port->pcie->dev;
> +	struct mtk_pcie *pcie = port->pcie;
> +	struct device *dev = pcie->dev;
>  	int err;
>  
>  	err = clk_prepare_enable(port->sys_ck);
> @@ -250,13 +262,8 @@ static void mtk_pcie_enable_ports(struct mtk_pcie_port *port)
>  		goto err_phy_on;
>  	}
>  
> -	mtk_pcie_assert_ports(port);
> -
> -	/* if link up, then setup root port configuration space */
> -	if (mtk_pcie_link_up(port)) {
> -		mtk_pcie_configure_rc(port);
> +	if (!pcie->soc->startup(port))
>  		return;
> -	}
>  
>  	dev_info(dev, "Port%d link down\n", port->index);
>  
> @@ -480,7 +487,7 @@ static int mtk_pcie_register_host(struct pci_host_bridge *host)
>  
>  	host->busnr = pcie->busn.start;
>  	host->dev.parent = pcie->dev;
> -	host->ops = &mtk_pcie_ops;
> +	host->ops = pcie->soc->ops;
>  	host->map_irq = of_irq_parse_and_map_pci;
>  	host->swizzle_irq = pci_common_swizzle;
>  
> @@ -513,6 +520,7 @@ static int mtk_pcie_probe(struct platform_device *pdev)
>  	pcie = pci_host_bridge_priv(host);
>  
>  	pcie->dev = dev;
> +	pcie->soc = of_device_get_match_data(dev);
>  	platform_set_drvdata(pdev, pcie);
>  	INIT_LIST_HEAD(&pcie->ports);
>  
> @@ -537,9 +545,14 @@ static int mtk_pcie_probe(struct platform_device *pdev)
>  	return err;
>  }
>  
> +static struct mtk_pcie_soc mtk_pcie_soc_v1 = {
> +	.ops = &mtk_pcie_ops,
> +	.startup = mtk_pcie_startup_ports,
> +};
> +
>  static const struct of_device_id mtk_pcie_ids[] = {
> -	{ .compatible = "mediatek,mt7623-pcie"},
> -	{ .compatible = "mediatek,mt2701-pcie"},
> +	{ .compatible = "mediatek,mt2701-pcie", .data = &mtk_pcie_soc_v1 },
> +	{ .compatible = "mediatek,mt7623-pcie", .data = &mtk_pcie_soc_v1 },
>  	{},
>  };
>  

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v2 1/5] PCI: mediatek: Add a structure to abstract the controller generations
@ 2017-07-27  3:19     ` Honghui Zhang
  0 siblings, 0 replies; 80+ messages in thread
From: Honghui Zhang @ 2017-07-27  3:19 UTC (permalink / raw)
  To: bhelgaas-hpIqsD4AKlfQT0dZR+AlfA
  Cc: robh-+zGGX9k9yNkdnm+yROfE0A, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	matthias.bgg-Re5JQEeQqe8AvxtiuMwx3w,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-pci-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	yingjoe.chen-NuS5LvNUpcJWk0Htik3J/w,
	eddie.huang-NuS5LvNUpcJWk0Htik3J/w,
	ryder.lee-NuS5LvNUpcJWk0Htik3J/w,
	hongkun.cao-NuS5LvNUpcJWk0Htik3J/w,
	youlin.pei-NuS5LvNUpcJWk0Htik3J/w,
	yong.wu-NuS5LvNUpcJWk0Htik3J/w, yt.shen-NuS5LvNUpcJWk0Htik3J/w,
	sean.wang-NuS5LvNUpcJWk0Htik3J/w,
	xinping.qian-NuS5LvNUpcJWk0Htik3J/w

On Thu, 2017-07-27 at 10:58 +0800, honghui.zhang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org wrote:
> From: Ryder Lee <ryder.lee-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
> 
> Introduce a structure "mtk_pcie_soc" to abstract the differences between
> controller generations, and the .startup() hook is used to encapsulate
> some SoC-dependent related setting. In doing so, the common code which
> will be reused by future chips.
> 
> In addition, we change the approaches to waiting Gen2 training by using
> readl_poll_timeout() calls.
> 
> Signed-off-by: Ryder Lee <ryder.lee-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
> Signed-off-by: Honghui Zhang <honghui.zhang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
> ---
>  drivers/pci/host/pcie-mediatek.c | 81 +++++++++++++++++++++++-----------------
>  1 file changed, 47 insertions(+), 34 deletions(-)
> 
> diff --git a/drivers/pci/host/pcie-mediatek.c b/drivers/pci/host/pcie-mediatek.c
> index 5a9d858..7f952a4 100644
> --- a/drivers/pci/host/pcie-mediatek.c
> +++ b/drivers/pci/host/pcie-mediatek.c
> @@ -16,6 +16,7 @@
>  

Sorry about the disturb, I send the wrong patch for this one.
I will resend the right version for this last patch.

thanks.
>  #include <linux/clk.h>
>  #include <linux/delay.h>
> +#include <linux/iopoll.h>
>  #include <linux/kernel.h>
>  #include <linux/of_address.h>
>  #include <linux/of_pci.h>
> @@ -63,6 +64,18 @@
>  #define PCIE_FC_CREDIT_MASK	(GENMASK(31, 31) | GENMASK(28, 16))
>  #define PCIE_FC_CREDIT_VAL(x)	((x) << 16)
>  
> +struct mtk_pcie_port;
> +
> +/**
> + * struct mtk_pcie_soc - differentiate between host generations
> + * @ops: pointer to configuration access functions
> + * @startup: pointer to controller setting functions
> + */
> +struct mtk_pcie_soc {
> +	struct pci_ops *ops;
> +	int (*startup)(struct mtk_pcie_port *port);
> +};
> +
>  /**
>   * struct mtk_pcie_port - PCIe port information
>   * @base: IO mapped register base
> @@ -96,6 +109,7 @@ struct mtk_pcie_port {
>   * @busn: bus range
>   * @offset: IO / Memory offset
>   * @ports: pointer to PCIe port information
> + * @soc: pointer to SoC-dependent operations
>   */
>  struct mtk_pcie {
>  	struct device *dev;
> @@ -111,13 +125,9 @@ struct mtk_pcie {
>  		resource_size_t io;
>  	} offset;
>  	struct list_head ports;
> +	const struct mtk_pcie_soc *soc;
>  };
>  
> -static inline bool mtk_pcie_link_up(struct mtk_pcie_port *port)
> -{
> -	return !!(readl(port->base + PCIE_LINK_STATUS) & PCIE_PORT_LINKUP);
> -}
> -
>  static void mtk_pcie_subsys_powerdown(struct mtk_pcie *pcie)
>  {
>  	struct device *dev = pcie->dev;
> @@ -171,12 +181,30 @@ static struct pci_ops mtk_pcie_ops = {
>  	.write = pci_generic_config_write,
>  };
>  
> -static void mtk_pcie_configure_rc(struct mtk_pcie_port *port)
> +static int mtk_pcie_startup_ports(struct mtk_pcie_port *port)
>  {
>  	struct mtk_pcie *pcie = port->pcie;
>  	u32 func = PCI_FUNC(port->index << 3);
>  	u32 slot = PCI_SLOT(port->index << 3);
>  	u32 val;
> +	int err;
> +
> +	/* assert port PERST_N */
> +	val = readl(pcie->base + PCIE_SYS_CFG);
> +	val |= PCIE_PORT_PERST(port->index);
> +	writel(val, pcie->base + PCIE_SYS_CFG);
> +
> +	/* de-assert port PERST_N */
> +	val = readl(pcie->base + PCIE_SYS_CFG);
> +	val &= ~PCIE_PORT_PERST(port->index);
> +	writel(val, pcie->base + PCIE_SYS_CFG);
> +
> +	/* 100ms timeout value should be enough for Gen1/2 training */
> +	err = readl_poll_timeout(port->base + PCIE_LINK_STATUS, val,
> +				 !!(val & PCIE_PORT_LINKUP), 20,
> +				 100 * USEC_PER_MSEC);
> +	if (err)
> +		return -ETIMEDOUT;
>  
>  	/* enable interrupt */
>  	val = readl(pcie->base + PCIE_INT_ENABLE);
> @@ -209,30 +237,14 @@ static void mtk_pcie_configure_rc(struct mtk_pcie_port *port)
>  	writel(PCIE_CONF_ADDR(PCIE_FTS_NUM, func, slot, 0),
>  	       pcie->base + PCIE_CFG_ADDR);
>  	writel(val, pcie->base + PCIE_CFG_DATA);
> -}
>  
> -static void mtk_pcie_assert_ports(struct mtk_pcie_port *port)
> -{
> -	struct mtk_pcie *pcie = port->pcie;
> -	u32 val;
> -
> -	/* assert port PERST_N */
> -	val = readl(pcie->base + PCIE_SYS_CFG);
> -	val |= PCIE_PORT_PERST(port->index);
> -	writel(val, pcie->base + PCIE_SYS_CFG);
> -
> -	/* de-assert port PERST_N */
> -	val = readl(pcie->base + PCIE_SYS_CFG);
> -	val &= ~PCIE_PORT_PERST(port->index);
> -	writel(val, pcie->base + PCIE_SYS_CFG);
> -
> -	/* PCIe v2.0 need at least 100ms delay to train from Gen1 to Gen2 */
> -	msleep(100);
> +	return 0;
>  }
>  
>  static void mtk_pcie_enable_ports(struct mtk_pcie_port *port)
>  {
> -	struct device *dev = port->pcie->dev;
> +	struct mtk_pcie *pcie = port->pcie;
> +	struct device *dev = pcie->dev;
>  	int err;
>  
>  	err = clk_prepare_enable(port->sys_ck);
> @@ -250,13 +262,8 @@ static void mtk_pcie_enable_ports(struct mtk_pcie_port *port)
>  		goto err_phy_on;
>  	}
>  
> -	mtk_pcie_assert_ports(port);
> -
> -	/* if link up, then setup root port configuration space */
> -	if (mtk_pcie_link_up(port)) {
> -		mtk_pcie_configure_rc(port);
> +	if (!pcie->soc->startup(port))
>  		return;
> -	}
>  
>  	dev_info(dev, "Port%d link down\n", port->index);
>  
> @@ -480,7 +487,7 @@ static int mtk_pcie_register_host(struct pci_host_bridge *host)
>  
>  	host->busnr = pcie->busn.start;
>  	host->dev.parent = pcie->dev;
> -	host->ops = &mtk_pcie_ops;
> +	host->ops = pcie->soc->ops;
>  	host->map_irq = of_irq_parse_and_map_pci;
>  	host->swizzle_irq = pci_common_swizzle;
>  
> @@ -513,6 +520,7 @@ static int mtk_pcie_probe(struct platform_device *pdev)
>  	pcie = pci_host_bridge_priv(host);
>  
>  	pcie->dev = dev;
> +	pcie->soc = of_device_get_match_data(dev);
>  	platform_set_drvdata(pdev, pcie);
>  	INIT_LIST_HEAD(&pcie->ports);
>  
> @@ -537,9 +545,14 @@ static int mtk_pcie_probe(struct platform_device *pdev)
>  	return err;
>  }
>  
> +static struct mtk_pcie_soc mtk_pcie_soc_v1 = {
> +	.ops = &mtk_pcie_ops,
> +	.startup = mtk_pcie_startup_ports,
> +};
> +
>  static const struct of_device_id mtk_pcie_ids[] = {
> -	{ .compatible = "mediatek,mt7623-pcie"},
> -	{ .compatible = "mediatek,mt2701-pcie"},
> +	{ .compatible = "mediatek,mt2701-pcie", .data = &mtk_pcie_soc_v1 },
> +	{ .compatible = "mediatek,mt7623-pcie", .data = &mtk_pcie_soc_v1 },
>  	{},
>  };
>  


--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v2 1/5] PCI: mediatek: Add a structure to abstract the controller generations
@ 2017-07-27  3:19     ` Honghui Zhang
  0 siblings, 0 replies; 80+ messages in thread
From: Honghui Zhang @ 2017-07-27  3:19 UTC (permalink / raw)
  To: bhelgaas
  Cc: youlin.pei, devicetree, hongkun.cao, ryder.lee, linux-pci,
	sean.wang, xinping.qian, linux-kernel, robh+dt, yt.shen, robh,
	linux-mediatek, yong.wu, matthias.bgg, yingjoe.chen, eddie.huang,
	linux-arm-kernel

On Thu, 2017-07-27 at 10:58 +0800, honghui.zhang@mediatek.com wrote:
> From: Ryder Lee <ryder.lee@mediatek.com>
> 
> Introduce a structure "mtk_pcie_soc" to abstract the differences between
> controller generations, and the .startup() hook is used to encapsulate
> some SoC-dependent related setting. In doing so, the common code which
> will be reused by future chips.
> 
> In addition, we change the approaches to waiting Gen2 training by using
> readl_poll_timeout() calls.
> 
> Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> Signed-off-by: Honghui Zhang <honghui.zhang@mediatek.com>
> ---
>  drivers/pci/host/pcie-mediatek.c | 81 +++++++++++++++++++++++-----------------
>  1 file changed, 47 insertions(+), 34 deletions(-)
> 
> diff --git a/drivers/pci/host/pcie-mediatek.c b/drivers/pci/host/pcie-mediatek.c
> index 5a9d858..7f952a4 100644
> --- a/drivers/pci/host/pcie-mediatek.c
> +++ b/drivers/pci/host/pcie-mediatek.c
> @@ -16,6 +16,7 @@
>  

Sorry about the disturb, I send the wrong patch for this one.
I will resend the right version for this last patch.

thanks.
>  #include <linux/clk.h>
>  #include <linux/delay.h>
> +#include <linux/iopoll.h>
>  #include <linux/kernel.h>
>  #include <linux/of_address.h>
>  #include <linux/of_pci.h>
> @@ -63,6 +64,18 @@
>  #define PCIE_FC_CREDIT_MASK	(GENMASK(31, 31) | GENMASK(28, 16))
>  #define PCIE_FC_CREDIT_VAL(x)	((x) << 16)
>  
> +struct mtk_pcie_port;
> +
> +/**
> + * struct mtk_pcie_soc - differentiate between host generations
> + * @ops: pointer to configuration access functions
> + * @startup: pointer to controller setting functions
> + */
> +struct mtk_pcie_soc {
> +	struct pci_ops *ops;
> +	int (*startup)(struct mtk_pcie_port *port);
> +};
> +
>  /**
>   * struct mtk_pcie_port - PCIe port information
>   * @base: IO mapped register base
> @@ -96,6 +109,7 @@ struct mtk_pcie_port {
>   * @busn: bus range
>   * @offset: IO / Memory offset
>   * @ports: pointer to PCIe port information
> + * @soc: pointer to SoC-dependent operations
>   */
>  struct mtk_pcie {
>  	struct device *dev;
> @@ -111,13 +125,9 @@ struct mtk_pcie {
>  		resource_size_t io;
>  	} offset;
>  	struct list_head ports;
> +	const struct mtk_pcie_soc *soc;
>  };
>  
> -static inline bool mtk_pcie_link_up(struct mtk_pcie_port *port)
> -{
> -	return !!(readl(port->base + PCIE_LINK_STATUS) & PCIE_PORT_LINKUP);
> -}
> -
>  static void mtk_pcie_subsys_powerdown(struct mtk_pcie *pcie)
>  {
>  	struct device *dev = pcie->dev;
> @@ -171,12 +181,30 @@ static struct pci_ops mtk_pcie_ops = {
>  	.write = pci_generic_config_write,
>  };
>  
> -static void mtk_pcie_configure_rc(struct mtk_pcie_port *port)
> +static int mtk_pcie_startup_ports(struct mtk_pcie_port *port)
>  {
>  	struct mtk_pcie *pcie = port->pcie;
>  	u32 func = PCI_FUNC(port->index << 3);
>  	u32 slot = PCI_SLOT(port->index << 3);
>  	u32 val;
> +	int err;
> +
> +	/* assert port PERST_N */
> +	val = readl(pcie->base + PCIE_SYS_CFG);
> +	val |= PCIE_PORT_PERST(port->index);
> +	writel(val, pcie->base + PCIE_SYS_CFG);
> +
> +	/* de-assert port PERST_N */
> +	val = readl(pcie->base + PCIE_SYS_CFG);
> +	val &= ~PCIE_PORT_PERST(port->index);
> +	writel(val, pcie->base + PCIE_SYS_CFG);
> +
> +	/* 100ms timeout value should be enough for Gen1/2 training */
> +	err = readl_poll_timeout(port->base + PCIE_LINK_STATUS, val,
> +				 !!(val & PCIE_PORT_LINKUP), 20,
> +				 100 * USEC_PER_MSEC);
> +	if (err)
> +		return -ETIMEDOUT;
>  
>  	/* enable interrupt */
>  	val = readl(pcie->base + PCIE_INT_ENABLE);
> @@ -209,30 +237,14 @@ static void mtk_pcie_configure_rc(struct mtk_pcie_port *port)
>  	writel(PCIE_CONF_ADDR(PCIE_FTS_NUM, func, slot, 0),
>  	       pcie->base + PCIE_CFG_ADDR);
>  	writel(val, pcie->base + PCIE_CFG_DATA);
> -}
>  
> -static void mtk_pcie_assert_ports(struct mtk_pcie_port *port)
> -{
> -	struct mtk_pcie *pcie = port->pcie;
> -	u32 val;
> -
> -	/* assert port PERST_N */
> -	val = readl(pcie->base + PCIE_SYS_CFG);
> -	val |= PCIE_PORT_PERST(port->index);
> -	writel(val, pcie->base + PCIE_SYS_CFG);
> -
> -	/* de-assert port PERST_N */
> -	val = readl(pcie->base + PCIE_SYS_CFG);
> -	val &= ~PCIE_PORT_PERST(port->index);
> -	writel(val, pcie->base + PCIE_SYS_CFG);
> -
> -	/* PCIe v2.0 need at least 100ms delay to train from Gen1 to Gen2 */
> -	msleep(100);
> +	return 0;
>  }
>  
>  static void mtk_pcie_enable_ports(struct mtk_pcie_port *port)
>  {
> -	struct device *dev = port->pcie->dev;
> +	struct mtk_pcie *pcie = port->pcie;
> +	struct device *dev = pcie->dev;
>  	int err;
>  
>  	err = clk_prepare_enable(port->sys_ck);
> @@ -250,13 +262,8 @@ static void mtk_pcie_enable_ports(struct mtk_pcie_port *port)
>  		goto err_phy_on;
>  	}
>  
> -	mtk_pcie_assert_ports(port);
> -
> -	/* if link up, then setup root port configuration space */
> -	if (mtk_pcie_link_up(port)) {
> -		mtk_pcie_configure_rc(port);
> +	if (!pcie->soc->startup(port))
>  		return;
> -	}
>  
>  	dev_info(dev, "Port%d link down\n", port->index);
>  
> @@ -480,7 +487,7 @@ static int mtk_pcie_register_host(struct pci_host_bridge *host)
>  
>  	host->busnr = pcie->busn.start;
>  	host->dev.parent = pcie->dev;
> -	host->ops = &mtk_pcie_ops;
> +	host->ops = pcie->soc->ops;
>  	host->map_irq = of_irq_parse_and_map_pci;
>  	host->swizzle_irq = pci_common_swizzle;
>  
> @@ -513,6 +520,7 @@ static int mtk_pcie_probe(struct platform_device *pdev)
>  	pcie = pci_host_bridge_priv(host);
>  
>  	pcie->dev = dev;
> +	pcie->soc = of_device_get_match_data(dev);
>  	platform_set_drvdata(pdev, pcie);
>  	INIT_LIST_HEAD(&pcie->ports);
>  
> @@ -537,9 +545,14 @@ static int mtk_pcie_probe(struct platform_device *pdev)
>  	return err;
>  }
>  
> +static struct mtk_pcie_soc mtk_pcie_soc_v1 = {
> +	.ops = &mtk_pcie_ops,
> +	.startup = mtk_pcie_startup_ports,
> +};
> +
>  static const struct of_device_id mtk_pcie_ids[] = {
> -	{ .compatible = "mediatek,mt7623-pcie"},
> -	{ .compatible = "mediatek,mt2701-pcie"},
> +	{ .compatible = "mediatek,mt2701-pcie", .data = &mtk_pcie_soc_v1 },
> +	{ .compatible = "mediatek,mt7623-pcie", .data = &mtk_pcie_soc_v1 },
>  	{},
>  };
>  



_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 80+ messages in thread

* [PATCH v2 1/5] PCI: mediatek: Add a structure to abstract the controller generations
@ 2017-07-27  3:19     ` Honghui Zhang
  0 siblings, 0 replies; 80+ messages in thread
From: Honghui Zhang @ 2017-07-27  3:19 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 2017-07-27 at 10:58 +0800, honghui.zhang at mediatek.com wrote:
> From: Ryder Lee <ryder.lee@mediatek.com>
> 
> Introduce a structure "mtk_pcie_soc" to abstract the differences between
> controller generations, and the .startup() hook is used to encapsulate
> some SoC-dependent related setting. In doing so, the common code which
> will be reused by future chips.
> 
> In addition, we change the approaches to waiting Gen2 training by using
> readl_poll_timeout() calls.
> 
> Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> Signed-off-by: Honghui Zhang <honghui.zhang@mediatek.com>
> ---
>  drivers/pci/host/pcie-mediatek.c | 81 +++++++++++++++++++++++-----------------
>  1 file changed, 47 insertions(+), 34 deletions(-)
> 
> diff --git a/drivers/pci/host/pcie-mediatek.c b/drivers/pci/host/pcie-mediatek.c
> index 5a9d858..7f952a4 100644
> --- a/drivers/pci/host/pcie-mediatek.c
> +++ b/drivers/pci/host/pcie-mediatek.c
> @@ -16,6 +16,7 @@
>  

Sorry about the disturb, I send the wrong patch for this one.
I will resend the right version for this last patch.

thanks.
>  #include <linux/clk.h>
>  #include <linux/delay.h>
> +#include <linux/iopoll.h>
>  #include <linux/kernel.h>
>  #include <linux/of_address.h>
>  #include <linux/of_pci.h>
> @@ -63,6 +64,18 @@
>  #define PCIE_FC_CREDIT_MASK	(GENMASK(31, 31) | GENMASK(28, 16))
>  #define PCIE_FC_CREDIT_VAL(x)	((x) << 16)
>  
> +struct mtk_pcie_port;
> +
> +/**
> + * struct mtk_pcie_soc - differentiate between host generations
> + * @ops: pointer to configuration access functions
> + * @startup: pointer to controller setting functions
> + */
> +struct mtk_pcie_soc {
> +	struct pci_ops *ops;
> +	int (*startup)(struct mtk_pcie_port *port);
> +};
> +
>  /**
>   * struct mtk_pcie_port - PCIe port information
>   * @base: IO mapped register base
> @@ -96,6 +109,7 @@ struct mtk_pcie_port {
>   * @busn: bus range
>   * @offset: IO / Memory offset
>   * @ports: pointer to PCIe port information
> + * @soc: pointer to SoC-dependent operations
>   */
>  struct mtk_pcie {
>  	struct device *dev;
> @@ -111,13 +125,9 @@ struct mtk_pcie {
>  		resource_size_t io;
>  	} offset;
>  	struct list_head ports;
> +	const struct mtk_pcie_soc *soc;
>  };
>  
> -static inline bool mtk_pcie_link_up(struct mtk_pcie_port *port)
> -{
> -	return !!(readl(port->base + PCIE_LINK_STATUS) & PCIE_PORT_LINKUP);
> -}
> -
>  static void mtk_pcie_subsys_powerdown(struct mtk_pcie *pcie)
>  {
>  	struct device *dev = pcie->dev;
> @@ -171,12 +181,30 @@ static struct pci_ops mtk_pcie_ops = {
>  	.write = pci_generic_config_write,
>  };
>  
> -static void mtk_pcie_configure_rc(struct mtk_pcie_port *port)
> +static int mtk_pcie_startup_ports(struct mtk_pcie_port *port)
>  {
>  	struct mtk_pcie *pcie = port->pcie;
>  	u32 func = PCI_FUNC(port->index << 3);
>  	u32 slot = PCI_SLOT(port->index << 3);
>  	u32 val;
> +	int err;
> +
> +	/* assert port PERST_N */
> +	val = readl(pcie->base + PCIE_SYS_CFG);
> +	val |= PCIE_PORT_PERST(port->index);
> +	writel(val, pcie->base + PCIE_SYS_CFG);
> +
> +	/* de-assert port PERST_N */
> +	val = readl(pcie->base + PCIE_SYS_CFG);
> +	val &= ~PCIE_PORT_PERST(port->index);
> +	writel(val, pcie->base + PCIE_SYS_CFG);
> +
> +	/* 100ms timeout value should be enough for Gen1/2 training */
> +	err = readl_poll_timeout(port->base + PCIE_LINK_STATUS, val,
> +				 !!(val & PCIE_PORT_LINKUP), 20,
> +				 100 * USEC_PER_MSEC);
> +	if (err)
> +		return -ETIMEDOUT;
>  
>  	/* enable interrupt */
>  	val = readl(pcie->base + PCIE_INT_ENABLE);
> @@ -209,30 +237,14 @@ static void mtk_pcie_configure_rc(struct mtk_pcie_port *port)
>  	writel(PCIE_CONF_ADDR(PCIE_FTS_NUM, func, slot, 0),
>  	       pcie->base + PCIE_CFG_ADDR);
>  	writel(val, pcie->base + PCIE_CFG_DATA);
> -}
>  
> -static void mtk_pcie_assert_ports(struct mtk_pcie_port *port)
> -{
> -	struct mtk_pcie *pcie = port->pcie;
> -	u32 val;
> -
> -	/* assert port PERST_N */
> -	val = readl(pcie->base + PCIE_SYS_CFG);
> -	val |= PCIE_PORT_PERST(port->index);
> -	writel(val, pcie->base + PCIE_SYS_CFG);
> -
> -	/* de-assert port PERST_N */
> -	val = readl(pcie->base + PCIE_SYS_CFG);
> -	val &= ~PCIE_PORT_PERST(port->index);
> -	writel(val, pcie->base + PCIE_SYS_CFG);
> -
> -	/* PCIe v2.0 need at least 100ms delay to train from Gen1 to Gen2 */
> -	msleep(100);
> +	return 0;
>  }
>  
>  static void mtk_pcie_enable_ports(struct mtk_pcie_port *port)
>  {
> -	struct device *dev = port->pcie->dev;
> +	struct mtk_pcie *pcie = port->pcie;
> +	struct device *dev = pcie->dev;
>  	int err;
>  
>  	err = clk_prepare_enable(port->sys_ck);
> @@ -250,13 +262,8 @@ static void mtk_pcie_enable_ports(struct mtk_pcie_port *port)
>  		goto err_phy_on;
>  	}
>  
> -	mtk_pcie_assert_ports(port);
> -
> -	/* if link up, then setup root port configuration space */
> -	if (mtk_pcie_link_up(port)) {
> -		mtk_pcie_configure_rc(port);
> +	if (!pcie->soc->startup(port))
>  		return;
> -	}
>  
>  	dev_info(dev, "Port%d link down\n", port->index);
>  
> @@ -480,7 +487,7 @@ static int mtk_pcie_register_host(struct pci_host_bridge *host)
>  
>  	host->busnr = pcie->busn.start;
>  	host->dev.parent = pcie->dev;
> -	host->ops = &mtk_pcie_ops;
> +	host->ops = pcie->soc->ops;
>  	host->map_irq = of_irq_parse_and_map_pci;
>  	host->swizzle_irq = pci_common_swizzle;
>  
> @@ -513,6 +520,7 @@ static int mtk_pcie_probe(struct platform_device *pdev)
>  	pcie = pci_host_bridge_priv(host);
>  
>  	pcie->dev = dev;
> +	pcie->soc = of_device_get_match_data(dev);
>  	platform_set_drvdata(pdev, pcie);
>  	INIT_LIST_HEAD(&pcie->ports);
>  
> @@ -537,9 +545,14 @@ static int mtk_pcie_probe(struct platform_device *pdev)
>  	return err;
>  }
>  
> +static struct mtk_pcie_soc mtk_pcie_soc_v1 = {
> +	.ops = &mtk_pcie_ops,
> +	.startup = mtk_pcie_startup_ports,
> +};
> +
>  static const struct of_device_id mtk_pcie_ids[] = {
> -	{ .compatible = "mediatek,mt7623-pcie"},
> -	{ .compatible = "mediatek,mt2701-pcie"},
> +	{ .compatible = "mediatek,mt2701-pcie", .data = &mtk_pcie_soc_v1 },
> +	{ .compatible = "mediatek,mt7623-pcie", .data = &mtk_pcie_soc_v1 },
>  	{},
>  };
>  

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v2 1/5] PCI: mediatek: Add a structure to abstract the controller generations
  2017-07-27  3:19     ` Honghui Zhang
  (?)
  (?)
@ 2017-07-27  3:28       ` Honghui Zhang
  -1 siblings, 0 replies; 80+ messages in thread
From: Honghui Zhang @ 2017-07-27  3:28 UTC (permalink / raw)
  To: bhelgaas
  Cc: youlin.pei, devicetree, hongkun.cao, ryder.lee, linux-pci,
	sean.wang, xinping.qian, linux-kernel, robh+dt, yt.shen, robh,
	linux-mediatek, yong.wu, matthias.bgg, yingjoe.chen, eddie.huang,
	linux-arm-kernel

On Thu, 2017-07-27 at 11:19 +0800, Honghui Zhang wrote:
> On Thu, 2017-07-27 at 10:58 +0800, honghui.zhang@mediatek.com wrote:
> > From: Ryder Lee <ryder.lee@mediatek.com>
> > 
> > Introduce a structure "mtk_pcie_soc" to abstract the differences between
> > controller generations, and the .startup() hook is used to encapsulate
> > some SoC-dependent related setting. In doing so, the common code which
> > will be reused by future chips.
> > 
> > In addition, we change the approaches to waiting Gen2 training by using
> > readl_poll_timeout() calls.
> > 
> > Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> > Signed-off-by: Honghui Zhang <honghui.zhang@mediatek.com>
> > ---
> >  drivers/pci/host/pcie-mediatek.c | 81 +++++++++++++++++++++++-----------------
> >  1 file changed, 47 insertions(+), 34 deletions(-)
> > 
> > diff --git a/drivers/pci/host/pcie-mediatek.c b/drivers/pci/host/pcie-mediatek.c
> > index 5a9d858..7f952a4 100644
> > --- a/drivers/pci/host/pcie-mediatek.c
> > +++ b/drivers/pci/host/pcie-mediatek.c
> > @@ -16,6 +16,7 @@
> >  
> 
> Sorry about the disturb, I send the wrong patch for this one.
> I will resend the right version for this last patch.
> 

Sorry, I reply to the wrong patch mail.
I meant to re-send the patch:
[PATCH v2 5/5] dt-bindings: PCI: add support for new generation
controller, not this one.

This one is the right patch.

tahnks.

> thanks.
> >  #include <linux/clk.h>
> >  #include <linux/delay.h>
> > +#include <linux/iopoll.h>
> >  #include <linux/kernel.h>
> >  #include <linux/of_address.h>
> >  #include <linux/of_pci.h>
> > @@ -63,6 +64,18 @@
> >  #define PCIE_FC_CREDIT_MASK	(GENMASK(31, 31) | GENMASK(28, 16))
> >  #define PCIE_FC_CREDIT_VAL(x)	((x) << 16)
> >  
> > +struct mtk_pcie_port;
> > +
> > +/**
> > + * struct mtk_pcie_soc - differentiate between host generations
> > + * @ops: pointer to configuration access functions
> > + * @startup: pointer to controller setting functions
> > + */
> > +struct mtk_pcie_soc {
> > +	struct pci_ops *ops;
> > +	int (*startup)(struct mtk_pcie_port *port);
> > +};
> > +
> >  /**
> >   * struct mtk_pcie_port - PCIe port information
> >   * @base: IO mapped register base
> > @@ -96,6 +109,7 @@ struct mtk_pcie_port {
> >   * @busn: bus range
> >   * @offset: IO / Memory offset
> >   * @ports: pointer to PCIe port information
> > + * @soc: pointer to SoC-dependent operations
> >   */
> >  struct mtk_pcie {
> >  	struct device *dev;
> > @@ -111,13 +125,9 @@ struct mtk_pcie {
> >  		resource_size_t io;
> >  	} offset;
> >  	struct list_head ports;
> > +	const struct mtk_pcie_soc *soc;
> >  };
> >  
> > -static inline bool mtk_pcie_link_up(struct mtk_pcie_port *port)
> > -{
> > -	return !!(readl(port->base + PCIE_LINK_STATUS) & PCIE_PORT_LINKUP);
> > -}
> > -
> >  static void mtk_pcie_subsys_powerdown(struct mtk_pcie *pcie)
> >  {
> >  	struct device *dev = pcie->dev;
> > @@ -171,12 +181,30 @@ static struct pci_ops mtk_pcie_ops = {
> >  	.write = pci_generic_config_write,
> >  };
> >  
> > -static void mtk_pcie_configure_rc(struct mtk_pcie_port *port)
> > +static int mtk_pcie_startup_ports(struct mtk_pcie_port *port)
> >  {
> >  	struct mtk_pcie *pcie = port->pcie;
> >  	u32 func = PCI_FUNC(port->index << 3);
> >  	u32 slot = PCI_SLOT(port->index << 3);
> >  	u32 val;
> > +	int err;
> > +
> > +	/* assert port PERST_N */
> > +	val = readl(pcie->base + PCIE_SYS_CFG);
> > +	val |= PCIE_PORT_PERST(port->index);
> > +	writel(val, pcie->base + PCIE_SYS_CFG);
> > +
> > +	/* de-assert port PERST_N */
> > +	val = readl(pcie->base + PCIE_SYS_CFG);
> > +	val &= ~PCIE_PORT_PERST(port->index);
> > +	writel(val, pcie->base + PCIE_SYS_CFG);
> > +
> > +	/* 100ms timeout value should be enough for Gen1/2 training */
> > +	err = readl_poll_timeout(port->base + PCIE_LINK_STATUS, val,
> > +				 !!(val & PCIE_PORT_LINKUP), 20,
> > +				 100 * USEC_PER_MSEC);
> > +	if (err)
> > +		return -ETIMEDOUT;
> >  
> >  	/* enable interrupt */
> >  	val = readl(pcie->base + PCIE_INT_ENABLE);
> > @@ -209,30 +237,14 @@ static void mtk_pcie_configure_rc(struct mtk_pcie_port *port)
> >  	writel(PCIE_CONF_ADDR(PCIE_FTS_NUM, func, slot, 0),
> >  	       pcie->base + PCIE_CFG_ADDR);
> >  	writel(val, pcie->base + PCIE_CFG_DATA);
> > -}
> >  
> > -static void mtk_pcie_assert_ports(struct mtk_pcie_port *port)
> > -{
> > -	struct mtk_pcie *pcie = port->pcie;
> > -	u32 val;
> > -
> > -	/* assert port PERST_N */
> > -	val = readl(pcie->base + PCIE_SYS_CFG);
> > -	val |= PCIE_PORT_PERST(port->index);
> > -	writel(val, pcie->base + PCIE_SYS_CFG);
> > -
> > -	/* de-assert port PERST_N */
> > -	val = readl(pcie->base + PCIE_SYS_CFG);
> > -	val &= ~PCIE_PORT_PERST(port->index);
> > -	writel(val, pcie->base + PCIE_SYS_CFG);
> > -
> > -	/* PCIe v2.0 need at least 100ms delay to train from Gen1 to Gen2 */
> > -	msleep(100);
> > +	return 0;
> >  }
> >  
> >  static void mtk_pcie_enable_ports(struct mtk_pcie_port *port)
> >  {
> > -	struct device *dev = port->pcie->dev;
> > +	struct mtk_pcie *pcie = port->pcie;
> > +	struct device *dev = pcie->dev;
> >  	int err;
> >  
> >  	err = clk_prepare_enable(port->sys_ck);
> > @@ -250,13 +262,8 @@ static void mtk_pcie_enable_ports(struct mtk_pcie_port *port)
> >  		goto err_phy_on;
> >  	}
> >  
> > -	mtk_pcie_assert_ports(port);
> > -
> > -	/* if link up, then setup root port configuration space */
> > -	if (mtk_pcie_link_up(port)) {
> > -		mtk_pcie_configure_rc(port);
> > +	if (!pcie->soc->startup(port))
> >  		return;
> > -	}
> >  
> >  	dev_info(dev, "Port%d link down\n", port->index);
> >  
> > @@ -480,7 +487,7 @@ static int mtk_pcie_register_host(struct pci_host_bridge *host)
> >  
> >  	host->busnr = pcie->busn.start;
> >  	host->dev.parent = pcie->dev;
> > -	host->ops = &mtk_pcie_ops;
> > +	host->ops = pcie->soc->ops;
> >  	host->map_irq = of_irq_parse_and_map_pci;
> >  	host->swizzle_irq = pci_common_swizzle;
> >  
> > @@ -513,6 +520,7 @@ static int mtk_pcie_probe(struct platform_device *pdev)
> >  	pcie = pci_host_bridge_priv(host);
> >  
> >  	pcie->dev = dev;
> > +	pcie->soc = of_device_get_match_data(dev);
> >  	platform_set_drvdata(pdev, pcie);
> >  	INIT_LIST_HEAD(&pcie->ports);
> >  
> > @@ -537,9 +545,14 @@ static int mtk_pcie_probe(struct platform_device *pdev)
> >  	return err;
> >  }
> >  
> > +static struct mtk_pcie_soc mtk_pcie_soc_v1 = {
> > +	.ops = &mtk_pcie_ops,
> > +	.startup = mtk_pcie_startup_ports,
> > +};
> > +
> >  static const struct of_device_id mtk_pcie_ids[] = {
> > -	{ .compatible = "mediatek,mt7623-pcie"},
> > -	{ .compatible = "mediatek,mt2701-pcie"},
> > +	{ .compatible = "mediatek,mt2701-pcie", .data = &mtk_pcie_soc_v1 },
> > +	{ .compatible = "mediatek,mt7623-pcie", .data = &mtk_pcie_soc_v1 },
> >  	{},
> >  };
> >  
> 
> 
> 
> _______________________________________________
> Linux-mediatek mailing list
> Linux-mediatek@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v2 1/5] PCI: mediatek: Add a structure to abstract the controller generations
@ 2017-07-27  3:28       ` Honghui Zhang
  0 siblings, 0 replies; 80+ messages in thread
From: Honghui Zhang @ 2017-07-27  3:28 UTC (permalink / raw)
  To: bhelgaas
  Cc: youlin.pei, devicetree, hongkun.cao, ryder.lee, linux-pci,
	sean.wang, xinping.qian, linux-kernel, robh+dt, yt.shen, robh,
	linux-mediatek, yong.wu, matthias.bgg, yingjoe.chen, eddie.huang,
	linux-arm-kernel

On Thu, 2017-07-27 at 11:19 +0800, Honghui Zhang wrote:
> On Thu, 2017-07-27 at 10:58 +0800, honghui.zhang@mediatek.com wrote:
> > From: Ryder Lee <ryder.lee@mediatek.com>
> > 
> > Introduce a structure "mtk_pcie_soc" to abstract the differences between
> > controller generations, and the .startup() hook is used to encapsulate
> > some SoC-dependent related setting. In doing so, the common code which
> > will be reused by future chips.
> > 
> > In addition, we change the approaches to waiting Gen2 training by using
> > readl_poll_timeout() calls.
> > 
> > Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> > Signed-off-by: Honghui Zhang <honghui.zhang@mediatek.com>
> > ---
> >  drivers/pci/host/pcie-mediatek.c | 81 +++++++++++++++++++++++-----------------
> >  1 file changed, 47 insertions(+), 34 deletions(-)
> > 
> > diff --git a/drivers/pci/host/pcie-mediatek.c b/drivers/pci/host/pcie-mediatek.c
> > index 5a9d858..7f952a4 100644
> > --- a/drivers/pci/host/pcie-mediatek.c
> > +++ b/drivers/pci/host/pcie-mediatek.c
> > @@ -16,6 +16,7 @@
> >  
> 
> Sorry about the disturb, I send the wrong patch for this one.
> I will resend the right version for this last patch.
> 

Sorry, I reply to the wrong patch mail.
I meant to re-send the patch:
[PATCH v2 5/5] dt-bindings: PCI: add support for new generation
controller, not this one.

This one is the right patch.

tahnks.

> thanks.
> >  #include <linux/clk.h>
> >  #include <linux/delay.h>
> > +#include <linux/iopoll.h>
> >  #include <linux/kernel.h>
> >  #include <linux/of_address.h>
> >  #include <linux/of_pci.h>
> > @@ -63,6 +64,18 @@
> >  #define PCIE_FC_CREDIT_MASK	(GENMASK(31, 31) | GENMASK(28, 16))
> >  #define PCIE_FC_CREDIT_VAL(x)	((x) << 16)
> >  
> > +struct mtk_pcie_port;
> > +
> > +/**
> > + * struct mtk_pcie_soc - differentiate between host generations
> > + * @ops: pointer to configuration access functions
> > + * @startup: pointer to controller setting functions
> > + */
> > +struct mtk_pcie_soc {
> > +	struct pci_ops *ops;
> > +	int (*startup)(struct mtk_pcie_port *port);
> > +};
> > +
> >  /**
> >   * struct mtk_pcie_port - PCIe port information
> >   * @base: IO mapped register base
> > @@ -96,6 +109,7 @@ struct mtk_pcie_port {
> >   * @busn: bus range
> >   * @offset: IO / Memory offset
> >   * @ports: pointer to PCIe port information
> > + * @soc: pointer to SoC-dependent operations
> >   */
> >  struct mtk_pcie {
> >  	struct device *dev;
> > @@ -111,13 +125,9 @@ struct mtk_pcie {
> >  		resource_size_t io;
> >  	} offset;
> >  	struct list_head ports;
> > +	const struct mtk_pcie_soc *soc;
> >  };
> >  
> > -static inline bool mtk_pcie_link_up(struct mtk_pcie_port *port)
> > -{
> > -	return !!(readl(port->base + PCIE_LINK_STATUS) & PCIE_PORT_LINKUP);
> > -}
> > -
> >  static void mtk_pcie_subsys_powerdown(struct mtk_pcie *pcie)
> >  {
> >  	struct device *dev = pcie->dev;
> > @@ -171,12 +181,30 @@ static struct pci_ops mtk_pcie_ops = {
> >  	.write = pci_generic_config_write,
> >  };
> >  
> > -static void mtk_pcie_configure_rc(struct mtk_pcie_port *port)
> > +static int mtk_pcie_startup_ports(struct mtk_pcie_port *port)
> >  {
> >  	struct mtk_pcie *pcie = port->pcie;
> >  	u32 func = PCI_FUNC(port->index << 3);
> >  	u32 slot = PCI_SLOT(port->index << 3);
> >  	u32 val;
> > +	int err;
> > +
> > +	/* assert port PERST_N */
> > +	val = readl(pcie->base + PCIE_SYS_CFG);
> > +	val |= PCIE_PORT_PERST(port->index);
> > +	writel(val, pcie->base + PCIE_SYS_CFG);
> > +
> > +	/* de-assert port PERST_N */
> > +	val = readl(pcie->base + PCIE_SYS_CFG);
> > +	val &= ~PCIE_PORT_PERST(port->index);
> > +	writel(val, pcie->base + PCIE_SYS_CFG);
> > +
> > +	/* 100ms timeout value should be enough for Gen1/2 training */
> > +	err = readl_poll_timeout(port->base + PCIE_LINK_STATUS, val,
> > +				 !!(val & PCIE_PORT_LINKUP), 20,
> > +				 100 * USEC_PER_MSEC);
> > +	if (err)
> > +		return -ETIMEDOUT;
> >  
> >  	/* enable interrupt */
> >  	val = readl(pcie->base + PCIE_INT_ENABLE);
> > @@ -209,30 +237,14 @@ static void mtk_pcie_configure_rc(struct mtk_pcie_port *port)
> >  	writel(PCIE_CONF_ADDR(PCIE_FTS_NUM, func, slot, 0),
> >  	       pcie->base + PCIE_CFG_ADDR);
> >  	writel(val, pcie->base + PCIE_CFG_DATA);
> > -}
> >  
> > -static void mtk_pcie_assert_ports(struct mtk_pcie_port *port)
> > -{
> > -	struct mtk_pcie *pcie = port->pcie;
> > -	u32 val;
> > -
> > -	/* assert port PERST_N */
> > -	val = readl(pcie->base + PCIE_SYS_CFG);
> > -	val |= PCIE_PORT_PERST(port->index);
> > -	writel(val, pcie->base + PCIE_SYS_CFG);
> > -
> > -	/* de-assert port PERST_N */
> > -	val = readl(pcie->base + PCIE_SYS_CFG);
> > -	val &= ~PCIE_PORT_PERST(port->index);
> > -	writel(val, pcie->base + PCIE_SYS_CFG);
> > -
> > -	/* PCIe v2.0 need at least 100ms delay to train from Gen1 to Gen2 */
> > -	msleep(100);
> > +	return 0;
> >  }
> >  
> >  static void mtk_pcie_enable_ports(struct mtk_pcie_port *port)
> >  {
> > -	struct device *dev = port->pcie->dev;
> > +	struct mtk_pcie *pcie = port->pcie;
> > +	struct device *dev = pcie->dev;
> >  	int err;
> >  
> >  	err = clk_prepare_enable(port->sys_ck);
> > @@ -250,13 +262,8 @@ static void mtk_pcie_enable_ports(struct mtk_pcie_port *port)
> >  		goto err_phy_on;
> >  	}
> >  
> > -	mtk_pcie_assert_ports(port);
> > -
> > -	/* if link up, then setup root port configuration space */
> > -	if (mtk_pcie_link_up(port)) {
> > -		mtk_pcie_configure_rc(port);
> > +	if (!pcie->soc->startup(port))
> >  		return;
> > -	}
> >  
> >  	dev_info(dev, "Port%d link down\n", port->index);
> >  
> > @@ -480,7 +487,7 @@ static int mtk_pcie_register_host(struct pci_host_bridge *host)
> >  
> >  	host->busnr = pcie->busn.start;
> >  	host->dev.parent = pcie->dev;
> > -	host->ops = &mtk_pcie_ops;
> > +	host->ops = pcie->soc->ops;
> >  	host->map_irq = of_irq_parse_and_map_pci;
> >  	host->swizzle_irq = pci_common_swizzle;
> >  
> > @@ -513,6 +520,7 @@ static int mtk_pcie_probe(struct platform_device *pdev)
> >  	pcie = pci_host_bridge_priv(host);
> >  
> >  	pcie->dev = dev;
> > +	pcie->soc = of_device_get_match_data(dev);
> >  	platform_set_drvdata(pdev, pcie);
> >  	INIT_LIST_HEAD(&pcie->ports);
> >  
> > @@ -537,9 +545,14 @@ static int mtk_pcie_probe(struct platform_device *pdev)
> >  	return err;
> >  }
> >  
> > +static struct mtk_pcie_soc mtk_pcie_soc_v1 = {
> > +	.ops = &mtk_pcie_ops,
> > +	.startup = mtk_pcie_startup_ports,
> > +};
> > +
> >  static const struct of_device_id mtk_pcie_ids[] = {
> > -	{ .compatible = "mediatek,mt7623-pcie"},
> > -	{ .compatible = "mediatek,mt2701-pcie"},
> > +	{ .compatible = "mediatek,mt2701-pcie", .data = &mtk_pcie_soc_v1 },
> > +	{ .compatible = "mediatek,mt7623-pcie", .data = &mtk_pcie_soc_v1 },
> >  	{},
> >  };
> >  
> 
> 
> 
> _______________________________________________
> Linux-mediatek mailing list
> Linux-mediatek@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v2 1/5] PCI: mediatek: Add a structure to abstract the controller generations
@ 2017-07-27  3:28       ` Honghui Zhang
  0 siblings, 0 replies; 80+ messages in thread
From: Honghui Zhang @ 2017-07-27  3:28 UTC (permalink / raw)
  To: bhelgaas
  Cc: youlin.pei, devicetree, hongkun.cao, ryder.lee, linux-arm-kernel,
	linux-pci, sean.wang, linux-kernel, matthias.bgg, robh+dt,
	linux-mediatek, yong.wu, yt.shen, yingjoe.chen, eddie.huang,
	xinping.qian, robh

On Thu, 2017-07-27 at 11:19 +0800, Honghui Zhang wrote:
> On Thu, 2017-07-27 at 10:58 +0800, honghui.zhang@mediatek.com wrote:
> > From: Ryder Lee <ryder.lee@mediatek.com>
> > 
> > Introduce a structure "mtk_pcie_soc" to abstract the differences between
> > controller generations, and the .startup() hook is used to encapsulate
> > some SoC-dependent related setting. In doing so, the common code which
> > will be reused by future chips.
> > 
> > In addition, we change the approaches to waiting Gen2 training by using
> > readl_poll_timeout() calls.
> > 
> > Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> > Signed-off-by: Honghui Zhang <honghui.zhang@mediatek.com>
> > ---
> >  drivers/pci/host/pcie-mediatek.c | 81 +++++++++++++++++++++++-----------------
> >  1 file changed, 47 insertions(+), 34 deletions(-)
> > 
> > diff --git a/drivers/pci/host/pcie-mediatek.c b/drivers/pci/host/pcie-mediatek.c
> > index 5a9d858..7f952a4 100644
> > --- a/drivers/pci/host/pcie-mediatek.c
> > +++ b/drivers/pci/host/pcie-mediatek.c
> > @@ -16,6 +16,7 @@
> >  
> 
> Sorry about the disturb, I send the wrong patch for this one.
> I will resend the right version for this last patch.
> 

Sorry, I reply to the wrong patch mail.
I meant to re-send the patch:
[PATCH v2 5/5] dt-bindings: PCI: add support for new generation
controller, not this one.

This one is the right patch.

tahnks.

> thanks.
> >  #include <linux/clk.h>
> >  #include <linux/delay.h>
> > +#include <linux/iopoll.h>
> >  #include <linux/kernel.h>
> >  #include <linux/of_address.h>
> >  #include <linux/of_pci.h>
> > @@ -63,6 +64,18 @@
> >  #define PCIE_FC_CREDIT_MASK	(GENMASK(31, 31) | GENMASK(28, 16))
> >  #define PCIE_FC_CREDIT_VAL(x)	((x) << 16)
> >  
> > +struct mtk_pcie_port;
> > +
> > +/**
> > + * struct mtk_pcie_soc - differentiate between host generations
> > + * @ops: pointer to configuration access functions
> > + * @startup: pointer to controller setting functions
> > + */
> > +struct mtk_pcie_soc {
> > +	struct pci_ops *ops;
> > +	int (*startup)(struct mtk_pcie_port *port);
> > +};
> > +
> >  /**
> >   * struct mtk_pcie_port - PCIe port information
> >   * @base: IO mapped register base
> > @@ -96,6 +109,7 @@ struct mtk_pcie_port {
> >   * @busn: bus range
> >   * @offset: IO / Memory offset
> >   * @ports: pointer to PCIe port information
> > + * @soc: pointer to SoC-dependent operations
> >   */
> >  struct mtk_pcie {
> >  	struct device *dev;
> > @@ -111,13 +125,9 @@ struct mtk_pcie {
> >  		resource_size_t io;
> >  	} offset;
> >  	struct list_head ports;
> > +	const struct mtk_pcie_soc *soc;
> >  };
> >  
> > -static inline bool mtk_pcie_link_up(struct mtk_pcie_port *port)
> > -{
> > -	return !!(readl(port->base + PCIE_LINK_STATUS) & PCIE_PORT_LINKUP);
> > -}
> > -
> >  static void mtk_pcie_subsys_powerdown(struct mtk_pcie *pcie)
> >  {
> >  	struct device *dev = pcie->dev;
> > @@ -171,12 +181,30 @@ static struct pci_ops mtk_pcie_ops = {
> >  	.write = pci_generic_config_write,
> >  };
> >  
> > -static void mtk_pcie_configure_rc(struct mtk_pcie_port *port)
> > +static int mtk_pcie_startup_ports(struct mtk_pcie_port *port)
> >  {
> >  	struct mtk_pcie *pcie = port->pcie;
> >  	u32 func = PCI_FUNC(port->index << 3);
> >  	u32 slot = PCI_SLOT(port->index << 3);
> >  	u32 val;
> > +	int err;
> > +
> > +	/* assert port PERST_N */
> > +	val = readl(pcie->base + PCIE_SYS_CFG);
> > +	val |= PCIE_PORT_PERST(port->index);
> > +	writel(val, pcie->base + PCIE_SYS_CFG);
> > +
> > +	/* de-assert port PERST_N */
> > +	val = readl(pcie->base + PCIE_SYS_CFG);
> > +	val &= ~PCIE_PORT_PERST(port->index);
> > +	writel(val, pcie->base + PCIE_SYS_CFG);
> > +
> > +	/* 100ms timeout value should be enough for Gen1/2 training */
> > +	err = readl_poll_timeout(port->base + PCIE_LINK_STATUS, val,
> > +				 !!(val & PCIE_PORT_LINKUP), 20,
> > +				 100 * USEC_PER_MSEC);
> > +	if (err)
> > +		return -ETIMEDOUT;
> >  
> >  	/* enable interrupt */
> >  	val = readl(pcie->base + PCIE_INT_ENABLE);
> > @@ -209,30 +237,14 @@ static void mtk_pcie_configure_rc(struct mtk_pcie_port *port)
> >  	writel(PCIE_CONF_ADDR(PCIE_FTS_NUM, func, slot, 0),
> >  	       pcie->base + PCIE_CFG_ADDR);
> >  	writel(val, pcie->base + PCIE_CFG_DATA);
> > -}
> >  
> > -static void mtk_pcie_assert_ports(struct mtk_pcie_port *port)
> > -{
> > -	struct mtk_pcie *pcie = port->pcie;
> > -	u32 val;
> > -
> > -	/* assert port PERST_N */
> > -	val = readl(pcie->base + PCIE_SYS_CFG);
> > -	val |= PCIE_PORT_PERST(port->index);
> > -	writel(val, pcie->base + PCIE_SYS_CFG);
> > -
> > -	/* de-assert port PERST_N */
> > -	val = readl(pcie->base + PCIE_SYS_CFG);
> > -	val &= ~PCIE_PORT_PERST(port->index);
> > -	writel(val, pcie->base + PCIE_SYS_CFG);
> > -
> > -	/* PCIe v2.0 need at least 100ms delay to train from Gen1 to Gen2 */
> > -	msleep(100);
> > +	return 0;
> >  }
> >  
> >  static void mtk_pcie_enable_ports(struct mtk_pcie_port *port)
> >  {
> > -	struct device *dev = port->pcie->dev;
> > +	struct mtk_pcie *pcie = port->pcie;
> > +	struct device *dev = pcie->dev;
> >  	int err;
> >  
> >  	err = clk_prepare_enable(port->sys_ck);
> > @@ -250,13 +262,8 @@ static void mtk_pcie_enable_ports(struct mtk_pcie_port *port)
> >  		goto err_phy_on;
> >  	}
> >  
> > -	mtk_pcie_assert_ports(port);
> > -
> > -	/* if link up, then setup root port configuration space */
> > -	if (mtk_pcie_link_up(port)) {
> > -		mtk_pcie_configure_rc(port);
> > +	if (!pcie->soc->startup(port))
> >  		return;
> > -	}
> >  
> >  	dev_info(dev, "Port%d link down\n", port->index);
> >  
> > @@ -480,7 +487,7 @@ static int mtk_pcie_register_host(struct pci_host_bridge *host)
> >  
> >  	host->busnr = pcie->busn.start;
> >  	host->dev.parent = pcie->dev;
> > -	host->ops = &mtk_pcie_ops;
> > +	host->ops = pcie->soc->ops;
> >  	host->map_irq = of_irq_parse_and_map_pci;
> >  	host->swizzle_irq = pci_common_swizzle;
> >  
> > @@ -513,6 +520,7 @@ static int mtk_pcie_probe(struct platform_device *pdev)
> >  	pcie = pci_host_bridge_priv(host);
> >  
> >  	pcie->dev = dev;
> > +	pcie->soc = of_device_get_match_data(dev);
> >  	platform_set_drvdata(pdev, pcie);
> >  	INIT_LIST_HEAD(&pcie->ports);
> >  
> > @@ -537,9 +545,14 @@ static int mtk_pcie_probe(struct platform_device *pdev)
> >  	return err;
> >  }
> >  
> > +static struct mtk_pcie_soc mtk_pcie_soc_v1 = {
> > +	.ops = &mtk_pcie_ops,
> > +	.startup = mtk_pcie_startup_ports,
> > +};
> > +
> >  static const struct of_device_id mtk_pcie_ids[] = {
> > -	{ .compatible = "mediatek,mt7623-pcie"},
> > -	{ .compatible = "mediatek,mt2701-pcie"},
> > +	{ .compatible = "mediatek,mt2701-pcie", .data = &mtk_pcie_soc_v1 },
> > +	{ .compatible = "mediatek,mt7623-pcie", .data = &mtk_pcie_soc_v1 },
> >  	{},
> >  };
> >  
> 
> 
> 
> _______________________________________________
> Linux-mediatek mailing list
> Linux-mediatek@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-mediatek



_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 80+ messages in thread

* [PATCH v2 1/5] PCI: mediatek: Add a structure to abstract the controller generations
@ 2017-07-27  3:28       ` Honghui Zhang
  0 siblings, 0 replies; 80+ messages in thread
From: Honghui Zhang @ 2017-07-27  3:28 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 2017-07-27 at 11:19 +0800, Honghui Zhang wrote:
> On Thu, 2017-07-27 at 10:58 +0800, honghui.zhang at mediatek.com wrote:
> > From: Ryder Lee <ryder.lee@mediatek.com>
> > 
> > Introduce a structure "mtk_pcie_soc" to abstract the differences between
> > controller generations, and the .startup() hook is used to encapsulate
> > some SoC-dependent related setting. In doing so, the common code which
> > will be reused by future chips.
> > 
> > In addition, we change the approaches to waiting Gen2 training by using
> > readl_poll_timeout() calls.
> > 
> > Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> > Signed-off-by: Honghui Zhang <honghui.zhang@mediatek.com>
> > ---
> >  drivers/pci/host/pcie-mediatek.c | 81 +++++++++++++++++++++++-----------------
> >  1 file changed, 47 insertions(+), 34 deletions(-)
> > 
> > diff --git a/drivers/pci/host/pcie-mediatek.c b/drivers/pci/host/pcie-mediatek.c
> > index 5a9d858..7f952a4 100644
> > --- a/drivers/pci/host/pcie-mediatek.c
> > +++ b/drivers/pci/host/pcie-mediatek.c
> > @@ -16,6 +16,7 @@
> >  
> 
> Sorry about the disturb, I send the wrong patch for this one.
> I will resend the right version for this last patch.
> 

Sorry, I reply to the wrong patch mail.
I meant to re-send the patch:
[PATCH v2 5/5] dt-bindings: PCI: add support for new generation
controller, not this one.

This one is the right patch.

tahnks.

> thanks.
> >  #include <linux/clk.h>
> >  #include <linux/delay.h>
> > +#include <linux/iopoll.h>
> >  #include <linux/kernel.h>
> >  #include <linux/of_address.h>
> >  #include <linux/of_pci.h>
> > @@ -63,6 +64,18 @@
> >  #define PCIE_FC_CREDIT_MASK	(GENMASK(31, 31) | GENMASK(28, 16))
> >  #define PCIE_FC_CREDIT_VAL(x)	((x) << 16)
> >  
> > +struct mtk_pcie_port;
> > +
> > +/**
> > + * struct mtk_pcie_soc - differentiate between host generations
> > + * @ops: pointer to configuration access functions
> > + * @startup: pointer to controller setting functions
> > + */
> > +struct mtk_pcie_soc {
> > +	struct pci_ops *ops;
> > +	int (*startup)(struct mtk_pcie_port *port);
> > +};
> > +
> >  /**
> >   * struct mtk_pcie_port - PCIe port information
> >   * @base: IO mapped register base
> > @@ -96,6 +109,7 @@ struct mtk_pcie_port {
> >   * @busn: bus range
> >   * @offset: IO / Memory offset
> >   * @ports: pointer to PCIe port information
> > + * @soc: pointer to SoC-dependent operations
> >   */
> >  struct mtk_pcie {
> >  	struct device *dev;
> > @@ -111,13 +125,9 @@ struct mtk_pcie {
> >  		resource_size_t io;
> >  	} offset;
> >  	struct list_head ports;
> > +	const struct mtk_pcie_soc *soc;
> >  };
> >  
> > -static inline bool mtk_pcie_link_up(struct mtk_pcie_port *port)
> > -{
> > -	return !!(readl(port->base + PCIE_LINK_STATUS) & PCIE_PORT_LINKUP);
> > -}
> > -
> >  static void mtk_pcie_subsys_powerdown(struct mtk_pcie *pcie)
> >  {
> >  	struct device *dev = pcie->dev;
> > @@ -171,12 +181,30 @@ static struct pci_ops mtk_pcie_ops = {
> >  	.write = pci_generic_config_write,
> >  };
> >  
> > -static void mtk_pcie_configure_rc(struct mtk_pcie_port *port)
> > +static int mtk_pcie_startup_ports(struct mtk_pcie_port *port)
> >  {
> >  	struct mtk_pcie *pcie = port->pcie;
> >  	u32 func = PCI_FUNC(port->index << 3);
> >  	u32 slot = PCI_SLOT(port->index << 3);
> >  	u32 val;
> > +	int err;
> > +
> > +	/* assert port PERST_N */
> > +	val = readl(pcie->base + PCIE_SYS_CFG);
> > +	val |= PCIE_PORT_PERST(port->index);
> > +	writel(val, pcie->base + PCIE_SYS_CFG);
> > +
> > +	/* de-assert port PERST_N */
> > +	val = readl(pcie->base + PCIE_SYS_CFG);
> > +	val &= ~PCIE_PORT_PERST(port->index);
> > +	writel(val, pcie->base + PCIE_SYS_CFG);
> > +
> > +	/* 100ms timeout value should be enough for Gen1/2 training */
> > +	err = readl_poll_timeout(port->base + PCIE_LINK_STATUS, val,
> > +				 !!(val & PCIE_PORT_LINKUP), 20,
> > +				 100 * USEC_PER_MSEC);
> > +	if (err)
> > +		return -ETIMEDOUT;
> >  
> >  	/* enable interrupt */
> >  	val = readl(pcie->base + PCIE_INT_ENABLE);
> > @@ -209,30 +237,14 @@ static void mtk_pcie_configure_rc(struct mtk_pcie_port *port)
> >  	writel(PCIE_CONF_ADDR(PCIE_FTS_NUM, func, slot, 0),
> >  	       pcie->base + PCIE_CFG_ADDR);
> >  	writel(val, pcie->base + PCIE_CFG_DATA);
> > -}
> >  
> > -static void mtk_pcie_assert_ports(struct mtk_pcie_port *port)
> > -{
> > -	struct mtk_pcie *pcie = port->pcie;
> > -	u32 val;
> > -
> > -	/* assert port PERST_N */
> > -	val = readl(pcie->base + PCIE_SYS_CFG);
> > -	val |= PCIE_PORT_PERST(port->index);
> > -	writel(val, pcie->base + PCIE_SYS_CFG);
> > -
> > -	/* de-assert port PERST_N */
> > -	val = readl(pcie->base + PCIE_SYS_CFG);
> > -	val &= ~PCIE_PORT_PERST(port->index);
> > -	writel(val, pcie->base + PCIE_SYS_CFG);
> > -
> > -	/* PCIe v2.0 need at least 100ms delay to train from Gen1 to Gen2 */
> > -	msleep(100);
> > +	return 0;
> >  }
> >  
> >  static void mtk_pcie_enable_ports(struct mtk_pcie_port *port)
> >  {
> > -	struct device *dev = port->pcie->dev;
> > +	struct mtk_pcie *pcie = port->pcie;
> > +	struct device *dev = pcie->dev;
> >  	int err;
> >  
> >  	err = clk_prepare_enable(port->sys_ck);
> > @@ -250,13 +262,8 @@ static void mtk_pcie_enable_ports(struct mtk_pcie_port *port)
> >  		goto err_phy_on;
> >  	}
> >  
> > -	mtk_pcie_assert_ports(port);
> > -
> > -	/* if link up, then setup root port configuration space */
> > -	if (mtk_pcie_link_up(port)) {
> > -		mtk_pcie_configure_rc(port);
> > +	if (!pcie->soc->startup(port))
> >  		return;
> > -	}
> >  
> >  	dev_info(dev, "Port%d link down\n", port->index);
> >  
> > @@ -480,7 +487,7 @@ static int mtk_pcie_register_host(struct pci_host_bridge *host)
> >  
> >  	host->busnr = pcie->busn.start;
> >  	host->dev.parent = pcie->dev;
> > -	host->ops = &mtk_pcie_ops;
> > +	host->ops = pcie->soc->ops;
> >  	host->map_irq = of_irq_parse_and_map_pci;
> >  	host->swizzle_irq = pci_common_swizzle;
> >  
> > @@ -513,6 +520,7 @@ static int mtk_pcie_probe(struct platform_device *pdev)
> >  	pcie = pci_host_bridge_priv(host);
> >  
> >  	pcie->dev = dev;
> > +	pcie->soc = of_device_get_match_data(dev);
> >  	platform_set_drvdata(pdev, pcie);
> >  	INIT_LIST_HEAD(&pcie->ports);
> >  
> > @@ -537,9 +545,14 @@ static int mtk_pcie_probe(struct platform_device *pdev)
> >  	return err;
> >  }
> >  
> > +static struct mtk_pcie_soc mtk_pcie_soc_v1 = {
> > +	.ops = &mtk_pcie_ops,
> > +	.startup = mtk_pcie_startup_ports,
> > +};
> > +
> >  static const struct of_device_id mtk_pcie_ids[] = {
> > -	{ .compatible = "mediatek,mt7623-pcie"},
> > -	{ .compatible = "mediatek,mt2701-pcie"},
> > +	{ .compatible = "mediatek,mt2701-pcie", .data = &mtk_pcie_soc_v1 },
> > +	{ .compatible = "mediatek,mt7623-pcie", .data = &mtk_pcie_soc_v1 },
> >  	{},
> >  };
> >  
> 
> 
> 
> _______________________________________________
> Linux-mediatek mailing list
> Linux-mediatek at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v2 5/5] dt-bindings: PCI: add support for new generation controller
  2017-07-27  2:58   ` honghui.zhang
  (?)
  (?)
@ 2017-07-27  3:31     ` Honghui Zhang
  -1 siblings, 0 replies; 80+ messages in thread
From: Honghui Zhang @ 2017-07-27  3:31 UTC (permalink / raw)
  To: bhelgaas
  Cc: robh, robh+dt, matthias.bgg, linux-arm-kernel, linux-mediatek,
	linux-pci, linux-kernel, devicetree, yingjoe.chen, eddie.huang,
	ryder.lee, hongkun.cao, youlin.pei, yong.wu, yt.shen, sean.wang,
	xinping.qian

On Thu, 2017-07-27 at 10:58 +0800, honghui.zhang@mediatek.com wrote:
> From: Ryder Lee <ryder.lee@mediatek.com>
> 
> Add support for MediaTek new generation controller and update related
> properities.
> 
> Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> Signed-off-by: Honghui Zhang <honghui.zhang@mediatek.com>
> ---
>  .../devicetree/bindings/pci/mediatek-pcie.txt      | 168 ++++++++++++++++++++-
>  1 file changed, 161 insertions(+), 7 deletions(-)
> 

Sorry about the disturb, I send the wrong local version  of this patch.
[PATCH v2 5/5] dt-bindings: PCI: add support for new generation
 controller

The right version for this patch have been re-send.

thanks.

> diff --git a/Documentation/devicetree/bindings/pci/mediatek-pcie.txt b/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
> index a968f25..179329b 100644
> --- a/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
> +++ b/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
> @@ -3,18 +3,31 @@ MediaTek Gen2 PCIe controller
>  Required properties:
>  - compatible: Should contain one of the following string:
>  	"mediatek,mt2701-pcie"
> +	"mediatek,mt2712-pcie"
> +	"mediatek,mt7622-pcie"
>  	"mediatek,mt7623-pcie"
>  - device_type: Must be "pci"
> -- reg: Base addresses and lengths of the PCIe controller.
> +- reg: Base addresses and lengths of the PICe subsys and root ports.
> +- reg-names: Names of the above areas to use during resource look-up.
>  - #address-cells: Address representation for root ports (must be 3)
>  - #size-cells: Size representation for root ports (must be 2)
>  - clocks: Must contain an entry for each entry in clock-names.
>    See ../clocks/clock-bindings.txt for details.
> -- clock-names: Must include the following entries:
> -  - free_ck :for reference clock of PCIe subsys
> -  - sys_ck0 :for clock of Port0
> -  - sys_ck1 :for clock of Port1
> -  - sys_ck2 :for clock of Port2
> +- clock-names:
> +  Mandatory entries:
> +   - sys_ckN :transaction layer and data link layer clock
> +  Required entries for MT2701/MT7623:
> +   - free_ck :for reference clock of PCIe subsys
> +  Required entries for MT2712/MT7622:
> +   - ahb_ckN :AHB slave interface operating clock for CSR access and RC
> +	      initiated MMIO access
> +  Required entries for MT7622:
> +   - axi_ckN :application layer MMIO channel operating clock
> +   - aux_ckN :pe2_mac_bridge and pe2_mac_core operating clock when
> +	      pcie_mac_ck/pcie_pipe_ck is turned off
> +   - obff_ckN :OBFF functional block operating clock
> +   - pipe_ckN :LTSSM and phy/mac layer operating clock
> +  where N starting from 0 to the maximum number of root ports.
>  - phys: List of PHY specifiers (used by generic PHY framework).
>  - phy-names : Must be "pcie-phy0", "pcie-phy1", "pcie-phyN".. based on the
>    number of PHYs as specified in *phys* property.
> @@ -33,6 +46,10 @@ Required properties for MT7623/MT2701:
>  - reset-names: Must be "pcie-rst0", "pcie-rst1", "pcie-rstN".. based on the
>    number of root ports.
>  
> +Required properties for MT2712/MT7622:
> +-interrupts: A list of interrupt outputs of the controller, must have one
> +	     entry for each PCIe port
> +
>  In addition, the device tree node must have sub-nodes describing each
>  PCIe port interface, having the following mandatory properties:
>  
> @@ -50,7 +67,7 @@ Required properties:
>    property is sufficient.
>  - num-lanes: Number of lanes to use for this port.
>  
> -Examples:
> +Examples for MT7623:
>  
>  	hifsys: syscon@1a000000 {
>  		compatible = "mediatek,mt7623-hifsys",
> @@ -68,6 +85,7 @@ Examples:
>  		      <0 0x1a142000 0 0x1000>, /* Port0 registers */
>  		      <0 0x1a143000 0 0x1000>, /* Port1 registers */
>  		      <0 0x1a144000 0 0x1000>; /* Port2 registers */
> +		reg-names = "subsys", "port0", "port1", "port2";
>  		#address-cells = <3>;
>  		#size-cells = <2>;
>  		#interrupt-cells = <1>;
> @@ -127,3 +145,139 @@ Examples:
>  			num-lanes = <1>;
>  		};
>  	};
> +
> +Examples for MT2712:
> +	pcie: pcie@11700000 {
> +		compatible = "mediatek,generic-pcie-v2";
> +		device_type = "pci";
> +		reg = <0 0x11700000 0 0x1000>,
> +		      <0 0x112ff000 0 0x1000>;
> +		reg-names = "port0", "port1";
> +		#address-cells = <3>;
> +		#size-cells = <2>;
> +		interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>,
> +			     <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
> +		clocks = <&pericfg CLK_PERI_PCIE0>,
> +			 <&pericfg CLK_PERI_PCIE1>,
> +			 <&topckgen CLK_TOP_PE2_MAC_P0_SEL>,
> +			 <&topckgen CLK_TOP_PE2_MAC_P1_SEL>;
> +		clock-names = "sys_ck0", "sys_ck1", "ahb_ck0", "ahb_ck1";
> +		phys = <&pcie0_phy PHY_TYPE_PCIE>, <&pcie1_phy PHY_TYPE_PCIE>;
> +		phy-names = "pcie-phy0", "pcie-phy1";
> +		bus-range = <0x00 0xff>;
> +		ranges = <0x82000000 0 0x20000000  0x0 0x20000000  0 0x10000000>;
> +
> +		pcie0: pcie@0,0 {
> +			device_type = "pci";
> +			reg = <0x0000 0 0 0 0>;
> +			#address-cells = <3>;
> +			#size-cells = <2>;
> +			#interrupt-cells = <1>;
> +			ranges;
> +			num-lanes = <1>;
> +			interrupt-map-mask = <0 0 0 7>;
> +			interrupt-map = <0 0 0 1 &pcie_intc0 0>,
> +					<0 0 0 2 &pcie_intc0 1>,
> +					<0 0 0 3 &pcie_intc0 2>,
> +					<0 0 0 4 &pcie_intc0 3>;
> +			pcie_intc0: interrupt-controller {
> +				interrupt-controller;
> +				#address-cells = <0>;
> +				#interrupt-cells = <1>;
> +			};
> +		};
> +
> +		pcie1: pcie@1,0 {
> +			device_type = "pci";
> +			reg = <0x0800 0 0 0 0>;
> +			#address-cells = <3>;
> +			#size-cells = <2>;
> +			#interrupt-cells = <1>;
> +			ranges;
> +			num-lanes = <1>;
> +			interrupt-map-mask = <0 0 0 7>;
> +			interrupt-map = <0 0 0 1 &pcie_intc1 0>,
> +					<0 0 0 2 &pcie_intc1 1>,
> +					<0 0 0 3 &pcie_intc1 2>,
> +					<0 0 0 4 &pcie_intc1 3>;
> +			pcie_intc1: interrupt-controller {
> +				interrupt-controller;
> +				#address-cells = <0>;
> +				#interrupt-cells = <1>;
> +			};
> +		};
> +	};
> +
> +Examples for MT7622:
> +	pcie: pcie@1a140000 {
> +		compatible = "mediatek,generic-pcie-v2";
> +		device_type = "pci";
> +		reg = <0 0x1a140000 0 0x1000>,
> +		      <0 0x1a143000 0 0x1000>,
> +		      <0 0x1a145000 0 0x1000>;
> +		reg-names = "subsys", "port0", "port1";
> +		#address-cells = <3>;
> +		#size-cells = <2>;
> +		interrupts = <GIC_SPI 228 IRQ_TYPE_LEVEL_LOW>,
> +			     <GIC_SPI 229 IRQ_TYPE_LEVEL_LOW>;
> +		clocks = <&pciesys CLK_PCIE_P0_MAC_EN>,
> +			 <&pciesys CLK_PCIE_P1_MAC_EN>,
> +			 <&pciesys CLK_PCIE_P0_AHB_EN>,
> +			 <&pciesys CLK_PCIE_P1_AHB_EN>,
> +			 <&pciesys CLK_PCIE_P0_AUX_EN>,
> +			 <&pciesys CLK_PCIE_P1_AUX_EN>,
> +			 <&pciesys CLK_PCIE_P0_AXI_EN>,
> +			 <&pciesys CLK_PCIE_P1_AXI_EN>,
> +			 <&pciesys CLK_PCIE_P0_OBFF_EN>,
> +			 <&pciesys CLK_PCIE_P1_OBFF_EN>,
> +			 <&pciesys CLK_PCIE_P0_PIPE_EN>,
> +			 <&pciesys CLK_PCIE_P1_PIPE_EN>;
> +		clock-names = "sys_ck0", "sys_ck1", "ahb_ck0", "ahb_ck1",
> +			      "aux_ck0", "aux_ck1", "axi_ck0", "axi_ck1",
> +			      "obff_ck0", "obff_ck1", "pipe_ck0", "pipe_ck1";
> +		phys = <&pcie0_phy PHY_TYPE_PCIE>, <&pcie1_phy PHY_TYPE_PCIE>;
> +		phy-names = "pcie-phy0", "pcie-phy1";
> +		power-domains = <&scpsys MT7622_POWER_DOMAIN_HIF0>;
> +		bus-range = <0x00 0xff>;
> +		ranges = <0x82000000 0 0x20000000  0x0 0x20000000  0 0x10000000>;
> +
> +		pcie0: pcie@0,0 {
> +			device_type = "pci";
> +			reg = <0x0000 0 0 0 0>;
> +			#address-cells = <3>;
> +			#size-cells = <2>;
> +			#interrupt-cells = <1>;
> +			ranges;
> +			num-lanes = <1>;
> +			interrupt-map-mask = <0 0 0 7>;
> +			interrupt-map = <0 0 0 1 &pcie_intc0 0>,
> +					<0 0 0 2 &pcie_intc0 1>,
> +					<0 0 0 3 &pcie_intc0 2>,
> +					<0 0 0 4 &pcie_intc0 3>;
> +			pcie_intc0: interrupt-controller {
> +				interrupt-controller;
> +				#address-cells = <0>;
> +				#interrupt-cells = <1>;
> +			};
> +		};
> +
> +		pcie1: pcie@1,0 {
> +			device_type = "pci";
> +			reg = <0x0800 0 0 0 0>;
> +			#address-cells = <3>;
> +			#size-cells = <2>;
> +			#interrupt-cells = <1>;
> +			ranges;
> +			num-lanes = <1>;
> +			interrupt-map-mask = <0 0 0 7>;
> +			interrupt-map = <0 0 0 1 &pcie_intc1 0>,
> +					<0 0 0 2 &pcie_intc1 1>,
> +					<0 0 0 3 &pcie_intc1 2>,
> +					<0 0 0 4 &pcie_intc1 3>;
> +			pcie_intc1: interrupt-controller {
> +				interrupt-controller;
> +				#address-cells = <0>;
> +				#interrupt-cells = <1>;
> +			};
> +		};
> +	};

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v2 5/5] dt-bindings: PCI: add support for new generation controller
@ 2017-07-27  3:31     ` Honghui Zhang
  0 siblings, 0 replies; 80+ messages in thread
From: Honghui Zhang @ 2017-07-27  3:31 UTC (permalink / raw)
  To: bhelgaas
  Cc: robh, robh+dt, matthias.bgg, linux-arm-kernel, linux-mediatek,
	linux-pci, linux-kernel, devicetree, yingjoe.chen, eddie.huang,
	ryder.lee, hongkun.cao, youlin.pei, yong.wu, yt.shen, sean.wang,
	xinping.qian

On Thu, 2017-07-27 at 10:58 +0800, honghui.zhang@mediatek.com wrote:
> From: Ryder Lee <ryder.lee@mediatek.com>
> 
> Add support for MediaTek new generation controller and update related
> properities.
> 
> Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> Signed-off-by: Honghui Zhang <honghui.zhang@mediatek.com>
> ---
>  .../devicetree/bindings/pci/mediatek-pcie.txt      | 168 ++++++++++++++++++++-
>  1 file changed, 161 insertions(+), 7 deletions(-)
> 

Sorry about the disturb, I send the wrong local version  of this patch.
[PATCH v2 5/5] dt-bindings: PCI: add support for new generation
 controller

The right version for this patch have been re-send.

thanks.

> diff --git a/Documentation/devicetree/bindings/pci/mediatek-pcie.txt b/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
> index a968f25..179329b 100644
> --- a/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
> +++ b/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
> @@ -3,18 +3,31 @@ MediaTek Gen2 PCIe controller
>  Required properties:
>  - compatible: Should contain one of the following string:
>  	"mediatek,mt2701-pcie"
> +	"mediatek,mt2712-pcie"
> +	"mediatek,mt7622-pcie"
>  	"mediatek,mt7623-pcie"
>  - device_type: Must be "pci"
> -- reg: Base addresses and lengths of the PCIe controller.
> +- reg: Base addresses and lengths of the PICe subsys and root ports.
> +- reg-names: Names of the above areas to use during resource look-up.
>  - #address-cells: Address representation for root ports (must be 3)
>  - #size-cells: Size representation for root ports (must be 2)
>  - clocks: Must contain an entry for each entry in clock-names.
>    See ../clocks/clock-bindings.txt for details.
> -- clock-names: Must include the following entries:
> -  - free_ck :for reference clock of PCIe subsys
> -  - sys_ck0 :for clock of Port0
> -  - sys_ck1 :for clock of Port1
> -  - sys_ck2 :for clock of Port2
> +- clock-names:
> +  Mandatory entries:
> +   - sys_ckN :transaction layer and data link layer clock
> +  Required entries for MT2701/MT7623:
> +   - free_ck :for reference clock of PCIe subsys
> +  Required entries for MT2712/MT7622:
> +   - ahb_ckN :AHB slave interface operating clock for CSR access and RC
> +	      initiated MMIO access
> +  Required entries for MT7622:
> +   - axi_ckN :application layer MMIO channel operating clock
> +   - aux_ckN :pe2_mac_bridge and pe2_mac_core operating clock when
> +	      pcie_mac_ck/pcie_pipe_ck is turned off
> +   - obff_ckN :OBFF functional block operating clock
> +   - pipe_ckN :LTSSM and phy/mac layer operating clock
> +  where N starting from 0 to the maximum number of root ports.
>  - phys: List of PHY specifiers (used by generic PHY framework).
>  - phy-names : Must be "pcie-phy0", "pcie-phy1", "pcie-phyN".. based on the
>    number of PHYs as specified in *phys* property.
> @@ -33,6 +46,10 @@ Required properties for MT7623/MT2701:
>  - reset-names: Must be "pcie-rst0", "pcie-rst1", "pcie-rstN".. based on the
>    number of root ports.
>  
> +Required properties for MT2712/MT7622:
> +-interrupts: A list of interrupt outputs of the controller, must have one
> +	     entry for each PCIe port
> +
>  In addition, the device tree node must have sub-nodes describing each
>  PCIe port interface, having the following mandatory properties:
>  
> @@ -50,7 +67,7 @@ Required properties:
>    property is sufficient.
>  - num-lanes: Number of lanes to use for this port.
>  
> -Examples:
> +Examples for MT7623:
>  
>  	hifsys: syscon@1a000000 {
>  		compatible = "mediatek,mt7623-hifsys",
> @@ -68,6 +85,7 @@ Examples:
>  		      <0 0x1a142000 0 0x1000>, /* Port0 registers */
>  		      <0 0x1a143000 0 0x1000>, /* Port1 registers */
>  		      <0 0x1a144000 0 0x1000>; /* Port2 registers */
> +		reg-names = "subsys", "port0", "port1", "port2";
>  		#address-cells = <3>;
>  		#size-cells = <2>;
>  		#interrupt-cells = <1>;
> @@ -127,3 +145,139 @@ Examples:
>  			num-lanes = <1>;
>  		};
>  	};
> +
> +Examples for MT2712:
> +	pcie: pcie@11700000 {
> +		compatible = "mediatek,generic-pcie-v2";
> +		device_type = "pci";
> +		reg = <0 0x11700000 0 0x1000>,
> +		      <0 0x112ff000 0 0x1000>;
> +		reg-names = "port0", "port1";
> +		#address-cells = <3>;
> +		#size-cells = <2>;
> +		interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>,
> +			     <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
> +		clocks = <&pericfg CLK_PERI_PCIE0>,
> +			 <&pericfg CLK_PERI_PCIE1>,
> +			 <&topckgen CLK_TOP_PE2_MAC_P0_SEL>,
> +			 <&topckgen CLK_TOP_PE2_MAC_P1_SEL>;
> +		clock-names = "sys_ck0", "sys_ck1", "ahb_ck0", "ahb_ck1";
> +		phys = <&pcie0_phy PHY_TYPE_PCIE>, <&pcie1_phy PHY_TYPE_PCIE>;
> +		phy-names = "pcie-phy0", "pcie-phy1";
> +		bus-range = <0x00 0xff>;
> +		ranges = <0x82000000 0 0x20000000  0x0 0x20000000  0 0x10000000>;
> +
> +		pcie0: pcie@0,0 {
> +			device_type = "pci";
> +			reg = <0x0000 0 0 0 0>;
> +			#address-cells = <3>;
> +			#size-cells = <2>;
> +			#interrupt-cells = <1>;
> +			ranges;
> +			num-lanes = <1>;
> +			interrupt-map-mask = <0 0 0 7>;
> +			interrupt-map = <0 0 0 1 &pcie_intc0 0>,
> +					<0 0 0 2 &pcie_intc0 1>,
> +					<0 0 0 3 &pcie_intc0 2>,
> +					<0 0 0 4 &pcie_intc0 3>;
> +			pcie_intc0: interrupt-controller {
> +				interrupt-controller;
> +				#address-cells = <0>;
> +				#interrupt-cells = <1>;
> +			};
> +		};
> +
> +		pcie1: pcie@1,0 {
> +			device_type = "pci";
> +			reg = <0x0800 0 0 0 0>;
> +			#address-cells = <3>;
> +			#size-cells = <2>;
> +			#interrupt-cells = <1>;
> +			ranges;
> +			num-lanes = <1>;
> +			interrupt-map-mask = <0 0 0 7>;
> +			interrupt-map = <0 0 0 1 &pcie_intc1 0>,
> +					<0 0 0 2 &pcie_intc1 1>,
> +					<0 0 0 3 &pcie_intc1 2>,
> +					<0 0 0 4 &pcie_intc1 3>;
> +			pcie_intc1: interrupt-controller {
> +				interrupt-controller;
> +				#address-cells = <0>;
> +				#interrupt-cells = <1>;
> +			};
> +		};
> +	};
> +
> +Examples for MT7622:
> +	pcie: pcie@1a140000 {
> +		compatible = "mediatek,generic-pcie-v2";
> +		device_type = "pci";
> +		reg = <0 0x1a140000 0 0x1000>,
> +		      <0 0x1a143000 0 0x1000>,
> +		      <0 0x1a145000 0 0x1000>;
> +		reg-names = "subsys", "port0", "port1";
> +		#address-cells = <3>;
> +		#size-cells = <2>;
> +		interrupts = <GIC_SPI 228 IRQ_TYPE_LEVEL_LOW>,
> +			     <GIC_SPI 229 IRQ_TYPE_LEVEL_LOW>;
> +		clocks = <&pciesys CLK_PCIE_P0_MAC_EN>,
> +			 <&pciesys CLK_PCIE_P1_MAC_EN>,
> +			 <&pciesys CLK_PCIE_P0_AHB_EN>,
> +			 <&pciesys CLK_PCIE_P1_AHB_EN>,
> +			 <&pciesys CLK_PCIE_P0_AUX_EN>,
> +			 <&pciesys CLK_PCIE_P1_AUX_EN>,
> +			 <&pciesys CLK_PCIE_P0_AXI_EN>,
> +			 <&pciesys CLK_PCIE_P1_AXI_EN>,
> +			 <&pciesys CLK_PCIE_P0_OBFF_EN>,
> +			 <&pciesys CLK_PCIE_P1_OBFF_EN>,
> +			 <&pciesys CLK_PCIE_P0_PIPE_EN>,
> +			 <&pciesys CLK_PCIE_P1_PIPE_EN>;
> +		clock-names = "sys_ck0", "sys_ck1", "ahb_ck0", "ahb_ck1",
> +			      "aux_ck0", "aux_ck1", "axi_ck0", "axi_ck1",
> +			      "obff_ck0", "obff_ck1", "pipe_ck0", "pipe_ck1";
> +		phys = <&pcie0_phy PHY_TYPE_PCIE>, <&pcie1_phy PHY_TYPE_PCIE>;
> +		phy-names = "pcie-phy0", "pcie-phy1";
> +		power-domains = <&scpsys MT7622_POWER_DOMAIN_HIF0>;
> +		bus-range = <0x00 0xff>;
> +		ranges = <0x82000000 0 0x20000000  0x0 0x20000000  0 0x10000000>;
> +
> +		pcie0: pcie@0,0 {
> +			device_type = "pci";
> +			reg = <0x0000 0 0 0 0>;
> +			#address-cells = <3>;
> +			#size-cells = <2>;
> +			#interrupt-cells = <1>;
> +			ranges;
> +			num-lanes = <1>;
> +			interrupt-map-mask = <0 0 0 7>;
> +			interrupt-map = <0 0 0 1 &pcie_intc0 0>,
> +					<0 0 0 2 &pcie_intc0 1>,
> +					<0 0 0 3 &pcie_intc0 2>,
> +					<0 0 0 4 &pcie_intc0 3>;
> +			pcie_intc0: interrupt-controller {
> +				interrupt-controller;
> +				#address-cells = <0>;
> +				#interrupt-cells = <1>;
> +			};
> +		};
> +
> +		pcie1: pcie@1,0 {
> +			device_type = "pci";
> +			reg = <0x0800 0 0 0 0>;
> +			#address-cells = <3>;
> +			#size-cells = <2>;
> +			#interrupt-cells = <1>;
> +			ranges;
> +			num-lanes = <1>;
> +			interrupt-map-mask = <0 0 0 7>;
> +			interrupt-map = <0 0 0 1 &pcie_intc1 0>,
> +					<0 0 0 2 &pcie_intc1 1>,
> +					<0 0 0 3 &pcie_intc1 2>,
> +					<0 0 0 4 &pcie_intc1 3>;
> +			pcie_intc1: interrupt-controller {
> +				interrupt-controller;
> +				#address-cells = <0>;
> +				#interrupt-cells = <1>;
> +			};
> +		};
> +	};

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v2 5/5] dt-bindings: PCI: add support for new generation controller
@ 2017-07-27  3:31     ` Honghui Zhang
  0 siblings, 0 replies; 80+ messages in thread
From: Honghui Zhang @ 2017-07-27  3:31 UTC (permalink / raw)
  To: bhelgaas
  Cc: youlin.pei, devicetree, hongkun.cao, ryder.lee, linux-pci,
	sean.wang, xinping.qian, linux-kernel, robh+dt, yt.shen, robh,
	linux-mediatek, yong.wu, matthias.bgg, yingjoe.chen, eddie.huang,
	linux-arm-kernel

On Thu, 2017-07-27 at 10:58 +0800, honghui.zhang@mediatek.com wrote:
> From: Ryder Lee <ryder.lee@mediatek.com>
> 
> Add support for MediaTek new generation controller and update related
> properities.
> 
> Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> Signed-off-by: Honghui Zhang <honghui.zhang@mediatek.com>
> ---
>  .../devicetree/bindings/pci/mediatek-pcie.txt      | 168 ++++++++++++++++++++-
>  1 file changed, 161 insertions(+), 7 deletions(-)
> 

Sorry about the disturb, I send the wrong local version  of this patch.
[PATCH v2 5/5] dt-bindings: PCI: add support for new generation
 controller

The right version for this patch have been re-send.

thanks.

> diff --git a/Documentation/devicetree/bindings/pci/mediatek-pcie.txt b/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
> index a968f25..179329b 100644
> --- a/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
> +++ b/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
> @@ -3,18 +3,31 @@ MediaTek Gen2 PCIe controller
>  Required properties:
>  - compatible: Should contain one of the following string:
>  	"mediatek,mt2701-pcie"
> +	"mediatek,mt2712-pcie"
> +	"mediatek,mt7622-pcie"
>  	"mediatek,mt7623-pcie"
>  - device_type: Must be "pci"
> -- reg: Base addresses and lengths of the PCIe controller.
> +- reg: Base addresses and lengths of the PICe subsys and root ports.
> +- reg-names: Names of the above areas to use during resource look-up.
>  - #address-cells: Address representation for root ports (must be 3)
>  - #size-cells: Size representation for root ports (must be 2)
>  - clocks: Must contain an entry for each entry in clock-names.
>    See ../clocks/clock-bindings.txt for details.
> -- clock-names: Must include the following entries:
> -  - free_ck :for reference clock of PCIe subsys
> -  - sys_ck0 :for clock of Port0
> -  - sys_ck1 :for clock of Port1
> -  - sys_ck2 :for clock of Port2
> +- clock-names:
> +  Mandatory entries:
> +   - sys_ckN :transaction layer and data link layer clock
> +  Required entries for MT2701/MT7623:
> +   - free_ck :for reference clock of PCIe subsys
> +  Required entries for MT2712/MT7622:
> +   - ahb_ckN :AHB slave interface operating clock for CSR access and RC
> +	      initiated MMIO access
> +  Required entries for MT7622:
> +   - axi_ckN :application layer MMIO channel operating clock
> +   - aux_ckN :pe2_mac_bridge and pe2_mac_core operating clock when
> +	      pcie_mac_ck/pcie_pipe_ck is turned off
> +   - obff_ckN :OBFF functional block operating clock
> +   - pipe_ckN :LTSSM and phy/mac layer operating clock
> +  where N starting from 0 to the maximum number of root ports.
>  - phys: List of PHY specifiers (used by generic PHY framework).
>  - phy-names : Must be "pcie-phy0", "pcie-phy1", "pcie-phyN".. based on the
>    number of PHYs as specified in *phys* property.
> @@ -33,6 +46,10 @@ Required properties for MT7623/MT2701:
>  - reset-names: Must be "pcie-rst0", "pcie-rst1", "pcie-rstN".. based on the
>    number of root ports.
>  
> +Required properties for MT2712/MT7622:
> +-interrupts: A list of interrupt outputs of the controller, must have one
> +	     entry for each PCIe port
> +
>  In addition, the device tree node must have sub-nodes describing each
>  PCIe port interface, having the following mandatory properties:
>  
> @@ -50,7 +67,7 @@ Required properties:
>    property is sufficient.
>  - num-lanes: Number of lanes to use for this port.
>  
> -Examples:
> +Examples for MT7623:
>  
>  	hifsys: syscon@1a000000 {
>  		compatible = "mediatek,mt7623-hifsys",
> @@ -68,6 +85,7 @@ Examples:
>  		      <0 0x1a142000 0 0x1000>, /* Port0 registers */
>  		      <0 0x1a143000 0 0x1000>, /* Port1 registers */
>  		      <0 0x1a144000 0 0x1000>; /* Port2 registers */
> +		reg-names = "subsys", "port0", "port1", "port2";
>  		#address-cells = <3>;
>  		#size-cells = <2>;
>  		#interrupt-cells = <1>;
> @@ -127,3 +145,139 @@ Examples:
>  			num-lanes = <1>;
>  		};
>  	};
> +
> +Examples for MT2712:
> +	pcie: pcie@11700000 {
> +		compatible = "mediatek,generic-pcie-v2";
> +		device_type = "pci";
> +		reg = <0 0x11700000 0 0x1000>,
> +		      <0 0x112ff000 0 0x1000>;
> +		reg-names = "port0", "port1";
> +		#address-cells = <3>;
> +		#size-cells = <2>;
> +		interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>,
> +			     <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
> +		clocks = <&pericfg CLK_PERI_PCIE0>,
> +			 <&pericfg CLK_PERI_PCIE1>,
> +			 <&topckgen CLK_TOP_PE2_MAC_P0_SEL>,
> +			 <&topckgen CLK_TOP_PE2_MAC_P1_SEL>;
> +		clock-names = "sys_ck0", "sys_ck1", "ahb_ck0", "ahb_ck1";
> +		phys = <&pcie0_phy PHY_TYPE_PCIE>, <&pcie1_phy PHY_TYPE_PCIE>;
> +		phy-names = "pcie-phy0", "pcie-phy1";
> +		bus-range = <0x00 0xff>;
> +		ranges = <0x82000000 0 0x20000000  0x0 0x20000000  0 0x10000000>;
> +
> +		pcie0: pcie@0,0 {
> +			device_type = "pci";
> +			reg = <0x0000 0 0 0 0>;
> +			#address-cells = <3>;
> +			#size-cells = <2>;
> +			#interrupt-cells = <1>;
> +			ranges;
> +			num-lanes = <1>;
> +			interrupt-map-mask = <0 0 0 7>;
> +			interrupt-map = <0 0 0 1 &pcie_intc0 0>,
> +					<0 0 0 2 &pcie_intc0 1>,
> +					<0 0 0 3 &pcie_intc0 2>,
> +					<0 0 0 4 &pcie_intc0 3>;
> +			pcie_intc0: interrupt-controller {
> +				interrupt-controller;
> +				#address-cells = <0>;
> +				#interrupt-cells = <1>;
> +			};
> +		};
> +
> +		pcie1: pcie@1,0 {
> +			device_type = "pci";
> +			reg = <0x0800 0 0 0 0>;
> +			#address-cells = <3>;
> +			#size-cells = <2>;
> +			#interrupt-cells = <1>;
> +			ranges;
> +			num-lanes = <1>;
> +			interrupt-map-mask = <0 0 0 7>;
> +			interrupt-map = <0 0 0 1 &pcie_intc1 0>,
> +					<0 0 0 2 &pcie_intc1 1>,
> +					<0 0 0 3 &pcie_intc1 2>,
> +					<0 0 0 4 &pcie_intc1 3>;
> +			pcie_intc1: interrupt-controller {
> +				interrupt-controller;
> +				#address-cells = <0>;
> +				#interrupt-cells = <1>;
> +			};
> +		};
> +	};
> +
> +Examples for MT7622:
> +	pcie: pcie@1a140000 {
> +		compatible = "mediatek,generic-pcie-v2";
> +		device_type = "pci";
> +		reg = <0 0x1a140000 0 0x1000>,
> +		      <0 0x1a143000 0 0x1000>,
> +		      <0 0x1a145000 0 0x1000>;
> +		reg-names = "subsys", "port0", "port1";
> +		#address-cells = <3>;
> +		#size-cells = <2>;
> +		interrupts = <GIC_SPI 228 IRQ_TYPE_LEVEL_LOW>,
> +			     <GIC_SPI 229 IRQ_TYPE_LEVEL_LOW>;
> +		clocks = <&pciesys CLK_PCIE_P0_MAC_EN>,
> +			 <&pciesys CLK_PCIE_P1_MAC_EN>,
> +			 <&pciesys CLK_PCIE_P0_AHB_EN>,
> +			 <&pciesys CLK_PCIE_P1_AHB_EN>,
> +			 <&pciesys CLK_PCIE_P0_AUX_EN>,
> +			 <&pciesys CLK_PCIE_P1_AUX_EN>,
> +			 <&pciesys CLK_PCIE_P0_AXI_EN>,
> +			 <&pciesys CLK_PCIE_P1_AXI_EN>,
> +			 <&pciesys CLK_PCIE_P0_OBFF_EN>,
> +			 <&pciesys CLK_PCIE_P1_OBFF_EN>,
> +			 <&pciesys CLK_PCIE_P0_PIPE_EN>,
> +			 <&pciesys CLK_PCIE_P1_PIPE_EN>;
> +		clock-names = "sys_ck0", "sys_ck1", "ahb_ck0", "ahb_ck1",
> +			      "aux_ck0", "aux_ck1", "axi_ck0", "axi_ck1",
> +			      "obff_ck0", "obff_ck1", "pipe_ck0", "pipe_ck1";
> +		phys = <&pcie0_phy PHY_TYPE_PCIE>, <&pcie1_phy PHY_TYPE_PCIE>;
> +		phy-names = "pcie-phy0", "pcie-phy1";
> +		power-domains = <&scpsys MT7622_POWER_DOMAIN_HIF0>;
> +		bus-range = <0x00 0xff>;
> +		ranges = <0x82000000 0 0x20000000  0x0 0x20000000  0 0x10000000>;
> +
> +		pcie0: pcie@0,0 {
> +			device_type = "pci";
> +			reg = <0x0000 0 0 0 0>;
> +			#address-cells = <3>;
> +			#size-cells = <2>;
> +			#interrupt-cells = <1>;
> +			ranges;
> +			num-lanes = <1>;
> +			interrupt-map-mask = <0 0 0 7>;
> +			interrupt-map = <0 0 0 1 &pcie_intc0 0>,
> +					<0 0 0 2 &pcie_intc0 1>,
> +					<0 0 0 3 &pcie_intc0 2>,
> +					<0 0 0 4 &pcie_intc0 3>;
> +			pcie_intc0: interrupt-controller {
> +				interrupt-controller;
> +				#address-cells = <0>;
> +				#interrupt-cells = <1>;
> +			};
> +		};
> +
> +		pcie1: pcie@1,0 {
> +			device_type = "pci";
> +			reg = <0x0800 0 0 0 0>;
> +			#address-cells = <3>;
> +			#size-cells = <2>;
> +			#interrupt-cells = <1>;
> +			ranges;
> +			num-lanes = <1>;
> +			interrupt-map-mask = <0 0 0 7>;
> +			interrupt-map = <0 0 0 1 &pcie_intc1 0>,
> +					<0 0 0 2 &pcie_intc1 1>,
> +					<0 0 0 3 &pcie_intc1 2>,
> +					<0 0 0 4 &pcie_intc1 3>;
> +			pcie_intc1: interrupt-controller {
> +				interrupt-controller;
> +				#address-cells = <0>;
> +				#interrupt-cells = <1>;
> +			};
> +		};
> +	};



_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 80+ messages in thread

* [PATCH v2 5/5] dt-bindings: PCI: add support for new generation controller
@ 2017-07-27  3:31     ` Honghui Zhang
  0 siblings, 0 replies; 80+ messages in thread
From: Honghui Zhang @ 2017-07-27  3:31 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 2017-07-27 at 10:58 +0800, honghui.zhang at mediatek.com wrote:
> From: Ryder Lee <ryder.lee@mediatek.com>
> 
> Add support for MediaTek new generation controller and update related
> properities.
> 
> Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> Signed-off-by: Honghui Zhang <honghui.zhang@mediatek.com>
> ---
>  .../devicetree/bindings/pci/mediatek-pcie.txt      | 168 ++++++++++++++++++++-
>  1 file changed, 161 insertions(+), 7 deletions(-)
> 

Sorry about the disturb, I send the wrong local version  of this patch.
[PATCH v2 5/5] dt-bindings: PCI: add support for new generation
 controller

The right version for this patch have been re-send.

thanks.

> diff --git a/Documentation/devicetree/bindings/pci/mediatek-pcie.txt b/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
> index a968f25..179329b 100644
> --- a/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
> +++ b/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
> @@ -3,18 +3,31 @@ MediaTek Gen2 PCIe controller
>  Required properties:
>  - compatible: Should contain one of the following string:
>  	"mediatek,mt2701-pcie"
> +	"mediatek,mt2712-pcie"
> +	"mediatek,mt7622-pcie"
>  	"mediatek,mt7623-pcie"
>  - device_type: Must be "pci"
> -- reg: Base addresses and lengths of the PCIe controller.
> +- reg: Base addresses and lengths of the PICe subsys and root ports.
> +- reg-names: Names of the above areas to use during resource look-up.
>  - #address-cells: Address representation for root ports (must be 3)
>  - #size-cells: Size representation for root ports (must be 2)
>  - clocks: Must contain an entry for each entry in clock-names.
>    See ../clocks/clock-bindings.txt for details.
> -- clock-names: Must include the following entries:
> -  - free_ck :for reference clock of PCIe subsys
> -  - sys_ck0 :for clock of Port0
> -  - sys_ck1 :for clock of Port1
> -  - sys_ck2 :for clock of Port2
> +- clock-names:
> +  Mandatory entries:
> +   - sys_ckN :transaction layer and data link layer clock
> +  Required entries for MT2701/MT7623:
> +   - free_ck :for reference clock of PCIe subsys
> +  Required entries for MT2712/MT7622:
> +   - ahb_ckN :AHB slave interface operating clock for CSR access and RC
> +	      initiated MMIO access
> +  Required entries for MT7622:
> +   - axi_ckN :application layer MMIO channel operating clock
> +   - aux_ckN :pe2_mac_bridge and pe2_mac_core operating clock when
> +	      pcie_mac_ck/pcie_pipe_ck is turned off
> +   - obff_ckN :OBFF functional block operating clock
> +   - pipe_ckN :LTSSM and phy/mac layer operating clock
> +  where N starting from 0 to the maximum number of root ports.
>  - phys: List of PHY specifiers (used by generic PHY framework).
>  - phy-names : Must be "pcie-phy0", "pcie-phy1", "pcie-phyN".. based on the
>    number of PHYs as specified in *phys* property.
> @@ -33,6 +46,10 @@ Required properties for MT7623/MT2701:
>  - reset-names: Must be "pcie-rst0", "pcie-rst1", "pcie-rstN".. based on the
>    number of root ports.
>  
> +Required properties for MT2712/MT7622:
> +-interrupts: A list of interrupt outputs of the controller, must have one
> +	     entry for each PCIe port
> +
>  In addition, the device tree node must have sub-nodes describing each
>  PCIe port interface, having the following mandatory properties:
>  
> @@ -50,7 +67,7 @@ Required properties:
>    property is sufficient.
>  - num-lanes: Number of lanes to use for this port.
>  
> -Examples:
> +Examples for MT7623:
>  
>  	hifsys: syscon at 1a000000 {
>  		compatible = "mediatek,mt7623-hifsys",
> @@ -68,6 +85,7 @@ Examples:
>  		      <0 0x1a142000 0 0x1000>, /* Port0 registers */
>  		      <0 0x1a143000 0 0x1000>, /* Port1 registers */
>  		      <0 0x1a144000 0 0x1000>; /* Port2 registers */
> +		reg-names = "subsys", "port0", "port1", "port2";
>  		#address-cells = <3>;
>  		#size-cells = <2>;
>  		#interrupt-cells = <1>;
> @@ -127,3 +145,139 @@ Examples:
>  			num-lanes = <1>;
>  		};
>  	};
> +
> +Examples for MT2712:
> +	pcie: pcie at 11700000 {
> +		compatible = "mediatek,generic-pcie-v2";
> +		device_type = "pci";
> +		reg = <0 0x11700000 0 0x1000>,
> +		      <0 0x112ff000 0 0x1000>;
> +		reg-names = "port0", "port1";
> +		#address-cells = <3>;
> +		#size-cells = <2>;
> +		interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>,
> +			     <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
> +		clocks = <&pericfg CLK_PERI_PCIE0>,
> +			 <&pericfg CLK_PERI_PCIE1>,
> +			 <&topckgen CLK_TOP_PE2_MAC_P0_SEL>,
> +			 <&topckgen CLK_TOP_PE2_MAC_P1_SEL>;
> +		clock-names = "sys_ck0", "sys_ck1", "ahb_ck0", "ahb_ck1";
> +		phys = <&pcie0_phy PHY_TYPE_PCIE>, <&pcie1_phy PHY_TYPE_PCIE>;
> +		phy-names = "pcie-phy0", "pcie-phy1";
> +		bus-range = <0x00 0xff>;
> +		ranges = <0x82000000 0 0x20000000  0x0 0x20000000  0 0x10000000>;
> +
> +		pcie0: pcie at 0,0 {
> +			device_type = "pci";
> +			reg = <0x0000 0 0 0 0>;
> +			#address-cells = <3>;
> +			#size-cells = <2>;
> +			#interrupt-cells = <1>;
> +			ranges;
> +			num-lanes = <1>;
> +			interrupt-map-mask = <0 0 0 7>;
> +			interrupt-map = <0 0 0 1 &pcie_intc0 0>,
> +					<0 0 0 2 &pcie_intc0 1>,
> +					<0 0 0 3 &pcie_intc0 2>,
> +					<0 0 0 4 &pcie_intc0 3>;
> +			pcie_intc0: interrupt-controller {
> +				interrupt-controller;
> +				#address-cells = <0>;
> +				#interrupt-cells = <1>;
> +			};
> +		};
> +
> +		pcie1: pcie at 1,0 {
> +			device_type = "pci";
> +			reg = <0x0800 0 0 0 0>;
> +			#address-cells = <3>;
> +			#size-cells = <2>;
> +			#interrupt-cells = <1>;
> +			ranges;
> +			num-lanes = <1>;
> +			interrupt-map-mask = <0 0 0 7>;
> +			interrupt-map = <0 0 0 1 &pcie_intc1 0>,
> +					<0 0 0 2 &pcie_intc1 1>,
> +					<0 0 0 3 &pcie_intc1 2>,
> +					<0 0 0 4 &pcie_intc1 3>;
> +			pcie_intc1: interrupt-controller {
> +				interrupt-controller;
> +				#address-cells = <0>;
> +				#interrupt-cells = <1>;
> +			};
> +		};
> +	};
> +
> +Examples for MT7622:
> +	pcie: pcie at 1a140000 {
> +		compatible = "mediatek,generic-pcie-v2";
> +		device_type = "pci";
> +		reg = <0 0x1a140000 0 0x1000>,
> +		      <0 0x1a143000 0 0x1000>,
> +		      <0 0x1a145000 0 0x1000>;
> +		reg-names = "subsys", "port0", "port1";
> +		#address-cells = <3>;
> +		#size-cells = <2>;
> +		interrupts = <GIC_SPI 228 IRQ_TYPE_LEVEL_LOW>,
> +			     <GIC_SPI 229 IRQ_TYPE_LEVEL_LOW>;
> +		clocks = <&pciesys CLK_PCIE_P0_MAC_EN>,
> +			 <&pciesys CLK_PCIE_P1_MAC_EN>,
> +			 <&pciesys CLK_PCIE_P0_AHB_EN>,
> +			 <&pciesys CLK_PCIE_P1_AHB_EN>,
> +			 <&pciesys CLK_PCIE_P0_AUX_EN>,
> +			 <&pciesys CLK_PCIE_P1_AUX_EN>,
> +			 <&pciesys CLK_PCIE_P0_AXI_EN>,
> +			 <&pciesys CLK_PCIE_P1_AXI_EN>,
> +			 <&pciesys CLK_PCIE_P0_OBFF_EN>,
> +			 <&pciesys CLK_PCIE_P1_OBFF_EN>,
> +			 <&pciesys CLK_PCIE_P0_PIPE_EN>,
> +			 <&pciesys CLK_PCIE_P1_PIPE_EN>;
> +		clock-names = "sys_ck0", "sys_ck1", "ahb_ck0", "ahb_ck1",
> +			      "aux_ck0", "aux_ck1", "axi_ck0", "axi_ck1",
> +			      "obff_ck0", "obff_ck1", "pipe_ck0", "pipe_ck1";
> +		phys = <&pcie0_phy PHY_TYPE_PCIE>, <&pcie1_phy PHY_TYPE_PCIE>;
> +		phy-names = "pcie-phy0", "pcie-phy1";
> +		power-domains = <&scpsys MT7622_POWER_DOMAIN_HIF0>;
> +		bus-range = <0x00 0xff>;
> +		ranges = <0x82000000 0 0x20000000  0x0 0x20000000  0 0x10000000>;
> +
> +		pcie0: pcie at 0,0 {
> +			device_type = "pci";
> +			reg = <0x0000 0 0 0 0>;
> +			#address-cells = <3>;
> +			#size-cells = <2>;
> +			#interrupt-cells = <1>;
> +			ranges;
> +			num-lanes = <1>;
> +			interrupt-map-mask = <0 0 0 7>;
> +			interrupt-map = <0 0 0 1 &pcie_intc0 0>,
> +					<0 0 0 2 &pcie_intc0 1>,
> +					<0 0 0 3 &pcie_intc0 2>,
> +					<0 0 0 4 &pcie_intc0 3>;
> +			pcie_intc0: interrupt-controller {
> +				interrupt-controller;
> +				#address-cells = <0>;
> +				#interrupt-cells = <1>;
> +			};
> +		};
> +
> +		pcie1: pcie at 1,0 {
> +			device_type = "pci";
> +			reg = <0x0800 0 0 0 0>;
> +			#address-cells = <3>;
> +			#size-cells = <2>;
> +			#interrupt-cells = <1>;
> +			ranges;
> +			num-lanes = <1>;
> +			interrupt-map-mask = <0 0 0 7>;
> +			interrupt-map = <0 0 0 1 &pcie_intc1 0>,
> +					<0 0 0 2 &pcie_intc1 1>,
> +					<0 0 0 3 &pcie_intc1 2>,
> +					<0 0 0 4 &pcie_intc1 3>;
> +			pcie_intc1: interrupt-controller {
> +				interrupt-controller;
> +				#address-cells = <0>;
> +				#interrupt-cells = <1>;
> +			};
> +		};
> +	};

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v2 5/5] dt-bindings: PCI: add support for new generation controller
@ 2017-07-27  3:38     ` Honghui Zhang
  0 siblings, 0 replies; 80+ messages in thread
From: Honghui Zhang @ 2017-07-27  3:38 UTC (permalink / raw)
  To: bhelgaas
  Cc: robh, robh+dt, matthias.bgg, linux-arm-kernel, linux-mediatek,
	linux-pci, linux-kernel, devicetree, yingjoe.chen, eddie.huang,
	ryder.lee, hongkun.cao, youlin.pei, yong.wu, yt.shen, sean.wang,
	xinping.qian

On Thu, 2017-07-27 at 10:58 +0800, honghui.zhang@mediatek.com wrote:
> From: Ryder Lee <ryder.lee@mediatek.com>
> 
> Add support for MediaTek new generation controller and update related
> properities.
> 
> Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> Signed-off-by: Honghui Zhang <honghui.zhang@mediatek.com>
> ---
>  .../devicetree/bindings/pci/mediatek-pcie.txt      | 168 ++++++++++++++++++++-
>  1 file changed, 161 insertions(+), 7 deletions(-)
> 

Sorry for the disturb, I send the wrong patch from my local version for
this patch: 
[PATCH v2 5/5] dt-bindings: PCI: add support for new generation
 controller

And the new right version have been re-send.

thanks.

> diff --git a/Documentation/devicetree/bindings/pci/mediatek-pcie.txt b/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
> index a968f25..179329b 100644
> --- a/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
> +++ b/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
> @@ -3,18 +3,31 @@ MediaTek Gen2 PCIe controller
>  Required properties:
>  - compatible: Should contain one of the following string:
>  	"mediatek,mt2701-pcie"
> +	"mediatek,mt2712-pcie"
> +	"mediatek,mt7622-pcie"
>  	"mediatek,mt7623-pcie"
>  - device_type: Must be "pci"
> -- reg: Base addresses and lengths of the PCIe controller.
> +- reg: Base addresses and lengths of the PICe subsys and root ports.
> +- reg-names: Names of the above areas to use during resource look-up.
>  - #address-cells: Address representation for root ports (must be 3)
>  - #size-cells: Size representation for root ports (must be 2)
>  - clocks: Must contain an entry for each entry in clock-names.
>    See ../clocks/clock-bindings.txt for details.
> -- clock-names: Must include the following entries:
> -  - free_ck :for reference clock of PCIe subsys
> -  - sys_ck0 :for clock of Port0
> -  - sys_ck1 :for clock of Port1
> -  - sys_ck2 :for clock of Port2
> +- clock-names:
> +  Mandatory entries:
> +   - sys_ckN :transaction layer and data link layer clock
> +  Required entries for MT2701/MT7623:
> +   - free_ck :for reference clock of PCIe subsys
> +  Required entries for MT2712/MT7622:
> +   - ahb_ckN :AHB slave interface operating clock for CSR access and RC
> +	      initiated MMIO access
> +  Required entries for MT7622:
> +   - axi_ckN :application layer MMIO channel operating clock
> +   - aux_ckN :pe2_mac_bridge and pe2_mac_core operating clock when
> +	      pcie_mac_ck/pcie_pipe_ck is turned off
> +   - obff_ckN :OBFF functional block operating clock
> +   - pipe_ckN :LTSSM and phy/mac layer operating clock
> +  where N starting from 0 to the maximum number of root ports.
>  - phys: List of PHY specifiers (used by generic PHY framework).
>  - phy-names : Must be "pcie-phy0", "pcie-phy1", "pcie-phyN".. based on the
>    number of PHYs as specified in *phys* property.
> @@ -33,6 +46,10 @@ Required properties for MT7623/MT2701:
>  - reset-names: Must be "pcie-rst0", "pcie-rst1", "pcie-rstN".. based on the
>    number of root ports.
>  
> +Required properties for MT2712/MT7622:
> +-interrupts: A list of interrupt outputs of the controller, must have one
> +	     entry for each PCIe port
> +
>  In addition, the device tree node must have sub-nodes describing each
>  PCIe port interface, having the following mandatory properties:
>  
> @@ -50,7 +67,7 @@ Required properties:
>    property is sufficient.
>  - num-lanes: Number of lanes to use for this port.
>  
> -Examples:
> +Examples for MT7623:
>  
>  	hifsys: syscon@1a000000 {
>  		compatible = "mediatek,mt7623-hifsys",
> @@ -68,6 +85,7 @@ Examples:
>  		      <0 0x1a142000 0 0x1000>, /* Port0 registers */
>  		      <0 0x1a143000 0 0x1000>, /* Port1 registers */
>  		      <0 0x1a144000 0 0x1000>; /* Port2 registers */
> +		reg-names = "subsys", "port0", "port1", "port2";
>  		#address-cells = <3>;
>  		#size-cells = <2>;
>  		#interrupt-cells = <1>;
> @@ -127,3 +145,139 @@ Examples:
>  			num-lanes = <1>;
>  		};
>  	};
> +
> +Examples for MT2712:
> +	pcie: pcie@11700000 {
> +		compatible = "mediatek,generic-pcie-v2";
> +		device_type = "pci";
> +		reg = <0 0x11700000 0 0x1000>,
> +		      <0 0x112ff000 0 0x1000>;
> +		reg-names = "port0", "port1";
> +		#address-cells = <3>;
> +		#size-cells = <2>;
> +		interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>,
> +			     <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
> +		clocks = <&pericfg CLK_PERI_PCIE0>,
> +			 <&pericfg CLK_PERI_PCIE1>,
> +			 <&topckgen CLK_TOP_PE2_MAC_P0_SEL>,
> +			 <&topckgen CLK_TOP_PE2_MAC_P1_SEL>;
> +		clock-names = "sys_ck0", "sys_ck1", "ahb_ck0", "ahb_ck1";
> +		phys = <&pcie0_phy PHY_TYPE_PCIE>, <&pcie1_phy PHY_TYPE_PCIE>;
> +		phy-names = "pcie-phy0", "pcie-phy1";
> +		bus-range = <0x00 0xff>;
> +		ranges = <0x82000000 0 0x20000000  0x0 0x20000000  0 0x10000000>;
> +
> +		pcie0: pcie@0,0 {
> +			device_type = "pci";
> +			reg = <0x0000 0 0 0 0>;
> +			#address-cells = <3>;
> +			#size-cells = <2>;
> +			#interrupt-cells = <1>;
> +			ranges;
> +			num-lanes = <1>;
> +			interrupt-map-mask = <0 0 0 7>;
> +			interrupt-map = <0 0 0 1 &pcie_intc0 0>,
> +					<0 0 0 2 &pcie_intc0 1>,
> +					<0 0 0 3 &pcie_intc0 2>,
> +					<0 0 0 4 &pcie_intc0 3>;
> +			pcie_intc0: interrupt-controller {
> +				interrupt-controller;
> +				#address-cells = <0>;
> +				#interrupt-cells = <1>;
> +			};
> +		};
> +
> +		pcie1: pcie@1,0 {
> +			device_type = "pci";
> +			reg = <0x0800 0 0 0 0>;
> +			#address-cells = <3>;
> +			#size-cells = <2>;
> +			#interrupt-cells = <1>;
> +			ranges;
> +			num-lanes = <1>;
> +			interrupt-map-mask = <0 0 0 7>;
> +			interrupt-map = <0 0 0 1 &pcie_intc1 0>,
> +					<0 0 0 2 &pcie_intc1 1>,
> +					<0 0 0 3 &pcie_intc1 2>,
> +					<0 0 0 4 &pcie_intc1 3>;
> +			pcie_intc1: interrupt-controller {
> +				interrupt-controller;
> +				#address-cells = <0>;
> +				#interrupt-cells = <1>;
> +			};
> +		};
> +	};
> +
> +Examples for MT7622:
> +	pcie: pcie@1a140000 {
> +		compatible = "mediatek,generic-pcie-v2";
> +		device_type = "pci";
> +		reg = <0 0x1a140000 0 0x1000>,
> +		      <0 0x1a143000 0 0x1000>,
> +		      <0 0x1a145000 0 0x1000>;
> +		reg-names = "subsys", "port0", "port1";
> +		#address-cells = <3>;
> +		#size-cells = <2>;
> +		interrupts = <GIC_SPI 228 IRQ_TYPE_LEVEL_LOW>,
> +			     <GIC_SPI 229 IRQ_TYPE_LEVEL_LOW>;
> +		clocks = <&pciesys CLK_PCIE_P0_MAC_EN>,
> +			 <&pciesys CLK_PCIE_P1_MAC_EN>,
> +			 <&pciesys CLK_PCIE_P0_AHB_EN>,
> +			 <&pciesys CLK_PCIE_P1_AHB_EN>,
> +			 <&pciesys CLK_PCIE_P0_AUX_EN>,
> +			 <&pciesys CLK_PCIE_P1_AUX_EN>,
> +			 <&pciesys CLK_PCIE_P0_AXI_EN>,
> +			 <&pciesys CLK_PCIE_P1_AXI_EN>,
> +			 <&pciesys CLK_PCIE_P0_OBFF_EN>,
> +			 <&pciesys CLK_PCIE_P1_OBFF_EN>,
> +			 <&pciesys CLK_PCIE_P0_PIPE_EN>,
> +			 <&pciesys CLK_PCIE_P1_PIPE_EN>;
> +		clock-names = "sys_ck0", "sys_ck1", "ahb_ck0", "ahb_ck1",
> +			      "aux_ck0", "aux_ck1", "axi_ck0", "axi_ck1",
> +			      "obff_ck0", "obff_ck1", "pipe_ck0", "pipe_ck1";
> +		phys = <&pcie0_phy PHY_TYPE_PCIE>, <&pcie1_phy PHY_TYPE_PCIE>;
> +		phy-names = "pcie-phy0", "pcie-phy1";
> +		power-domains = <&scpsys MT7622_POWER_DOMAIN_HIF0>;
> +		bus-range = <0x00 0xff>;
> +		ranges = <0x82000000 0 0x20000000  0x0 0x20000000  0 0x10000000>;
> +
> +		pcie0: pcie@0,0 {
> +			device_type = "pci";
> +			reg = <0x0000 0 0 0 0>;
> +			#address-cells = <3>;
> +			#size-cells = <2>;
> +			#interrupt-cells = <1>;
> +			ranges;
> +			num-lanes = <1>;
> +			interrupt-map-mask = <0 0 0 7>;
> +			interrupt-map = <0 0 0 1 &pcie_intc0 0>,
> +					<0 0 0 2 &pcie_intc0 1>,
> +					<0 0 0 3 &pcie_intc0 2>,
> +					<0 0 0 4 &pcie_intc0 3>;
> +			pcie_intc0: interrupt-controller {
> +				interrupt-controller;
> +				#address-cells = <0>;
> +				#interrupt-cells = <1>;
> +			};
> +		};
> +
> +		pcie1: pcie@1,0 {
> +			device_type = "pci";
> +			reg = <0x0800 0 0 0 0>;
> +			#address-cells = <3>;
> +			#size-cells = <2>;
> +			#interrupt-cells = <1>;
> +			ranges;
> +			num-lanes = <1>;
> +			interrupt-map-mask = <0 0 0 7>;
> +			interrupt-map = <0 0 0 1 &pcie_intc1 0>,
> +					<0 0 0 2 &pcie_intc1 1>,
> +					<0 0 0 3 &pcie_intc1 2>,
> +					<0 0 0 4 &pcie_intc1 3>;
> +			pcie_intc1: interrupt-controller {
> +				interrupt-controller;
> +				#address-cells = <0>;
> +				#interrupt-cells = <1>;
> +			};
> +		};
> +	};

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v2 5/5] dt-bindings: PCI: add support for new generation controller
@ 2017-07-27  3:38     ` Honghui Zhang
  0 siblings, 0 replies; 80+ messages in thread
From: Honghui Zhang @ 2017-07-27  3:38 UTC (permalink / raw)
  To: bhelgaas-hpIqsD4AKlfQT0dZR+AlfA
  Cc: robh-+zGGX9k9yNkdnm+yROfE0A, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	matthias.bgg-Re5JQEeQqe8AvxtiuMwx3w,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-pci-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	yingjoe.chen-NuS5LvNUpcJWk0Htik3J/w,
	eddie.huang-NuS5LvNUpcJWk0Htik3J/w,
	ryder.lee-NuS5LvNUpcJWk0Htik3J/w,
	hongkun.cao-NuS5LvNUpcJWk0Htik3J/w,
	youlin.pei-NuS5LvNUpcJWk0Htik3J/w,
	yong.wu-NuS5LvNUpcJWk0Htik3J/w, yt.shen-NuS5LvNUpcJWk0Htik3J/w,
	sean.wang-NuS5LvNUpcJWk0Htik3J/w,
	xinping.qian-NuS5LvNUpcJWk0Htik3J/w

On Thu, 2017-07-27 at 10:58 +0800, honghui.zhang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org wrote:
> From: Ryder Lee <ryder.lee-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
> 
> Add support for MediaTek new generation controller and update related
> properities.
> 
> Signed-off-by: Ryder Lee <ryder.lee-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
> Signed-off-by: Honghui Zhang <honghui.zhang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
> ---
>  .../devicetree/bindings/pci/mediatek-pcie.txt      | 168 ++++++++++++++++++++-
>  1 file changed, 161 insertions(+), 7 deletions(-)
> 

Sorry for the disturb, I send the wrong patch from my local version for
this patch: 
[PATCH v2 5/5] dt-bindings: PCI: add support for new generation
 controller

And the new right version have been re-send.

thanks.

> diff --git a/Documentation/devicetree/bindings/pci/mediatek-pcie.txt b/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
> index a968f25..179329b 100644
> --- a/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
> +++ b/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
> @@ -3,18 +3,31 @@ MediaTek Gen2 PCIe controller
>  Required properties:
>  - compatible: Should contain one of the following string:
>  	"mediatek,mt2701-pcie"
> +	"mediatek,mt2712-pcie"
> +	"mediatek,mt7622-pcie"
>  	"mediatek,mt7623-pcie"
>  - device_type: Must be "pci"
> -- reg: Base addresses and lengths of the PCIe controller.
> +- reg: Base addresses and lengths of the PICe subsys and root ports.
> +- reg-names: Names of the above areas to use during resource look-up.
>  - #address-cells: Address representation for root ports (must be 3)
>  - #size-cells: Size representation for root ports (must be 2)
>  - clocks: Must contain an entry for each entry in clock-names.
>    See ../clocks/clock-bindings.txt for details.
> -- clock-names: Must include the following entries:
> -  - free_ck :for reference clock of PCIe subsys
> -  - sys_ck0 :for clock of Port0
> -  - sys_ck1 :for clock of Port1
> -  - sys_ck2 :for clock of Port2
> +- clock-names:
> +  Mandatory entries:
> +   - sys_ckN :transaction layer and data link layer clock
> +  Required entries for MT2701/MT7623:
> +   - free_ck :for reference clock of PCIe subsys
> +  Required entries for MT2712/MT7622:
> +   - ahb_ckN :AHB slave interface operating clock for CSR access and RC
> +	      initiated MMIO access
> +  Required entries for MT7622:
> +   - axi_ckN :application layer MMIO channel operating clock
> +   - aux_ckN :pe2_mac_bridge and pe2_mac_core operating clock when
> +	      pcie_mac_ck/pcie_pipe_ck is turned off
> +   - obff_ckN :OBFF functional block operating clock
> +   - pipe_ckN :LTSSM and phy/mac layer operating clock
> +  where N starting from 0 to the maximum number of root ports.
>  - phys: List of PHY specifiers (used by generic PHY framework).
>  - phy-names : Must be "pcie-phy0", "pcie-phy1", "pcie-phyN".. based on the
>    number of PHYs as specified in *phys* property.
> @@ -33,6 +46,10 @@ Required properties for MT7623/MT2701:
>  - reset-names: Must be "pcie-rst0", "pcie-rst1", "pcie-rstN".. based on the
>    number of root ports.
>  
> +Required properties for MT2712/MT7622:
> +-interrupts: A list of interrupt outputs of the controller, must have one
> +	     entry for each PCIe port
> +
>  In addition, the device tree node must have sub-nodes describing each
>  PCIe port interface, having the following mandatory properties:
>  
> @@ -50,7 +67,7 @@ Required properties:
>    property is sufficient.
>  - num-lanes: Number of lanes to use for this port.
>  
> -Examples:
> +Examples for MT7623:
>  
>  	hifsys: syscon@1a000000 {
>  		compatible = "mediatek,mt7623-hifsys",
> @@ -68,6 +85,7 @@ Examples:
>  		      <0 0x1a142000 0 0x1000>, /* Port0 registers */
>  		      <0 0x1a143000 0 0x1000>, /* Port1 registers */
>  		      <0 0x1a144000 0 0x1000>; /* Port2 registers */
> +		reg-names = "subsys", "port0", "port1", "port2";
>  		#address-cells = <3>;
>  		#size-cells = <2>;
>  		#interrupt-cells = <1>;
> @@ -127,3 +145,139 @@ Examples:
>  			num-lanes = <1>;
>  		};
>  	};
> +
> +Examples for MT2712:
> +	pcie: pcie@11700000 {
> +		compatible = "mediatek,generic-pcie-v2";
> +		device_type = "pci";
> +		reg = <0 0x11700000 0 0x1000>,
> +		      <0 0x112ff000 0 0x1000>;
> +		reg-names = "port0", "port1";
> +		#address-cells = <3>;
> +		#size-cells = <2>;
> +		interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>,
> +			     <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
> +		clocks = <&pericfg CLK_PERI_PCIE0>,
> +			 <&pericfg CLK_PERI_PCIE1>,
> +			 <&topckgen CLK_TOP_PE2_MAC_P0_SEL>,
> +			 <&topckgen CLK_TOP_PE2_MAC_P1_SEL>;
> +		clock-names = "sys_ck0", "sys_ck1", "ahb_ck0", "ahb_ck1";
> +		phys = <&pcie0_phy PHY_TYPE_PCIE>, <&pcie1_phy PHY_TYPE_PCIE>;
> +		phy-names = "pcie-phy0", "pcie-phy1";
> +		bus-range = <0x00 0xff>;
> +		ranges = <0x82000000 0 0x20000000  0x0 0x20000000  0 0x10000000>;
> +
> +		pcie0: pcie@0,0 {
> +			device_type = "pci";
> +			reg = <0x0000 0 0 0 0>;
> +			#address-cells = <3>;
> +			#size-cells = <2>;
> +			#interrupt-cells = <1>;
> +			ranges;
> +			num-lanes = <1>;
> +			interrupt-map-mask = <0 0 0 7>;
> +			interrupt-map = <0 0 0 1 &pcie_intc0 0>,
> +					<0 0 0 2 &pcie_intc0 1>,
> +					<0 0 0 3 &pcie_intc0 2>,
> +					<0 0 0 4 &pcie_intc0 3>;
> +			pcie_intc0: interrupt-controller {
> +				interrupt-controller;
> +				#address-cells = <0>;
> +				#interrupt-cells = <1>;
> +			};
> +		};
> +
> +		pcie1: pcie@1,0 {
> +			device_type = "pci";
> +			reg = <0x0800 0 0 0 0>;
> +			#address-cells = <3>;
> +			#size-cells = <2>;
> +			#interrupt-cells = <1>;
> +			ranges;
> +			num-lanes = <1>;
> +			interrupt-map-mask = <0 0 0 7>;
> +			interrupt-map = <0 0 0 1 &pcie_intc1 0>,
> +					<0 0 0 2 &pcie_intc1 1>,
> +					<0 0 0 3 &pcie_intc1 2>,
> +					<0 0 0 4 &pcie_intc1 3>;
> +			pcie_intc1: interrupt-controller {
> +				interrupt-controller;
> +				#address-cells = <0>;
> +				#interrupt-cells = <1>;
> +			};
> +		};
> +	};
> +
> +Examples for MT7622:
> +	pcie: pcie@1a140000 {
> +		compatible = "mediatek,generic-pcie-v2";
> +		device_type = "pci";
> +		reg = <0 0x1a140000 0 0x1000>,
> +		      <0 0x1a143000 0 0x1000>,
> +		      <0 0x1a145000 0 0x1000>;
> +		reg-names = "subsys", "port0", "port1";
> +		#address-cells = <3>;
> +		#size-cells = <2>;
> +		interrupts = <GIC_SPI 228 IRQ_TYPE_LEVEL_LOW>,
> +			     <GIC_SPI 229 IRQ_TYPE_LEVEL_LOW>;
> +		clocks = <&pciesys CLK_PCIE_P0_MAC_EN>,
> +			 <&pciesys CLK_PCIE_P1_MAC_EN>,
> +			 <&pciesys CLK_PCIE_P0_AHB_EN>,
> +			 <&pciesys CLK_PCIE_P1_AHB_EN>,
> +			 <&pciesys CLK_PCIE_P0_AUX_EN>,
> +			 <&pciesys CLK_PCIE_P1_AUX_EN>,
> +			 <&pciesys CLK_PCIE_P0_AXI_EN>,
> +			 <&pciesys CLK_PCIE_P1_AXI_EN>,
> +			 <&pciesys CLK_PCIE_P0_OBFF_EN>,
> +			 <&pciesys CLK_PCIE_P1_OBFF_EN>,
> +			 <&pciesys CLK_PCIE_P0_PIPE_EN>,
> +			 <&pciesys CLK_PCIE_P1_PIPE_EN>;
> +		clock-names = "sys_ck0", "sys_ck1", "ahb_ck0", "ahb_ck1",
> +			      "aux_ck0", "aux_ck1", "axi_ck0", "axi_ck1",
> +			      "obff_ck0", "obff_ck1", "pipe_ck0", "pipe_ck1";
> +		phys = <&pcie0_phy PHY_TYPE_PCIE>, <&pcie1_phy PHY_TYPE_PCIE>;
> +		phy-names = "pcie-phy0", "pcie-phy1";
> +		power-domains = <&scpsys MT7622_POWER_DOMAIN_HIF0>;
> +		bus-range = <0x00 0xff>;
> +		ranges = <0x82000000 0 0x20000000  0x0 0x20000000  0 0x10000000>;
> +
> +		pcie0: pcie@0,0 {
> +			device_type = "pci";
> +			reg = <0x0000 0 0 0 0>;
> +			#address-cells = <3>;
> +			#size-cells = <2>;
> +			#interrupt-cells = <1>;
> +			ranges;
> +			num-lanes = <1>;
> +			interrupt-map-mask = <0 0 0 7>;
> +			interrupt-map = <0 0 0 1 &pcie_intc0 0>,
> +					<0 0 0 2 &pcie_intc0 1>,
> +					<0 0 0 3 &pcie_intc0 2>,
> +					<0 0 0 4 &pcie_intc0 3>;
> +			pcie_intc0: interrupt-controller {
> +				interrupt-controller;
> +				#address-cells = <0>;
> +				#interrupt-cells = <1>;
> +			};
> +		};
> +
> +		pcie1: pcie@1,0 {
> +			device_type = "pci";
> +			reg = <0x0800 0 0 0 0>;
> +			#address-cells = <3>;
> +			#size-cells = <2>;
> +			#interrupt-cells = <1>;
> +			ranges;
> +			num-lanes = <1>;
> +			interrupt-map-mask = <0 0 0 7>;
> +			interrupt-map = <0 0 0 1 &pcie_intc1 0>,
> +					<0 0 0 2 &pcie_intc1 1>,
> +					<0 0 0 3 &pcie_intc1 2>,
> +					<0 0 0 4 &pcie_intc1 3>;
> +			pcie_intc1: interrupt-controller {
> +				interrupt-controller;
> +				#address-cells = <0>;
> +				#interrupt-cells = <1>;
> +			};
> +		};
> +	};


--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v2 5/5] dt-bindings: PCI: add support for new generation controller
@ 2017-07-27  3:38     ` Honghui Zhang
  0 siblings, 0 replies; 80+ messages in thread
From: Honghui Zhang @ 2017-07-27  3:38 UTC (permalink / raw)
  To: bhelgaas
  Cc: youlin.pei, devicetree, hongkun.cao, ryder.lee, linux-pci,
	sean.wang, xinping.qian, linux-kernel, robh+dt, yt.shen, robh,
	linux-mediatek, yong.wu, matthias.bgg, yingjoe.chen, eddie.huang,
	linux-arm-kernel

On Thu, 2017-07-27 at 10:58 +0800, honghui.zhang@mediatek.com wrote:
> From: Ryder Lee <ryder.lee@mediatek.com>
> 
> Add support for MediaTek new generation controller and update related
> properities.
> 
> Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> Signed-off-by: Honghui Zhang <honghui.zhang@mediatek.com>
> ---
>  .../devicetree/bindings/pci/mediatek-pcie.txt      | 168 ++++++++++++++++++++-
>  1 file changed, 161 insertions(+), 7 deletions(-)
> 

Sorry for the disturb, I send the wrong patch from my local version for
this patch: 
[PATCH v2 5/5] dt-bindings: PCI: add support for new generation
 controller

And the new right version have been re-send.

thanks.

> diff --git a/Documentation/devicetree/bindings/pci/mediatek-pcie.txt b/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
> index a968f25..179329b 100644
> --- a/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
> +++ b/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
> @@ -3,18 +3,31 @@ MediaTek Gen2 PCIe controller
>  Required properties:
>  - compatible: Should contain one of the following string:
>  	"mediatek,mt2701-pcie"
> +	"mediatek,mt2712-pcie"
> +	"mediatek,mt7622-pcie"
>  	"mediatek,mt7623-pcie"
>  - device_type: Must be "pci"
> -- reg: Base addresses and lengths of the PCIe controller.
> +- reg: Base addresses and lengths of the PICe subsys and root ports.
> +- reg-names: Names of the above areas to use during resource look-up.
>  - #address-cells: Address representation for root ports (must be 3)
>  - #size-cells: Size representation for root ports (must be 2)
>  - clocks: Must contain an entry for each entry in clock-names.
>    See ../clocks/clock-bindings.txt for details.
> -- clock-names: Must include the following entries:
> -  - free_ck :for reference clock of PCIe subsys
> -  - sys_ck0 :for clock of Port0
> -  - sys_ck1 :for clock of Port1
> -  - sys_ck2 :for clock of Port2
> +- clock-names:
> +  Mandatory entries:
> +   - sys_ckN :transaction layer and data link layer clock
> +  Required entries for MT2701/MT7623:
> +   - free_ck :for reference clock of PCIe subsys
> +  Required entries for MT2712/MT7622:
> +   - ahb_ckN :AHB slave interface operating clock for CSR access and RC
> +	      initiated MMIO access
> +  Required entries for MT7622:
> +   - axi_ckN :application layer MMIO channel operating clock
> +   - aux_ckN :pe2_mac_bridge and pe2_mac_core operating clock when
> +	      pcie_mac_ck/pcie_pipe_ck is turned off
> +   - obff_ckN :OBFF functional block operating clock
> +   - pipe_ckN :LTSSM and phy/mac layer operating clock
> +  where N starting from 0 to the maximum number of root ports.
>  - phys: List of PHY specifiers (used by generic PHY framework).
>  - phy-names : Must be "pcie-phy0", "pcie-phy1", "pcie-phyN".. based on the
>    number of PHYs as specified in *phys* property.
> @@ -33,6 +46,10 @@ Required properties for MT7623/MT2701:
>  - reset-names: Must be "pcie-rst0", "pcie-rst1", "pcie-rstN".. based on the
>    number of root ports.
>  
> +Required properties for MT2712/MT7622:
> +-interrupts: A list of interrupt outputs of the controller, must have one
> +	     entry for each PCIe port
> +
>  In addition, the device tree node must have sub-nodes describing each
>  PCIe port interface, having the following mandatory properties:
>  
> @@ -50,7 +67,7 @@ Required properties:
>    property is sufficient.
>  - num-lanes: Number of lanes to use for this port.
>  
> -Examples:
> +Examples for MT7623:
>  
>  	hifsys: syscon@1a000000 {
>  		compatible = "mediatek,mt7623-hifsys",
> @@ -68,6 +85,7 @@ Examples:
>  		      <0 0x1a142000 0 0x1000>, /* Port0 registers */
>  		      <0 0x1a143000 0 0x1000>, /* Port1 registers */
>  		      <0 0x1a144000 0 0x1000>; /* Port2 registers */
> +		reg-names = "subsys", "port0", "port1", "port2";
>  		#address-cells = <3>;
>  		#size-cells = <2>;
>  		#interrupt-cells = <1>;
> @@ -127,3 +145,139 @@ Examples:
>  			num-lanes = <1>;
>  		};
>  	};
> +
> +Examples for MT2712:
> +	pcie: pcie@11700000 {
> +		compatible = "mediatek,generic-pcie-v2";
> +		device_type = "pci";
> +		reg = <0 0x11700000 0 0x1000>,
> +		      <0 0x112ff000 0 0x1000>;
> +		reg-names = "port0", "port1";
> +		#address-cells = <3>;
> +		#size-cells = <2>;
> +		interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>,
> +			     <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
> +		clocks = <&pericfg CLK_PERI_PCIE0>,
> +			 <&pericfg CLK_PERI_PCIE1>,
> +			 <&topckgen CLK_TOP_PE2_MAC_P0_SEL>,
> +			 <&topckgen CLK_TOP_PE2_MAC_P1_SEL>;
> +		clock-names = "sys_ck0", "sys_ck1", "ahb_ck0", "ahb_ck1";
> +		phys = <&pcie0_phy PHY_TYPE_PCIE>, <&pcie1_phy PHY_TYPE_PCIE>;
> +		phy-names = "pcie-phy0", "pcie-phy1";
> +		bus-range = <0x00 0xff>;
> +		ranges = <0x82000000 0 0x20000000  0x0 0x20000000  0 0x10000000>;
> +
> +		pcie0: pcie@0,0 {
> +			device_type = "pci";
> +			reg = <0x0000 0 0 0 0>;
> +			#address-cells = <3>;
> +			#size-cells = <2>;
> +			#interrupt-cells = <1>;
> +			ranges;
> +			num-lanes = <1>;
> +			interrupt-map-mask = <0 0 0 7>;
> +			interrupt-map = <0 0 0 1 &pcie_intc0 0>,
> +					<0 0 0 2 &pcie_intc0 1>,
> +					<0 0 0 3 &pcie_intc0 2>,
> +					<0 0 0 4 &pcie_intc0 3>;
> +			pcie_intc0: interrupt-controller {
> +				interrupt-controller;
> +				#address-cells = <0>;
> +				#interrupt-cells = <1>;
> +			};
> +		};
> +
> +		pcie1: pcie@1,0 {
> +			device_type = "pci";
> +			reg = <0x0800 0 0 0 0>;
> +			#address-cells = <3>;
> +			#size-cells = <2>;
> +			#interrupt-cells = <1>;
> +			ranges;
> +			num-lanes = <1>;
> +			interrupt-map-mask = <0 0 0 7>;
> +			interrupt-map = <0 0 0 1 &pcie_intc1 0>,
> +					<0 0 0 2 &pcie_intc1 1>,
> +					<0 0 0 3 &pcie_intc1 2>,
> +					<0 0 0 4 &pcie_intc1 3>;
> +			pcie_intc1: interrupt-controller {
> +				interrupt-controller;
> +				#address-cells = <0>;
> +				#interrupt-cells = <1>;
> +			};
> +		};
> +	};
> +
> +Examples for MT7622:
> +	pcie: pcie@1a140000 {
> +		compatible = "mediatek,generic-pcie-v2";
> +		device_type = "pci";
> +		reg = <0 0x1a140000 0 0x1000>,
> +		      <0 0x1a143000 0 0x1000>,
> +		      <0 0x1a145000 0 0x1000>;
> +		reg-names = "subsys", "port0", "port1";
> +		#address-cells = <3>;
> +		#size-cells = <2>;
> +		interrupts = <GIC_SPI 228 IRQ_TYPE_LEVEL_LOW>,
> +			     <GIC_SPI 229 IRQ_TYPE_LEVEL_LOW>;
> +		clocks = <&pciesys CLK_PCIE_P0_MAC_EN>,
> +			 <&pciesys CLK_PCIE_P1_MAC_EN>,
> +			 <&pciesys CLK_PCIE_P0_AHB_EN>,
> +			 <&pciesys CLK_PCIE_P1_AHB_EN>,
> +			 <&pciesys CLK_PCIE_P0_AUX_EN>,
> +			 <&pciesys CLK_PCIE_P1_AUX_EN>,
> +			 <&pciesys CLK_PCIE_P0_AXI_EN>,
> +			 <&pciesys CLK_PCIE_P1_AXI_EN>,
> +			 <&pciesys CLK_PCIE_P0_OBFF_EN>,
> +			 <&pciesys CLK_PCIE_P1_OBFF_EN>,
> +			 <&pciesys CLK_PCIE_P0_PIPE_EN>,
> +			 <&pciesys CLK_PCIE_P1_PIPE_EN>;
> +		clock-names = "sys_ck0", "sys_ck1", "ahb_ck0", "ahb_ck1",
> +			      "aux_ck0", "aux_ck1", "axi_ck0", "axi_ck1",
> +			      "obff_ck0", "obff_ck1", "pipe_ck0", "pipe_ck1";
> +		phys = <&pcie0_phy PHY_TYPE_PCIE>, <&pcie1_phy PHY_TYPE_PCIE>;
> +		phy-names = "pcie-phy0", "pcie-phy1";
> +		power-domains = <&scpsys MT7622_POWER_DOMAIN_HIF0>;
> +		bus-range = <0x00 0xff>;
> +		ranges = <0x82000000 0 0x20000000  0x0 0x20000000  0 0x10000000>;
> +
> +		pcie0: pcie@0,0 {
> +			device_type = "pci";
> +			reg = <0x0000 0 0 0 0>;
> +			#address-cells = <3>;
> +			#size-cells = <2>;
> +			#interrupt-cells = <1>;
> +			ranges;
> +			num-lanes = <1>;
> +			interrupt-map-mask = <0 0 0 7>;
> +			interrupt-map = <0 0 0 1 &pcie_intc0 0>,
> +					<0 0 0 2 &pcie_intc0 1>,
> +					<0 0 0 3 &pcie_intc0 2>,
> +					<0 0 0 4 &pcie_intc0 3>;
> +			pcie_intc0: interrupt-controller {
> +				interrupt-controller;
> +				#address-cells = <0>;
> +				#interrupt-cells = <1>;
> +			};
> +		};
> +
> +		pcie1: pcie@1,0 {
> +			device_type = "pci";
> +			reg = <0x0800 0 0 0 0>;
> +			#address-cells = <3>;
> +			#size-cells = <2>;
> +			#interrupt-cells = <1>;
> +			ranges;
> +			num-lanes = <1>;
> +			interrupt-map-mask = <0 0 0 7>;
> +			interrupt-map = <0 0 0 1 &pcie_intc1 0>,
> +					<0 0 0 2 &pcie_intc1 1>,
> +					<0 0 0 3 &pcie_intc1 2>,
> +					<0 0 0 4 &pcie_intc1 3>;
> +			pcie_intc1: interrupt-controller {
> +				interrupt-controller;
> +				#address-cells = <0>;
> +				#interrupt-cells = <1>;
> +			};
> +		};
> +	};



_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 80+ messages in thread

* [PATCH v2 5/5] dt-bindings: PCI: add support for new generation controller
@ 2017-07-27  3:38     ` Honghui Zhang
  0 siblings, 0 replies; 80+ messages in thread
From: Honghui Zhang @ 2017-07-27  3:38 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 2017-07-27 at 10:58 +0800, honghui.zhang at mediatek.com wrote:
> From: Ryder Lee <ryder.lee@mediatek.com>
> 
> Add support for MediaTek new generation controller and update related
> properities.
> 
> Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> Signed-off-by: Honghui Zhang <honghui.zhang@mediatek.com>
> ---
>  .../devicetree/bindings/pci/mediatek-pcie.txt      | 168 ++++++++++++++++++++-
>  1 file changed, 161 insertions(+), 7 deletions(-)
> 

Sorry for the disturb, I send the wrong patch from my local version for
this patch: 
[PATCH v2 5/5] dt-bindings: PCI: add support for new generation
 controller

And the new right version have been re-send.

thanks.

> diff --git a/Documentation/devicetree/bindings/pci/mediatek-pcie.txt b/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
> index a968f25..179329b 100644
> --- a/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
> +++ b/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
> @@ -3,18 +3,31 @@ MediaTek Gen2 PCIe controller
>  Required properties:
>  - compatible: Should contain one of the following string:
>  	"mediatek,mt2701-pcie"
> +	"mediatek,mt2712-pcie"
> +	"mediatek,mt7622-pcie"
>  	"mediatek,mt7623-pcie"
>  - device_type: Must be "pci"
> -- reg: Base addresses and lengths of the PCIe controller.
> +- reg: Base addresses and lengths of the PICe subsys and root ports.
> +- reg-names: Names of the above areas to use during resource look-up.
>  - #address-cells: Address representation for root ports (must be 3)
>  - #size-cells: Size representation for root ports (must be 2)
>  - clocks: Must contain an entry for each entry in clock-names.
>    See ../clocks/clock-bindings.txt for details.
> -- clock-names: Must include the following entries:
> -  - free_ck :for reference clock of PCIe subsys
> -  - sys_ck0 :for clock of Port0
> -  - sys_ck1 :for clock of Port1
> -  - sys_ck2 :for clock of Port2
> +- clock-names:
> +  Mandatory entries:
> +   - sys_ckN :transaction layer and data link layer clock
> +  Required entries for MT2701/MT7623:
> +   - free_ck :for reference clock of PCIe subsys
> +  Required entries for MT2712/MT7622:
> +   - ahb_ckN :AHB slave interface operating clock for CSR access and RC
> +	      initiated MMIO access
> +  Required entries for MT7622:
> +   - axi_ckN :application layer MMIO channel operating clock
> +   - aux_ckN :pe2_mac_bridge and pe2_mac_core operating clock when
> +	      pcie_mac_ck/pcie_pipe_ck is turned off
> +   - obff_ckN :OBFF functional block operating clock
> +   - pipe_ckN :LTSSM and phy/mac layer operating clock
> +  where N starting from 0 to the maximum number of root ports.
>  - phys: List of PHY specifiers (used by generic PHY framework).
>  - phy-names : Must be "pcie-phy0", "pcie-phy1", "pcie-phyN".. based on the
>    number of PHYs as specified in *phys* property.
> @@ -33,6 +46,10 @@ Required properties for MT7623/MT2701:
>  - reset-names: Must be "pcie-rst0", "pcie-rst1", "pcie-rstN".. based on the
>    number of root ports.
>  
> +Required properties for MT2712/MT7622:
> +-interrupts: A list of interrupt outputs of the controller, must have one
> +	     entry for each PCIe port
> +
>  In addition, the device tree node must have sub-nodes describing each
>  PCIe port interface, having the following mandatory properties:
>  
> @@ -50,7 +67,7 @@ Required properties:
>    property is sufficient.
>  - num-lanes: Number of lanes to use for this port.
>  
> -Examples:
> +Examples for MT7623:
>  
>  	hifsys: syscon at 1a000000 {
>  		compatible = "mediatek,mt7623-hifsys",
> @@ -68,6 +85,7 @@ Examples:
>  		      <0 0x1a142000 0 0x1000>, /* Port0 registers */
>  		      <0 0x1a143000 0 0x1000>, /* Port1 registers */
>  		      <0 0x1a144000 0 0x1000>; /* Port2 registers */
> +		reg-names = "subsys", "port0", "port1", "port2";
>  		#address-cells = <3>;
>  		#size-cells = <2>;
>  		#interrupt-cells = <1>;
> @@ -127,3 +145,139 @@ Examples:
>  			num-lanes = <1>;
>  		};
>  	};
> +
> +Examples for MT2712:
> +	pcie: pcie at 11700000 {
> +		compatible = "mediatek,generic-pcie-v2";
> +		device_type = "pci";
> +		reg = <0 0x11700000 0 0x1000>,
> +		      <0 0x112ff000 0 0x1000>;
> +		reg-names = "port0", "port1";
> +		#address-cells = <3>;
> +		#size-cells = <2>;
> +		interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>,
> +			     <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
> +		clocks = <&pericfg CLK_PERI_PCIE0>,
> +			 <&pericfg CLK_PERI_PCIE1>,
> +			 <&topckgen CLK_TOP_PE2_MAC_P0_SEL>,
> +			 <&topckgen CLK_TOP_PE2_MAC_P1_SEL>;
> +		clock-names = "sys_ck0", "sys_ck1", "ahb_ck0", "ahb_ck1";
> +		phys = <&pcie0_phy PHY_TYPE_PCIE>, <&pcie1_phy PHY_TYPE_PCIE>;
> +		phy-names = "pcie-phy0", "pcie-phy1";
> +		bus-range = <0x00 0xff>;
> +		ranges = <0x82000000 0 0x20000000  0x0 0x20000000  0 0x10000000>;
> +
> +		pcie0: pcie at 0,0 {
> +			device_type = "pci";
> +			reg = <0x0000 0 0 0 0>;
> +			#address-cells = <3>;
> +			#size-cells = <2>;
> +			#interrupt-cells = <1>;
> +			ranges;
> +			num-lanes = <1>;
> +			interrupt-map-mask = <0 0 0 7>;
> +			interrupt-map = <0 0 0 1 &pcie_intc0 0>,
> +					<0 0 0 2 &pcie_intc0 1>,
> +					<0 0 0 3 &pcie_intc0 2>,
> +					<0 0 0 4 &pcie_intc0 3>;
> +			pcie_intc0: interrupt-controller {
> +				interrupt-controller;
> +				#address-cells = <0>;
> +				#interrupt-cells = <1>;
> +			};
> +		};
> +
> +		pcie1: pcie at 1,0 {
> +			device_type = "pci";
> +			reg = <0x0800 0 0 0 0>;
> +			#address-cells = <3>;
> +			#size-cells = <2>;
> +			#interrupt-cells = <1>;
> +			ranges;
> +			num-lanes = <1>;
> +			interrupt-map-mask = <0 0 0 7>;
> +			interrupt-map = <0 0 0 1 &pcie_intc1 0>,
> +					<0 0 0 2 &pcie_intc1 1>,
> +					<0 0 0 3 &pcie_intc1 2>,
> +					<0 0 0 4 &pcie_intc1 3>;
> +			pcie_intc1: interrupt-controller {
> +				interrupt-controller;
> +				#address-cells = <0>;
> +				#interrupt-cells = <1>;
> +			};
> +		};
> +	};
> +
> +Examples for MT7622:
> +	pcie: pcie at 1a140000 {
> +		compatible = "mediatek,generic-pcie-v2";
> +		device_type = "pci";
> +		reg = <0 0x1a140000 0 0x1000>,
> +		      <0 0x1a143000 0 0x1000>,
> +		      <0 0x1a145000 0 0x1000>;
> +		reg-names = "subsys", "port0", "port1";
> +		#address-cells = <3>;
> +		#size-cells = <2>;
> +		interrupts = <GIC_SPI 228 IRQ_TYPE_LEVEL_LOW>,
> +			     <GIC_SPI 229 IRQ_TYPE_LEVEL_LOW>;
> +		clocks = <&pciesys CLK_PCIE_P0_MAC_EN>,
> +			 <&pciesys CLK_PCIE_P1_MAC_EN>,
> +			 <&pciesys CLK_PCIE_P0_AHB_EN>,
> +			 <&pciesys CLK_PCIE_P1_AHB_EN>,
> +			 <&pciesys CLK_PCIE_P0_AUX_EN>,
> +			 <&pciesys CLK_PCIE_P1_AUX_EN>,
> +			 <&pciesys CLK_PCIE_P0_AXI_EN>,
> +			 <&pciesys CLK_PCIE_P1_AXI_EN>,
> +			 <&pciesys CLK_PCIE_P0_OBFF_EN>,
> +			 <&pciesys CLK_PCIE_P1_OBFF_EN>,
> +			 <&pciesys CLK_PCIE_P0_PIPE_EN>,
> +			 <&pciesys CLK_PCIE_P1_PIPE_EN>;
> +		clock-names = "sys_ck0", "sys_ck1", "ahb_ck0", "ahb_ck1",
> +			      "aux_ck0", "aux_ck1", "axi_ck0", "axi_ck1",
> +			      "obff_ck0", "obff_ck1", "pipe_ck0", "pipe_ck1";
> +		phys = <&pcie0_phy PHY_TYPE_PCIE>, <&pcie1_phy PHY_TYPE_PCIE>;
> +		phy-names = "pcie-phy0", "pcie-phy1";
> +		power-domains = <&scpsys MT7622_POWER_DOMAIN_HIF0>;
> +		bus-range = <0x00 0xff>;
> +		ranges = <0x82000000 0 0x20000000  0x0 0x20000000  0 0x10000000>;
> +
> +		pcie0: pcie at 0,0 {
> +			device_type = "pci";
> +			reg = <0x0000 0 0 0 0>;
> +			#address-cells = <3>;
> +			#size-cells = <2>;
> +			#interrupt-cells = <1>;
> +			ranges;
> +			num-lanes = <1>;
> +			interrupt-map-mask = <0 0 0 7>;
> +			interrupt-map = <0 0 0 1 &pcie_intc0 0>,
> +					<0 0 0 2 &pcie_intc0 1>,
> +					<0 0 0 3 &pcie_intc0 2>,
> +					<0 0 0 4 &pcie_intc0 3>;
> +			pcie_intc0: interrupt-controller {
> +				interrupt-controller;
> +				#address-cells = <0>;
> +				#interrupt-cells = <1>;
> +			};
> +		};
> +
> +		pcie1: pcie at 1,0 {
> +			device_type = "pci";
> +			reg = <0x0800 0 0 0 0>;
> +			#address-cells = <3>;
> +			#size-cells = <2>;
> +			#interrupt-cells = <1>;
> +			ranges;
> +			num-lanes = <1>;
> +			interrupt-map-mask = <0 0 0 7>;
> +			interrupt-map = <0 0 0 1 &pcie_intc1 0>,
> +					<0 0 0 2 &pcie_intc1 1>,
> +					<0 0 0 3 &pcie_intc1 2>,
> +					<0 0 0 4 &pcie_intc1 3>;
> +			pcie_intc1: interrupt-controller {
> +				interrupt-controller;
> +				#address-cells = <0>;
> +				#interrupt-cells = <1>;
> +			};
> +		};
> +	};

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v2 3/5] dt-bindings: PCI: rename and cleanup MediaTek binding text
  2017-07-27  2:58   ` honghui.zhang
  (?)
@ 2017-08-03 19:10     ` Rob Herring
  -1 siblings, 0 replies; 80+ messages in thread
From: Rob Herring @ 2017-08-03 19:10 UTC (permalink / raw)
  To: honghui.zhang
  Cc: bhelgaas, robh, matthias.bgg, linux-arm-kernel, linux-mediatek,
	linux-pci, linux-kernel, devicetree, yingjoe.chen, eddie.huang,
	ryder.lee, hongkun.cao, youlin.pei, yong.wu, yt.shen, sean.wang,
	xinping.qian

On Thu, Jul 27, 2017 at 10:58:37AM +0800, honghui.zhang@mediatek.com wrote:
> From: Ryder Lee <ryder.lee@mediatek.com>
> 
> In order to accommodate other SoC generations, this patch updates filename
> to make it more generic, regroups specific properties by SoCs, and removes
> redundant descriptions.
> 
> Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> ---
>  ...{mediatek,mt7623-pcie.txt => mediatek-pcie.txt} | 29 +++++++++++-----------
>  1 file changed, 14 insertions(+), 15 deletions(-)
>  rename Documentation/devicetree/bindings/pci/{mediatek,mt7623-pcie.txt => mediatek-pcie.txt} (91%)

Acked-by: Rob Herring <robh@kernel.org>

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v2 3/5] dt-bindings: PCI: rename and cleanup MediaTek binding text
@ 2017-08-03 19:10     ` Rob Herring
  0 siblings, 0 replies; 80+ messages in thread
From: Rob Herring @ 2017-08-03 19:10 UTC (permalink / raw)
  To: honghui.zhang
  Cc: youlin.pei, devicetree, hongkun.cao, ryder.lee, linux-pci,
	sean.wang, xinping.qian, linux-kernel, yt.shen, matthias.bgg,
	robh, linux-mediatek, yong.wu, bhelgaas, yingjoe.chen,
	eddie.huang, linux-arm-kernel

On Thu, Jul 27, 2017 at 10:58:37AM +0800, honghui.zhang@mediatek.com wrote:
> From: Ryder Lee <ryder.lee@mediatek.com>
> 
> In order to accommodate other SoC generations, this patch updates filename
> to make it more generic, regroups specific properties by SoCs, and removes
> redundant descriptions.
> 
> Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> ---
>  ...{mediatek,mt7623-pcie.txt => mediatek-pcie.txt} | 29 +++++++++++-----------
>  1 file changed, 14 insertions(+), 15 deletions(-)
>  rename Documentation/devicetree/bindings/pci/{mediatek,mt7623-pcie.txt => mediatek-pcie.txt} (91%)

Acked-by: Rob Herring <robh@kernel.org>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 80+ messages in thread

* [PATCH v2 3/5] dt-bindings: PCI: rename and cleanup MediaTek binding text
@ 2017-08-03 19:10     ` Rob Herring
  0 siblings, 0 replies; 80+ messages in thread
From: Rob Herring @ 2017-08-03 19:10 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Jul 27, 2017 at 10:58:37AM +0800, honghui.zhang at mediatek.com wrote:
> From: Ryder Lee <ryder.lee@mediatek.com>
> 
> In order to accommodate other SoC generations, this patch updates filename
> to make it more generic, regroups specific properties by SoCs, and removes
> redundant descriptions.
> 
> Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> ---
>  ...{mediatek,mt7623-pcie.txt => mediatek-pcie.txt} | 29 +++++++++++-----------
>  1 file changed, 14 insertions(+), 15 deletions(-)
>  rename Documentation/devicetree/bindings/pci/{mediatek,mt7623-pcie.txt => mediatek-pcie.txt} (91%)

Acked-by: Rob Herring <robh@kernel.org>

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v2 1/5] PCI: mediatek: Add a structure to abstract the controller generations
  2017-07-27  2:58   ` honghui.zhang
  (?)
@ 2017-08-03 22:15     ` Bjorn Helgaas
  -1 siblings, 0 replies; 80+ messages in thread
From: Bjorn Helgaas @ 2017-08-03 22:15 UTC (permalink / raw)
  To: honghui.zhang
  Cc: bhelgaas, robh, robh+dt, matthias.bgg, linux-arm-kernel,
	linux-mediatek, linux-pci, linux-kernel, devicetree,
	yingjoe.chen, eddie.huang, ryder.lee, hongkun.cao, youlin.pei,
	yong.wu, yt.shen, sean.wang, xinping.qian

On Thu, Jul 27, 2017 at 10:58:35AM +0800, honghui.zhang@mediatek.com wrote:
> From: Ryder Lee <ryder.lee@mediatek.com>
> 
> Introduce a structure "mtk_pcie_soc" to abstract the differences between
> controller generations, and the .startup() hook is used to encapsulate
> some SoC-dependent related setting. In doing so, the common code which
> will be reused by future chips.
> 
> In addition, we change the approaches to waiting Gen2 training by using
> readl_poll_timeout() calls.

Please split the Gen2 training change to a separate patch, since
that's not related to the mtk_pcie_soc changes.

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v2 1/5] PCI: mediatek: Add a structure to abstract the controller generations
@ 2017-08-03 22:15     ` Bjorn Helgaas
  0 siblings, 0 replies; 80+ messages in thread
From: Bjorn Helgaas @ 2017-08-03 22:15 UTC (permalink / raw)
  To: honghui.zhang
  Cc: youlin.pei, devicetree, hongkun.cao, ryder.lee, linux-pci,
	sean.wang, xinping.qian, linux-kernel, robh+dt, yt.shen,
	matthias.bgg, robh, linux-mediatek, yong.wu, bhelgaas,
	yingjoe.chen, eddie.huang, linux-arm-kernel

On Thu, Jul 27, 2017 at 10:58:35AM +0800, honghui.zhang@mediatek.com wrote:
> From: Ryder Lee <ryder.lee@mediatek.com>
> 
> Introduce a structure "mtk_pcie_soc" to abstract the differences between
> controller generations, and the .startup() hook is used to encapsulate
> some SoC-dependent related setting. In doing so, the common code which
> will be reused by future chips.
> 
> In addition, we change the approaches to waiting Gen2 training by using
> readl_poll_timeout() calls.

Please split the Gen2 training change to a separate patch, since
that's not related to the mtk_pcie_soc changes.

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 80+ messages in thread

* [PATCH v2 1/5] PCI: mediatek: Add a structure to abstract the controller generations
@ 2017-08-03 22:15     ` Bjorn Helgaas
  0 siblings, 0 replies; 80+ messages in thread
From: Bjorn Helgaas @ 2017-08-03 22:15 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Jul 27, 2017 at 10:58:35AM +0800, honghui.zhang at mediatek.com wrote:
> From: Ryder Lee <ryder.lee@mediatek.com>
> 
> Introduce a structure "mtk_pcie_soc" to abstract the differences between
> controller generations, and the .startup() hook is used to encapsulate
> some SoC-dependent related setting. In doing so, the common code which
> will be reused by future chips.
> 
> In addition, we change the approaches to waiting Gen2 training by using
> readl_poll_timeout() calls.

Please split the Gen2 training change to a separate patch, since
that's not related to the mtk_pcie_soc changes.

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v2 3/5] dt-bindings: PCI: rename and cleanup MediaTek binding text
  2017-07-27  2:58   ` honghui.zhang
  (?)
@ 2017-08-03 22:17     ` Bjorn Helgaas
  -1 siblings, 0 replies; 80+ messages in thread
From: Bjorn Helgaas @ 2017-08-03 22:17 UTC (permalink / raw)
  To: honghui.zhang
  Cc: bhelgaas, robh, robh+dt, matthias.bgg, linux-arm-kernel,
	linux-mediatek, linux-pci, linux-kernel, devicetree,
	yingjoe.chen, eddie.huang, ryder.lee, youlin.pei, hongkun.cao,
	sean.wang, xinping.qian, yt.shen, yong.wu

On Thu, Jul 27, 2017 at 10:58:37AM +0800, honghui.zhang@mediatek.com wrote:
> From: Ryder Lee <ryder.lee@mediatek.com>
> 
> In order to accommodate other SoC generations, this patch updates filename
> to make it more generic, regroups specific properties by SoCs, and removes
> redundant descriptions.
> 
> Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> ---
>  ...{mediatek,mt7623-pcie.txt => mediatek-pcie.txt} | 29 +++++++++++-----------
>  1 file changed, 14 insertions(+), 15 deletions(-)
>  rename Documentation/devicetree/bindings/pci/{mediatek,mt7623-pcie.txt => mediatek-pcie.txt} (91%)
> 
> diff --git a/Documentation/devicetree/bindings/pci/mediatek,mt7623-pcie.txt b/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
> similarity index 91%
> rename from Documentation/devicetree/bindings/pci/mediatek,mt7623-pcie.txt
> rename to Documentation/devicetree/bindings/pci/mediatek-pcie.txt
> index fe80dda..a968f25 100644
> --- a/Documentation/devicetree/bindings/pci/mediatek,mt7623-pcie.txt
> +++ b/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
> @@ -1,18 +1,13 @@
> -MediaTek Gen2 PCIe controller which is available on MT7623 series SoCs
> -
> -PCIe subsys supports single root complex (RC) with 3 Root Ports. Each root
> -ports supports a Gen2 1-lane Link and has PIPE interface to PHY.
> +MediaTek Gen2 PCIe controller
>  
>  Required properties:
> -- compatible: Should contain "mediatek,mt7623-pcie".
> +- compatible: Should contain one of the following string:

s/string/strings/

> +	"mediatek,mt2701-pcie"
> +	"mediatek,mt7623-pcie"

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v2 3/5] dt-bindings: PCI: rename and cleanup MediaTek binding text
@ 2017-08-03 22:17     ` Bjorn Helgaas
  0 siblings, 0 replies; 80+ messages in thread
From: Bjorn Helgaas @ 2017-08-03 22:17 UTC (permalink / raw)
  To: honghui.zhang
  Cc: youlin.pei, devicetree, hongkun.cao, ryder.lee, linux-pci,
	sean.wang, yong.wu, linux-kernel, robh+dt, yt.shen, matthias.bgg,
	robh, linux-mediatek, xinping.qian, bhelgaas, yingjoe.chen,
	eddie.huang, linux-arm-kernel

On Thu, Jul 27, 2017 at 10:58:37AM +0800, honghui.zhang@mediatek.com wrote:
> From: Ryder Lee <ryder.lee@mediatek.com>
> 
> In order to accommodate other SoC generations, this patch updates filename
> to make it more generic, regroups specific properties by SoCs, and removes
> redundant descriptions.
> 
> Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> ---
>  ...{mediatek,mt7623-pcie.txt => mediatek-pcie.txt} | 29 +++++++++++-----------
>  1 file changed, 14 insertions(+), 15 deletions(-)
>  rename Documentation/devicetree/bindings/pci/{mediatek,mt7623-pcie.txt => mediatek-pcie.txt} (91%)
> 
> diff --git a/Documentation/devicetree/bindings/pci/mediatek,mt7623-pcie.txt b/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
> similarity index 91%
> rename from Documentation/devicetree/bindings/pci/mediatek,mt7623-pcie.txt
> rename to Documentation/devicetree/bindings/pci/mediatek-pcie.txt
> index fe80dda..a968f25 100644
> --- a/Documentation/devicetree/bindings/pci/mediatek,mt7623-pcie.txt
> +++ b/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
> @@ -1,18 +1,13 @@
> -MediaTek Gen2 PCIe controller which is available on MT7623 series SoCs
> -
> -PCIe subsys supports single root complex (RC) with 3 Root Ports. Each root
> -ports supports a Gen2 1-lane Link and has PIPE interface to PHY.
> +MediaTek Gen2 PCIe controller
>  
>  Required properties:
> -- compatible: Should contain "mediatek,mt7623-pcie".
> +- compatible: Should contain one of the following string:

s/string/strings/

> +	"mediatek,mt2701-pcie"
> +	"mediatek,mt7623-pcie"

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 80+ messages in thread

* [PATCH v2 3/5] dt-bindings: PCI: rename and cleanup MediaTek binding text
@ 2017-08-03 22:17     ` Bjorn Helgaas
  0 siblings, 0 replies; 80+ messages in thread
From: Bjorn Helgaas @ 2017-08-03 22:17 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Jul 27, 2017 at 10:58:37AM +0800, honghui.zhang at mediatek.com wrote:
> From: Ryder Lee <ryder.lee@mediatek.com>
> 
> In order to accommodate other SoC generations, this patch updates filename
> to make it more generic, regroups specific properties by SoCs, and removes
> redundant descriptions.
> 
> Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> ---
>  ...{mediatek,mt7623-pcie.txt => mediatek-pcie.txt} | 29 +++++++++++-----------
>  1 file changed, 14 insertions(+), 15 deletions(-)
>  rename Documentation/devicetree/bindings/pci/{mediatek,mt7623-pcie.txt => mediatek-pcie.txt} (91%)
> 
> diff --git a/Documentation/devicetree/bindings/pci/mediatek,mt7623-pcie.txt b/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
> similarity index 91%
> rename from Documentation/devicetree/bindings/pci/mediatek,mt7623-pcie.txt
> rename to Documentation/devicetree/bindings/pci/mediatek-pcie.txt
> index fe80dda..a968f25 100644
> --- a/Documentation/devicetree/bindings/pci/mediatek,mt7623-pcie.txt
> +++ b/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
> @@ -1,18 +1,13 @@
> -MediaTek Gen2 PCIe controller which is available on MT7623 series SoCs
> -
> -PCIe subsys supports single root complex (RC) with 3 Root Ports. Each root
> -ports supports a Gen2 1-lane Link and has PIPE interface to PHY.
> +MediaTek Gen2 PCIe controller
>  
>  Required properties:
> -- compatible: Should contain "mediatek,mt7623-pcie".
> +- compatible: Should contain one of the following string:

s/string/strings/

> +	"mediatek,mt2701-pcie"
> +	"mediatek,mt7623-pcie"

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v2 4/5] PCI: mediatek: Add new generation controller support
  2017-07-27  2:58   ` honghui.zhang
  (?)
@ 2017-08-03 22:42     ` Bjorn Helgaas
  -1 siblings, 0 replies; 80+ messages in thread
From: Bjorn Helgaas @ 2017-08-03 22:42 UTC (permalink / raw)
  To: honghui.zhang
  Cc: bhelgaas, robh, robh+dt, matthias.bgg, linux-arm-kernel,
	linux-mediatek, linux-pci, linux-kernel, devicetree,
	yingjoe.chen, eddie.huang, ryder.lee, hongkun.cao, youlin.pei,
	yong.wu, yt.shen, sean.wang, xinping.qian

On Thu, Jul 27, 2017 at 10:58:38AM +0800, honghui.zhang@mediatek.com wrote:
> From: Ryder Lee <ryder.lee@mediatek.com>
> 
> Add support for new Gen2 controller which has two root ports and shares
> the probing flow with legacy controller. Currently this IP block can be
> found on MT7622/MT2712.
> 
> Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> Signed-off-by: Honghui Zhang <honghui.zhang@mediatek.com>
> ---
>  drivers/pci/host/Kconfig         |   5 +-
>  drivers/pci/host/pcie-mediatek.c | 490 ++++++++++++++++++++++++++++++++++++++-
>  2 files changed, 489 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
> index 89d61c2..5b1ae9f 100644
> --- a/drivers/pci/host/Kconfig
> +++ b/drivers/pci/host/Kconfig
> @@ -182,14 +182,13 @@ config PCIE_ROCKCHIP
>  
>  config PCIE_MEDIATEK
>  	bool "MediaTek PCIe controller"
> -	depends on ARM && (ARCH_MEDIATEK || COMPILE_TEST)
> +	depends on (ARM || ARM64) && (ARCH_MEDIATEK || COMPILE_TEST)
>  	depends on OF
>  	depends on PCI
>  	select PCIEPORTBUS
>  	help
>  	  Say Y here if you want to enable PCIe controller support on
> -	  MT7623 series SoCs.  There is one single root complex with 3 root
> -	  ports available.  Each port supports Gen2 lane x1.
> +	  MediaTek SoCs.
>  
>  config PCIE_TANGO_SMP8759
>  	bool "Tango SMP8759 PCIe controller (DANGEROUS)"
> diff --git a/drivers/pci/host/pcie-mediatek.c b/drivers/pci/host/pcie-mediatek.c
> index f8e2f68..5fe92ff 100644
> --- a/drivers/pci/host/pcie-mediatek.c
> +++ b/drivers/pci/host/pcie-mediatek.c
> @@ -3,6 +3,7 @@
>   *
>   * Copyright (c) 2017 MediaTek Inc.
>   * Author: Ryder Lee <ryder.lee@mediatek.com>
> + *	   Honghui Zhang <honghui.zhang@mediatek.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
> @@ -17,6 +18,8 @@
>  #include <linux/clk.h>
>  #include <linux/delay.h>
>  #include <linux/iopoll.h>
> +#include <linux/irq.h>
> +#include <linux/irqdomain.h>
>  #include <linux/kernel.h>
>  #include <linux/of_address.h>
>  #include <linux/of_pci.h>
> @@ -64,16 +67,77 @@
>  #define PCIE_FC_CREDIT_MASK	(GENMASK(31, 31) | GENMASK(28, 16))
>  #define PCIE_FC_CREDIT_VAL(x)	((x) << 16)
>  
> +/* PCIe V2 share registers */
> +#define PCIE_SYS_CFG_V2		0x0
> +#define PCIE_CSR_LTSSM_EN(x)	BIT(0 + (x) * 8)
> +#define PCIE_CSR_ASPM_L1_EN(x)	BIT(1 + (x) * 8)
> +
> +/* PCIe V2 per-port registers */
> +#define PCIE_INT_MASK		0x420
> +#define INTX_MASK		GENMASK(19, 16)
> +#define INTX_SHIFT		16
> +#define INTX_NUM		4
> +#define PCIE_INT_STATUS		0x424
> +
> +#define PCIE_AHB_TRANS_BASE0_L	0x438
> +#define PCIE_AHB_TRANS_BASE0_H	0x43c
> +#define AHB2PCIE_BASEL(x)	((x) & GENMASK(31, 0))
> +#define AHB2PCIE_BASEH(x)	(((u64)(x) >> 32) & GENMASK(31, 0))
> +#define AHB2PCIE_SIZE(x)	((x) & GENMASK(4, 0))
> +#define PCIE_AXI_WINDOW0	0x448
> +#define WIN_ENABLE		BIT(7)
> +
> +/* PCIe V2 Configuration Transaction Header */
> +#define PCIE_CFG_HEADER0	0x460
> +#define PCIE_CFG_HEADER1	0x464
> +#define PCIE_CFG_HEADER2	0x468
> +#define PCIE_CFG_WDATA		0x470
> +#define PCIE_APP_TLP_REQ	0x488
> +#define PCIE_CFG_RDATA		0x48c
> +#define APP_CFG_REQ		BIT(0)
> +#define APP_CPL_STATUS		GENMASK(7, 5)
> +
> +#define CFG_WRRD_TYPE_0		4
> +#define CFG_WR_FMT		2
> +#define CFG_RD_FMT		0
> +
> +#define CFG_DW0_LENGTH(length)	((length) & GENMASK(9, 0))
> +#define CFG_DW0_TYPE(type)	(((type) << 24) & GENMASK(28, 24))
> +#define CFG_DW0_FMT(fmt)	(((fmt) << 29) & GENMASK(31, 29))
> +#define CFG_DW2_REGN(regn)	((regn) & GENMASK(11, 2))
> +#define CFG_DW2_FUN(fun)	(((fun) << 16) & GENMASK(18, 16))
> +#define CFG_DW2_DEV(dev)	(((dev) << 19) & GENMASK(23, 19))
> +#define CFG_DW2_BUS(bus)	(((bus) << 24) & GENMASK(31, 24))
> +#define CFG_HEADER_DW0(type, fmt) \
> +	(CFG_DW0_LENGTH(1) | CFG_DW0_TYPE(type) | CFG_DW0_FMT(fmt))
> +#define CFG_HEADER_DW1(where, size) \
> +	(GENMASK(((size) - 1), 0) << ((where) & 0x3))
> +#define CFG_HEADER_DW2(regn, fun, dev, bus) \
> +	(CFG_DW2_REGN(regn) | CFG_DW2_FUN(fun) | \
> +	CFG_DW2_DEV(dev) | CFG_DW2_BUS(bus))
> +
> +#define PCIE_RST_CTRL		0x510
> +#define PCIE_PHY_RSTB		BIT(0)
> +#define PCIE_PIPE_SRSTB		BIT(1)
> +#define PCIE_MAC_SRSTB		BIT(2)
> +#define PCIE_CRSTB		BIT(3)
> +#define PCIE_PERSTB		BIT(8)
> +#define PCI_LINKDOWN_RST_EN	GENMASK(15, 13)
> +#define PCIE_LINK_STATUS_V2	0x804
> +#define PCIE_PORT_LINKUP_V2	BIT(10)
> +
>  struct mtk_pcie_port;
>  
>  /**
>   * struct mtk_pcie_soc - differentiate between host generations
>   * @ops: pointer to configuration access functions
>   * @startup: pointer to controller setting functions
> + * @setup_irq: pointer to initialize irq functions

s/ irq / IRQ /

>   */
>  struct mtk_pcie_soc {
>  	struct pci_ops *ops;
>  	int (*startup)(struct mtk_pcie_port *port);
> +	int (*setup_irq)(struct mtk_pcie_port *port, struct device_node *node);
>  };
>  
>  /**
> @@ -82,10 +146,18 @@ struct mtk_pcie_soc {
>   * @list: port list
>   * @pcie: pointer to PCIe host info
>   * @reset: pointer to port reset control
> - * @sys_ck: pointer to bus clock
> + * @sys_ck: pointer to transaction/data link layer clock
> + * @ahb_ck: pinter to AHB slave interface operating clock for CSR access

s/pinter/pointer/

> + *          and RC initiated MMIO access
> + * @axi_ck: pointer to application layer MMIO channel operating clock
> + * @aux_ck: pointer to pe2_mac_bridge and pe2_mac_core operating clock
> + *          when pcie_mac_ck/pcie_pipe_ck is turned off
> + * @obff_ck: pointer to OBFF functional block operating clock
> + * @pipe_ck: pointer to LTSSM and phy/mac layer operating clock

s/phy/PHY/
s/mac/MAC/

>   * @phy: pointer to phy control block

s/ phy / PHY /

>   * @lane: lane count
>   * @index: port index
> + * @irq_domain: legacy intx irq domain

s/intx irq/INTx IRQ/

>   */
>  struct mtk_pcie_port {
>  	void __iomem *base;
> @@ -93,9 +165,15 @@ struct mtk_pcie_port {
>  	struct mtk_pcie *pcie;
>  	struct reset_control *reset;
>  	struct clk *sys_ck;
> +	struct clk *ahb_ck;
> +	struct clk *axi_ck;
> +	struct clk *aux_ck;
> +	struct clk *obff_ck;
> +	struct clk *pipe_ck;
>  	struct phy *phy;
>  	u32 lane;
>  	u32 index;
> +	struct irq_domain *irq_domain;
>  };
>  
>  /**
> @@ -156,6 +234,12 @@ static void mtk_pcie_put_resources(struct mtk_pcie *pcie)
>  
>  	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
>  		phy_power_off(port->phy);
> +		phy_exit(port->phy);
> +		clk_disable_unprepare(port->pipe_ck);
> +		clk_disable_unprepare(port->obff_ck);
> +		clk_disable_unprepare(port->axi_ck);
> +		clk_disable_unprepare(port->aux_ck);
> +		clk_disable_unprepare(port->ahb_ck);
>  		clk_disable_unprepare(port->sys_ck);
>  		mtk_pcie_port_free(port);
>  	}
> @@ -163,6 +247,298 @@ static void mtk_pcie_put_resources(struct mtk_pcie *pcie)
>  	mtk_pcie_subsys_powerdown(pcie);
>  }
>  
> +static int mtk_pcie_check_cfg_cpld(struct mtk_pcie_port *port)
> +{
> +	u32 val;
> +	int err;
> +
> +	err = readl_poll_timeout_atomic(port->base + PCIE_APP_TLP_REQ, val,
> +					!(val & APP_CFG_REQ), 10,
> +					100 * USEC_PER_MSEC);
> +	if (err)
> +		return PCIBIOS_SET_FAILED;
> +
> +	if (readl(port->base + PCIE_APP_TLP_REQ) & APP_CPL_STATUS)
> +		return PCIBIOS_SET_FAILED;
> +
> +	return PCIBIOS_SUCCESSFUL;
> +}
> +
> +static int mtk_pcie_hw_rd_cfg(struct mtk_pcie_port *port, u32 bus, u32 devfn,
> +			      int where, int size, u32 *val)
> +{
> +	int reg, shift = 8 * (where & 3);
> +
> +	/* Write PCIe Configuration Transaction Header for cfgrd */
> +	writel(CFG_HEADER_DW0(CFG_WRRD_TYPE_0, CFG_RD_FMT),
> +	       port->base + PCIE_CFG_HEADER0);
> +	writel(CFG_HEADER_DW1(where, size), port->base + PCIE_CFG_HEADER1);
> +	writel(CFG_HEADER_DW2(where, PCI_FUNC(devfn), PCI_SLOT(devfn), bus),
> +	       port->base + PCIE_CFG_HEADER2);
> +
> +	/* Triget h/w to transmit Cfgrd TLP */

s/Triget/Trigger/

> +	reg = readl(port->base + PCIE_APP_TLP_REQ);
> +	writel(reg | APP_CFG_REQ, port->base + PCIE_APP_TLP_REQ);
> +
> +	/* Check complete condition */

s/complete condition/completion status/ ?

> +	if (mtk_pcie_check_cfg_cpld(port))
> +		return PCIBIOS_SET_FAILED;
> +
> +	/* Read cpld payload of Cfgrd */
> +	*val = readl(port->base + PCIE_CFG_RDATA);
> +
> +	switch (size) {
> +	case 4:
> +		break;
> +	case 3:
> +		*val = (*val >> shift) & 0xffffff;
> +		break;
> +	case 2:
> +		*val = (*val >> shift) & 0xffff;
> +		break;
> +	case 1:
> +		*val = (*val >> shift) & 0xff;
> +		break;
> +	default:
> +		return PCIBIOS_BAD_REGISTER_NUMBER;
> +	}
> +
> +	return PCIBIOS_SUCCESSFUL;
> +}
> +
> +static int mtk_pcie_hw_wr_cfg(struct mtk_pcie_port *port, u32 bus, u32 devfn,
> +			      int where, int size, u32 val)
> +{
> +	/* Write PCIe Configuration Transaction Header for Cfgwr */
> +	writel(CFG_HEADER_DW0(CFG_WRRD_TYPE_0, CFG_WR_FMT),
> +	       port->base + PCIE_CFG_HEADER0);
> +	writel(CFG_HEADER_DW1(where, size), port->base + PCIE_CFG_HEADER1);
> +	writel(CFG_HEADER_DW2(where, PCI_FUNC(devfn), PCI_SLOT(devfn), bus),
> +	       port->base + PCIE_CFG_HEADER2);
> +
> +	/* Write cfgwr data */
> +	val = val << 8 * (where & 3);
> +	writel(val, port->base + PCIE_CFG_WDATA);
> +
> +	/* Triget h/w to transmit Cfgwr TLP */

s/Triget/Trigger/

> +	val = readl(port->base + PCIE_APP_TLP_REQ);
> +	val |= APP_CFG_REQ;
> +	writel(val, port->base + PCIE_APP_TLP_REQ);
> +
> +	/* Check complete condition */

s/complete condition/completion status/ ?

> +	return mtk_pcie_check_cfg_cpld(port);
> +}
> +
> +static struct mtk_pcie_port *mtk_pcie_find_port(struct mtk_pcie *pcie,
> +						struct pci_bus *bus, int devfn)
> +{
> +	struct pci_dev *dev;
> +	struct pci_bus *pbus;
> +	struct mtk_pcie_port *port, *tmp;
> +
> +	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
> +		if (bus->number == 0 && port->index == PCI_SLOT(devfn)) {
> +			return port;
> +		} else if (bus->number != 0) {
> +			pbus = bus;
> +			do {
> +				dev = pbus->self;
> +				if (port->index == PCI_SLOT(dev->devfn))
> +					return port;
> +				pbus = dev->bus;
> +			} while (dev->bus->number != 0);
> +		}
> +	}
> +
> +	return NULL;

You should be able to use sysdata to avoid searching the list.
See drivers/pci/host/pci-aardvark.c, for example.

> +}
> +
> +static int mtk_pcie_config_read(struct pci_bus *bus, unsigned int devfn,
> +				int where, int size, u32 *val)
> +{
> +	struct mtk_pcie_port *port;
> +	struct pci_host_bridge *host = pci_find_host_bridge(bus);
> +	struct mtk_pcie *pcie = pci_host_bridge_priv(host);

Sysdata should make this very simple; see advk_pcie_rd_conf().

> +	u32 bn = bus->number;
> +	int ret;
> +
> +	port = mtk_pcie_find_port(pcie, bus, devfn);
> +	if (!port) {
> +		*val = ~0;
> +		return PCIBIOS_DEVICE_NOT_FOUND;
> +	}
> +
> +	ret = mtk_pcie_hw_rd_cfg(port, bn, devfn, where, size, val);
> +	if (ret)
> +		*val = ~0;
> +
> +	return ret;
> +}
> +
> +static int mtk_pcie_config_write(struct pci_bus *bus, unsigned int devfn,
> +				 int where, int size, u32 val)
> +{
> +	u32 bn = bus->number;
> +	struct pci_host_bridge *host = pci_find_host_bridge(bus);
> +	struct mtk_pcie *pcie = pci_host_bridge_priv(host);
> +	struct mtk_pcie_port *port;
> +
> +	port = mtk_pcie_find_port(pcie, bus, devfn);
> +	if (!port)
> +		return PCIBIOS_DEVICE_NOT_FOUND;
> +
> +	return mtk_pcie_hw_wr_cfg(port, bn, devfn, where, size, val);
> +}
> +
> +static struct pci_ops mtk_pcie_ops_v2 = {
> +	.read  = mtk_pcie_config_read,
> +	.write = mtk_pcie_config_write,
> +};
> +
> +static int mtk_pcie_startup_ports_v2(struct mtk_pcie_port *port)
> +{
> +	struct mtk_pcie *pcie = port->pcie;
> +	struct resource *mem = &pcie->mem;
> +	u32 val;
> +	size_t size;
> +	int err;
> +
> +	/* mt7622 platforms need to enable LTSSM and ASPM from PCIe subsys */
> +	if (pcie->base) {
> +		val = readl(pcie->base + PCIE_SYS_CFG_V2);
> +		val |= PCIE_CSR_LTSSM_EN(port->index) |
> +		       PCIE_CSR_ASPM_L1_EN(port->index);
> +		writel(val, pcie->base + PCIE_SYS_CFG_V2);
> +	}
> +
> +	/* Assert all reset signals */
> +	writel(0, port->base + PCIE_RST_CTRL);
> +
> +	/*
> +	 * Enable rc internal reset.
> +	 * The reset will work when the link is from link up to link down.

?  That sentence doesn't parse for me.

> +	 */
> +	writel(PCI_LINKDOWN_RST_EN, port->base + PCIE_RST_CTRL);
> +
> +	/* De-assert phy, pe, pipe, mac and configuration reset	*/
> +	val = readl(port->base + PCIE_RST_CTRL);
> +	val |= PCIE_PHY_RSTB | PCIE_PERSTB | PCIE_PIPE_SRSTB |
> +	       PCIE_MAC_SRSTB | PCIE_CRSTB;
> +	writel(val, port->base + PCIE_RST_CTRL);
> +
> +	/* PCIe v2.0 need at least 100ms delay to train from Gen1 to Gen2 */
> +	err = readl_poll_timeout(port->base + PCIE_LINK_STATUS_V2, val,
> +				 !!(val & PCIE_PORT_LINKUP_V2), 20,
> +				 100 * USEC_PER_MSEC);
> +	if (err)
> +		return -ETIMEDOUT;
> +
> +	/* Set INTx mask */
> +	val = readl(port->base + PCIE_INT_MASK);
> +	val &= ~INTX_MASK;
> +	writel(val, port->base + PCIE_INT_MASK);
> +
> +	/* Set AHB to PCIe translation windows */
> +	size = mem->end - mem->start;
> +	val = AHB2PCIE_BASEL(mem->start) | AHB2PCIE_SIZE(fls(size));
> +	writel(val, port->base + PCIE_AHB_TRANS_BASE0_L);
> +
> +	val = AHB2PCIE_BASEH(mem->start);
> +	writel(val, port->base + PCIE_AHB_TRANS_BASE0_H);
> +
> +	/* Set PCIe to axi translation memory space.*/

s/axi/AXI/

> +	val = fls(0xffffffff) | WIN_ENABLE;
> +	writel(val, port->base + PCIE_AXI_WINDOW0);
> +
> +	return 0;
> +}
> +
> +static int mtk_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
> +			     irq_hw_number_t hwirq)
> +{
> +	irq_set_chip_and_handler(irq, &dummy_irq_chip, handle_simple_irq);
> +	irq_set_chip_data(irq, domain->host_data);
> +
> +	return 0;
> +}
> +
> +static const struct irq_domain_ops intx_domain_ops = {
> +	.map = mtk_pcie_intx_map,
> +};
> +
> +static int mtk_pcie_init_irq_domain(struct mtk_pcie_port *port,
> +				    struct device_node *node)
> +{
> +	struct device *dev = port->pcie->dev;
> +	struct device_node *pcie_intc_node;
> +
> +	/* Setup INTx */
> +	pcie_intc_node = of_get_next_child(node, NULL);
> +	if (!pcie_intc_node) {
> +		dev_err(dev, "No PCIe Intc node found\n");
> +		return PTR_ERR(pcie_intc_node);
> +	}
> +
> +	port->irq_domain = irq_domain_add_linear(pcie_intc_node, INTX_NUM,
> +						 &intx_domain_ops, port);

I think there's an issue here with a 4-element IRQ domain and the
hwirq numbers 1-4 from the of_irq_parse_and_map_pci() path, so INTD
may not work correctly.

See
http://lkml.kernel.org/r/20170801212931.GA26498@bhelgaas-glaptop.roam.corp.google.com
and related discussion.

> +	if (!port->irq_domain) {
> +		dev_err(dev, "Failed to get INTx IRQ domain\n");
> +		return PTR_ERR(port->irq_domain);
> +	}
> +
> +	return 0;
> +}
> +
> +static irqreturn_t mtk_pcie_intr_handler(int irq, void *data)
> +{
> +	struct mtk_pcie_port *port = (struct mtk_pcie_port *)data;
> +	struct device *dev = port->pcie->dev;
> +	unsigned long status;
> +	u32 virq;
> +	u32 bit = INTX_SHIFT;
> +
> +	while ((status = readl(port->base + PCIE_INT_STATUS)) & INTX_MASK) {
> +		for_each_set_bit_from(bit, &status, INTX_NUM + INTX_SHIFT) {
> +			/* Clear the INTx */
> +			writel(1 << bit, port->base + PCIE_INT_STATUS);
> +			virq = irq_find_mapping(port->irq_domain,
> +						bit - INTX_SHIFT);
> +			if (virq)
> +				generic_handle_irq(virq);
> +			else
> +				dev_err(dev, "unexpected IRQ, INT%d\n",
> +					bit - INTX_SHIFT);

PCI INTx are conventionally INTA, INTB, INTC, INTD (not INT1, INT2,
etc).

> +		}
> +	}
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static int mtk_pcie_setup_irq(struct mtk_pcie_port *port,
> +			      struct device_node *node)
> +{
> +	struct mtk_pcie *pcie = port->pcie;
> +	struct device *dev = pcie->dev;
> +	struct platform_device *pdev = to_platform_device(dev);
> +	int err, irq;
> +
> +	irq = platform_get_irq(pdev, port->index);
> +	err = devm_request_irq(dev, irq, mtk_pcie_intr_handler,
> +			       IRQF_SHARED, "mtk-pcie", port);
> +	if (err) {
> +		dev_err(dev, "unable to request irq %d\n", irq);

s/irq/IRQ/

> +		return err;
> +	}
> +
> +	err = mtk_pcie_init_irq_domain(port, node);
> +	if (err) {
> +		dev_err(dev, "failed to init pcie lagecy irq domain\n");

s/lagecy/legacy/
s/irq/IRQ/
s/pcie/PCIe/

> +		return -ENODEV;
> +	}
> +
> +	return 0;
> +}
> +
>  static void __iomem *mtk_pcie_map_bus(struct pci_bus *bus,
>  				      unsigned int devfn, int where)
>  {
> @@ -249,13 +625,49 @@ static void mtk_pcie_enable_ports(struct mtk_pcie_port *port)
>  
>  	err = clk_prepare_enable(port->sys_ck);
>  	if (err) {
> -		dev_err(dev, "failed to enable port%d clock\n", port->index);
> +		dev_err(dev, "failed to enable sys_ck%d\n", port->index);
>  		goto err_sys_clk;
>  	}
>  
> +	err = clk_prepare_enable(port->ahb_ck);
> +	if (err) {
> +		dev_err(dev, "failed to enable ahb_ck%d\n", port->index);
> +		goto err_ahb_clk;
> +	}
> +
> +	err = clk_prepare_enable(port->aux_ck);
> +	if (err) {
> +		dev_err(dev, "failed to enable aux_ck%d\n", port->index);
> +		goto err_aux_clk;
> +	}
> +
> +	err = clk_prepare_enable(port->axi_ck);
> +	if (err) {
> +		dev_err(dev, "failed to enable axi_ck%d\n", port->index);
> +		goto err_axi_clk;
> +	}
> +
> +	err = clk_prepare_enable(port->obff_ck);
> +	if (err) {
> +		dev_err(dev, "failed to enable obff_ck%d\n", port->index);
> +		goto err_obff_clk;
> +	}
> +
> +	err = clk_prepare_enable(port->pipe_ck);
> +	if (err) {
> +		dev_err(dev, "failed to enable pipe_ck%d\n", port->index);
> +		goto err_pipe_clk;
> +	}
> +
>  	reset_control_assert(port->reset);
>  	reset_control_deassert(port->reset);
>  
> +	err = phy_init(port->phy);
> +	if (err) {
> +		dev_err(dev, "failed to initialize port%d phy\n", port->index);
> +		goto err_phy_init;
> +	}
> +
>  	err = phy_power_on(port->phy);
>  	if (err) {
>  		dev_err(dev, "failed to power on port%d phy\n", port->index);
> @@ -269,6 +681,18 @@ static void mtk_pcie_enable_ports(struct mtk_pcie_port *port)
>  
>  	phy_power_off(port->phy);
>  err_phy_on:
> +	phy_exit(port->phy);
> +err_phy_init:
> +	clk_disable_unprepare(port->pipe_ck);
> +err_pipe_clk:
> +	clk_disable_unprepare(port->obff_ck);
> +err_obff_clk:
> +	clk_disable_unprepare(port->axi_ck);
> +err_axi_clk:
> +	clk_disable_unprepare(port->aux_ck);
> +err_aux_clk:
> +	clk_disable_unprepare(port->ahb_ck);
> +err_ahb_clk:
>  	clk_disable_unprepare(port->sys_ck);
>  err_sys_clk:
>  	mtk_pcie_port_free(port);
> @@ -306,10 +730,56 @@ static int mtk_pcie_parse_ports(struct mtk_pcie *pcie,
>  	snprintf(name, sizeof(name), "sys_ck%d", index);
>  	port->sys_ck = devm_clk_get(dev, name);
>  	if (IS_ERR(port->sys_ck)) {
> -		dev_err(dev, "failed to get port%d clock\n", index);
> +		dev_err(dev, "failed to get sys_ck%d\n", index);
>  		return PTR_ERR(port->sys_ck);
>  	}
>  
> +	/* sys_ck might be divided into the following parts in some chips */
> +	snprintf(name, sizeof(name), "ahb_ck%d", index);
> +	port->ahb_ck = devm_clk_get(dev, name);
> +	if (IS_ERR(port->ahb_ck)) {
> +		if (PTR_ERR(port->ahb_ck) == -EPROBE_DEFER)
> +			return -EPROBE_DEFER;
> +
> +		port->ahb_ck = NULL;
> +	}
> +
> +	snprintf(name, sizeof(name), "axi_ck%d", index);
> +	port->axi_ck = devm_clk_get(dev, name);
> +	if (IS_ERR(port->axi_ck)) {
> +		if (PTR_ERR(port->axi_ck) == -EPROBE_DEFER)
> +			return -EPROBE_DEFER;
> +
> +		port->axi_ck = NULL;
> +	}
> +
> +	snprintf(name, sizeof(name), "aux_ck%d", index);
> +	port->aux_ck = devm_clk_get(dev, name);
> +	if (IS_ERR(port->aux_ck)) {
> +		if (PTR_ERR(port->aux_ck) == -EPROBE_DEFER)
> +			return -EPROBE_DEFER;
> +
> +		port->aux_ck = NULL;
> +	}
> +
> +	snprintf(name, sizeof(name), "obff_ck%d", index);
> +	port->obff_ck = devm_clk_get(dev, name);
> +	if (IS_ERR(port->obff_ck)) {
> +		if (PTR_ERR(port->obff_ck) == -EPROBE_DEFER)
> +			return -EPROBE_DEFER;
> +
> +		port->obff_ck = NULL;
> +	}
> +
> +	snprintf(name, sizeof(name), "pipe_ck%d", index);
> +	port->pipe_ck = devm_clk_get(dev, name);
> +	if (IS_ERR(port->pipe_ck)) {
> +		if (PTR_ERR(port->pipe_ck) == -EPROBE_DEFER)
> +			return -EPROBE_DEFER;
> +
> +		port->pipe_ck = NULL;
> +	}
> +
>  	snprintf(name, sizeof(name), "pcie-rst%d", index);
>  	port->reset = devm_reset_control_get_optional(dev, name);
>  	if (PTR_ERR(port->reset) == -EPROBE_DEFER)
> @@ -324,6 +794,12 @@ static int mtk_pcie_parse_ports(struct mtk_pcie *pcie,
>  	port->index = index;
>  	port->pcie = pcie;
>  
> +	if (pcie->soc->setup_irq) {
> +		err = pcie->soc->setup_irq(port, node);
> +		if (err)
> +			return err;
> +	}
> +
>  	INIT_LIST_HEAD(&port->list);
>  	list_add_tail(&port->list, &pcie->ports);
>  
> @@ -553,9 +1029,17 @@ static struct mtk_pcie_soc mtk_pcie_soc_v1 = {
>  	.startup = mtk_pcie_startup_ports,
>  };
>  
> +static struct mtk_pcie_soc mtk_pcie_soc_v2 = {
> +	.ops = &mtk_pcie_ops_v2,
> +	.startup = mtk_pcie_startup_ports_v2,
> +	.setup_irq = mtk_pcie_setup_irq,
> +};
> +
>  static const struct of_device_id mtk_pcie_ids[] = {
>  	{ .compatible = "mediatek,mt2701-pcie", .data = &mtk_pcie_soc_v1 },
>  	{ .compatible = "mediatek,mt7623-pcie", .data = &mtk_pcie_soc_v1 },
> +	{ .compatible = "mediatek,mt2712-pcie", .data = &mtk_pcie_soc_v2 },
> +	{ .compatible = "mediatek,mt7622-pcie", .data = &mtk_pcie_soc_v2 },
>  	{},
>  };
>  
> -- 
> 2.6.4
> 

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v2 4/5] PCI: mediatek: Add new generation controller support
@ 2017-08-03 22:42     ` Bjorn Helgaas
  0 siblings, 0 replies; 80+ messages in thread
From: Bjorn Helgaas @ 2017-08-03 22:42 UTC (permalink / raw)
  To: honghui.zhang
  Cc: youlin.pei, devicetree, hongkun.cao, ryder.lee, linux-pci,
	sean.wang, xinping.qian, linux-kernel, robh+dt, yt.shen,
	matthias.bgg, robh, linux-mediatek, yong.wu, bhelgaas,
	yingjoe.chen, eddie.huang, linux-arm-kernel

On Thu, Jul 27, 2017 at 10:58:38AM +0800, honghui.zhang@mediatek.com wrote:
> From: Ryder Lee <ryder.lee@mediatek.com>
> 
> Add support for new Gen2 controller which has two root ports and shares
> the probing flow with legacy controller. Currently this IP block can be
> found on MT7622/MT2712.
> 
> Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> Signed-off-by: Honghui Zhang <honghui.zhang@mediatek.com>
> ---
>  drivers/pci/host/Kconfig         |   5 +-
>  drivers/pci/host/pcie-mediatek.c | 490 ++++++++++++++++++++++++++++++++++++++-
>  2 files changed, 489 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
> index 89d61c2..5b1ae9f 100644
> --- a/drivers/pci/host/Kconfig
> +++ b/drivers/pci/host/Kconfig
> @@ -182,14 +182,13 @@ config PCIE_ROCKCHIP
>  
>  config PCIE_MEDIATEK
>  	bool "MediaTek PCIe controller"
> -	depends on ARM && (ARCH_MEDIATEK || COMPILE_TEST)
> +	depends on (ARM || ARM64) && (ARCH_MEDIATEK || COMPILE_TEST)
>  	depends on OF
>  	depends on PCI
>  	select PCIEPORTBUS
>  	help
>  	  Say Y here if you want to enable PCIe controller support on
> -	  MT7623 series SoCs.  There is one single root complex with 3 root
> -	  ports available.  Each port supports Gen2 lane x1.
> +	  MediaTek SoCs.
>  
>  config PCIE_TANGO_SMP8759
>  	bool "Tango SMP8759 PCIe controller (DANGEROUS)"
> diff --git a/drivers/pci/host/pcie-mediatek.c b/drivers/pci/host/pcie-mediatek.c
> index f8e2f68..5fe92ff 100644
> --- a/drivers/pci/host/pcie-mediatek.c
> +++ b/drivers/pci/host/pcie-mediatek.c
> @@ -3,6 +3,7 @@
>   *
>   * Copyright (c) 2017 MediaTek Inc.
>   * Author: Ryder Lee <ryder.lee@mediatek.com>
> + *	   Honghui Zhang <honghui.zhang@mediatek.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
> @@ -17,6 +18,8 @@
>  #include <linux/clk.h>
>  #include <linux/delay.h>
>  #include <linux/iopoll.h>
> +#include <linux/irq.h>
> +#include <linux/irqdomain.h>
>  #include <linux/kernel.h>
>  #include <linux/of_address.h>
>  #include <linux/of_pci.h>
> @@ -64,16 +67,77 @@
>  #define PCIE_FC_CREDIT_MASK	(GENMASK(31, 31) | GENMASK(28, 16))
>  #define PCIE_FC_CREDIT_VAL(x)	((x) << 16)
>  
> +/* PCIe V2 share registers */
> +#define PCIE_SYS_CFG_V2		0x0
> +#define PCIE_CSR_LTSSM_EN(x)	BIT(0 + (x) * 8)
> +#define PCIE_CSR_ASPM_L1_EN(x)	BIT(1 + (x) * 8)
> +
> +/* PCIe V2 per-port registers */
> +#define PCIE_INT_MASK		0x420
> +#define INTX_MASK		GENMASK(19, 16)
> +#define INTX_SHIFT		16
> +#define INTX_NUM		4
> +#define PCIE_INT_STATUS		0x424
> +
> +#define PCIE_AHB_TRANS_BASE0_L	0x438
> +#define PCIE_AHB_TRANS_BASE0_H	0x43c
> +#define AHB2PCIE_BASEL(x)	((x) & GENMASK(31, 0))
> +#define AHB2PCIE_BASEH(x)	(((u64)(x) >> 32) & GENMASK(31, 0))
> +#define AHB2PCIE_SIZE(x)	((x) & GENMASK(4, 0))
> +#define PCIE_AXI_WINDOW0	0x448
> +#define WIN_ENABLE		BIT(7)
> +
> +/* PCIe V2 Configuration Transaction Header */
> +#define PCIE_CFG_HEADER0	0x460
> +#define PCIE_CFG_HEADER1	0x464
> +#define PCIE_CFG_HEADER2	0x468
> +#define PCIE_CFG_WDATA		0x470
> +#define PCIE_APP_TLP_REQ	0x488
> +#define PCIE_CFG_RDATA		0x48c
> +#define APP_CFG_REQ		BIT(0)
> +#define APP_CPL_STATUS		GENMASK(7, 5)
> +
> +#define CFG_WRRD_TYPE_0		4
> +#define CFG_WR_FMT		2
> +#define CFG_RD_FMT		0
> +
> +#define CFG_DW0_LENGTH(length)	((length) & GENMASK(9, 0))
> +#define CFG_DW0_TYPE(type)	(((type) << 24) & GENMASK(28, 24))
> +#define CFG_DW0_FMT(fmt)	(((fmt) << 29) & GENMASK(31, 29))
> +#define CFG_DW2_REGN(regn)	((regn) & GENMASK(11, 2))
> +#define CFG_DW2_FUN(fun)	(((fun) << 16) & GENMASK(18, 16))
> +#define CFG_DW2_DEV(dev)	(((dev) << 19) & GENMASK(23, 19))
> +#define CFG_DW2_BUS(bus)	(((bus) << 24) & GENMASK(31, 24))
> +#define CFG_HEADER_DW0(type, fmt) \
> +	(CFG_DW0_LENGTH(1) | CFG_DW0_TYPE(type) | CFG_DW0_FMT(fmt))
> +#define CFG_HEADER_DW1(where, size) \
> +	(GENMASK(((size) - 1), 0) << ((where) & 0x3))
> +#define CFG_HEADER_DW2(regn, fun, dev, bus) \
> +	(CFG_DW2_REGN(regn) | CFG_DW2_FUN(fun) | \
> +	CFG_DW2_DEV(dev) | CFG_DW2_BUS(bus))
> +
> +#define PCIE_RST_CTRL		0x510
> +#define PCIE_PHY_RSTB		BIT(0)
> +#define PCIE_PIPE_SRSTB		BIT(1)
> +#define PCIE_MAC_SRSTB		BIT(2)
> +#define PCIE_CRSTB		BIT(3)
> +#define PCIE_PERSTB		BIT(8)
> +#define PCI_LINKDOWN_RST_EN	GENMASK(15, 13)
> +#define PCIE_LINK_STATUS_V2	0x804
> +#define PCIE_PORT_LINKUP_V2	BIT(10)
> +
>  struct mtk_pcie_port;
>  
>  /**
>   * struct mtk_pcie_soc - differentiate between host generations
>   * @ops: pointer to configuration access functions
>   * @startup: pointer to controller setting functions
> + * @setup_irq: pointer to initialize irq functions

s/ irq / IRQ /

>   */
>  struct mtk_pcie_soc {
>  	struct pci_ops *ops;
>  	int (*startup)(struct mtk_pcie_port *port);
> +	int (*setup_irq)(struct mtk_pcie_port *port, struct device_node *node);
>  };
>  
>  /**
> @@ -82,10 +146,18 @@ struct mtk_pcie_soc {
>   * @list: port list
>   * @pcie: pointer to PCIe host info
>   * @reset: pointer to port reset control
> - * @sys_ck: pointer to bus clock
> + * @sys_ck: pointer to transaction/data link layer clock
> + * @ahb_ck: pinter to AHB slave interface operating clock for CSR access

s/pinter/pointer/

> + *          and RC initiated MMIO access
> + * @axi_ck: pointer to application layer MMIO channel operating clock
> + * @aux_ck: pointer to pe2_mac_bridge and pe2_mac_core operating clock
> + *          when pcie_mac_ck/pcie_pipe_ck is turned off
> + * @obff_ck: pointer to OBFF functional block operating clock
> + * @pipe_ck: pointer to LTSSM and phy/mac layer operating clock

s/phy/PHY/
s/mac/MAC/

>   * @phy: pointer to phy control block

s/ phy / PHY /

>   * @lane: lane count
>   * @index: port index
> + * @irq_domain: legacy intx irq domain

s/intx irq/INTx IRQ/

>   */
>  struct mtk_pcie_port {
>  	void __iomem *base;
> @@ -93,9 +165,15 @@ struct mtk_pcie_port {
>  	struct mtk_pcie *pcie;
>  	struct reset_control *reset;
>  	struct clk *sys_ck;
> +	struct clk *ahb_ck;
> +	struct clk *axi_ck;
> +	struct clk *aux_ck;
> +	struct clk *obff_ck;
> +	struct clk *pipe_ck;
>  	struct phy *phy;
>  	u32 lane;
>  	u32 index;
> +	struct irq_domain *irq_domain;
>  };
>  
>  /**
> @@ -156,6 +234,12 @@ static void mtk_pcie_put_resources(struct mtk_pcie *pcie)
>  
>  	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
>  		phy_power_off(port->phy);
> +		phy_exit(port->phy);
> +		clk_disable_unprepare(port->pipe_ck);
> +		clk_disable_unprepare(port->obff_ck);
> +		clk_disable_unprepare(port->axi_ck);
> +		clk_disable_unprepare(port->aux_ck);
> +		clk_disable_unprepare(port->ahb_ck);
>  		clk_disable_unprepare(port->sys_ck);
>  		mtk_pcie_port_free(port);
>  	}
> @@ -163,6 +247,298 @@ static void mtk_pcie_put_resources(struct mtk_pcie *pcie)
>  	mtk_pcie_subsys_powerdown(pcie);
>  }
>  
> +static int mtk_pcie_check_cfg_cpld(struct mtk_pcie_port *port)
> +{
> +	u32 val;
> +	int err;
> +
> +	err = readl_poll_timeout_atomic(port->base + PCIE_APP_TLP_REQ, val,
> +					!(val & APP_CFG_REQ), 10,
> +					100 * USEC_PER_MSEC);
> +	if (err)
> +		return PCIBIOS_SET_FAILED;
> +
> +	if (readl(port->base + PCIE_APP_TLP_REQ) & APP_CPL_STATUS)
> +		return PCIBIOS_SET_FAILED;
> +
> +	return PCIBIOS_SUCCESSFUL;
> +}
> +
> +static int mtk_pcie_hw_rd_cfg(struct mtk_pcie_port *port, u32 bus, u32 devfn,
> +			      int where, int size, u32 *val)
> +{
> +	int reg, shift = 8 * (where & 3);
> +
> +	/* Write PCIe Configuration Transaction Header for cfgrd */
> +	writel(CFG_HEADER_DW0(CFG_WRRD_TYPE_0, CFG_RD_FMT),
> +	       port->base + PCIE_CFG_HEADER0);
> +	writel(CFG_HEADER_DW1(where, size), port->base + PCIE_CFG_HEADER1);
> +	writel(CFG_HEADER_DW2(where, PCI_FUNC(devfn), PCI_SLOT(devfn), bus),
> +	       port->base + PCIE_CFG_HEADER2);
> +
> +	/* Triget h/w to transmit Cfgrd TLP */

s/Triget/Trigger/

> +	reg = readl(port->base + PCIE_APP_TLP_REQ);
> +	writel(reg | APP_CFG_REQ, port->base + PCIE_APP_TLP_REQ);
> +
> +	/* Check complete condition */

s/complete condition/completion status/ ?

> +	if (mtk_pcie_check_cfg_cpld(port))
> +		return PCIBIOS_SET_FAILED;
> +
> +	/* Read cpld payload of Cfgrd */
> +	*val = readl(port->base + PCIE_CFG_RDATA);
> +
> +	switch (size) {
> +	case 4:
> +		break;
> +	case 3:
> +		*val = (*val >> shift) & 0xffffff;
> +		break;
> +	case 2:
> +		*val = (*val >> shift) & 0xffff;
> +		break;
> +	case 1:
> +		*val = (*val >> shift) & 0xff;
> +		break;
> +	default:
> +		return PCIBIOS_BAD_REGISTER_NUMBER;
> +	}
> +
> +	return PCIBIOS_SUCCESSFUL;
> +}
> +
> +static int mtk_pcie_hw_wr_cfg(struct mtk_pcie_port *port, u32 bus, u32 devfn,
> +			      int where, int size, u32 val)
> +{
> +	/* Write PCIe Configuration Transaction Header for Cfgwr */
> +	writel(CFG_HEADER_DW0(CFG_WRRD_TYPE_0, CFG_WR_FMT),
> +	       port->base + PCIE_CFG_HEADER0);
> +	writel(CFG_HEADER_DW1(where, size), port->base + PCIE_CFG_HEADER1);
> +	writel(CFG_HEADER_DW2(where, PCI_FUNC(devfn), PCI_SLOT(devfn), bus),
> +	       port->base + PCIE_CFG_HEADER2);
> +
> +	/* Write cfgwr data */
> +	val = val << 8 * (where & 3);
> +	writel(val, port->base + PCIE_CFG_WDATA);
> +
> +	/* Triget h/w to transmit Cfgwr TLP */

s/Triget/Trigger/

> +	val = readl(port->base + PCIE_APP_TLP_REQ);
> +	val |= APP_CFG_REQ;
> +	writel(val, port->base + PCIE_APP_TLP_REQ);
> +
> +	/* Check complete condition */

s/complete condition/completion status/ ?

> +	return mtk_pcie_check_cfg_cpld(port);
> +}
> +
> +static struct mtk_pcie_port *mtk_pcie_find_port(struct mtk_pcie *pcie,
> +						struct pci_bus *bus, int devfn)
> +{
> +	struct pci_dev *dev;
> +	struct pci_bus *pbus;
> +	struct mtk_pcie_port *port, *tmp;
> +
> +	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
> +		if (bus->number == 0 && port->index == PCI_SLOT(devfn)) {
> +			return port;
> +		} else if (bus->number != 0) {
> +			pbus = bus;
> +			do {
> +				dev = pbus->self;
> +				if (port->index == PCI_SLOT(dev->devfn))
> +					return port;
> +				pbus = dev->bus;
> +			} while (dev->bus->number != 0);
> +		}
> +	}
> +
> +	return NULL;

You should be able to use sysdata to avoid searching the list.
See drivers/pci/host/pci-aardvark.c, for example.

> +}
> +
> +static int mtk_pcie_config_read(struct pci_bus *bus, unsigned int devfn,
> +				int where, int size, u32 *val)
> +{
> +	struct mtk_pcie_port *port;
> +	struct pci_host_bridge *host = pci_find_host_bridge(bus);
> +	struct mtk_pcie *pcie = pci_host_bridge_priv(host);

Sysdata should make this very simple; see advk_pcie_rd_conf().

> +	u32 bn = bus->number;
> +	int ret;
> +
> +	port = mtk_pcie_find_port(pcie, bus, devfn);
> +	if (!port) {
> +		*val = ~0;
> +		return PCIBIOS_DEVICE_NOT_FOUND;
> +	}
> +
> +	ret = mtk_pcie_hw_rd_cfg(port, bn, devfn, where, size, val);
> +	if (ret)
> +		*val = ~0;
> +
> +	return ret;
> +}
> +
> +static int mtk_pcie_config_write(struct pci_bus *bus, unsigned int devfn,
> +				 int where, int size, u32 val)
> +{
> +	u32 bn = bus->number;
> +	struct pci_host_bridge *host = pci_find_host_bridge(bus);
> +	struct mtk_pcie *pcie = pci_host_bridge_priv(host);
> +	struct mtk_pcie_port *port;
> +
> +	port = mtk_pcie_find_port(pcie, bus, devfn);
> +	if (!port)
> +		return PCIBIOS_DEVICE_NOT_FOUND;
> +
> +	return mtk_pcie_hw_wr_cfg(port, bn, devfn, where, size, val);
> +}
> +
> +static struct pci_ops mtk_pcie_ops_v2 = {
> +	.read  = mtk_pcie_config_read,
> +	.write = mtk_pcie_config_write,
> +};
> +
> +static int mtk_pcie_startup_ports_v2(struct mtk_pcie_port *port)
> +{
> +	struct mtk_pcie *pcie = port->pcie;
> +	struct resource *mem = &pcie->mem;
> +	u32 val;
> +	size_t size;
> +	int err;
> +
> +	/* mt7622 platforms need to enable LTSSM and ASPM from PCIe subsys */
> +	if (pcie->base) {
> +		val = readl(pcie->base + PCIE_SYS_CFG_V2);
> +		val |= PCIE_CSR_LTSSM_EN(port->index) |
> +		       PCIE_CSR_ASPM_L1_EN(port->index);
> +		writel(val, pcie->base + PCIE_SYS_CFG_V2);
> +	}
> +
> +	/* Assert all reset signals */
> +	writel(0, port->base + PCIE_RST_CTRL);
> +
> +	/*
> +	 * Enable rc internal reset.
> +	 * The reset will work when the link is from link up to link down.

?  That sentence doesn't parse for me.

> +	 */
> +	writel(PCI_LINKDOWN_RST_EN, port->base + PCIE_RST_CTRL);
> +
> +	/* De-assert phy, pe, pipe, mac and configuration reset	*/
> +	val = readl(port->base + PCIE_RST_CTRL);
> +	val |= PCIE_PHY_RSTB | PCIE_PERSTB | PCIE_PIPE_SRSTB |
> +	       PCIE_MAC_SRSTB | PCIE_CRSTB;
> +	writel(val, port->base + PCIE_RST_CTRL);
> +
> +	/* PCIe v2.0 need at least 100ms delay to train from Gen1 to Gen2 */
> +	err = readl_poll_timeout(port->base + PCIE_LINK_STATUS_V2, val,
> +				 !!(val & PCIE_PORT_LINKUP_V2), 20,
> +				 100 * USEC_PER_MSEC);
> +	if (err)
> +		return -ETIMEDOUT;
> +
> +	/* Set INTx mask */
> +	val = readl(port->base + PCIE_INT_MASK);
> +	val &= ~INTX_MASK;
> +	writel(val, port->base + PCIE_INT_MASK);
> +
> +	/* Set AHB to PCIe translation windows */
> +	size = mem->end - mem->start;
> +	val = AHB2PCIE_BASEL(mem->start) | AHB2PCIE_SIZE(fls(size));
> +	writel(val, port->base + PCIE_AHB_TRANS_BASE0_L);
> +
> +	val = AHB2PCIE_BASEH(mem->start);
> +	writel(val, port->base + PCIE_AHB_TRANS_BASE0_H);
> +
> +	/* Set PCIe to axi translation memory space.*/

s/axi/AXI/

> +	val = fls(0xffffffff) | WIN_ENABLE;
> +	writel(val, port->base + PCIE_AXI_WINDOW0);
> +
> +	return 0;
> +}
> +
> +static int mtk_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
> +			     irq_hw_number_t hwirq)
> +{
> +	irq_set_chip_and_handler(irq, &dummy_irq_chip, handle_simple_irq);
> +	irq_set_chip_data(irq, domain->host_data);
> +
> +	return 0;
> +}
> +
> +static const struct irq_domain_ops intx_domain_ops = {
> +	.map = mtk_pcie_intx_map,
> +};
> +
> +static int mtk_pcie_init_irq_domain(struct mtk_pcie_port *port,
> +				    struct device_node *node)
> +{
> +	struct device *dev = port->pcie->dev;
> +	struct device_node *pcie_intc_node;
> +
> +	/* Setup INTx */
> +	pcie_intc_node = of_get_next_child(node, NULL);
> +	if (!pcie_intc_node) {
> +		dev_err(dev, "No PCIe Intc node found\n");
> +		return PTR_ERR(pcie_intc_node);
> +	}
> +
> +	port->irq_domain = irq_domain_add_linear(pcie_intc_node, INTX_NUM,
> +						 &intx_domain_ops, port);

I think there's an issue here with a 4-element IRQ domain and the
hwirq numbers 1-4 from the of_irq_parse_and_map_pci() path, so INTD
may not work correctly.

See
http://lkml.kernel.org/r/20170801212931.GA26498@bhelgaas-glaptop.roam.corp.google.com
and related discussion.

> +	if (!port->irq_domain) {
> +		dev_err(dev, "Failed to get INTx IRQ domain\n");
> +		return PTR_ERR(port->irq_domain);
> +	}
> +
> +	return 0;
> +}
> +
> +static irqreturn_t mtk_pcie_intr_handler(int irq, void *data)
> +{
> +	struct mtk_pcie_port *port = (struct mtk_pcie_port *)data;
> +	struct device *dev = port->pcie->dev;
> +	unsigned long status;
> +	u32 virq;
> +	u32 bit = INTX_SHIFT;
> +
> +	while ((status = readl(port->base + PCIE_INT_STATUS)) & INTX_MASK) {
> +		for_each_set_bit_from(bit, &status, INTX_NUM + INTX_SHIFT) {
> +			/* Clear the INTx */
> +			writel(1 << bit, port->base + PCIE_INT_STATUS);
> +			virq = irq_find_mapping(port->irq_domain,
> +						bit - INTX_SHIFT);
> +			if (virq)
> +				generic_handle_irq(virq);
> +			else
> +				dev_err(dev, "unexpected IRQ, INT%d\n",
> +					bit - INTX_SHIFT);

PCI INTx are conventionally INTA, INTB, INTC, INTD (not INT1, INT2,
etc).

> +		}
> +	}
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static int mtk_pcie_setup_irq(struct mtk_pcie_port *port,
> +			      struct device_node *node)
> +{
> +	struct mtk_pcie *pcie = port->pcie;
> +	struct device *dev = pcie->dev;
> +	struct platform_device *pdev = to_platform_device(dev);
> +	int err, irq;
> +
> +	irq = platform_get_irq(pdev, port->index);
> +	err = devm_request_irq(dev, irq, mtk_pcie_intr_handler,
> +			       IRQF_SHARED, "mtk-pcie", port);
> +	if (err) {
> +		dev_err(dev, "unable to request irq %d\n", irq);

s/irq/IRQ/

> +		return err;
> +	}
> +
> +	err = mtk_pcie_init_irq_domain(port, node);
> +	if (err) {
> +		dev_err(dev, "failed to init pcie lagecy irq domain\n");

s/lagecy/legacy/
s/irq/IRQ/
s/pcie/PCIe/

> +		return -ENODEV;
> +	}
> +
> +	return 0;
> +}
> +
>  static void __iomem *mtk_pcie_map_bus(struct pci_bus *bus,
>  				      unsigned int devfn, int where)
>  {
> @@ -249,13 +625,49 @@ static void mtk_pcie_enable_ports(struct mtk_pcie_port *port)
>  
>  	err = clk_prepare_enable(port->sys_ck);
>  	if (err) {
> -		dev_err(dev, "failed to enable port%d clock\n", port->index);
> +		dev_err(dev, "failed to enable sys_ck%d\n", port->index);
>  		goto err_sys_clk;
>  	}
>  
> +	err = clk_prepare_enable(port->ahb_ck);
> +	if (err) {
> +		dev_err(dev, "failed to enable ahb_ck%d\n", port->index);
> +		goto err_ahb_clk;
> +	}
> +
> +	err = clk_prepare_enable(port->aux_ck);
> +	if (err) {
> +		dev_err(dev, "failed to enable aux_ck%d\n", port->index);
> +		goto err_aux_clk;
> +	}
> +
> +	err = clk_prepare_enable(port->axi_ck);
> +	if (err) {
> +		dev_err(dev, "failed to enable axi_ck%d\n", port->index);
> +		goto err_axi_clk;
> +	}
> +
> +	err = clk_prepare_enable(port->obff_ck);
> +	if (err) {
> +		dev_err(dev, "failed to enable obff_ck%d\n", port->index);
> +		goto err_obff_clk;
> +	}
> +
> +	err = clk_prepare_enable(port->pipe_ck);
> +	if (err) {
> +		dev_err(dev, "failed to enable pipe_ck%d\n", port->index);
> +		goto err_pipe_clk;
> +	}
> +
>  	reset_control_assert(port->reset);
>  	reset_control_deassert(port->reset);
>  
> +	err = phy_init(port->phy);
> +	if (err) {
> +		dev_err(dev, "failed to initialize port%d phy\n", port->index);
> +		goto err_phy_init;
> +	}
> +
>  	err = phy_power_on(port->phy);
>  	if (err) {
>  		dev_err(dev, "failed to power on port%d phy\n", port->index);
> @@ -269,6 +681,18 @@ static void mtk_pcie_enable_ports(struct mtk_pcie_port *port)
>  
>  	phy_power_off(port->phy);
>  err_phy_on:
> +	phy_exit(port->phy);
> +err_phy_init:
> +	clk_disable_unprepare(port->pipe_ck);
> +err_pipe_clk:
> +	clk_disable_unprepare(port->obff_ck);
> +err_obff_clk:
> +	clk_disable_unprepare(port->axi_ck);
> +err_axi_clk:
> +	clk_disable_unprepare(port->aux_ck);
> +err_aux_clk:
> +	clk_disable_unprepare(port->ahb_ck);
> +err_ahb_clk:
>  	clk_disable_unprepare(port->sys_ck);
>  err_sys_clk:
>  	mtk_pcie_port_free(port);
> @@ -306,10 +730,56 @@ static int mtk_pcie_parse_ports(struct mtk_pcie *pcie,
>  	snprintf(name, sizeof(name), "sys_ck%d", index);
>  	port->sys_ck = devm_clk_get(dev, name);
>  	if (IS_ERR(port->sys_ck)) {
> -		dev_err(dev, "failed to get port%d clock\n", index);
> +		dev_err(dev, "failed to get sys_ck%d\n", index);
>  		return PTR_ERR(port->sys_ck);
>  	}
>  
> +	/* sys_ck might be divided into the following parts in some chips */
> +	snprintf(name, sizeof(name), "ahb_ck%d", index);
> +	port->ahb_ck = devm_clk_get(dev, name);
> +	if (IS_ERR(port->ahb_ck)) {
> +		if (PTR_ERR(port->ahb_ck) == -EPROBE_DEFER)
> +			return -EPROBE_DEFER;
> +
> +		port->ahb_ck = NULL;
> +	}
> +
> +	snprintf(name, sizeof(name), "axi_ck%d", index);
> +	port->axi_ck = devm_clk_get(dev, name);
> +	if (IS_ERR(port->axi_ck)) {
> +		if (PTR_ERR(port->axi_ck) == -EPROBE_DEFER)
> +			return -EPROBE_DEFER;
> +
> +		port->axi_ck = NULL;
> +	}
> +
> +	snprintf(name, sizeof(name), "aux_ck%d", index);
> +	port->aux_ck = devm_clk_get(dev, name);
> +	if (IS_ERR(port->aux_ck)) {
> +		if (PTR_ERR(port->aux_ck) == -EPROBE_DEFER)
> +			return -EPROBE_DEFER;
> +
> +		port->aux_ck = NULL;
> +	}
> +
> +	snprintf(name, sizeof(name), "obff_ck%d", index);
> +	port->obff_ck = devm_clk_get(dev, name);
> +	if (IS_ERR(port->obff_ck)) {
> +		if (PTR_ERR(port->obff_ck) == -EPROBE_DEFER)
> +			return -EPROBE_DEFER;
> +
> +		port->obff_ck = NULL;
> +	}
> +
> +	snprintf(name, sizeof(name), "pipe_ck%d", index);
> +	port->pipe_ck = devm_clk_get(dev, name);
> +	if (IS_ERR(port->pipe_ck)) {
> +		if (PTR_ERR(port->pipe_ck) == -EPROBE_DEFER)
> +			return -EPROBE_DEFER;
> +
> +		port->pipe_ck = NULL;
> +	}
> +
>  	snprintf(name, sizeof(name), "pcie-rst%d", index);
>  	port->reset = devm_reset_control_get_optional(dev, name);
>  	if (PTR_ERR(port->reset) == -EPROBE_DEFER)
> @@ -324,6 +794,12 @@ static int mtk_pcie_parse_ports(struct mtk_pcie *pcie,
>  	port->index = index;
>  	port->pcie = pcie;
>  
> +	if (pcie->soc->setup_irq) {
> +		err = pcie->soc->setup_irq(port, node);
> +		if (err)
> +			return err;
> +	}
> +
>  	INIT_LIST_HEAD(&port->list);
>  	list_add_tail(&port->list, &pcie->ports);
>  
> @@ -553,9 +1029,17 @@ static struct mtk_pcie_soc mtk_pcie_soc_v1 = {
>  	.startup = mtk_pcie_startup_ports,
>  };
>  
> +static struct mtk_pcie_soc mtk_pcie_soc_v2 = {
> +	.ops = &mtk_pcie_ops_v2,
> +	.startup = mtk_pcie_startup_ports_v2,
> +	.setup_irq = mtk_pcie_setup_irq,
> +};
> +
>  static const struct of_device_id mtk_pcie_ids[] = {
>  	{ .compatible = "mediatek,mt2701-pcie", .data = &mtk_pcie_soc_v1 },
>  	{ .compatible = "mediatek,mt7623-pcie", .data = &mtk_pcie_soc_v1 },
> +	{ .compatible = "mediatek,mt2712-pcie", .data = &mtk_pcie_soc_v2 },
> +	{ .compatible = "mediatek,mt7622-pcie", .data = &mtk_pcie_soc_v2 },
>  	{},
>  };
>  
> -- 
> 2.6.4
> 

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 80+ messages in thread

* [PATCH v2 4/5] PCI: mediatek: Add new generation controller support
@ 2017-08-03 22:42     ` Bjorn Helgaas
  0 siblings, 0 replies; 80+ messages in thread
From: Bjorn Helgaas @ 2017-08-03 22:42 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Jul 27, 2017 at 10:58:38AM +0800, honghui.zhang at mediatek.com wrote:
> From: Ryder Lee <ryder.lee@mediatek.com>
> 
> Add support for new Gen2 controller which has two root ports and shares
> the probing flow with legacy controller. Currently this IP block can be
> found on MT7622/MT2712.
> 
> Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> Signed-off-by: Honghui Zhang <honghui.zhang@mediatek.com>
> ---
>  drivers/pci/host/Kconfig         |   5 +-
>  drivers/pci/host/pcie-mediatek.c | 490 ++++++++++++++++++++++++++++++++++++++-
>  2 files changed, 489 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
> index 89d61c2..5b1ae9f 100644
> --- a/drivers/pci/host/Kconfig
> +++ b/drivers/pci/host/Kconfig
> @@ -182,14 +182,13 @@ config PCIE_ROCKCHIP
>  
>  config PCIE_MEDIATEK
>  	bool "MediaTek PCIe controller"
> -	depends on ARM && (ARCH_MEDIATEK || COMPILE_TEST)
> +	depends on (ARM || ARM64) && (ARCH_MEDIATEK || COMPILE_TEST)
>  	depends on OF
>  	depends on PCI
>  	select PCIEPORTBUS
>  	help
>  	  Say Y here if you want to enable PCIe controller support on
> -	  MT7623 series SoCs.  There is one single root complex with 3 root
> -	  ports available.  Each port supports Gen2 lane x1.
> +	  MediaTek SoCs.
>  
>  config PCIE_TANGO_SMP8759
>  	bool "Tango SMP8759 PCIe controller (DANGEROUS)"
> diff --git a/drivers/pci/host/pcie-mediatek.c b/drivers/pci/host/pcie-mediatek.c
> index f8e2f68..5fe92ff 100644
> --- a/drivers/pci/host/pcie-mediatek.c
> +++ b/drivers/pci/host/pcie-mediatek.c
> @@ -3,6 +3,7 @@
>   *
>   * Copyright (c) 2017 MediaTek Inc.
>   * Author: Ryder Lee <ryder.lee@mediatek.com>
> + *	   Honghui Zhang <honghui.zhang@mediatek.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
> @@ -17,6 +18,8 @@
>  #include <linux/clk.h>
>  #include <linux/delay.h>
>  #include <linux/iopoll.h>
> +#include <linux/irq.h>
> +#include <linux/irqdomain.h>
>  #include <linux/kernel.h>
>  #include <linux/of_address.h>
>  #include <linux/of_pci.h>
> @@ -64,16 +67,77 @@
>  #define PCIE_FC_CREDIT_MASK	(GENMASK(31, 31) | GENMASK(28, 16))
>  #define PCIE_FC_CREDIT_VAL(x)	((x) << 16)
>  
> +/* PCIe V2 share registers */
> +#define PCIE_SYS_CFG_V2		0x0
> +#define PCIE_CSR_LTSSM_EN(x)	BIT(0 + (x) * 8)
> +#define PCIE_CSR_ASPM_L1_EN(x)	BIT(1 + (x) * 8)
> +
> +/* PCIe V2 per-port registers */
> +#define PCIE_INT_MASK		0x420
> +#define INTX_MASK		GENMASK(19, 16)
> +#define INTX_SHIFT		16
> +#define INTX_NUM		4
> +#define PCIE_INT_STATUS		0x424
> +
> +#define PCIE_AHB_TRANS_BASE0_L	0x438
> +#define PCIE_AHB_TRANS_BASE0_H	0x43c
> +#define AHB2PCIE_BASEL(x)	((x) & GENMASK(31, 0))
> +#define AHB2PCIE_BASEH(x)	(((u64)(x) >> 32) & GENMASK(31, 0))
> +#define AHB2PCIE_SIZE(x)	((x) & GENMASK(4, 0))
> +#define PCIE_AXI_WINDOW0	0x448
> +#define WIN_ENABLE		BIT(7)
> +
> +/* PCIe V2 Configuration Transaction Header */
> +#define PCIE_CFG_HEADER0	0x460
> +#define PCIE_CFG_HEADER1	0x464
> +#define PCIE_CFG_HEADER2	0x468
> +#define PCIE_CFG_WDATA		0x470
> +#define PCIE_APP_TLP_REQ	0x488
> +#define PCIE_CFG_RDATA		0x48c
> +#define APP_CFG_REQ		BIT(0)
> +#define APP_CPL_STATUS		GENMASK(7, 5)
> +
> +#define CFG_WRRD_TYPE_0		4
> +#define CFG_WR_FMT		2
> +#define CFG_RD_FMT		0
> +
> +#define CFG_DW0_LENGTH(length)	((length) & GENMASK(9, 0))
> +#define CFG_DW0_TYPE(type)	(((type) << 24) & GENMASK(28, 24))
> +#define CFG_DW0_FMT(fmt)	(((fmt) << 29) & GENMASK(31, 29))
> +#define CFG_DW2_REGN(regn)	((regn) & GENMASK(11, 2))
> +#define CFG_DW2_FUN(fun)	(((fun) << 16) & GENMASK(18, 16))
> +#define CFG_DW2_DEV(dev)	(((dev) << 19) & GENMASK(23, 19))
> +#define CFG_DW2_BUS(bus)	(((bus) << 24) & GENMASK(31, 24))
> +#define CFG_HEADER_DW0(type, fmt) \
> +	(CFG_DW0_LENGTH(1) | CFG_DW0_TYPE(type) | CFG_DW0_FMT(fmt))
> +#define CFG_HEADER_DW1(where, size) \
> +	(GENMASK(((size) - 1), 0) << ((where) & 0x3))
> +#define CFG_HEADER_DW2(regn, fun, dev, bus) \
> +	(CFG_DW2_REGN(regn) | CFG_DW2_FUN(fun) | \
> +	CFG_DW2_DEV(dev) | CFG_DW2_BUS(bus))
> +
> +#define PCIE_RST_CTRL		0x510
> +#define PCIE_PHY_RSTB		BIT(0)
> +#define PCIE_PIPE_SRSTB		BIT(1)
> +#define PCIE_MAC_SRSTB		BIT(2)
> +#define PCIE_CRSTB		BIT(3)
> +#define PCIE_PERSTB		BIT(8)
> +#define PCI_LINKDOWN_RST_EN	GENMASK(15, 13)
> +#define PCIE_LINK_STATUS_V2	0x804
> +#define PCIE_PORT_LINKUP_V2	BIT(10)
> +
>  struct mtk_pcie_port;
>  
>  /**
>   * struct mtk_pcie_soc - differentiate between host generations
>   * @ops: pointer to configuration access functions
>   * @startup: pointer to controller setting functions
> + * @setup_irq: pointer to initialize irq functions

s/ irq / IRQ /

>   */
>  struct mtk_pcie_soc {
>  	struct pci_ops *ops;
>  	int (*startup)(struct mtk_pcie_port *port);
> +	int (*setup_irq)(struct mtk_pcie_port *port, struct device_node *node);
>  };
>  
>  /**
> @@ -82,10 +146,18 @@ struct mtk_pcie_soc {
>   * @list: port list
>   * @pcie: pointer to PCIe host info
>   * @reset: pointer to port reset control
> - * @sys_ck: pointer to bus clock
> + * @sys_ck: pointer to transaction/data link layer clock
> + * @ahb_ck: pinter to AHB slave interface operating clock for CSR access

s/pinter/pointer/

> + *          and RC initiated MMIO access
> + * @axi_ck: pointer to application layer MMIO channel operating clock
> + * @aux_ck: pointer to pe2_mac_bridge and pe2_mac_core operating clock
> + *          when pcie_mac_ck/pcie_pipe_ck is turned off
> + * @obff_ck: pointer to OBFF functional block operating clock
> + * @pipe_ck: pointer to LTSSM and phy/mac layer operating clock

s/phy/PHY/
s/mac/MAC/

>   * @phy: pointer to phy control block

s/ phy / PHY /

>   * @lane: lane count
>   * @index: port index
> + * @irq_domain: legacy intx irq domain

s/intx irq/INTx IRQ/

>   */
>  struct mtk_pcie_port {
>  	void __iomem *base;
> @@ -93,9 +165,15 @@ struct mtk_pcie_port {
>  	struct mtk_pcie *pcie;
>  	struct reset_control *reset;
>  	struct clk *sys_ck;
> +	struct clk *ahb_ck;
> +	struct clk *axi_ck;
> +	struct clk *aux_ck;
> +	struct clk *obff_ck;
> +	struct clk *pipe_ck;
>  	struct phy *phy;
>  	u32 lane;
>  	u32 index;
> +	struct irq_domain *irq_domain;
>  };
>  
>  /**
> @@ -156,6 +234,12 @@ static void mtk_pcie_put_resources(struct mtk_pcie *pcie)
>  
>  	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
>  		phy_power_off(port->phy);
> +		phy_exit(port->phy);
> +		clk_disable_unprepare(port->pipe_ck);
> +		clk_disable_unprepare(port->obff_ck);
> +		clk_disable_unprepare(port->axi_ck);
> +		clk_disable_unprepare(port->aux_ck);
> +		clk_disable_unprepare(port->ahb_ck);
>  		clk_disable_unprepare(port->sys_ck);
>  		mtk_pcie_port_free(port);
>  	}
> @@ -163,6 +247,298 @@ static void mtk_pcie_put_resources(struct mtk_pcie *pcie)
>  	mtk_pcie_subsys_powerdown(pcie);
>  }
>  
> +static int mtk_pcie_check_cfg_cpld(struct mtk_pcie_port *port)
> +{
> +	u32 val;
> +	int err;
> +
> +	err = readl_poll_timeout_atomic(port->base + PCIE_APP_TLP_REQ, val,
> +					!(val & APP_CFG_REQ), 10,
> +					100 * USEC_PER_MSEC);
> +	if (err)
> +		return PCIBIOS_SET_FAILED;
> +
> +	if (readl(port->base + PCIE_APP_TLP_REQ) & APP_CPL_STATUS)
> +		return PCIBIOS_SET_FAILED;
> +
> +	return PCIBIOS_SUCCESSFUL;
> +}
> +
> +static int mtk_pcie_hw_rd_cfg(struct mtk_pcie_port *port, u32 bus, u32 devfn,
> +			      int where, int size, u32 *val)
> +{
> +	int reg, shift = 8 * (where & 3);
> +
> +	/* Write PCIe Configuration Transaction Header for cfgrd */
> +	writel(CFG_HEADER_DW0(CFG_WRRD_TYPE_0, CFG_RD_FMT),
> +	       port->base + PCIE_CFG_HEADER0);
> +	writel(CFG_HEADER_DW1(where, size), port->base + PCIE_CFG_HEADER1);
> +	writel(CFG_HEADER_DW2(where, PCI_FUNC(devfn), PCI_SLOT(devfn), bus),
> +	       port->base + PCIE_CFG_HEADER2);
> +
> +	/* Triget h/w to transmit Cfgrd TLP */

s/Triget/Trigger/

> +	reg = readl(port->base + PCIE_APP_TLP_REQ);
> +	writel(reg | APP_CFG_REQ, port->base + PCIE_APP_TLP_REQ);
> +
> +	/* Check complete condition */

s/complete condition/completion status/ ?

> +	if (mtk_pcie_check_cfg_cpld(port))
> +		return PCIBIOS_SET_FAILED;
> +
> +	/* Read cpld payload of Cfgrd */
> +	*val = readl(port->base + PCIE_CFG_RDATA);
> +
> +	switch (size) {
> +	case 4:
> +		break;
> +	case 3:
> +		*val = (*val >> shift) & 0xffffff;
> +		break;
> +	case 2:
> +		*val = (*val >> shift) & 0xffff;
> +		break;
> +	case 1:
> +		*val = (*val >> shift) & 0xff;
> +		break;
> +	default:
> +		return PCIBIOS_BAD_REGISTER_NUMBER;
> +	}
> +
> +	return PCIBIOS_SUCCESSFUL;
> +}
> +
> +static int mtk_pcie_hw_wr_cfg(struct mtk_pcie_port *port, u32 bus, u32 devfn,
> +			      int where, int size, u32 val)
> +{
> +	/* Write PCIe Configuration Transaction Header for Cfgwr */
> +	writel(CFG_HEADER_DW0(CFG_WRRD_TYPE_0, CFG_WR_FMT),
> +	       port->base + PCIE_CFG_HEADER0);
> +	writel(CFG_HEADER_DW1(where, size), port->base + PCIE_CFG_HEADER1);
> +	writel(CFG_HEADER_DW2(where, PCI_FUNC(devfn), PCI_SLOT(devfn), bus),
> +	       port->base + PCIE_CFG_HEADER2);
> +
> +	/* Write cfgwr data */
> +	val = val << 8 * (where & 3);
> +	writel(val, port->base + PCIE_CFG_WDATA);
> +
> +	/* Triget h/w to transmit Cfgwr TLP */

s/Triget/Trigger/

> +	val = readl(port->base + PCIE_APP_TLP_REQ);
> +	val |= APP_CFG_REQ;
> +	writel(val, port->base + PCIE_APP_TLP_REQ);
> +
> +	/* Check complete condition */

s/complete condition/completion status/ ?

> +	return mtk_pcie_check_cfg_cpld(port);
> +}
> +
> +static struct mtk_pcie_port *mtk_pcie_find_port(struct mtk_pcie *pcie,
> +						struct pci_bus *bus, int devfn)
> +{
> +	struct pci_dev *dev;
> +	struct pci_bus *pbus;
> +	struct mtk_pcie_port *port, *tmp;
> +
> +	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
> +		if (bus->number == 0 && port->index == PCI_SLOT(devfn)) {
> +			return port;
> +		} else if (bus->number != 0) {
> +			pbus = bus;
> +			do {
> +				dev = pbus->self;
> +				if (port->index == PCI_SLOT(dev->devfn))
> +					return port;
> +				pbus = dev->bus;
> +			} while (dev->bus->number != 0);
> +		}
> +	}
> +
> +	return NULL;

You should be able to use sysdata to avoid searching the list.
See drivers/pci/host/pci-aardvark.c, for example.

> +}
> +
> +static int mtk_pcie_config_read(struct pci_bus *bus, unsigned int devfn,
> +				int where, int size, u32 *val)
> +{
> +	struct mtk_pcie_port *port;
> +	struct pci_host_bridge *host = pci_find_host_bridge(bus);
> +	struct mtk_pcie *pcie = pci_host_bridge_priv(host);

Sysdata should make this very simple; see advk_pcie_rd_conf().

> +	u32 bn = bus->number;
> +	int ret;
> +
> +	port = mtk_pcie_find_port(pcie, bus, devfn);
> +	if (!port) {
> +		*val = ~0;
> +		return PCIBIOS_DEVICE_NOT_FOUND;
> +	}
> +
> +	ret = mtk_pcie_hw_rd_cfg(port, bn, devfn, where, size, val);
> +	if (ret)
> +		*val = ~0;
> +
> +	return ret;
> +}
> +
> +static int mtk_pcie_config_write(struct pci_bus *bus, unsigned int devfn,
> +				 int where, int size, u32 val)
> +{
> +	u32 bn = bus->number;
> +	struct pci_host_bridge *host = pci_find_host_bridge(bus);
> +	struct mtk_pcie *pcie = pci_host_bridge_priv(host);
> +	struct mtk_pcie_port *port;
> +
> +	port = mtk_pcie_find_port(pcie, bus, devfn);
> +	if (!port)
> +		return PCIBIOS_DEVICE_NOT_FOUND;
> +
> +	return mtk_pcie_hw_wr_cfg(port, bn, devfn, where, size, val);
> +}
> +
> +static struct pci_ops mtk_pcie_ops_v2 = {
> +	.read  = mtk_pcie_config_read,
> +	.write = mtk_pcie_config_write,
> +};
> +
> +static int mtk_pcie_startup_ports_v2(struct mtk_pcie_port *port)
> +{
> +	struct mtk_pcie *pcie = port->pcie;
> +	struct resource *mem = &pcie->mem;
> +	u32 val;
> +	size_t size;
> +	int err;
> +
> +	/* mt7622 platforms need to enable LTSSM and ASPM from PCIe subsys */
> +	if (pcie->base) {
> +		val = readl(pcie->base + PCIE_SYS_CFG_V2);
> +		val |= PCIE_CSR_LTSSM_EN(port->index) |
> +		       PCIE_CSR_ASPM_L1_EN(port->index);
> +		writel(val, pcie->base + PCIE_SYS_CFG_V2);
> +	}
> +
> +	/* Assert all reset signals */
> +	writel(0, port->base + PCIE_RST_CTRL);
> +
> +	/*
> +	 * Enable rc internal reset.
> +	 * The reset will work when the link is from link up to link down.

?  That sentence doesn't parse for me.

> +	 */
> +	writel(PCI_LINKDOWN_RST_EN, port->base + PCIE_RST_CTRL);
> +
> +	/* De-assert phy, pe, pipe, mac and configuration reset	*/
> +	val = readl(port->base + PCIE_RST_CTRL);
> +	val |= PCIE_PHY_RSTB | PCIE_PERSTB | PCIE_PIPE_SRSTB |
> +	       PCIE_MAC_SRSTB | PCIE_CRSTB;
> +	writel(val, port->base + PCIE_RST_CTRL);
> +
> +	/* PCIe v2.0 need at least 100ms delay to train from Gen1 to Gen2 */
> +	err = readl_poll_timeout(port->base + PCIE_LINK_STATUS_V2, val,
> +				 !!(val & PCIE_PORT_LINKUP_V2), 20,
> +				 100 * USEC_PER_MSEC);
> +	if (err)
> +		return -ETIMEDOUT;
> +
> +	/* Set INTx mask */
> +	val = readl(port->base + PCIE_INT_MASK);
> +	val &= ~INTX_MASK;
> +	writel(val, port->base + PCIE_INT_MASK);
> +
> +	/* Set AHB to PCIe translation windows */
> +	size = mem->end - mem->start;
> +	val = AHB2PCIE_BASEL(mem->start) | AHB2PCIE_SIZE(fls(size));
> +	writel(val, port->base + PCIE_AHB_TRANS_BASE0_L);
> +
> +	val = AHB2PCIE_BASEH(mem->start);
> +	writel(val, port->base + PCIE_AHB_TRANS_BASE0_H);
> +
> +	/* Set PCIe to axi translation memory space.*/

s/axi/AXI/

> +	val = fls(0xffffffff) | WIN_ENABLE;
> +	writel(val, port->base + PCIE_AXI_WINDOW0);
> +
> +	return 0;
> +}
> +
> +static int mtk_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
> +			     irq_hw_number_t hwirq)
> +{
> +	irq_set_chip_and_handler(irq, &dummy_irq_chip, handle_simple_irq);
> +	irq_set_chip_data(irq, domain->host_data);
> +
> +	return 0;
> +}
> +
> +static const struct irq_domain_ops intx_domain_ops = {
> +	.map = mtk_pcie_intx_map,
> +};
> +
> +static int mtk_pcie_init_irq_domain(struct mtk_pcie_port *port,
> +				    struct device_node *node)
> +{
> +	struct device *dev = port->pcie->dev;
> +	struct device_node *pcie_intc_node;
> +
> +	/* Setup INTx */
> +	pcie_intc_node = of_get_next_child(node, NULL);
> +	if (!pcie_intc_node) {
> +		dev_err(dev, "No PCIe Intc node found\n");
> +		return PTR_ERR(pcie_intc_node);
> +	}
> +
> +	port->irq_domain = irq_domain_add_linear(pcie_intc_node, INTX_NUM,
> +						 &intx_domain_ops, port);

I think there's an issue here with a 4-element IRQ domain and the
hwirq numbers 1-4 from the of_irq_parse_and_map_pci() path, so INTD
may not work correctly.

See
http://lkml.kernel.org/r/20170801212931.GA26498 at bhelgaas-glaptop.roam.corp.google.com
and related discussion.

> +	if (!port->irq_domain) {
> +		dev_err(dev, "Failed to get INTx IRQ domain\n");
> +		return PTR_ERR(port->irq_domain);
> +	}
> +
> +	return 0;
> +}
> +
> +static irqreturn_t mtk_pcie_intr_handler(int irq, void *data)
> +{
> +	struct mtk_pcie_port *port = (struct mtk_pcie_port *)data;
> +	struct device *dev = port->pcie->dev;
> +	unsigned long status;
> +	u32 virq;
> +	u32 bit = INTX_SHIFT;
> +
> +	while ((status = readl(port->base + PCIE_INT_STATUS)) & INTX_MASK) {
> +		for_each_set_bit_from(bit, &status, INTX_NUM + INTX_SHIFT) {
> +			/* Clear the INTx */
> +			writel(1 << bit, port->base + PCIE_INT_STATUS);
> +			virq = irq_find_mapping(port->irq_domain,
> +						bit - INTX_SHIFT);
> +			if (virq)
> +				generic_handle_irq(virq);
> +			else
> +				dev_err(dev, "unexpected IRQ, INT%d\n",
> +					bit - INTX_SHIFT);

PCI INTx are conventionally INTA, INTB, INTC, INTD (not INT1, INT2,
etc).

> +		}
> +	}
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static int mtk_pcie_setup_irq(struct mtk_pcie_port *port,
> +			      struct device_node *node)
> +{
> +	struct mtk_pcie *pcie = port->pcie;
> +	struct device *dev = pcie->dev;
> +	struct platform_device *pdev = to_platform_device(dev);
> +	int err, irq;
> +
> +	irq = platform_get_irq(pdev, port->index);
> +	err = devm_request_irq(dev, irq, mtk_pcie_intr_handler,
> +			       IRQF_SHARED, "mtk-pcie", port);
> +	if (err) {
> +		dev_err(dev, "unable to request irq %d\n", irq);

s/irq/IRQ/

> +		return err;
> +	}
> +
> +	err = mtk_pcie_init_irq_domain(port, node);
> +	if (err) {
> +		dev_err(dev, "failed to init pcie lagecy irq domain\n");

s/lagecy/legacy/
s/irq/IRQ/
s/pcie/PCIe/

> +		return -ENODEV;
> +	}
> +
> +	return 0;
> +}
> +
>  static void __iomem *mtk_pcie_map_bus(struct pci_bus *bus,
>  				      unsigned int devfn, int where)
>  {
> @@ -249,13 +625,49 @@ static void mtk_pcie_enable_ports(struct mtk_pcie_port *port)
>  
>  	err = clk_prepare_enable(port->sys_ck);
>  	if (err) {
> -		dev_err(dev, "failed to enable port%d clock\n", port->index);
> +		dev_err(dev, "failed to enable sys_ck%d\n", port->index);
>  		goto err_sys_clk;
>  	}
>  
> +	err = clk_prepare_enable(port->ahb_ck);
> +	if (err) {
> +		dev_err(dev, "failed to enable ahb_ck%d\n", port->index);
> +		goto err_ahb_clk;
> +	}
> +
> +	err = clk_prepare_enable(port->aux_ck);
> +	if (err) {
> +		dev_err(dev, "failed to enable aux_ck%d\n", port->index);
> +		goto err_aux_clk;
> +	}
> +
> +	err = clk_prepare_enable(port->axi_ck);
> +	if (err) {
> +		dev_err(dev, "failed to enable axi_ck%d\n", port->index);
> +		goto err_axi_clk;
> +	}
> +
> +	err = clk_prepare_enable(port->obff_ck);
> +	if (err) {
> +		dev_err(dev, "failed to enable obff_ck%d\n", port->index);
> +		goto err_obff_clk;
> +	}
> +
> +	err = clk_prepare_enable(port->pipe_ck);
> +	if (err) {
> +		dev_err(dev, "failed to enable pipe_ck%d\n", port->index);
> +		goto err_pipe_clk;
> +	}
> +
>  	reset_control_assert(port->reset);
>  	reset_control_deassert(port->reset);
>  
> +	err = phy_init(port->phy);
> +	if (err) {
> +		dev_err(dev, "failed to initialize port%d phy\n", port->index);
> +		goto err_phy_init;
> +	}
> +
>  	err = phy_power_on(port->phy);
>  	if (err) {
>  		dev_err(dev, "failed to power on port%d phy\n", port->index);
> @@ -269,6 +681,18 @@ static void mtk_pcie_enable_ports(struct mtk_pcie_port *port)
>  
>  	phy_power_off(port->phy);
>  err_phy_on:
> +	phy_exit(port->phy);
> +err_phy_init:
> +	clk_disable_unprepare(port->pipe_ck);
> +err_pipe_clk:
> +	clk_disable_unprepare(port->obff_ck);
> +err_obff_clk:
> +	clk_disable_unprepare(port->axi_ck);
> +err_axi_clk:
> +	clk_disable_unprepare(port->aux_ck);
> +err_aux_clk:
> +	clk_disable_unprepare(port->ahb_ck);
> +err_ahb_clk:
>  	clk_disable_unprepare(port->sys_ck);
>  err_sys_clk:
>  	mtk_pcie_port_free(port);
> @@ -306,10 +730,56 @@ static int mtk_pcie_parse_ports(struct mtk_pcie *pcie,
>  	snprintf(name, sizeof(name), "sys_ck%d", index);
>  	port->sys_ck = devm_clk_get(dev, name);
>  	if (IS_ERR(port->sys_ck)) {
> -		dev_err(dev, "failed to get port%d clock\n", index);
> +		dev_err(dev, "failed to get sys_ck%d\n", index);
>  		return PTR_ERR(port->sys_ck);
>  	}
>  
> +	/* sys_ck might be divided into the following parts in some chips */
> +	snprintf(name, sizeof(name), "ahb_ck%d", index);
> +	port->ahb_ck = devm_clk_get(dev, name);
> +	if (IS_ERR(port->ahb_ck)) {
> +		if (PTR_ERR(port->ahb_ck) == -EPROBE_DEFER)
> +			return -EPROBE_DEFER;
> +
> +		port->ahb_ck = NULL;
> +	}
> +
> +	snprintf(name, sizeof(name), "axi_ck%d", index);
> +	port->axi_ck = devm_clk_get(dev, name);
> +	if (IS_ERR(port->axi_ck)) {
> +		if (PTR_ERR(port->axi_ck) == -EPROBE_DEFER)
> +			return -EPROBE_DEFER;
> +
> +		port->axi_ck = NULL;
> +	}
> +
> +	snprintf(name, sizeof(name), "aux_ck%d", index);
> +	port->aux_ck = devm_clk_get(dev, name);
> +	if (IS_ERR(port->aux_ck)) {
> +		if (PTR_ERR(port->aux_ck) == -EPROBE_DEFER)
> +			return -EPROBE_DEFER;
> +
> +		port->aux_ck = NULL;
> +	}
> +
> +	snprintf(name, sizeof(name), "obff_ck%d", index);
> +	port->obff_ck = devm_clk_get(dev, name);
> +	if (IS_ERR(port->obff_ck)) {
> +		if (PTR_ERR(port->obff_ck) == -EPROBE_DEFER)
> +			return -EPROBE_DEFER;
> +
> +		port->obff_ck = NULL;
> +	}
> +
> +	snprintf(name, sizeof(name), "pipe_ck%d", index);
> +	port->pipe_ck = devm_clk_get(dev, name);
> +	if (IS_ERR(port->pipe_ck)) {
> +		if (PTR_ERR(port->pipe_ck) == -EPROBE_DEFER)
> +			return -EPROBE_DEFER;
> +
> +		port->pipe_ck = NULL;
> +	}
> +
>  	snprintf(name, sizeof(name), "pcie-rst%d", index);
>  	port->reset = devm_reset_control_get_optional(dev, name);
>  	if (PTR_ERR(port->reset) == -EPROBE_DEFER)
> @@ -324,6 +794,12 @@ static int mtk_pcie_parse_ports(struct mtk_pcie *pcie,
>  	port->index = index;
>  	port->pcie = pcie;
>  
> +	if (pcie->soc->setup_irq) {
> +		err = pcie->soc->setup_irq(port, node);
> +		if (err)
> +			return err;
> +	}
> +
>  	INIT_LIST_HEAD(&port->list);
>  	list_add_tail(&port->list, &pcie->ports);
>  
> @@ -553,9 +1029,17 @@ static struct mtk_pcie_soc mtk_pcie_soc_v1 = {
>  	.startup = mtk_pcie_startup_ports,
>  };
>  
> +static struct mtk_pcie_soc mtk_pcie_soc_v2 = {
> +	.ops = &mtk_pcie_ops_v2,
> +	.startup = mtk_pcie_startup_ports_v2,
> +	.setup_irq = mtk_pcie_setup_irq,
> +};
> +
>  static const struct of_device_id mtk_pcie_ids[] = {
>  	{ .compatible = "mediatek,mt2701-pcie", .data = &mtk_pcie_soc_v1 },
>  	{ .compatible = "mediatek,mt7623-pcie", .data = &mtk_pcie_soc_v1 },
> +	{ .compatible = "mediatek,mt2712-pcie", .data = &mtk_pcie_soc_v2 },
> +	{ .compatible = "mediatek,mt7622-pcie", .data = &mtk_pcie_soc_v2 },
>  	{},
>  };
>  
> -- 
> 2.6.4
> 

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v2 5/5] dt-bindings: PCI: add support for new generation controller
  2017-07-27  2:58   ` honghui.zhang
  (?)
@ 2017-08-03 22:45     ` Bjorn Helgaas
  -1 siblings, 0 replies; 80+ messages in thread
From: Bjorn Helgaas @ 2017-08-03 22:45 UTC (permalink / raw)
  To: honghui.zhang
  Cc: bhelgaas, robh, robh+dt, matthias.bgg, linux-arm-kernel,
	linux-mediatek, linux-pci, linux-kernel, devicetree,
	yingjoe.chen, eddie.huang, ryder.lee, youlin.pei, hongkun.cao,
	sean.wang, xinping.qian, yt.shen, yong.wu

On Thu, Jul 27, 2017 at 10:58:39AM +0800, honghui.zhang@mediatek.com wrote:
> From: Ryder Lee <ryder.lee@mediatek.com>
> 
> Add support for MediaTek new generation controller and update related
> properities.
> 
> Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> Signed-off-by: Honghui Zhang <honghui.zhang@mediatek.com>
> ---
>  .../devicetree/bindings/pci/mediatek-pcie.txt      | 168 ++++++++++++++++++++-
>  1 file changed, 161 insertions(+), 7 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/pci/mediatek-pcie.txt b/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
> index a968f25..179329b 100644
> --- a/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
> +++ b/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
> @@ -3,18 +3,31 @@ MediaTek Gen2 PCIe controller
>  Required properties:
>  - compatible: Should contain one of the following string:
>  	"mediatek,mt2701-pcie"
> +	"mediatek,mt2712-pcie"
> +	"mediatek,mt7622-pcie"
>  	"mediatek,mt7623-pcie"
>  - device_type: Must be "pci"
> -- reg: Base addresses and lengths of the PCIe controller.
> +- reg: Base addresses and lengths of the PICe subsys and root ports.

s/PICe/PCIe/

> +- reg-names: Names of the above areas to use during resource look-up.
>  - #address-cells: Address representation for root ports (must be 3)
>  - #size-cells: Size representation for root ports (must be 2)
>  - clocks: Must contain an entry for each entry in clock-names.
>    See ../clocks/clock-bindings.txt for details.
> -- clock-names: Must include the following entries:
> -  - free_ck :for reference clock of PCIe subsys
> -  - sys_ck0 :for clock of Port0
> -  - sys_ck1 :for clock of Port1
> -  - sys_ck2 :for clock of Port2
> +- clock-names:
> +  Mandatory entries:
> +   - sys_ckN :transaction layer and data link layer clock
> +  Required entries for MT2701/MT7623:
> +   - free_ck :for reference clock of PCIe subsys
> +  Required entries for MT2712/MT7622:
> +   - ahb_ckN :AHB slave interface operating clock for CSR access and RC
> +	      initiated MMIO access
> +  Required entries for MT7622:
> +   - axi_ckN :application layer MMIO channel operating clock
> +   - aux_ckN :pe2_mac_bridge and pe2_mac_core operating clock when
> +	      pcie_mac_ck/pcie_pipe_ck is turned off
> +   - obff_ckN :OBFF functional block operating clock
> +   - pipe_ckN :LTSSM and phy/mac layer operating clock

s/phy/PHY/
s/mac/MAC/

> +  where N starting from 0 to the maximum number of root ports.

Probably to "one less than the number of root ports"?

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v2 5/5] dt-bindings: PCI: add support for new generation controller
@ 2017-08-03 22:45     ` Bjorn Helgaas
  0 siblings, 0 replies; 80+ messages in thread
From: Bjorn Helgaas @ 2017-08-03 22:45 UTC (permalink / raw)
  To: honghui.zhang
  Cc: youlin.pei, devicetree, hongkun.cao, ryder.lee, linux-pci,
	sean.wang, yong.wu, linux-kernel, robh+dt, yt.shen, matthias.bgg,
	robh, linux-mediatek, xinping.qian, bhelgaas, yingjoe.chen,
	eddie.huang, linux-arm-kernel

On Thu, Jul 27, 2017 at 10:58:39AM +0800, honghui.zhang@mediatek.com wrote:
> From: Ryder Lee <ryder.lee@mediatek.com>
> 
> Add support for MediaTek new generation controller and update related
> properities.
> 
> Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> Signed-off-by: Honghui Zhang <honghui.zhang@mediatek.com>
> ---
>  .../devicetree/bindings/pci/mediatek-pcie.txt      | 168 ++++++++++++++++++++-
>  1 file changed, 161 insertions(+), 7 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/pci/mediatek-pcie.txt b/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
> index a968f25..179329b 100644
> --- a/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
> +++ b/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
> @@ -3,18 +3,31 @@ MediaTek Gen2 PCIe controller
>  Required properties:
>  - compatible: Should contain one of the following string:
>  	"mediatek,mt2701-pcie"
> +	"mediatek,mt2712-pcie"
> +	"mediatek,mt7622-pcie"
>  	"mediatek,mt7623-pcie"
>  - device_type: Must be "pci"
> -- reg: Base addresses and lengths of the PCIe controller.
> +- reg: Base addresses and lengths of the PICe subsys and root ports.

s/PICe/PCIe/

> +- reg-names: Names of the above areas to use during resource look-up.
>  - #address-cells: Address representation for root ports (must be 3)
>  - #size-cells: Size representation for root ports (must be 2)
>  - clocks: Must contain an entry for each entry in clock-names.
>    See ../clocks/clock-bindings.txt for details.
> -- clock-names: Must include the following entries:
> -  - free_ck :for reference clock of PCIe subsys
> -  - sys_ck0 :for clock of Port0
> -  - sys_ck1 :for clock of Port1
> -  - sys_ck2 :for clock of Port2
> +- clock-names:
> +  Mandatory entries:
> +   - sys_ckN :transaction layer and data link layer clock
> +  Required entries for MT2701/MT7623:
> +   - free_ck :for reference clock of PCIe subsys
> +  Required entries for MT2712/MT7622:
> +   - ahb_ckN :AHB slave interface operating clock for CSR access and RC
> +	      initiated MMIO access
> +  Required entries for MT7622:
> +   - axi_ckN :application layer MMIO channel operating clock
> +   - aux_ckN :pe2_mac_bridge and pe2_mac_core operating clock when
> +	      pcie_mac_ck/pcie_pipe_ck is turned off
> +   - obff_ckN :OBFF functional block operating clock
> +   - pipe_ckN :LTSSM and phy/mac layer operating clock

s/phy/PHY/
s/mac/MAC/

> +  where N starting from 0 to the maximum number of root ports.

Probably to "one less than the number of root ports"?

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 80+ messages in thread

* [PATCH v2 5/5] dt-bindings: PCI: add support for new generation controller
@ 2017-08-03 22:45     ` Bjorn Helgaas
  0 siblings, 0 replies; 80+ messages in thread
From: Bjorn Helgaas @ 2017-08-03 22:45 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Jul 27, 2017 at 10:58:39AM +0800, honghui.zhang at mediatek.com wrote:
> From: Ryder Lee <ryder.lee@mediatek.com>
> 
> Add support for MediaTek new generation controller and update related
> properities.
> 
> Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> Signed-off-by: Honghui Zhang <honghui.zhang@mediatek.com>
> ---
>  .../devicetree/bindings/pci/mediatek-pcie.txt      | 168 ++++++++++++++++++++-
>  1 file changed, 161 insertions(+), 7 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/pci/mediatek-pcie.txt b/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
> index a968f25..179329b 100644
> --- a/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
> +++ b/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
> @@ -3,18 +3,31 @@ MediaTek Gen2 PCIe controller
>  Required properties:
>  - compatible: Should contain one of the following string:
>  	"mediatek,mt2701-pcie"
> +	"mediatek,mt2712-pcie"
> +	"mediatek,mt7622-pcie"
>  	"mediatek,mt7623-pcie"
>  - device_type: Must be "pci"
> -- reg: Base addresses and lengths of the PCIe controller.
> +- reg: Base addresses and lengths of the PICe subsys and root ports.

s/PICe/PCIe/

> +- reg-names: Names of the above areas to use during resource look-up.
>  - #address-cells: Address representation for root ports (must be 3)
>  - #size-cells: Size representation for root ports (must be 2)
>  - clocks: Must contain an entry for each entry in clock-names.
>    See ../clocks/clock-bindings.txt for details.
> -- clock-names: Must include the following entries:
> -  - free_ck :for reference clock of PCIe subsys
> -  - sys_ck0 :for clock of Port0
> -  - sys_ck1 :for clock of Port1
> -  - sys_ck2 :for clock of Port2
> +- clock-names:
> +  Mandatory entries:
> +   - sys_ckN :transaction layer and data link layer clock
> +  Required entries for MT2701/MT7623:
> +   - free_ck :for reference clock of PCIe subsys
> +  Required entries for MT2712/MT7622:
> +   - ahb_ckN :AHB slave interface operating clock for CSR access and RC
> +	      initiated MMIO access
> +  Required entries for MT7622:
> +   - axi_ckN :application layer MMIO channel operating clock
> +   - aux_ckN :pe2_mac_bridge and pe2_mac_core operating clock when
> +	      pcie_mac_ck/pcie_pipe_ck is turned off
> +   - obff_ckN :OBFF functional block operating clock
> +   - pipe_ckN :LTSSM and phy/mac layer operating clock

s/phy/PHY/
s/mac/MAC/

> +  where N starting from 0 to the maximum number of root ports.

Probably to "one less than the number of root ports"?

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v2 4/5] PCI: mediatek: Add new generation controller support
@ 2017-08-04  8:39       ` Honghui Zhang
  0 siblings, 0 replies; 80+ messages in thread
From: Honghui Zhang @ 2017-08-04  8:39 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: bhelgaas, robh, robh+dt, matthias.bgg, linux-arm-kernel,
	linux-mediatek, linux-pci, linux-kernel, devicetree,
	yingjoe.chen, eddie.huang, ryder.lee, hongkun.cao, youlin.pei,
	yong.wu, yt.shen, sean.wang, xinping.qian

Hi, Bjorn,
	Thanks very much for your reviews.
The mis-spells will be fixed in next version.


On Thu, 2017-08-03 at 17:42 -0500, Bjorn Helgaas wrote:


......
> > +}
> > +
> > +static struct mtk_pcie_port *mtk_pcie_find_port(struct mtk_pcie *pcie,
> > +						struct pci_bus *bus, int devfn)
> > +{
> > +	struct pci_dev *dev;
> > +	struct pci_bus *pbus;
> > +	struct mtk_pcie_port *port, *tmp;
> > +
> > +	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
> > +		if (bus->number == 0 && port->index == PCI_SLOT(devfn)) {
> > +			return port;
> > +		} else if (bus->number != 0) {
> > +			pbus = bus;
> > +			do {
> > +				dev = pbus->self;
> > +				if (port->index == PCI_SLOT(dev->devfn))
> > +					return port;
> > +				pbus = dev->bus;
> > +			} while (dev->bus->number != 0);
> > +		}
> > +	}
> > +
> > +	return NULL;
> 
> You should be able to use sysdata to avoid searching the list.
> See drivers/pci/host/pci-aardvark.c, for example.
> 

I could put the mtk_pcie * in sysdata, but still need to searching the
list to get the mtk_pcie_port *, how about:

	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
		if (port->index == PCI_SLOT(devfn))
			return port;
	}

> > +}
> > +
> > +static int mtk_pcie_config_read(struct pci_bus *bus, unsigned int devfn,
> > +				int where, int size, u32 *val)
> > +{
> > +	struct mtk_pcie_port *port;
> > +	struct pci_host_bridge *host = pci_find_host_bridge(bus);
> > +	struct mtk_pcie *pcie = pci_host_bridge_priv(host);
> 
> Sysdata should make this very simple; see advk_pcie_rd_conf().

thanks.

> 
> > +	u32 bn = bus->number;
> > +	int ret;
> > +
> > +	port = mtk_pcie_find_port(pcie, bus, devfn);
> > +	if (!port) {
> > +		*val = ~0;
> > +		return PCIBIOS_DEVICE_NOT_FOUND;
> > +	}
> > +
> > +	ret = mtk_pcie_hw_rd_cfg(port, bn, devfn, where, size, val);
> > +	if (ret)
> > +		*val = ~0;
> > +
> > +	return ret;
> > +}
> > +
> > +static int mtk_pcie_config_write(struct pci_bus *bus, unsigned int devfn,
> > +				 int where, int size, u32 val)
> > +{
> > +	u32 bn = bus->number;
> > +	struct pci_host_bridge *host = pci_find_host_bridge(bus);
> > +	struct mtk_pcie *pcie = pci_host_bridge_priv(host);
> > +	struct mtk_pcie_port *port;
> > +
> > +	port = mtk_pcie_find_port(pcie, bus, devfn);
> > +	if (!port)
> > +		return PCIBIOS_DEVICE_NOT_FOUND;
> > +
> > +	return mtk_pcie_hw_wr_cfg(port, bn, devfn, where, size, val);
> > +}
> > +
> > +static struct pci_ops mtk_pcie_ops_v2 = {
> > +	.read  = mtk_pcie_config_read,
> > +	.write = mtk_pcie_config_write,
> > +};
> > +
> > +static int mtk_pcie_startup_ports_v2(struct mtk_pcie_port *port)
> > +{
> > +	struct mtk_pcie *pcie = port->pcie;
> > +	struct resource *mem = &pcie->mem;
> > +	u32 val;
> > +	size_t size;
> > +	int err;
> > +
> > +	/* mt7622 platforms need to enable LTSSM and ASPM from PCIe subsys */
> > +	if (pcie->base) {
> > +		val = readl(pcie->base + PCIE_SYS_CFG_V2);
> > +		val |= PCIE_CSR_LTSSM_EN(port->index) |
> > +		       PCIE_CSR_ASPM_L1_EN(port->index);
> > +		writel(val, pcie->base + PCIE_SYS_CFG_V2);
> > +	}
> > +
> > +	/* Assert all reset signals */
> > +	writel(0, port->base + PCIE_RST_CTRL);
> > +
> > +	/*
> > +	 * Enable rc internal reset.
> > +	 * The reset will work when the link is from link up to link down.
> 
> ?  That sentence doesn't parse for me.

What about:

	/*
	 * Enable PCIe link down reset, if link status changed from link up to
	 * link down, this will reset MAC control registers and configuration
	 * space.
	 */

> 
> > +	 */
> > +	writel(PCI_LINKDOWN_RST_EN, port->base + PCIE_RST_CTRL);
> > +
> > +	/* De-assert phy, pe, pipe, mac and configuration reset	*/
> > +	val = readl(port->base + PCIE_RST_CTRL);
> > +	val |= PCIE_PHY_RSTB | PCIE_PERSTB | PCIE_PIPE_SRSTB |
> > +	       PCIE_MAC_SRSTB | PCIE_CRSTB;
> > +	writel(val, port->base + PCIE_RST_CTRL);
> > +
> > +	/* PCIe v2.0 need at least 100ms delay to train from Gen1 to Gen2 */
> > +	err = readl_poll_timeout(port->base + PCIE_LINK_STATUS_V2, val,
> > +				 !!(val & PCIE_PORT_LINKUP_V2), 20,
> > +				 100 * USEC_PER_MSEC);
> > +	if (err)
> > +		return -ETIMEDOUT;
> > +
> > +	/* Set INTx mask */
> > +	val = readl(port->base + PCIE_INT_MASK);
> > +	val &= ~INTX_MASK;
> > +	writel(val, port->base + PCIE_INT_MASK);
> > +
> > +	/* Set AHB to PCIe translation windows */
> > +	size = mem->end - mem->start;
> > +	val = AHB2PCIE_BASEL(mem->start) | AHB2PCIE_SIZE(fls(size));
> > +	writel(val, port->base + PCIE_AHB_TRANS_BASE0_L);
> > +
> > +	val = AHB2PCIE_BASEH(mem->start);
> > +	writel(val, port->base + PCIE_AHB_TRANS_BASE0_H);
> > +
> > +	/* Set PCIe to axi translation memory space.*/
> 
> s/axi/AXI/
> 
> > +	val = fls(0xffffffff) | WIN_ENABLE;
> > +	writel(val, port->base + PCIE_AXI_WINDOW0);
> > +
> > +	return 0;
> > +}
> > +
> > +static int mtk_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
> > +			     irq_hw_number_t hwirq)
> > +{
> > +	irq_set_chip_and_handler(irq, &dummy_irq_chip, handle_simple_irq);
> > +	irq_set_chip_data(irq, domain->host_data);
> > +
> > +	return 0;
> > +}
> > +
> > +static const struct irq_domain_ops intx_domain_ops = {
> > +	.map = mtk_pcie_intx_map,
> > +};
> > +
> > +static int mtk_pcie_init_irq_domain(struct mtk_pcie_port *port,
> > +				    struct device_node *node)
> > +{
> > +	struct device *dev = port->pcie->dev;
> > +	struct device_node *pcie_intc_node;
> > +
> > +	/* Setup INTx */
> > +	pcie_intc_node = of_get_next_child(node, NULL);
> > +	if (!pcie_intc_node) {
> > +		dev_err(dev, "No PCIe Intc node found\n");
> > +		return PTR_ERR(pcie_intc_node);
> > +	}
> > +
> > +	port->irq_domain = irq_domain_add_linear(pcie_intc_node, INTX_NUM,
> > +						 &intx_domain_ops, port);
> 
> I think there's an issue here with a 4-element IRQ domain and the
> hwirq numbers 1-4 from the of_irq_parse_and_map_pci() path, so INTD
> may not work correctly.
> 
> See
> http://lkml.kernel.org/r/20170801212931.GA26498@bhelgaas-glaptop.roam.corp.google.com
> and related discussion.
> 

Sorry, I did not get this,
I do some test with an intel E350T4 PCIe NICs, it's a x1 lane
multi-function device.
What I got from the log is below:
->of_irq_parse_and_map_pci
	->of_irq_parse_pci
		->irq_create_of_mapping
			->irq_create_fwspec_mapping
				->irq_domain_translate
				which will go through
				d->ops->translate #the hwirq really start from 0

And I tested every NIC port of the Intel E350T4 with tftp transfer data,
seems all are OK with this code.

What I got from the proc is as below:
cat /proc/interrupts
           CPU0       CPU1       CPU2       
  1:          0          0          0     GICv2  25 Level     vgic
  3:       5042        224        206     GICv2  30 Level     arch_timer
  4:          0          0          0     GICv2  27 Level     kvm guest
timer
  6:        201          0          0  MT_SYSIRQ  91 Level     ttyS0
  7:         57          0          0  MT_SYSIRQ 115 Level     mtk-pcie
  8:          0          0          0  MT_SYSIRQ 117 Level     mtk-pcie
  9:          9          0          0     dummy   0 Edge      eth0
 10:         40          0          0     dummy   1 Edge      eth1
 11:          5          0          0     dummy   2 Edge      eth2
 12:          3          0          0     dummy   3 Edge      eth3
IPI0:       314        507       1164       Rescheduling interrupts

or did I missed something?


> > +	if (!port->irq_domain) {
> > +		dev_err(dev, "Failed to get INTx IRQ domain\n");
> > +		return PTR_ERR(port->irq_domain);
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static irqreturn_t mtk_pcie_intr_handler(int irq, void *data)
> > +{
> > +	struct mtk_pcie_port *port = (struct mtk_pcie_port *)data;
> > +	struct device *dev = port->pcie->dev;
> > +	unsigned long status;
> > +	u32 virq;
> > +	u32 bit = INTX_SHIFT;
> > +
> > +	while ((status = readl(port->base + PCIE_INT_STATUS)) & INTX_MASK) {
> > +		for_each_set_bit_from(bit, &status, INTX_NUM + INTX_SHIFT) {
> > +			/* Clear the INTx */
> > +			writel(1 << bit, port->base + PCIE_INT_STATUS);
> > +			virq = irq_find_mapping(port->irq_domain,
> > +						bit - INTX_SHIFT);
> > +			if (virq)
> > +				generic_handle_irq(virq);
> > +			else
> > +				dev_err(dev, "unexpected IRQ, INT%d\n",
> > +					bit - INTX_SHIFT);
> 
> PCI INTx are conventionally INTA, INTB, INTC, INTD (not INT1, INT2,
> etc).
> 
> > +		}
> > +	}
> > +
> > +	return IRQ_HANDLED;
> > +}
> > +
> > +static int mtk_pcie_setup_irq(struct mtk_pcie_port *port,
> > +			      struct device_node *node)
> > +{
> > +	struct mtk_pcie *pcie = port->pcie;
> > +	struct device *dev = pcie->dev;
> > +	struct platform_device *pdev = to_platform_device(dev);
> > +	int err, irq;
> > +
> > +	irq = platform_get_irq(pdev, port->index);
> > +	err = devm_request_irq(dev, irq, mtk_pcie_intr_handler,
> > +			       IRQF_SHARED, "mtk-pcie", port);
> > +	if (err) {
> > +		dev_err(dev, "unable to request irq %d\n", irq);
> 
> s/irq/IRQ/
> 
> > +		return err;
> > +	}
> > +
> > +	err = mtk_pcie_init_irq_domain(port, node);
> > +	if (err) {
> > +		dev_err(dev, "failed to init pcie lagecy irq domain\n");
> 
> s/lagecy/legacy/
> s/irq/IRQ/
> s/pcie/PCIe/
> 
> > +		return -ENODEV;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> >  static void __iomem *mtk_pcie_map_bus(struct pci_bus *bus,
> >  				      unsigned int devfn, int where)
> >  {
> > @@ -249,13 +625,49 @@ static void mtk_pcie_enable_ports(struct mtk_pcie_port *port)
> >  
> >  	err = clk_prepare_enable(port->sys_ck);
> >  	if (err) {
> > -		dev_err(dev, "failed to enable port%d clock\n", port->index);
> > +		dev_err(dev, "failed to enable sys_ck%d\n", port->index);
> >  		goto err_sys_clk;
> >  	}
> >  
> > +	err = clk_prepare_enable(port->ahb_ck);
> > +	if (err) {
> > +		dev_err(dev, "failed to enable ahb_ck%d\n", port->index);
> > +		goto err_ahb_clk;
> > +	}
> > +
> > +	err = clk_prepare_enable(port->aux_ck);
> > +	if (err) {
> > +		dev_err(dev, "failed to enable aux_ck%d\n", port->index);
> > +		goto err_aux_clk;
> > +	}
> > +
> > +	err = clk_prepare_enable(port->axi_ck);
> > +	if (err) {
> > +		dev_err(dev, "failed to enable axi_ck%d\n", port->index);
> > +		goto err_axi_clk;
> > +	}
> > +
> > +	err = clk_prepare_enable(port->obff_ck);
> > +	if (err) {
> > +		dev_err(dev, "failed to enable obff_ck%d\n", port->index);
> > +		goto err_obff_clk;
> > +	}
> > +
> > +	err = clk_prepare_enable(port->pipe_ck);
> > +	if (err) {
> > +		dev_err(dev, "failed to enable pipe_ck%d\n", port->index);
> > +		goto err_pipe_clk;
> > +	}
> > +
> >  	reset_control_assert(port->reset);
> >  	reset_control_deassert(port->reset);
> >  
> > +	err = phy_init(port->phy);
> > +	if (err) {
> > +		dev_err(dev, "failed to initialize port%d phy\n", port->index);
> > +		goto err_phy_init;
> > +	}
> > +
> >  	err = phy_power_on(port->phy);
> >  	if (err) {
> >  		dev_err(dev, "failed to power on port%d phy\n", port->index);
> > @@ -269,6 +681,18 @@ static void mtk_pcie_enable_ports(struct mtk_pcie_port *port)
> >  
> >  	phy_power_off(port->phy);
> >  err_phy_on:
> > +	phy_exit(port->phy);
> > +err_phy_init:
> > +	clk_disable_unprepare(port->pipe_ck);
> > +err_pipe_clk:
> > +	clk_disable_unprepare(port->obff_ck);
> > +err_obff_clk:
> > +	clk_disable_unprepare(port->axi_ck);
> > +err_axi_clk:
> > +	clk_disable_unprepare(port->aux_ck);
> > +err_aux_clk:
> > +	clk_disable_unprepare(port->ahb_ck);
> > +err_ahb_clk:
> >  	clk_disable_unprepare(port->sys_ck);
> >  err_sys_clk:
> >  	mtk_pcie_port_free(port);
> > @@ -306,10 +730,56 @@ static int mtk_pcie_parse_ports(struct mtk_pcie *pcie,
> >  	snprintf(name, sizeof(name), "sys_ck%d", index);
> >  	port->sys_ck = devm_clk_get(dev, name);
> >  	if (IS_ERR(port->sys_ck)) {
> > -		dev_err(dev, "failed to get port%d clock\n", index);
> > +		dev_err(dev, "failed to get sys_ck%d\n", index);
> >  		return PTR_ERR(port->sys_ck);
> >  	}
> >  
> > +	/* sys_ck might be divided into the following parts in some chips */
> > +	snprintf(name, sizeof(name), "ahb_ck%d", index);
> > +	port->ahb_ck = devm_clk_get(dev, name);
> > +	if (IS_ERR(port->ahb_ck)) {
> > +		if (PTR_ERR(port->ahb_ck) == -EPROBE_DEFER)
> > +			return -EPROBE_DEFER;
> > +
> > +		port->ahb_ck = NULL;
> > +	}
> > +
> > +	snprintf(name, sizeof(name), "axi_ck%d", index);
> > +	port->axi_ck = devm_clk_get(dev, name);
> > +	if (IS_ERR(port->axi_ck)) {
> > +		if (PTR_ERR(port->axi_ck) == -EPROBE_DEFER)
> > +			return -EPROBE_DEFER;
> > +
> > +		port->axi_ck = NULL;
> > +	}
> > +
> > +	snprintf(name, sizeof(name), "aux_ck%d", index);
> > +	port->aux_ck = devm_clk_get(dev, name);
> > +	if (IS_ERR(port->aux_ck)) {
> > +		if (PTR_ERR(port->aux_ck) == -EPROBE_DEFER)
> > +			return -EPROBE_DEFER;
> > +
> > +		port->aux_ck = NULL;
> > +	}
> > +
> > +	snprintf(name, sizeof(name), "obff_ck%d", index);
> > +	port->obff_ck = devm_clk_get(dev, name);
> > +	if (IS_ERR(port->obff_ck)) {
> > +		if (PTR_ERR(port->obff_ck) == -EPROBE_DEFER)
> > +			return -EPROBE_DEFER;
> > +
> > +		port->obff_ck = NULL;
> > +	}
> > +
> > +	snprintf(name, sizeof(name), "pipe_ck%d", index);
> > +	port->pipe_ck = devm_clk_get(dev, name);
> > +	if (IS_ERR(port->pipe_ck)) {
> > +		if (PTR_ERR(port->pipe_ck) == -EPROBE_DEFER)
> > +			return -EPROBE_DEFER;
> > +
> > +		port->pipe_ck = NULL;
> > +	}
> > +
> >  	snprintf(name, sizeof(name), "pcie-rst%d", index);
> >  	port->reset = devm_reset_control_get_optional(dev, name);
> >  	if (PTR_ERR(port->reset) == -EPROBE_DEFER)
> > @@ -324,6 +794,12 @@ static int mtk_pcie_parse_ports(struct mtk_pcie *pcie,
> >  	port->index = index;
> >  	port->pcie = pcie;
> >  
> > +	if (pcie->soc->setup_irq) {
> > +		err = pcie->soc->setup_irq(port, node);
> > +		if (err)
> > +			return err;
> > +	}
> > +
> >  	INIT_LIST_HEAD(&port->list);
> >  	list_add_tail(&port->list, &pcie->ports);
> >  
> > @@ -553,9 +1029,17 @@ static struct mtk_pcie_soc mtk_pcie_soc_v1 = {
> >  	.startup = mtk_pcie_startup_ports,
> >  };
> >  
> > +static struct mtk_pcie_soc mtk_pcie_soc_v2 = {
> > +	.ops = &mtk_pcie_ops_v2,
> > +	.startup = mtk_pcie_startup_ports_v2,
> > +	.setup_irq = mtk_pcie_setup_irq,
> > +};
> > +
> >  static const struct of_device_id mtk_pcie_ids[] = {
> >  	{ .compatible = "mediatek,mt2701-pcie", .data = &mtk_pcie_soc_v1 },
> >  	{ .compatible = "mediatek,mt7623-pcie", .data = &mtk_pcie_soc_v1 },
> > +	{ .compatible = "mediatek,mt2712-pcie", .data = &mtk_pcie_soc_v2 },
> > +	{ .compatible = "mediatek,mt7622-pcie", .data = &mtk_pcie_soc_v2 },
> >  	{},
> >  };
> >  
> > -- 
> > 2.6.4
> > 

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v2 4/5] PCI: mediatek: Add new generation controller support
@ 2017-08-04  8:39       ` Honghui Zhang
  0 siblings, 0 replies; 80+ messages in thread
From: Honghui Zhang @ 2017-08-04  8:39 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: bhelgaas-hpIqsD4AKlfQT0dZR+AlfA, robh-+zGGX9k9yNkdnm+yROfE0A,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	matthias.bgg-Re5JQEeQqe8AvxtiuMwx3w,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-pci-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	yingjoe.chen-NuS5LvNUpcJWk0Htik3J/w,
	eddie.huang-NuS5LvNUpcJWk0Htik3J/w,
	ryder.lee-NuS5LvNUpcJWk0Htik3J/w,
	hongkun.cao-NuS5LvNUpcJWk0Htik3J/w,
	youlin.pei-NuS5LvNUpcJWk0Htik3J/w,
	yong.wu-NuS5LvNUpcJWk0Htik3J/w, yt.shen-NuS5LvNUpcJWk0Htik3J/w,
	sean.wang-NuS5LvNUpcJWk0Htik3J/w,
	xinping.qian-NuS5LvNUpcJWk0Htik3J/w

Hi, Bjorn,
	Thanks very much for your reviews.
The mis-spells will be fixed in next version.


On Thu, 2017-08-03 at 17:42 -0500, Bjorn Helgaas wrote:


......
> > +}
> > +
> > +static struct mtk_pcie_port *mtk_pcie_find_port(struct mtk_pcie *pcie,
> > +						struct pci_bus *bus, int devfn)
> > +{
> > +	struct pci_dev *dev;
> > +	struct pci_bus *pbus;
> > +	struct mtk_pcie_port *port, *tmp;
> > +
> > +	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
> > +		if (bus->number == 0 && port->index == PCI_SLOT(devfn)) {
> > +			return port;
> > +		} else if (bus->number != 0) {
> > +			pbus = bus;
> > +			do {
> > +				dev = pbus->self;
> > +				if (port->index == PCI_SLOT(dev->devfn))
> > +					return port;
> > +				pbus = dev->bus;
> > +			} while (dev->bus->number != 0);
> > +		}
> > +	}
> > +
> > +	return NULL;
> 
> You should be able to use sysdata to avoid searching the list.
> See drivers/pci/host/pci-aardvark.c, for example.
> 

I could put the mtk_pcie * in sysdata, but still need to searching the
list to get the mtk_pcie_port *, how about:

	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
		if (port->index == PCI_SLOT(devfn))
			return port;
	}

> > +}
> > +
> > +static int mtk_pcie_config_read(struct pci_bus *bus, unsigned int devfn,
> > +				int where, int size, u32 *val)
> > +{
> > +	struct mtk_pcie_port *port;
> > +	struct pci_host_bridge *host = pci_find_host_bridge(bus);
> > +	struct mtk_pcie *pcie = pci_host_bridge_priv(host);
> 
> Sysdata should make this very simple; see advk_pcie_rd_conf().

thanks.

> 
> > +	u32 bn = bus->number;
> > +	int ret;
> > +
> > +	port = mtk_pcie_find_port(pcie, bus, devfn);
> > +	if (!port) {
> > +		*val = ~0;
> > +		return PCIBIOS_DEVICE_NOT_FOUND;
> > +	}
> > +
> > +	ret = mtk_pcie_hw_rd_cfg(port, bn, devfn, where, size, val);
> > +	if (ret)
> > +		*val = ~0;
> > +
> > +	return ret;
> > +}
> > +
> > +static int mtk_pcie_config_write(struct pci_bus *bus, unsigned int devfn,
> > +				 int where, int size, u32 val)
> > +{
> > +	u32 bn = bus->number;
> > +	struct pci_host_bridge *host = pci_find_host_bridge(bus);
> > +	struct mtk_pcie *pcie = pci_host_bridge_priv(host);
> > +	struct mtk_pcie_port *port;
> > +
> > +	port = mtk_pcie_find_port(pcie, bus, devfn);
> > +	if (!port)
> > +		return PCIBIOS_DEVICE_NOT_FOUND;
> > +
> > +	return mtk_pcie_hw_wr_cfg(port, bn, devfn, where, size, val);
> > +}
> > +
> > +static struct pci_ops mtk_pcie_ops_v2 = {
> > +	.read  = mtk_pcie_config_read,
> > +	.write = mtk_pcie_config_write,
> > +};
> > +
> > +static int mtk_pcie_startup_ports_v2(struct mtk_pcie_port *port)
> > +{
> > +	struct mtk_pcie *pcie = port->pcie;
> > +	struct resource *mem = &pcie->mem;
> > +	u32 val;
> > +	size_t size;
> > +	int err;
> > +
> > +	/* mt7622 platforms need to enable LTSSM and ASPM from PCIe subsys */
> > +	if (pcie->base) {
> > +		val = readl(pcie->base + PCIE_SYS_CFG_V2);
> > +		val |= PCIE_CSR_LTSSM_EN(port->index) |
> > +		       PCIE_CSR_ASPM_L1_EN(port->index);
> > +		writel(val, pcie->base + PCIE_SYS_CFG_V2);
> > +	}
> > +
> > +	/* Assert all reset signals */
> > +	writel(0, port->base + PCIE_RST_CTRL);
> > +
> > +	/*
> > +	 * Enable rc internal reset.
> > +	 * The reset will work when the link is from link up to link down.
> 
> ?  That sentence doesn't parse for me.

What about:

	/*
	 * Enable PCIe link down reset, if link status changed from link up to
	 * link down, this will reset MAC control registers and configuration
	 * space.
	 */

> 
> > +	 */
> > +	writel(PCI_LINKDOWN_RST_EN, port->base + PCIE_RST_CTRL);
> > +
> > +	/* De-assert phy, pe, pipe, mac and configuration reset	*/
> > +	val = readl(port->base + PCIE_RST_CTRL);
> > +	val |= PCIE_PHY_RSTB | PCIE_PERSTB | PCIE_PIPE_SRSTB |
> > +	       PCIE_MAC_SRSTB | PCIE_CRSTB;
> > +	writel(val, port->base + PCIE_RST_CTRL);
> > +
> > +	/* PCIe v2.0 need at least 100ms delay to train from Gen1 to Gen2 */
> > +	err = readl_poll_timeout(port->base + PCIE_LINK_STATUS_V2, val,
> > +				 !!(val & PCIE_PORT_LINKUP_V2), 20,
> > +				 100 * USEC_PER_MSEC);
> > +	if (err)
> > +		return -ETIMEDOUT;
> > +
> > +	/* Set INTx mask */
> > +	val = readl(port->base + PCIE_INT_MASK);
> > +	val &= ~INTX_MASK;
> > +	writel(val, port->base + PCIE_INT_MASK);
> > +
> > +	/* Set AHB to PCIe translation windows */
> > +	size = mem->end - mem->start;
> > +	val = AHB2PCIE_BASEL(mem->start) | AHB2PCIE_SIZE(fls(size));
> > +	writel(val, port->base + PCIE_AHB_TRANS_BASE0_L);
> > +
> > +	val = AHB2PCIE_BASEH(mem->start);
> > +	writel(val, port->base + PCIE_AHB_TRANS_BASE0_H);
> > +
> > +	/* Set PCIe to axi translation memory space.*/
> 
> s/axi/AXI/
> 
> > +	val = fls(0xffffffff) | WIN_ENABLE;
> > +	writel(val, port->base + PCIE_AXI_WINDOW0);
> > +
> > +	return 0;
> > +}
> > +
> > +static int mtk_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
> > +			     irq_hw_number_t hwirq)
> > +{
> > +	irq_set_chip_and_handler(irq, &dummy_irq_chip, handle_simple_irq);
> > +	irq_set_chip_data(irq, domain->host_data);
> > +
> > +	return 0;
> > +}
> > +
> > +static const struct irq_domain_ops intx_domain_ops = {
> > +	.map = mtk_pcie_intx_map,
> > +};
> > +
> > +static int mtk_pcie_init_irq_domain(struct mtk_pcie_port *port,
> > +				    struct device_node *node)
> > +{
> > +	struct device *dev = port->pcie->dev;
> > +	struct device_node *pcie_intc_node;
> > +
> > +	/* Setup INTx */
> > +	pcie_intc_node = of_get_next_child(node, NULL);
> > +	if (!pcie_intc_node) {
> > +		dev_err(dev, "No PCIe Intc node found\n");
> > +		return PTR_ERR(pcie_intc_node);
> > +	}
> > +
> > +	port->irq_domain = irq_domain_add_linear(pcie_intc_node, INTX_NUM,
> > +						 &intx_domain_ops, port);
> 
> I think there's an issue here with a 4-element IRQ domain and the
> hwirq numbers 1-4 from the of_irq_parse_and_map_pci() path, so INTD
> may not work correctly.
> 
> See
> http://lkml.kernel.org/r/20170801212931.GA26498-1RhO1Y9PlrlHTL0Zs8A6p5iNqAH0jzoTYJqu5kTmcBRl57MIdRCFDg@public.gmane.org
> and related discussion.
> 

Sorry, I did not get this,
I do some test with an intel E350T4 PCIe NICs, it's a x1 lane
multi-function device.
What I got from the log is below:
->of_irq_parse_and_map_pci
	->of_irq_parse_pci
		->irq_create_of_mapping
			->irq_create_fwspec_mapping
				->irq_domain_translate
				which will go through
				d->ops->translate #the hwirq really start from 0

And I tested every NIC port of the Intel E350T4 with tftp transfer data,
seems all are OK with this code.

What I got from the proc is as below:
cat /proc/interrupts
           CPU0       CPU1       CPU2       
  1:          0          0          0     GICv2  25 Level     vgic
  3:       5042        224        206     GICv2  30 Level     arch_timer
  4:          0          0          0     GICv2  27 Level     kvm guest
timer
  6:        201          0          0  MT_SYSIRQ  91 Level     ttyS0
  7:         57          0          0  MT_SYSIRQ 115 Level     mtk-pcie
  8:          0          0          0  MT_SYSIRQ 117 Level     mtk-pcie
  9:          9          0          0     dummy   0 Edge      eth0
 10:         40          0          0     dummy   1 Edge      eth1
 11:          5          0          0     dummy   2 Edge      eth2
 12:          3          0          0     dummy   3 Edge      eth3
IPI0:       314        507       1164       Rescheduling interrupts

or did I missed something?


> > +	if (!port->irq_domain) {
> > +		dev_err(dev, "Failed to get INTx IRQ domain\n");
> > +		return PTR_ERR(port->irq_domain);
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static irqreturn_t mtk_pcie_intr_handler(int irq, void *data)
> > +{
> > +	struct mtk_pcie_port *port = (struct mtk_pcie_port *)data;
> > +	struct device *dev = port->pcie->dev;
> > +	unsigned long status;
> > +	u32 virq;
> > +	u32 bit = INTX_SHIFT;
> > +
> > +	while ((status = readl(port->base + PCIE_INT_STATUS)) & INTX_MASK) {
> > +		for_each_set_bit_from(bit, &status, INTX_NUM + INTX_SHIFT) {
> > +			/* Clear the INTx */
> > +			writel(1 << bit, port->base + PCIE_INT_STATUS);
> > +			virq = irq_find_mapping(port->irq_domain,
> > +						bit - INTX_SHIFT);
> > +			if (virq)
> > +				generic_handle_irq(virq);
> > +			else
> > +				dev_err(dev, "unexpected IRQ, INT%d\n",
> > +					bit - INTX_SHIFT);
> 
> PCI INTx are conventionally INTA, INTB, INTC, INTD (not INT1, INT2,
> etc).
> 
> > +		}
> > +	}
> > +
> > +	return IRQ_HANDLED;
> > +}
> > +
> > +static int mtk_pcie_setup_irq(struct mtk_pcie_port *port,
> > +			      struct device_node *node)
> > +{
> > +	struct mtk_pcie *pcie = port->pcie;
> > +	struct device *dev = pcie->dev;
> > +	struct platform_device *pdev = to_platform_device(dev);
> > +	int err, irq;
> > +
> > +	irq = platform_get_irq(pdev, port->index);
> > +	err = devm_request_irq(dev, irq, mtk_pcie_intr_handler,
> > +			       IRQF_SHARED, "mtk-pcie", port);
> > +	if (err) {
> > +		dev_err(dev, "unable to request irq %d\n", irq);
> 
> s/irq/IRQ/
> 
> > +		return err;
> > +	}
> > +
> > +	err = mtk_pcie_init_irq_domain(port, node);
> > +	if (err) {
> > +		dev_err(dev, "failed to init pcie lagecy irq domain\n");
> 
> s/lagecy/legacy/
> s/irq/IRQ/
> s/pcie/PCIe/
> 
> > +		return -ENODEV;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> >  static void __iomem *mtk_pcie_map_bus(struct pci_bus *bus,
> >  				      unsigned int devfn, int where)
> >  {
> > @@ -249,13 +625,49 @@ static void mtk_pcie_enable_ports(struct mtk_pcie_port *port)
> >  
> >  	err = clk_prepare_enable(port->sys_ck);
> >  	if (err) {
> > -		dev_err(dev, "failed to enable port%d clock\n", port->index);
> > +		dev_err(dev, "failed to enable sys_ck%d\n", port->index);
> >  		goto err_sys_clk;
> >  	}
> >  
> > +	err = clk_prepare_enable(port->ahb_ck);
> > +	if (err) {
> > +		dev_err(dev, "failed to enable ahb_ck%d\n", port->index);
> > +		goto err_ahb_clk;
> > +	}
> > +
> > +	err = clk_prepare_enable(port->aux_ck);
> > +	if (err) {
> > +		dev_err(dev, "failed to enable aux_ck%d\n", port->index);
> > +		goto err_aux_clk;
> > +	}
> > +
> > +	err = clk_prepare_enable(port->axi_ck);
> > +	if (err) {
> > +		dev_err(dev, "failed to enable axi_ck%d\n", port->index);
> > +		goto err_axi_clk;
> > +	}
> > +
> > +	err = clk_prepare_enable(port->obff_ck);
> > +	if (err) {
> > +		dev_err(dev, "failed to enable obff_ck%d\n", port->index);
> > +		goto err_obff_clk;
> > +	}
> > +
> > +	err = clk_prepare_enable(port->pipe_ck);
> > +	if (err) {
> > +		dev_err(dev, "failed to enable pipe_ck%d\n", port->index);
> > +		goto err_pipe_clk;
> > +	}
> > +
> >  	reset_control_assert(port->reset);
> >  	reset_control_deassert(port->reset);
> >  
> > +	err = phy_init(port->phy);
> > +	if (err) {
> > +		dev_err(dev, "failed to initialize port%d phy\n", port->index);
> > +		goto err_phy_init;
> > +	}
> > +
> >  	err = phy_power_on(port->phy);
> >  	if (err) {
> >  		dev_err(dev, "failed to power on port%d phy\n", port->index);
> > @@ -269,6 +681,18 @@ static void mtk_pcie_enable_ports(struct mtk_pcie_port *port)
> >  
> >  	phy_power_off(port->phy);
> >  err_phy_on:
> > +	phy_exit(port->phy);
> > +err_phy_init:
> > +	clk_disable_unprepare(port->pipe_ck);
> > +err_pipe_clk:
> > +	clk_disable_unprepare(port->obff_ck);
> > +err_obff_clk:
> > +	clk_disable_unprepare(port->axi_ck);
> > +err_axi_clk:
> > +	clk_disable_unprepare(port->aux_ck);
> > +err_aux_clk:
> > +	clk_disable_unprepare(port->ahb_ck);
> > +err_ahb_clk:
> >  	clk_disable_unprepare(port->sys_ck);
> >  err_sys_clk:
> >  	mtk_pcie_port_free(port);
> > @@ -306,10 +730,56 @@ static int mtk_pcie_parse_ports(struct mtk_pcie *pcie,
> >  	snprintf(name, sizeof(name), "sys_ck%d", index);
> >  	port->sys_ck = devm_clk_get(dev, name);
> >  	if (IS_ERR(port->sys_ck)) {
> > -		dev_err(dev, "failed to get port%d clock\n", index);
> > +		dev_err(dev, "failed to get sys_ck%d\n", index);
> >  		return PTR_ERR(port->sys_ck);
> >  	}
> >  
> > +	/* sys_ck might be divided into the following parts in some chips */
> > +	snprintf(name, sizeof(name), "ahb_ck%d", index);
> > +	port->ahb_ck = devm_clk_get(dev, name);
> > +	if (IS_ERR(port->ahb_ck)) {
> > +		if (PTR_ERR(port->ahb_ck) == -EPROBE_DEFER)
> > +			return -EPROBE_DEFER;
> > +
> > +		port->ahb_ck = NULL;
> > +	}
> > +
> > +	snprintf(name, sizeof(name), "axi_ck%d", index);
> > +	port->axi_ck = devm_clk_get(dev, name);
> > +	if (IS_ERR(port->axi_ck)) {
> > +		if (PTR_ERR(port->axi_ck) == -EPROBE_DEFER)
> > +			return -EPROBE_DEFER;
> > +
> > +		port->axi_ck = NULL;
> > +	}
> > +
> > +	snprintf(name, sizeof(name), "aux_ck%d", index);
> > +	port->aux_ck = devm_clk_get(dev, name);
> > +	if (IS_ERR(port->aux_ck)) {
> > +		if (PTR_ERR(port->aux_ck) == -EPROBE_DEFER)
> > +			return -EPROBE_DEFER;
> > +
> > +		port->aux_ck = NULL;
> > +	}
> > +
> > +	snprintf(name, sizeof(name), "obff_ck%d", index);
> > +	port->obff_ck = devm_clk_get(dev, name);
> > +	if (IS_ERR(port->obff_ck)) {
> > +		if (PTR_ERR(port->obff_ck) == -EPROBE_DEFER)
> > +			return -EPROBE_DEFER;
> > +
> > +		port->obff_ck = NULL;
> > +	}
> > +
> > +	snprintf(name, sizeof(name), "pipe_ck%d", index);
> > +	port->pipe_ck = devm_clk_get(dev, name);
> > +	if (IS_ERR(port->pipe_ck)) {
> > +		if (PTR_ERR(port->pipe_ck) == -EPROBE_DEFER)
> > +			return -EPROBE_DEFER;
> > +
> > +		port->pipe_ck = NULL;
> > +	}
> > +
> >  	snprintf(name, sizeof(name), "pcie-rst%d", index);
> >  	port->reset = devm_reset_control_get_optional(dev, name);
> >  	if (PTR_ERR(port->reset) == -EPROBE_DEFER)
> > @@ -324,6 +794,12 @@ static int mtk_pcie_parse_ports(struct mtk_pcie *pcie,
> >  	port->index = index;
> >  	port->pcie = pcie;
> >  
> > +	if (pcie->soc->setup_irq) {
> > +		err = pcie->soc->setup_irq(port, node);
> > +		if (err)
> > +			return err;
> > +	}
> > +
> >  	INIT_LIST_HEAD(&port->list);
> >  	list_add_tail(&port->list, &pcie->ports);
> >  
> > @@ -553,9 +1029,17 @@ static struct mtk_pcie_soc mtk_pcie_soc_v1 = {
> >  	.startup = mtk_pcie_startup_ports,
> >  };
> >  
> > +static struct mtk_pcie_soc mtk_pcie_soc_v2 = {
> > +	.ops = &mtk_pcie_ops_v2,
> > +	.startup = mtk_pcie_startup_ports_v2,
> > +	.setup_irq = mtk_pcie_setup_irq,
> > +};
> > +
> >  static const struct of_device_id mtk_pcie_ids[] = {
> >  	{ .compatible = "mediatek,mt2701-pcie", .data = &mtk_pcie_soc_v1 },
> >  	{ .compatible = "mediatek,mt7623-pcie", .data = &mtk_pcie_soc_v1 },
> > +	{ .compatible = "mediatek,mt2712-pcie", .data = &mtk_pcie_soc_v2 },
> > +	{ .compatible = "mediatek,mt7622-pcie", .data = &mtk_pcie_soc_v2 },
> >  	{},
> >  };
> >  
> > -- 
> > 2.6.4
> > 


--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 80+ messages in thread

* [PATCH v2 4/5] PCI: mediatek: Add new generation controller support
@ 2017-08-04  8:39       ` Honghui Zhang
  0 siblings, 0 replies; 80+ messages in thread
From: Honghui Zhang @ 2017-08-04  8:39 UTC (permalink / raw)
  To: linux-arm-kernel

Hi, Bjorn,
	Thanks very much for your reviews.
The mis-spells will be fixed in next version.


On Thu, 2017-08-03 at 17:42 -0500, Bjorn Helgaas wrote:


......
> > +}
> > +
> > +static struct mtk_pcie_port *mtk_pcie_find_port(struct mtk_pcie *pcie,
> > +						struct pci_bus *bus, int devfn)
> > +{
> > +	struct pci_dev *dev;
> > +	struct pci_bus *pbus;
> > +	struct mtk_pcie_port *port, *tmp;
> > +
> > +	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
> > +		if (bus->number == 0 && port->index == PCI_SLOT(devfn)) {
> > +			return port;
> > +		} else if (bus->number != 0) {
> > +			pbus = bus;
> > +			do {
> > +				dev = pbus->self;
> > +				if (port->index == PCI_SLOT(dev->devfn))
> > +					return port;
> > +				pbus = dev->bus;
> > +			} while (dev->bus->number != 0);
> > +		}
> > +	}
> > +
> > +	return NULL;
> 
> You should be able to use sysdata to avoid searching the list.
> See drivers/pci/host/pci-aardvark.c, for example.
> 

I could put the mtk_pcie * in sysdata, but still need to searching the
list to get the mtk_pcie_port *, how about:

	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
		if (port->index == PCI_SLOT(devfn))
			return port;
	}

> > +}
> > +
> > +static int mtk_pcie_config_read(struct pci_bus *bus, unsigned int devfn,
> > +				int where, int size, u32 *val)
> > +{
> > +	struct mtk_pcie_port *port;
> > +	struct pci_host_bridge *host = pci_find_host_bridge(bus);
> > +	struct mtk_pcie *pcie = pci_host_bridge_priv(host);
> 
> Sysdata should make this very simple; see advk_pcie_rd_conf().

thanks.

> 
> > +	u32 bn = bus->number;
> > +	int ret;
> > +
> > +	port = mtk_pcie_find_port(pcie, bus, devfn);
> > +	if (!port) {
> > +		*val = ~0;
> > +		return PCIBIOS_DEVICE_NOT_FOUND;
> > +	}
> > +
> > +	ret = mtk_pcie_hw_rd_cfg(port, bn, devfn, where, size, val);
> > +	if (ret)
> > +		*val = ~0;
> > +
> > +	return ret;
> > +}
> > +
> > +static int mtk_pcie_config_write(struct pci_bus *bus, unsigned int devfn,
> > +				 int where, int size, u32 val)
> > +{
> > +	u32 bn = bus->number;
> > +	struct pci_host_bridge *host = pci_find_host_bridge(bus);
> > +	struct mtk_pcie *pcie = pci_host_bridge_priv(host);
> > +	struct mtk_pcie_port *port;
> > +
> > +	port = mtk_pcie_find_port(pcie, bus, devfn);
> > +	if (!port)
> > +		return PCIBIOS_DEVICE_NOT_FOUND;
> > +
> > +	return mtk_pcie_hw_wr_cfg(port, bn, devfn, where, size, val);
> > +}
> > +
> > +static struct pci_ops mtk_pcie_ops_v2 = {
> > +	.read  = mtk_pcie_config_read,
> > +	.write = mtk_pcie_config_write,
> > +};
> > +
> > +static int mtk_pcie_startup_ports_v2(struct mtk_pcie_port *port)
> > +{
> > +	struct mtk_pcie *pcie = port->pcie;
> > +	struct resource *mem = &pcie->mem;
> > +	u32 val;
> > +	size_t size;
> > +	int err;
> > +
> > +	/* mt7622 platforms need to enable LTSSM and ASPM from PCIe subsys */
> > +	if (pcie->base) {
> > +		val = readl(pcie->base + PCIE_SYS_CFG_V2);
> > +		val |= PCIE_CSR_LTSSM_EN(port->index) |
> > +		       PCIE_CSR_ASPM_L1_EN(port->index);
> > +		writel(val, pcie->base + PCIE_SYS_CFG_V2);
> > +	}
> > +
> > +	/* Assert all reset signals */
> > +	writel(0, port->base + PCIE_RST_CTRL);
> > +
> > +	/*
> > +	 * Enable rc internal reset.
> > +	 * The reset will work when the link is from link up to link down.
> 
> ?  That sentence doesn't parse for me.

What about:

	/*
	 * Enable PCIe link down reset, if link status changed from link up to
	 * link down, this will reset MAC control registers and configuration
	 * space.
	 */

> 
> > +	 */
> > +	writel(PCI_LINKDOWN_RST_EN, port->base + PCIE_RST_CTRL);
> > +
> > +	/* De-assert phy, pe, pipe, mac and configuration reset	*/
> > +	val = readl(port->base + PCIE_RST_CTRL);
> > +	val |= PCIE_PHY_RSTB | PCIE_PERSTB | PCIE_PIPE_SRSTB |
> > +	       PCIE_MAC_SRSTB | PCIE_CRSTB;
> > +	writel(val, port->base + PCIE_RST_CTRL);
> > +
> > +	/* PCIe v2.0 need at least 100ms delay to train from Gen1 to Gen2 */
> > +	err = readl_poll_timeout(port->base + PCIE_LINK_STATUS_V2, val,
> > +				 !!(val & PCIE_PORT_LINKUP_V2), 20,
> > +				 100 * USEC_PER_MSEC);
> > +	if (err)
> > +		return -ETIMEDOUT;
> > +
> > +	/* Set INTx mask */
> > +	val = readl(port->base + PCIE_INT_MASK);
> > +	val &= ~INTX_MASK;
> > +	writel(val, port->base + PCIE_INT_MASK);
> > +
> > +	/* Set AHB to PCIe translation windows */
> > +	size = mem->end - mem->start;
> > +	val = AHB2PCIE_BASEL(mem->start) | AHB2PCIE_SIZE(fls(size));
> > +	writel(val, port->base + PCIE_AHB_TRANS_BASE0_L);
> > +
> > +	val = AHB2PCIE_BASEH(mem->start);
> > +	writel(val, port->base + PCIE_AHB_TRANS_BASE0_H);
> > +
> > +	/* Set PCIe to axi translation memory space.*/
> 
> s/axi/AXI/
> 
> > +	val = fls(0xffffffff) | WIN_ENABLE;
> > +	writel(val, port->base + PCIE_AXI_WINDOW0);
> > +
> > +	return 0;
> > +}
> > +
> > +static int mtk_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
> > +			     irq_hw_number_t hwirq)
> > +{
> > +	irq_set_chip_and_handler(irq, &dummy_irq_chip, handle_simple_irq);
> > +	irq_set_chip_data(irq, domain->host_data);
> > +
> > +	return 0;
> > +}
> > +
> > +static const struct irq_domain_ops intx_domain_ops = {
> > +	.map = mtk_pcie_intx_map,
> > +};
> > +
> > +static int mtk_pcie_init_irq_domain(struct mtk_pcie_port *port,
> > +				    struct device_node *node)
> > +{
> > +	struct device *dev = port->pcie->dev;
> > +	struct device_node *pcie_intc_node;
> > +
> > +	/* Setup INTx */
> > +	pcie_intc_node = of_get_next_child(node, NULL);
> > +	if (!pcie_intc_node) {
> > +		dev_err(dev, "No PCIe Intc node found\n");
> > +		return PTR_ERR(pcie_intc_node);
> > +	}
> > +
> > +	port->irq_domain = irq_domain_add_linear(pcie_intc_node, INTX_NUM,
> > +						 &intx_domain_ops, port);
> 
> I think there's an issue here with a 4-element IRQ domain and the
> hwirq numbers 1-4 from the of_irq_parse_and_map_pci() path, so INTD
> may not work correctly.
> 
> See
> http://lkml.kernel.org/r/20170801212931.GA26498 at bhelgaas-glaptop.roam.corp.google.com
> and related discussion.
> 

Sorry, I did not get this,
I do some test with an intel E350T4 PCIe NICs, it's a x1 lane
multi-function device.
What I got from the log is below:
->of_irq_parse_and_map_pci
	->of_irq_parse_pci
		->irq_create_of_mapping
			->irq_create_fwspec_mapping
				->irq_domain_translate
				which will go through
				d->ops->translate #the hwirq really start from 0

And I tested every NIC port of the Intel E350T4 with tftp transfer data,
seems all are OK with this code.

What I got from the proc is as below:
cat /proc/interrupts
           CPU0       CPU1       CPU2       
  1:          0          0          0     GICv2  25 Level     vgic
  3:       5042        224        206     GICv2  30 Level     arch_timer
  4:          0          0          0     GICv2  27 Level     kvm guest
timer
  6:        201          0          0  MT_SYSIRQ  91 Level     ttyS0
  7:         57          0          0  MT_SYSIRQ 115 Level     mtk-pcie
  8:          0          0          0  MT_SYSIRQ 117 Level     mtk-pcie
  9:          9          0          0     dummy   0 Edge      eth0
 10:         40          0          0     dummy   1 Edge      eth1
 11:          5          0          0     dummy   2 Edge      eth2
 12:          3          0          0     dummy   3 Edge      eth3
IPI0:       314        507       1164       Rescheduling interrupts

or did I missed something?


> > +	if (!port->irq_domain) {
> > +		dev_err(dev, "Failed to get INTx IRQ domain\n");
> > +		return PTR_ERR(port->irq_domain);
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static irqreturn_t mtk_pcie_intr_handler(int irq, void *data)
> > +{
> > +	struct mtk_pcie_port *port = (struct mtk_pcie_port *)data;
> > +	struct device *dev = port->pcie->dev;
> > +	unsigned long status;
> > +	u32 virq;
> > +	u32 bit = INTX_SHIFT;
> > +
> > +	while ((status = readl(port->base + PCIE_INT_STATUS)) & INTX_MASK) {
> > +		for_each_set_bit_from(bit, &status, INTX_NUM + INTX_SHIFT) {
> > +			/* Clear the INTx */
> > +			writel(1 << bit, port->base + PCIE_INT_STATUS);
> > +			virq = irq_find_mapping(port->irq_domain,
> > +						bit - INTX_SHIFT);
> > +			if (virq)
> > +				generic_handle_irq(virq);
> > +			else
> > +				dev_err(dev, "unexpected IRQ, INT%d\n",
> > +					bit - INTX_SHIFT);
> 
> PCI INTx are conventionally INTA, INTB, INTC, INTD (not INT1, INT2,
> etc).
> 
> > +		}
> > +	}
> > +
> > +	return IRQ_HANDLED;
> > +}
> > +
> > +static int mtk_pcie_setup_irq(struct mtk_pcie_port *port,
> > +			      struct device_node *node)
> > +{
> > +	struct mtk_pcie *pcie = port->pcie;
> > +	struct device *dev = pcie->dev;
> > +	struct platform_device *pdev = to_platform_device(dev);
> > +	int err, irq;
> > +
> > +	irq = platform_get_irq(pdev, port->index);
> > +	err = devm_request_irq(dev, irq, mtk_pcie_intr_handler,
> > +			       IRQF_SHARED, "mtk-pcie", port);
> > +	if (err) {
> > +		dev_err(dev, "unable to request irq %d\n", irq);
> 
> s/irq/IRQ/
> 
> > +		return err;
> > +	}
> > +
> > +	err = mtk_pcie_init_irq_domain(port, node);
> > +	if (err) {
> > +		dev_err(dev, "failed to init pcie lagecy irq domain\n");
> 
> s/lagecy/legacy/
> s/irq/IRQ/
> s/pcie/PCIe/
> 
> > +		return -ENODEV;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> >  static void __iomem *mtk_pcie_map_bus(struct pci_bus *bus,
> >  				      unsigned int devfn, int where)
> >  {
> > @@ -249,13 +625,49 @@ static void mtk_pcie_enable_ports(struct mtk_pcie_port *port)
> >  
> >  	err = clk_prepare_enable(port->sys_ck);
> >  	if (err) {
> > -		dev_err(dev, "failed to enable port%d clock\n", port->index);
> > +		dev_err(dev, "failed to enable sys_ck%d\n", port->index);
> >  		goto err_sys_clk;
> >  	}
> >  
> > +	err = clk_prepare_enable(port->ahb_ck);
> > +	if (err) {
> > +		dev_err(dev, "failed to enable ahb_ck%d\n", port->index);
> > +		goto err_ahb_clk;
> > +	}
> > +
> > +	err = clk_prepare_enable(port->aux_ck);
> > +	if (err) {
> > +		dev_err(dev, "failed to enable aux_ck%d\n", port->index);
> > +		goto err_aux_clk;
> > +	}
> > +
> > +	err = clk_prepare_enable(port->axi_ck);
> > +	if (err) {
> > +		dev_err(dev, "failed to enable axi_ck%d\n", port->index);
> > +		goto err_axi_clk;
> > +	}
> > +
> > +	err = clk_prepare_enable(port->obff_ck);
> > +	if (err) {
> > +		dev_err(dev, "failed to enable obff_ck%d\n", port->index);
> > +		goto err_obff_clk;
> > +	}
> > +
> > +	err = clk_prepare_enable(port->pipe_ck);
> > +	if (err) {
> > +		dev_err(dev, "failed to enable pipe_ck%d\n", port->index);
> > +		goto err_pipe_clk;
> > +	}
> > +
> >  	reset_control_assert(port->reset);
> >  	reset_control_deassert(port->reset);
> >  
> > +	err = phy_init(port->phy);
> > +	if (err) {
> > +		dev_err(dev, "failed to initialize port%d phy\n", port->index);
> > +		goto err_phy_init;
> > +	}
> > +
> >  	err = phy_power_on(port->phy);
> >  	if (err) {
> >  		dev_err(dev, "failed to power on port%d phy\n", port->index);
> > @@ -269,6 +681,18 @@ static void mtk_pcie_enable_ports(struct mtk_pcie_port *port)
> >  
> >  	phy_power_off(port->phy);
> >  err_phy_on:
> > +	phy_exit(port->phy);
> > +err_phy_init:
> > +	clk_disable_unprepare(port->pipe_ck);
> > +err_pipe_clk:
> > +	clk_disable_unprepare(port->obff_ck);
> > +err_obff_clk:
> > +	clk_disable_unprepare(port->axi_ck);
> > +err_axi_clk:
> > +	clk_disable_unprepare(port->aux_ck);
> > +err_aux_clk:
> > +	clk_disable_unprepare(port->ahb_ck);
> > +err_ahb_clk:
> >  	clk_disable_unprepare(port->sys_ck);
> >  err_sys_clk:
> >  	mtk_pcie_port_free(port);
> > @@ -306,10 +730,56 @@ static int mtk_pcie_parse_ports(struct mtk_pcie *pcie,
> >  	snprintf(name, sizeof(name), "sys_ck%d", index);
> >  	port->sys_ck = devm_clk_get(dev, name);
> >  	if (IS_ERR(port->sys_ck)) {
> > -		dev_err(dev, "failed to get port%d clock\n", index);
> > +		dev_err(dev, "failed to get sys_ck%d\n", index);
> >  		return PTR_ERR(port->sys_ck);
> >  	}
> >  
> > +	/* sys_ck might be divided into the following parts in some chips */
> > +	snprintf(name, sizeof(name), "ahb_ck%d", index);
> > +	port->ahb_ck = devm_clk_get(dev, name);
> > +	if (IS_ERR(port->ahb_ck)) {
> > +		if (PTR_ERR(port->ahb_ck) == -EPROBE_DEFER)
> > +			return -EPROBE_DEFER;
> > +
> > +		port->ahb_ck = NULL;
> > +	}
> > +
> > +	snprintf(name, sizeof(name), "axi_ck%d", index);
> > +	port->axi_ck = devm_clk_get(dev, name);
> > +	if (IS_ERR(port->axi_ck)) {
> > +		if (PTR_ERR(port->axi_ck) == -EPROBE_DEFER)
> > +			return -EPROBE_DEFER;
> > +
> > +		port->axi_ck = NULL;
> > +	}
> > +
> > +	snprintf(name, sizeof(name), "aux_ck%d", index);
> > +	port->aux_ck = devm_clk_get(dev, name);
> > +	if (IS_ERR(port->aux_ck)) {
> > +		if (PTR_ERR(port->aux_ck) == -EPROBE_DEFER)
> > +			return -EPROBE_DEFER;
> > +
> > +		port->aux_ck = NULL;
> > +	}
> > +
> > +	snprintf(name, sizeof(name), "obff_ck%d", index);
> > +	port->obff_ck = devm_clk_get(dev, name);
> > +	if (IS_ERR(port->obff_ck)) {
> > +		if (PTR_ERR(port->obff_ck) == -EPROBE_DEFER)
> > +			return -EPROBE_DEFER;
> > +
> > +		port->obff_ck = NULL;
> > +	}
> > +
> > +	snprintf(name, sizeof(name), "pipe_ck%d", index);
> > +	port->pipe_ck = devm_clk_get(dev, name);
> > +	if (IS_ERR(port->pipe_ck)) {
> > +		if (PTR_ERR(port->pipe_ck) == -EPROBE_DEFER)
> > +			return -EPROBE_DEFER;
> > +
> > +		port->pipe_ck = NULL;
> > +	}
> > +
> >  	snprintf(name, sizeof(name), "pcie-rst%d", index);
> >  	port->reset = devm_reset_control_get_optional(dev, name);
> >  	if (PTR_ERR(port->reset) == -EPROBE_DEFER)
> > @@ -324,6 +794,12 @@ static int mtk_pcie_parse_ports(struct mtk_pcie *pcie,
> >  	port->index = index;
> >  	port->pcie = pcie;
> >  
> > +	if (pcie->soc->setup_irq) {
> > +		err = pcie->soc->setup_irq(port, node);
> > +		if (err)
> > +			return err;
> > +	}
> > +
> >  	INIT_LIST_HEAD(&port->list);
> >  	list_add_tail(&port->list, &pcie->ports);
> >  
> > @@ -553,9 +1029,17 @@ static struct mtk_pcie_soc mtk_pcie_soc_v1 = {
> >  	.startup = mtk_pcie_startup_ports,
> >  };
> >  
> > +static struct mtk_pcie_soc mtk_pcie_soc_v2 = {
> > +	.ops = &mtk_pcie_ops_v2,
> > +	.startup = mtk_pcie_startup_ports_v2,
> > +	.setup_irq = mtk_pcie_setup_irq,
> > +};
> > +
> >  static const struct of_device_id mtk_pcie_ids[] = {
> >  	{ .compatible = "mediatek,mt2701-pcie", .data = &mtk_pcie_soc_v1 },
> >  	{ .compatible = "mediatek,mt7623-pcie", .data = &mtk_pcie_soc_v1 },
> > +	{ .compatible = "mediatek,mt2712-pcie", .data = &mtk_pcie_soc_v2 },
> > +	{ .compatible = "mediatek,mt7622-pcie", .data = &mtk_pcie_soc_v2 },
> >  	{},
> >  };
> >  
> > -- 
> > 2.6.4
> > 

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v2 4/5] PCI: mediatek: Add new generation controller support
  2017-08-04  8:39       ` Honghui Zhang
  (?)
@ 2017-08-04 13:18         ` Bjorn Helgaas
  -1 siblings, 0 replies; 80+ messages in thread
From: Bjorn Helgaas @ 2017-08-04 13:18 UTC (permalink / raw)
  To: Honghui Zhang
  Cc: bhelgaas, robh, robh+dt, matthias.bgg, linux-arm-kernel,
	linux-mediatek, linux-pci, linux-kernel, devicetree,
	yingjoe.chen, eddie.huang, ryder.lee, hongkun.cao, youlin.pei,
	yong.wu, yt.shen, sean.wang, xinping.qian

On Fri, Aug 04, 2017 at 04:39:36PM +0800, Honghui Zhang wrote:
> On Thu, 2017-08-03 at 17:42 -0500, Bjorn Helgaas wrote:
> 
> 
> ......
> > > +}
> > > +
> > > +static struct mtk_pcie_port *mtk_pcie_find_port(struct mtk_pcie *pcie,
> > > +						struct pci_bus *bus, int devfn)
> > > +{
> > > +	struct pci_dev *dev;
> > > +	struct pci_bus *pbus;
> > > +	struct mtk_pcie_port *port, *tmp;
> > > +
> > > +	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
> > > +		if (bus->number == 0 && port->index == PCI_SLOT(devfn)) {
> > > +			return port;
> > > +		} else if (bus->number != 0) {
> > > +			pbus = bus;
> > > +			do {
> > > +				dev = pbus->self;
> > > +				if (port->index == PCI_SLOT(dev->devfn))
> > > +					return port;
> > > +				pbus = dev->bus;
> > > +			} while (dev->bus->number != 0);
> > > +		}
> > > +	}
> > > +
> > > +	return NULL;
> > 
> > You should be able to use sysdata to avoid searching the list.
> > See drivers/pci/host/pci-aardvark.c, for example.
> > 
> 
> I could put the mtk_pcie * in sysdata, but still need to searching the
> list to get the mtk_pcie_port *, how about:
> 
> 	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
> 		if (port->index == PCI_SLOT(devfn))
> 			return port;
> 	}

No.  Other drivers don't need to search the list.  Please take a look
at them and see how they solve this problem.  I don't think your
hardware is fundamentally different in a way that means you need to
search when the others don't.

> > > +	 * Enable rc internal reset.
> > > +	 * The reset will work when the link is from link up to link down.
> > 
> > ?  That sentence doesn't parse for me.
> 
> What about:
> 
> 	/*
> 	 * Enable PCIe link down reset, if link status changed from link up to
> 	 * link down, this will reset MAC control registers and configuration
> 	 * space.
> 	 */

That at least parses as a sentence.

> > > +	port->irq_domain = irq_domain_add_linear(pcie_intc_node, INTX_NUM,
> > > +						 &intx_domain_ops, port);
> > 
> > I think there's an issue here with a 4-element IRQ domain and the
> > hwirq numbers 1-4 from the of_irq_parse_and_map_pci() path, so INTD
> > may not work correctly.
> > 
> > See
> > http://lkml.kernel.org/r/20170801212931.GA26498@bhelgaas-glaptop.roam.corp.google.com
> > and related discussion.
> 
> Sorry, I did not get this,
> I do some test with an intel E350T4 PCIe NICs, it's a x1 lane
> multi-function device.
> What I got from the log is below:
> ->of_irq_parse_and_map_pci
> 	->of_irq_parse_pci
> 		->irq_create_of_mapping
> 			->irq_create_fwspec_mapping
> 				->irq_domain_translate
> 				which will go through
> 				d->ops->translate #the hwirq really start from 0
> 
> And I tested every NIC port of the Intel E350T4 with tftp transfer data,
> seems all are OK with this code.

OK.  I don't know what d->ops->translate is involved here, but if it
works, I guess this is OK for now.  We're trying to clean this up and
make it consistent across all the drivers.  Many of them allocate a
5-element IRQ domain, some make a 4-element domain, and on some of
them INTD doesn't work.  It's a mess.

Bjorn

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v2 4/5] PCI: mediatek: Add new generation controller support
@ 2017-08-04 13:18         ` Bjorn Helgaas
  0 siblings, 0 replies; 80+ messages in thread
From: Bjorn Helgaas @ 2017-08-04 13:18 UTC (permalink / raw)
  To: Honghui Zhang
  Cc: youlin.pei, devicetree, hongkun.cao, ryder.lee, linux-pci,
	sean.wang, xinping.qian, linux-kernel, robh+dt, yt.shen,
	matthias.bgg, robh, linux-mediatek, yong.wu, bhelgaas,
	yingjoe.chen, eddie.huang, linux-arm-kernel

On Fri, Aug 04, 2017 at 04:39:36PM +0800, Honghui Zhang wrote:
> On Thu, 2017-08-03 at 17:42 -0500, Bjorn Helgaas wrote:
> 
> 
> ......
> > > +}
> > > +
> > > +static struct mtk_pcie_port *mtk_pcie_find_port(struct mtk_pcie *pcie,
> > > +						struct pci_bus *bus, int devfn)
> > > +{
> > > +	struct pci_dev *dev;
> > > +	struct pci_bus *pbus;
> > > +	struct mtk_pcie_port *port, *tmp;
> > > +
> > > +	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
> > > +		if (bus->number == 0 && port->index == PCI_SLOT(devfn)) {
> > > +			return port;
> > > +		} else if (bus->number != 0) {
> > > +			pbus = bus;
> > > +			do {
> > > +				dev = pbus->self;
> > > +				if (port->index == PCI_SLOT(dev->devfn))
> > > +					return port;
> > > +				pbus = dev->bus;
> > > +			} while (dev->bus->number != 0);
> > > +		}
> > > +	}
> > > +
> > > +	return NULL;
> > 
> > You should be able to use sysdata to avoid searching the list.
> > See drivers/pci/host/pci-aardvark.c, for example.
> > 
> 
> I could put the mtk_pcie * in sysdata, but still need to searching the
> list to get the mtk_pcie_port *, how about:
> 
> 	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
> 		if (port->index == PCI_SLOT(devfn))
> 			return port;
> 	}

No.  Other drivers don't need to search the list.  Please take a look
at them and see how they solve this problem.  I don't think your
hardware is fundamentally different in a way that means you need to
search when the others don't.

> > > +	 * Enable rc internal reset.
> > > +	 * The reset will work when the link is from link up to link down.
> > 
> > ?  That sentence doesn't parse for me.
> 
> What about:
> 
> 	/*
> 	 * Enable PCIe link down reset, if link status changed from link up to
> 	 * link down, this will reset MAC control registers and configuration
> 	 * space.
> 	 */

That at least parses as a sentence.

> > > +	port->irq_domain = irq_domain_add_linear(pcie_intc_node, INTX_NUM,
> > > +						 &intx_domain_ops, port);
> > 
> > I think there's an issue here with a 4-element IRQ domain and the
> > hwirq numbers 1-4 from the of_irq_parse_and_map_pci() path, so INTD
> > may not work correctly.
> > 
> > See
> > http://lkml.kernel.org/r/20170801212931.GA26498@bhelgaas-glaptop.roam.corp.google.com
> > and related discussion.
> 
> Sorry, I did not get this,
> I do some test with an intel E350T4 PCIe NICs, it's a x1 lane
> multi-function device.
> What I got from the log is below:
> ->of_irq_parse_and_map_pci
> 	->of_irq_parse_pci
> 		->irq_create_of_mapping
> 			->irq_create_fwspec_mapping
> 				->irq_domain_translate
> 				which will go through
> 				d->ops->translate #the hwirq really start from 0
> 
> And I tested every NIC port of the Intel E350T4 with tftp transfer data,
> seems all are OK with this code.

OK.  I don't know what d->ops->translate is involved here, but if it
works, I guess this is OK for now.  We're trying to clean this up and
make it consistent across all the drivers.  Many of them allocate a
5-element IRQ domain, some make a 4-element domain, and on some of
them INTD doesn't work.  It's a mess.

Bjorn

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 80+ messages in thread

* [PATCH v2 4/5] PCI: mediatek: Add new generation controller support
@ 2017-08-04 13:18         ` Bjorn Helgaas
  0 siblings, 0 replies; 80+ messages in thread
From: Bjorn Helgaas @ 2017-08-04 13:18 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Aug 04, 2017 at 04:39:36PM +0800, Honghui Zhang wrote:
> On Thu, 2017-08-03 at 17:42 -0500, Bjorn Helgaas wrote:
> 
> 
> ......
> > > +}
> > > +
> > > +static struct mtk_pcie_port *mtk_pcie_find_port(struct mtk_pcie *pcie,
> > > +						struct pci_bus *bus, int devfn)
> > > +{
> > > +	struct pci_dev *dev;
> > > +	struct pci_bus *pbus;
> > > +	struct mtk_pcie_port *port, *tmp;
> > > +
> > > +	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
> > > +		if (bus->number == 0 && port->index == PCI_SLOT(devfn)) {
> > > +			return port;
> > > +		} else if (bus->number != 0) {
> > > +			pbus = bus;
> > > +			do {
> > > +				dev = pbus->self;
> > > +				if (port->index == PCI_SLOT(dev->devfn))
> > > +					return port;
> > > +				pbus = dev->bus;
> > > +			} while (dev->bus->number != 0);
> > > +		}
> > > +	}
> > > +
> > > +	return NULL;
> > 
> > You should be able to use sysdata to avoid searching the list.
> > See drivers/pci/host/pci-aardvark.c, for example.
> > 
> 
> I could put the mtk_pcie * in sysdata, but still need to searching the
> list to get the mtk_pcie_port *, how about:
> 
> 	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
> 		if (port->index == PCI_SLOT(devfn))
> 			return port;
> 	}

No.  Other drivers don't need to search the list.  Please take a look
at them and see how they solve this problem.  I don't think your
hardware is fundamentally different in a way that means you need to
search when the others don't.

> > > +	 * Enable rc internal reset.
> > > +	 * The reset will work when the link is from link up to link down.
> > 
> > ?  That sentence doesn't parse for me.
> 
> What about:
> 
> 	/*
> 	 * Enable PCIe link down reset, if link status changed from link up to
> 	 * link down, this will reset MAC control registers and configuration
> 	 * space.
> 	 */

That at least parses as a sentence.

> > > +	port->irq_domain = irq_domain_add_linear(pcie_intc_node, INTX_NUM,
> > > +						 &intx_domain_ops, port);
> > 
> > I think there's an issue here with a 4-element IRQ domain and the
> > hwirq numbers 1-4 from the of_irq_parse_and_map_pci() path, so INTD
> > may not work correctly.
> > 
> > See
> > http://lkml.kernel.org/r/20170801212931.GA26498 at bhelgaas-glaptop.roam.corp.google.com
> > and related discussion.
> 
> Sorry, I did not get this,
> I do some test with an intel E350T4 PCIe NICs, it's a x1 lane
> multi-function device.
> What I got from the log is below:
> ->of_irq_parse_and_map_pci
> 	->of_irq_parse_pci
> 		->irq_create_of_mapping
> 			->irq_create_fwspec_mapping
> 				->irq_domain_translate
> 				which will go through
> 				d->ops->translate #the hwirq really start from 0
> 
> And I tested every NIC port of the Intel E350T4 with tftp transfer data,
> seems all are OK with this code.

OK.  I don't know what d->ops->translate is involved here, but if it
works, I guess this is OK for now.  We're trying to clean this up and
make it consistent across all the drivers.  Many of them allocate a
5-element IRQ domain, some make a 4-element domain, and on some of
them INTD doesn't work.  It's a mess.

Bjorn

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v2 4/5] PCI: mediatek: Add new generation controller support
  2017-08-04 13:18         ` Bjorn Helgaas
  (?)
@ 2017-08-05  4:52           ` Ryder Lee
  -1 siblings, 0 replies; 80+ messages in thread
From: Ryder Lee @ 2017-08-05  4:52 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Honghui Zhang, bhelgaas, robh, robh+dt, matthias.bgg,
	linux-arm-kernel, linux-mediatek, linux-pci, linux-kernel,
	devicetree, yingjoe.chen, eddie.huang, hongkun.cao, youlin.pei,
	yong.wu, yt.shen, sean.wang, xinping.qian

Hi Honghui, Bjorn,

On Fri, 2017-08-04 at 08:18 -0500, Bjorn Helgaas wrote:
> On Fri, Aug 04, 2017 at 04:39:36PM +0800, Honghui Zhang wrote:
> > On Thu, 2017-08-03 at 17:42 -0500, Bjorn Helgaas wrote:
> > > > +
> > > > +static struct mtk_pcie_port *mtk_pcie_find_port(struct mtk_pcie *pcie,
> > > > +						struct pci_bus *bus, int devfn)
> > > > +{
> > > > +	struct pci_dev *dev;
> > > > +	struct pci_bus *pbus;
> > > > +	struct mtk_pcie_port *port, *tmp;
> > > > +
> > > > +	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
> > > > +		if (bus->number == 0 && port->index == PCI_SLOT(devfn)) {
> > > > +			return port;
> > > > +		} else if (bus->number != 0) {
> > > > +			pbus = bus;
> > > > +			do {
> > > > +				dev = pbus->self;
> > > > +				if (port->index == PCI_SLOT(dev->devfn))
> > > > +					return port;
> > > > +				pbus = dev->bus;
> > > > +			} while (dev->bus->number != 0);
> > > > +		}
> > > > +	}
> > > > +
> > > > +	return NULL;
> > > 
> > > You should be able to use sysdata to avoid searching the list.
> > > See drivers/pci/host/pci-aardvark.c, for example.
> > > 
> > 
> > I could put the mtk_pcie * in sysdata, but still need to searching the
> > list to get the mtk_pcie_port *, how about:
> > 
> > 	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
> > 		if (port->index == PCI_SLOT(devfn))
> > 			return port;
> > 	}
> 
> No.  Other drivers don't need to search the list.  Please take a look
> at them and see how they solve this problem.  I don't think your
> hardware is fundamentally different in a way that means you need to
> search when the others don't.
> 

I'm not directly involved in this generation, but I guess the main reason why Honghui need to do that is just because this hardware access configuration space via per-port registers, not just for the guard.  
Currently, We had a host bridge with two ports (two subnodes in binding text), thus he tried to tells them apart so that he can get the correct registers.

Some platforms don't need to do that since they just have a single port (no more subnodes), the others might have specific/shared registers to access configuration space. (e.g. Tegra, MTK legacy IP block).
Or, he can split them into two independent nodes, but it will break common probing flow by doing so. (I'd prefer to use subnodes.)

Ryder

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v2 4/5] PCI: mediatek: Add new generation controller support
@ 2017-08-05  4:52           ` Ryder Lee
  0 siblings, 0 replies; 80+ messages in thread
From: Ryder Lee @ 2017-08-05  4:52 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Honghui Zhang, bhelgaas, robh, robh+dt, matthias.bgg,
	linux-arm-kernel, linux-mediatek, linux-pci, linux-kernel,
	devicetree, yingjoe.chen, eddie.huang, hongkun.cao, youlin.pei,
	yong.wu, yt.shen, sean.wang, xinping.qian

Hi Honghui, Bjorn,

On Fri, 2017-08-04 at 08:18 -0500, Bjorn Helgaas wrote:
> On Fri, Aug 04, 2017 at 04:39:36PM +0800, Honghui Zhang wrote:
> > On Thu, 2017-08-03 at 17:42 -0500, Bjorn Helgaas wrote:
> > > > +
> > > > +static struct mtk_pcie_port *mtk_pcie_find_port(struct mtk_pcie *pcie,
> > > > +						struct pci_bus *bus, int devfn)
> > > > +{
> > > > +	struct pci_dev *dev;
> > > > +	struct pci_bus *pbus;
> > > > +	struct mtk_pcie_port *port, *tmp;
> > > > +
> > > > +	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
> > > > +		if (bus->number == 0 && port->index == PCI_SLOT(devfn)) {
> > > > +			return port;
> > > > +		} else if (bus->number != 0) {
> > > > +			pbus = bus;
> > > > +			do {
> > > > +				dev = pbus->self;
> > > > +				if (port->index == PCI_SLOT(dev->devfn))
> > > > +					return port;
> > > > +				pbus = dev->bus;
> > > > +			} while (dev->bus->number != 0);
> > > > +		}
> > > > +	}
> > > > +
> > > > +	return NULL;
> > > 
> > > You should be able to use sysdata to avoid searching the list.
> > > See drivers/pci/host/pci-aardvark.c, for example.
> > > 
> > 
> > I could put the mtk_pcie * in sysdata, but still need to searching the
> > list to get the mtk_pcie_port *, how about:
> > 
> > 	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
> > 		if (port->index == PCI_SLOT(devfn))
> > 			return port;
> > 	}
> 
> No.  Other drivers don't need to search the list.  Please take a look
> at them and see how they solve this problem.  I don't think your
> hardware is fundamentally different in a way that means you need to
> search when the others don't.
> 

I'm not directly involved in this generation, but I guess the main reason why Honghui need to do that is just because this hardware access configuration space via per-port registers, not just for the guard.  
Currently, We had a host bridge with two ports (two subnodes in binding text), thus he tried to tells them apart so that he can get the correct registers.

Some platforms don't need to do that since they just have a single port (no more subnodes), the others might have specific/shared registers to access configuration space. (e.g. Tegra, MTK legacy IP block).
Or, he can split them into two independent nodes, but it will break common probing flow by doing so. (I'd prefer to use subnodes.)

Ryder

^ permalink raw reply	[flat|nested] 80+ messages in thread

* [PATCH v2 4/5] PCI: mediatek: Add new generation controller support
@ 2017-08-05  4:52           ` Ryder Lee
  0 siblings, 0 replies; 80+ messages in thread
From: Ryder Lee @ 2017-08-05  4:52 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Honghui, Bjorn,

On Fri, 2017-08-04 at 08:18 -0500, Bjorn Helgaas wrote:
> On Fri, Aug 04, 2017 at 04:39:36PM +0800, Honghui Zhang wrote:
> > On Thu, 2017-08-03 at 17:42 -0500, Bjorn Helgaas wrote:
> > > > +
> > > > +static struct mtk_pcie_port *mtk_pcie_find_port(struct mtk_pcie *pcie,
> > > > +						struct pci_bus *bus, int devfn)
> > > > +{
> > > > +	struct pci_dev *dev;
> > > > +	struct pci_bus *pbus;
> > > > +	struct mtk_pcie_port *port, *tmp;
> > > > +
> > > > +	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
> > > > +		if (bus->number == 0 && port->index == PCI_SLOT(devfn)) {
> > > > +			return port;
> > > > +		} else if (bus->number != 0) {
> > > > +			pbus = bus;
> > > > +			do {
> > > > +				dev = pbus->self;
> > > > +				if (port->index == PCI_SLOT(dev->devfn))
> > > > +					return port;
> > > > +				pbus = dev->bus;
> > > > +			} while (dev->bus->number != 0);
> > > > +		}
> > > > +	}
> > > > +
> > > > +	return NULL;
> > > 
> > > You should be able to use sysdata to avoid searching the list.
> > > See drivers/pci/host/pci-aardvark.c, for example.
> > > 
> > 
> > I could put the mtk_pcie * in sysdata, but still need to searching the
> > list to get the mtk_pcie_port *, how about:
> > 
> > 	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
> > 		if (port->index == PCI_SLOT(devfn))
> > 			return port;
> > 	}
> 
> No.  Other drivers don't need to search the list.  Please take a look
> at them and see how they solve this problem.  I don't think your
> hardware is fundamentally different in a way that means you need to
> search when the others don't.
> 

I'm not directly involved in this generation, but I guess the main reason why Honghui need to do that is just because this hardware access configuration space via per-port registers, not just for the guard.  
Currently, We had a host bridge with two ports (two subnodes in binding text), thus he tried to tells them apart so that he can get the correct registers.

Some platforms don't need to do that since they just have a single port (no more subnodes), the others might have specific/shared registers to access configuration space. (e.g. Tegra, MTK legacy IP block).
Or, he can split them into two independent nodes, but it will break common probing flow by doing so. (I'd prefer to use subnodes.)

Ryder

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v2 4/5] PCI: mediatek: Add new generation controller support
  2017-08-05  4:52           ` Ryder Lee
  (?)
@ 2017-08-05  6:16             ` Ryder Lee
  -1 siblings, 0 replies; 80+ messages in thread
From: Ryder Lee @ 2017-08-05  6:16 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Honghui Zhang, bhelgaas, robh, robh+dt, matthias.bgg,
	linux-arm-kernel, linux-mediatek, linux-pci, linux-kernel,
	devicetree, yingjoe.chen, eddie.huang, hongkun.cao, youlin.pei,
	yong.wu, yt.shen, sean.wang, xinping.qian

On Sat, 2017-08-05 at 12:52 +0800, Ryder Lee wrote:
> Hi Honghui, Bjorn,
> 
> On Fri, 2017-08-04 at 08:18 -0500, Bjorn Helgaas wrote:
> > On Fri, Aug 04, 2017 at 04:39:36PM +0800, Honghui Zhang wrote:
> > > On Thu, 2017-08-03 at 17:42 -0500, Bjorn Helgaas wrote:
> > > > > +
> > > > > +static struct mtk_pcie_port *mtk_pcie_find_port(struct mtk_pcie *pcie,
> > > > > +						struct pci_bus *bus, int devfn)
> > > > > +{
> > > > > +	struct pci_dev *dev;
> > > > > +	struct pci_bus *pbus;
> > > > > +	struct mtk_pcie_port *port, *tmp;
> > > > > +
> > > > > +	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
> > > > > +		if (bus->number == 0 && port->index == PCI_SLOT(devfn)) {
> > > > > +			return port;
> > > > > +		} else if (bus->number != 0) {
> > > > > +			pbus = bus;
> > > > > +			do {
> > > > > +				dev = pbus->self;
> > > > > +				if (port->index == PCI_SLOT(dev->devfn))
> > > > > +					return port;
> > > > > +				pbus = dev->bus;
> > > > > +			} while (dev->bus->number != 0);
> > > > > +		}
> > > > > +	}
> > > > > +
> > > > > +	return NULL;
> > > > 
> > > > You should be able to use sysdata to avoid searching the list.
> > > > See drivers/pci/host/pci-aardvark.c, for example.
> > > > 
> > > 
> > > I could put the mtk_pcie * in sysdata, but still need to searching the
> > > list to get the mtk_pcie_port *, how about:
> > > 
> > > 	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
> > > 		if (port->index == PCI_SLOT(devfn))
> > > 			return port;
> > > 	}
> > 
> > No.  Other drivers don't need to search the list.  Please take a look
> > at them and see how they solve this problem.  I don't think your
> > hardware is fundamentally different in a way that means you need to
> > search when the others don't.
> > 
> 
> I'm not directly involved in this generation, but I guess the main reason why Honghui need to do that is just because this hardware access configuration space via per-port registers, not just for the guard.  
> Currently, We had a host bridge with two ports (two subnodes in binding text), thus he tried to tells them apart so that he can get the correct registers.
> 
> Some platforms don't need to do that since they just have a single port (no more subnodes), the others might have specific/shared registers to access configuration space. (e.g. Tegra, MTK legacy IP block).
> Or, he can split them into two independent nodes, but it will break common probing flow by doing so. (I'd prefer to use subnodes.)
> 
> Ryder
> 

Sorry for the typesetting in previous mail and noise again,

I've took a look at pci-rcar-gen2.c, this is a similar case I can found
for Honghui's case. It gathers two ports reg regions into one, and uses
the "slot id" to calculate the cfg base of each port.

Perhaps this is a example for those who need to use subnodes and use
port registers for cfg operation. Not sure whether it's worthwhile doing
that since we need to changes ports/host structures.

Ryder.

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v2 4/5] PCI: mediatek: Add new generation controller support
@ 2017-08-05  6:16             ` Ryder Lee
  0 siblings, 0 replies; 80+ messages in thread
From: Ryder Lee @ 2017-08-05  6:16 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Honghui Zhang, bhelgaas, robh, robh+dt, matthias.bgg,
	linux-arm-kernel, linux-mediatek, linux-pci, linux-kernel,
	devicetree, yingjoe.chen, eddie.huang, hongkun.cao, youlin.pei,
	yong.wu, yt.shen, sean.wang, xinping.qian

On Sat, 2017-08-05 at 12:52 +0800, Ryder Lee wrote:
> Hi Honghui, Bjorn,
> 
> On Fri, 2017-08-04 at 08:18 -0500, Bjorn Helgaas wrote:
> > On Fri, Aug 04, 2017 at 04:39:36PM +0800, Honghui Zhang wrote:
> > > On Thu, 2017-08-03 at 17:42 -0500, Bjorn Helgaas wrote:
> > > > > +
> > > > > +static struct mtk_pcie_port *mtk_pcie_find_port(struct mtk_pcie *pcie,
> > > > > +						struct pci_bus *bus, int devfn)
> > > > > +{
> > > > > +	struct pci_dev *dev;
> > > > > +	struct pci_bus *pbus;
> > > > > +	struct mtk_pcie_port *port, *tmp;
> > > > > +
> > > > > +	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
> > > > > +		if (bus->number == 0 && port->index == PCI_SLOT(devfn)) {
> > > > > +			return port;
> > > > > +		} else if (bus->number != 0) {
> > > > > +			pbus = bus;
> > > > > +			do {
> > > > > +				dev = pbus->self;
> > > > > +				if (port->index == PCI_SLOT(dev->devfn))
> > > > > +					return port;
> > > > > +				pbus = dev->bus;
> > > > > +			} while (dev->bus->number != 0);
> > > > > +		}
> > > > > +	}
> > > > > +
> > > > > +	return NULL;
> > > > 
> > > > You should be able to use sysdata to avoid searching the list.
> > > > See drivers/pci/host/pci-aardvark.c, for example.
> > > > 
> > > 
> > > I could put the mtk_pcie * in sysdata, but still need to searching the
> > > list to get the mtk_pcie_port *, how about:
> > > 
> > > 	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
> > > 		if (port->index == PCI_SLOT(devfn))
> > > 			return port;
> > > 	}
> > 
> > No.  Other drivers don't need to search the list.  Please take a look
> > at them and see how they solve this problem.  I don't think your
> > hardware is fundamentally different in a way that means you need to
> > search when the others don't.
> > 
> 
> I'm not directly involved in this generation, but I guess the main reason why Honghui need to do that is just because this hardware access configuration space via per-port registers, not just for the guard.  
> Currently, We had a host bridge with two ports (two subnodes in binding text), thus he tried to tells them apart so that he can get the correct registers.
> 
> Some platforms don't need to do that since they just have a single port (no more subnodes), the others might have specific/shared registers to access configuration space. (e.g. Tegra, MTK legacy IP block).
> Or, he can split them into two independent nodes, but it will break common probing flow by doing so. (I'd prefer to use subnodes.)
> 
> Ryder
> 

Sorry for the typesetting in previous mail and noise again,

I've took a look at pci-rcar-gen2.c, this is a similar case I can found
for Honghui's case. It gathers two ports reg regions into one, and uses
the "slot id" to calculate the cfg base of each port.

Perhaps this is a example for those who need to use subnodes and use
port registers for cfg operation. Not sure whether it's worthwhile doing
that since we need to changes ports/host structures.

Ryder.

^ permalink raw reply	[flat|nested] 80+ messages in thread

* [PATCH v2 4/5] PCI: mediatek: Add new generation controller support
@ 2017-08-05  6:16             ` Ryder Lee
  0 siblings, 0 replies; 80+ messages in thread
From: Ryder Lee @ 2017-08-05  6:16 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, 2017-08-05 at 12:52 +0800, Ryder Lee wrote:
> Hi Honghui, Bjorn,
> 
> On Fri, 2017-08-04 at 08:18 -0500, Bjorn Helgaas wrote:
> > On Fri, Aug 04, 2017 at 04:39:36PM +0800, Honghui Zhang wrote:
> > > On Thu, 2017-08-03 at 17:42 -0500, Bjorn Helgaas wrote:
> > > > > +
> > > > > +static struct mtk_pcie_port *mtk_pcie_find_port(struct mtk_pcie *pcie,
> > > > > +						struct pci_bus *bus, int devfn)
> > > > > +{
> > > > > +	struct pci_dev *dev;
> > > > > +	struct pci_bus *pbus;
> > > > > +	struct mtk_pcie_port *port, *tmp;
> > > > > +
> > > > > +	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
> > > > > +		if (bus->number == 0 && port->index == PCI_SLOT(devfn)) {
> > > > > +			return port;
> > > > > +		} else if (bus->number != 0) {
> > > > > +			pbus = bus;
> > > > > +			do {
> > > > > +				dev = pbus->self;
> > > > > +				if (port->index == PCI_SLOT(dev->devfn))
> > > > > +					return port;
> > > > > +				pbus = dev->bus;
> > > > > +			} while (dev->bus->number != 0);
> > > > > +		}
> > > > > +	}
> > > > > +
> > > > > +	return NULL;
> > > > 
> > > > You should be able to use sysdata to avoid searching the list.
> > > > See drivers/pci/host/pci-aardvark.c, for example.
> > > > 
> > > 
> > > I could put the mtk_pcie * in sysdata, but still need to searching the
> > > list to get the mtk_pcie_port *, how about:
> > > 
> > > 	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
> > > 		if (port->index == PCI_SLOT(devfn))
> > > 			return port;
> > > 	}
> > 
> > No.  Other drivers don't need to search the list.  Please take a look
> > at them and see how they solve this problem.  I don't think your
> > hardware is fundamentally different in a way that means you need to
> > search when the others don't.
> > 
> 
> I'm not directly involved in this generation, but I guess the main reason why Honghui need to do that is just because this hardware access configuration space via per-port registers, not just for the guard.  
> Currently, We had a host bridge with two ports (two subnodes in binding text), thus he tried to tells them apart so that he can get the correct registers.
> 
> Some platforms don't need to do that since they just have a single port (no more subnodes), the others might have specific/shared registers to access configuration space. (e.g. Tegra, MTK legacy IP block).
> Or, he can split them into two independent nodes, but it will break common probing flow by doing so. (I'd prefer to use subnodes.)
> 
> Ryder
> 

Sorry for the typesetting in previous mail and noise again,

I've took a look at pci-rcar-gen2.c, this is a similar case I can found
for Honghui's case. It gathers two ports reg regions into one, and uses
the "slot id" to calculate the cfg base of each port.

Perhaps this is a example for those who need to use subnodes and use
port registers for cfg operation. Not sure whether it's worthwhile doing
that since we need to changes ports/host structures.

Ryder.

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v2 4/5] PCI: mediatek: Add new generation controller support
  2017-08-05  6:16             ` Ryder Lee
  (?)
@ 2017-08-07  3:40               ` Honghui Zhang
  -1 siblings, 0 replies; 80+ messages in thread
From: Honghui Zhang @ 2017-08-07  3:40 UTC (permalink / raw)
  To: Ryder Lee
  Cc: Bjorn Helgaas, bhelgaas, robh, robh+dt, matthias.bgg,
	linux-arm-kernel, linux-mediatek, linux-pci, linux-kernel,
	devicetree, yingjoe.chen, eddie.huang, hongkun.cao, youlin.pei,
	yong.wu, yt.shen, sean.wang, xinping.qian

On Sat, 2017-08-05 at 14:16 +0800, Ryder Lee wrote:
> On Sat, 2017-08-05 at 12:52 +0800, Ryder Lee wrote:
> > Hi Honghui, Bjorn,
> > 
> > On Fri, 2017-08-04 at 08:18 -0500, Bjorn Helgaas wrote:
> > > On Fri, Aug 04, 2017 at 04:39:36PM +0800, Honghui Zhang wrote:
> > > > On Thu, 2017-08-03 at 17:42 -0500, Bjorn Helgaas wrote:
> > > > > > +
> > > > > > +static struct mtk_pcie_port *mtk_pcie_find_port(struct mtk_pcie *pcie,
> > > > > > +						struct pci_bus *bus, int devfn)
> > > > > > +{
> > > > > > +	struct pci_dev *dev;
> > > > > > +	struct pci_bus *pbus;
> > > > > > +	struct mtk_pcie_port *port, *tmp;
> > > > > > +
> > > > > > +	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
> > > > > > +		if (bus->number == 0 && port->index == PCI_SLOT(devfn)) {
> > > > > > +			return port;
> > > > > > +		} else if (bus->number != 0) {
> > > > > > +			pbus = bus;
> > > > > > +			do {
> > > > > > +				dev = pbus->self;
> > > > > > +				if (port->index == PCI_SLOT(dev->devfn))
> > > > > > +					return port;
> > > > > > +				pbus = dev->bus;
> > > > > > +			} while (dev->bus->number != 0);
> > > > > > +		}
> > > > > > +	}
> > > > > > +
> > > > > > +	return NULL;
> > > > > 
> > > > > You should be able to use sysdata to avoid searching the list.
> > > > > See drivers/pci/host/pci-aardvark.c, for example.
> > > > > 
> > > > 
> > > > I could put the mtk_pcie * in sysdata, but still need to searching the
> > > > list to get the mtk_pcie_port *, how about:
> > > > 
> > > > 	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
> > > > 		if (port->index == PCI_SLOT(devfn))
> > > > 			return port;
> > > > 	}
> > > 
> > > No.  Other drivers don't need to search the list.  Please take a look
> > > at them and see how they solve this problem.  I don't think your
> > > hardware is fundamentally different in a way that means you need to
> > > search when the others don't.
> > > 
> > 
> > I'm not directly involved in this generation, but I guess the main reason why Honghui need to do that is just because this hardware access configuration space via per-port registers, not just for the guard.  
> > Currently, We had a host bridge with two ports (two subnodes in binding text), thus he tried to tells them apart so that he can get the correct registers.
> > 
> > Some platforms don't need to do that since they just have a single port (no more subnodes), the others might have specific/shared registers to access configuration space. (e.g. Tegra, MTK legacy IP block).
> > Or, he can split them into two independent nodes, but it will break common probing flow by doing so. (I'd prefer to use subnodes.)
> > 
> > Ryder
> > 
> 
> Sorry for the typesetting in previous mail and noise again,
> 
> I've took a look at pci-rcar-gen2.c, this is a similar case I can found
> for Honghui's case. It gathers two ports reg regions into one, and uses
> the "slot id" to calculate the cfg base of each port.
> 
> Perhaps this is a example for those who need to use subnodes and use
> port registers for cfg operation. Not sure whether it's worthwhile doing
> that since we need to changes ports/host structures.
> 
> Ryder.
> 
As Ryder's description, Mediatek's new generation HW blocks has two
separate ports, they have separate control register base address. We
must touch the per-port control register to access the EP's
configuration space. One port's control register is the only way to
access the EP's configuration space(the EP which is connect under this
very port).
Given an EP device, we need to determine which ports it's been
connected, and get the base address for that port. It's a bit like
pci-tegra/pci-mvebu.

Seems list is not forbidden, pci-tegra search the list to identify the
ports[1], mvebu use point array to search the ports[2], they have the
same functionality through different approach. I may propose another
patch to make the code like mvebu[2] if you insist, but I'm prefer the
current list way.

[1]http://elixir.free-electrons.com/linux/v4.13-rc4/source/drivers/pci/host/pci-tegra.c#L456
[2]http://elixir.free-electrons.com/linux/v4.13-rc4/source/drivers/pci/host/pci-mvebu.c#L780

thanks.
> 

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v2 4/5] PCI: mediatek: Add new generation controller support
@ 2017-08-07  3:40               ` Honghui Zhang
  0 siblings, 0 replies; 80+ messages in thread
From: Honghui Zhang @ 2017-08-07  3:40 UTC (permalink / raw)
  To: Ryder Lee
  Cc: Bjorn Helgaas, bhelgaas, robh, robh+dt, matthias.bgg,
	linux-arm-kernel, linux-mediatek, linux-pci, linux-kernel,
	devicetree, yingjoe.chen, eddie.huang, hongkun.cao, youlin.pei,
	yong.wu, yt.shen, sean.wang, xinping.qian

On Sat, 2017-08-05 at 14:16 +0800, Ryder Lee wrote:
> On Sat, 2017-08-05 at 12:52 +0800, Ryder Lee wrote:
> > Hi Honghui, Bjorn,
> > 
> > On Fri, 2017-08-04 at 08:18 -0500, Bjorn Helgaas wrote:
> > > On Fri, Aug 04, 2017 at 04:39:36PM +0800, Honghui Zhang wrote:
> > > > On Thu, 2017-08-03 at 17:42 -0500, Bjorn Helgaas wrote:
> > > > > > +
> > > > > > +static struct mtk_pcie_port *mtk_pcie_find_port(struct mtk_pcie *pcie,
> > > > > > +						struct pci_bus *bus, int devfn)
> > > > > > +{
> > > > > > +	struct pci_dev *dev;
> > > > > > +	struct pci_bus *pbus;
> > > > > > +	struct mtk_pcie_port *port, *tmp;
> > > > > > +
> > > > > > +	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
> > > > > > +		if (bus->number == 0 && port->index == PCI_SLOT(devfn)) {
> > > > > > +			return port;
> > > > > > +		} else if (bus->number != 0) {
> > > > > > +			pbus = bus;
> > > > > > +			do {
> > > > > > +				dev = pbus->self;
> > > > > > +				if (port->index == PCI_SLOT(dev->devfn))
> > > > > > +					return port;
> > > > > > +				pbus = dev->bus;
> > > > > > +			} while (dev->bus->number != 0);
> > > > > > +		}
> > > > > > +	}
> > > > > > +
> > > > > > +	return NULL;
> > > > > 
> > > > > You should be able to use sysdata to avoid searching the list.
> > > > > See drivers/pci/host/pci-aardvark.c, for example.
> > > > > 
> > > > 
> > > > I could put the mtk_pcie * in sysdata, but still need to searching the
> > > > list to get the mtk_pcie_port *, how about:
> > > > 
> > > > 	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
> > > > 		if (port->index == PCI_SLOT(devfn))
> > > > 			return port;
> > > > 	}
> > > 
> > > No.  Other drivers don't need to search the list.  Please take a look
> > > at them and see how they solve this problem.  I don't think your
> > > hardware is fundamentally different in a way that means you need to
> > > search when the others don't.
> > > 
> > 
> > I'm not directly involved in this generation, but I guess the main reason why Honghui need to do that is just because this hardware access configuration space via per-port registers, not just for the guard.  
> > Currently, We had a host bridge with two ports (two subnodes in binding text), thus he tried to tells them apart so that he can get the correct registers.
> > 
> > Some platforms don't need to do that since they just have a single port (no more subnodes), the others might have specific/shared registers to access configuration space. (e.g. Tegra, MTK legacy IP block).
> > Or, he can split them into two independent nodes, but it will break common probing flow by doing so. (I'd prefer to use subnodes.)
> > 
> > Ryder
> > 
> 
> Sorry for the typesetting in previous mail and noise again,
> 
> I've took a look at pci-rcar-gen2.c, this is a similar case I can found
> for Honghui's case. It gathers two ports reg regions into one, and uses
> the "slot id" to calculate the cfg base of each port.
> 
> Perhaps this is a example for those who need to use subnodes and use
> port registers for cfg operation. Not sure whether it's worthwhile doing
> that since we need to changes ports/host structures.
> 
> Ryder.
> 
As Ryder's description, Mediatek's new generation HW blocks has two
separate ports, they have separate control register base address. We
must touch the per-port control register to access the EP's
configuration space. One port's control register is the only way to
access the EP's configuration space(the EP which is connect under this
very port).
Given an EP device, we need to determine which ports it's been
connected, and get the base address for that port. It's a bit like
pci-tegra/pci-mvebu.

Seems list is not forbidden, pci-tegra search the list to identify the
ports[1], mvebu use point array to search the ports[2], they have the
same functionality through different approach. I may propose another
patch to make the code like mvebu[2] if you insist, but I'm prefer the
current list way.

[1]http://elixir.free-electrons.com/linux/v4.13-rc4/source/drivers/pci/host/pci-tegra.c#L456
[2]http://elixir.free-electrons.com/linux/v4.13-rc4/source/drivers/pci/host/pci-mvebu.c#L780

thanks.
> 

^ permalink raw reply	[flat|nested] 80+ messages in thread

* [PATCH v2 4/5] PCI: mediatek: Add new generation controller support
@ 2017-08-07  3:40               ` Honghui Zhang
  0 siblings, 0 replies; 80+ messages in thread
From: Honghui Zhang @ 2017-08-07  3:40 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, 2017-08-05 at 14:16 +0800, Ryder Lee wrote:
> On Sat, 2017-08-05 at 12:52 +0800, Ryder Lee wrote:
> > Hi Honghui, Bjorn,
> > 
> > On Fri, 2017-08-04 at 08:18 -0500, Bjorn Helgaas wrote:
> > > On Fri, Aug 04, 2017 at 04:39:36PM +0800, Honghui Zhang wrote:
> > > > On Thu, 2017-08-03 at 17:42 -0500, Bjorn Helgaas wrote:
> > > > > > +
> > > > > > +static struct mtk_pcie_port *mtk_pcie_find_port(struct mtk_pcie *pcie,
> > > > > > +						struct pci_bus *bus, int devfn)
> > > > > > +{
> > > > > > +	struct pci_dev *dev;
> > > > > > +	struct pci_bus *pbus;
> > > > > > +	struct mtk_pcie_port *port, *tmp;
> > > > > > +
> > > > > > +	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
> > > > > > +		if (bus->number == 0 && port->index == PCI_SLOT(devfn)) {
> > > > > > +			return port;
> > > > > > +		} else if (bus->number != 0) {
> > > > > > +			pbus = bus;
> > > > > > +			do {
> > > > > > +				dev = pbus->self;
> > > > > > +				if (port->index == PCI_SLOT(dev->devfn))
> > > > > > +					return port;
> > > > > > +				pbus = dev->bus;
> > > > > > +			} while (dev->bus->number != 0);
> > > > > > +		}
> > > > > > +	}
> > > > > > +
> > > > > > +	return NULL;
> > > > > 
> > > > > You should be able to use sysdata to avoid searching the list.
> > > > > See drivers/pci/host/pci-aardvark.c, for example.
> > > > > 
> > > > 
> > > > I could put the mtk_pcie * in sysdata, but still need to searching the
> > > > list to get the mtk_pcie_port *, how about:
> > > > 
> > > > 	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
> > > > 		if (port->index == PCI_SLOT(devfn))
> > > > 			return port;
> > > > 	}
> > > 
> > > No.  Other drivers don't need to search the list.  Please take a look
> > > at them and see how they solve this problem.  I don't think your
> > > hardware is fundamentally different in a way that means you need to
> > > search when the others don't.
> > > 
> > 
> > I'm not directly involved in this generation, but I guess the main reason why Honghui need to do that is just because this hardware access configuration space via per-port registers, not just for the guard.  
> > Currently, We had a host bridge with two ports (two subnodes in binding text), thus he tried to tells them apart so that he can get the correct registers.
> > 
> > Some platforms don't need to do that since they just have a single port (no more subnodes), the others might have specific/shared registers to access configuration space. (e.g. Tegra, MTK legacy IP block).
> > Or, he can split them into two independent nodes, but it will break common probing flow by doing so. (I'd prefer to use subnodes.)
> > 
> > Ryder
> > 
> 
> Sorry for the typesetting in previous mail and noise again,
> 
> I've took a look at pci-rcar-gen2.c, this is a similar case I can found
> for Honghui's case. It gathers two ports reg regions into one, and uses
> the "slot id" to calculate the cfg base of each port.
> 
> Perhaps this is a example for those who need to use subnodes and use
> port registers for cfg operation. Not sure whether it's worthwhile doing
> that since we need to changes ports/host structures.
> 
> Ryder.
> 
As Ryder's description, Mediatek's new generation HW blocks has two
separate ports, they have separate control register base address. We
must touch the per-port control register to access the EP's
configuration space. One port's control register is the only way to
access the EP's configuration space(the EP which is connect under this
very port).
Given an EP device, we need to determine which ports it's been
connected, and get the base address for that port. It's a bit like
pci-tegra/pci-mvebu.

Seems list is not forbidden, pci-tegra search the list to identify the
ports[1], mvebu use point array to search the ports[2], they have the
same functionality through different approach. I may propose another
patch to make the code like mvebu[2] if you insist, but I'm prefer the
current list way.

[1]http://elixir.free-electrons.com/linux/v4.13-rc4/source/drivers/pci/host/pci-tegra.c#L456
[2]http://elixir.free-electrons.com/linux/v4.13-rc4/source/drivers/pci/host/pci-mvebu.c#L780

thanks.
> 

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v2 4/5] PCI: mediatek: Add new generation controller support
  2017-08-05  4:52           ` Ryder Lee
  (?)
  (?)
@ 2017-08-08 20:16             ` Bjorn Helgaas
  -1 siblings, 0 replies; 80+ messages in thread
From: Bjorn Helgaas @ 2017-08-08 20:16 UTC (permalink / raw)
  To: Ryder Lee
  Cc: Honghui Zhang, bhelgaas, robh, robh+dt, matthias.bgg,
	linux-arm-kernel, linux-mediatek, linux-pci, linux-kernel,
	devicetree, yingjoe.chen, eddie.huang, hongkun.cao, youlin.pei,
	yong.wu, yt.shen, sean.wang, xinping.qian

On Sat, Aug 05, 2017 at 12:52:43PM +0800, Ryder Lee wrote:
> Hi Honghui, Bjorn,
> 
> On Fri, 2017-08-04 at 08:18 -0500, Bjorn Helgaas wrote:
> > On Fri, Aug 04, 2017 at 04:39:36PM +0800, Honghui Zhang wrote:
> > > On Thu, 2017-08-03 at 17:42 -0500, Bjorn Helgaas wrote:
> > > > > +
> > > > > +static struct mtk_pcie_port *mtk_pcie_find_port(struct mtk_pcie *pcie,
> > > > > +						struct pci_bus *bus, int devfn)
> > > > > +{
> > > > > +	struct pci_dev *dev;
> > > > > +	struct pci_bus *pbus;
> > > > > +	struct mtk_pcie_port *port, *tmp;
> > > > > +
> > > > > +	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
> > > > > +		if (bus->number == 0 && port->index == PCI_SLOT(devfn)) {
> > > > > +			return port;
> > > > > +		} else if (bus->number != 0) {
> > > > > +			pbus = bus;
> > > > > +			do {
> > > > > +				dev = pbus->self;
> > > > > +				if (port->index == PCI_SLOT(dev->devfn))
> > > > > +					return port;
> > > > > +				pbus = dev->bus;
> > > > > +			} while (dev->bus->number != 0);
> > > > > +		}
> > > > > +	}
> > > > > +
> > > > > +	return NULL;
> > > > 
> > > > You should be able to use sysdata to avoid searching the list.
> > > > See drivers/pci/host/pci-aardvark.c, for example.
> > > > 
> > > 
> > > I could put the mtk_pcie * in sysdata, but still need to searching the
> > > list to get the mtk_pcie_port *, how about:
> > > 
> > > 	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
> > > 		if (port->index == PCI_SLOT(devfn))
> > > 			return port;
> > > 	}
> > 
> > No.  Other drivers don't need to search the list.  Please take a look
> > at them and see how they solve this problem.  I don't think your
> > hardware is fundamentally different in a way that means you need to
> > search when the others don't.
> > 
> 
> I'm not directly involved in this generation, but I guess the main
> reason why Honghui need to do that is just because this hardware
> access configuration space via per-port registers, not just for the
> guard.  Currently, We had a host bridge with two ports (two subnodes
> in binding text), thus he tried to tells them apart so that he can
> get the correct registers.
> 
> Some platforms don't need to do that since they just have a single
> port (no more subnodes), the others might have specific/shared
> registers to access configuration space. (e.g. Tegra, MTK legacy IP
> block).  Or, he can split them into two independent nodes, but it
> will break common probing flow by doing so. (I'd prefer to use
> subnodes.)

The PCI core interface (pci_scan_root_bus_bridge()) starts with
sysdata in the struct pci_host_bridge, so every PCI bus under that
host bridge has the same sysdata.  

You have multiple root ports (sounds like two ports in this case)
under that host bridge.  Each port has independent interrupt mappings,
but the MMIO address space routed to the ports is described in the
upper-level host bridge (the "pcie" node in DT).  I assume the I/O and
MMIO routing through the root ports works as described in the
PCI-to-PCI bridge spec, using PCI_MEMORY_BASE, PCI_PREF_MEMORY_BASE,
etc.

If that's the case, I think your current DT "pcie" node is
appropriate, and both ports should have the same sysdata (as they do
in your current patch), and you do need some additional way to get
from that sysdata (the struct mtk_pcie) to the per-port data (the
struct mtk_pcie_port).

Apparently the two root ports of this MT7622/MT2712 controller are
hardwired at device (PCI_SLOT) 0 and 1.  Using a list to look that up
seems like a little overkill, since you could index an array by
PCI_SLOT(), but I guess you could do it either way.

I would probably rename "port->index" to "port->slot" or similar to
make it more obvious that it's not merely the Nth port we found; it's
the one that is hardwired at PCI_SLOT N.

Also, s/mtk_pcie_parse_ports/mtk_pcie_parse_port/, since it parses one
port each time you call it.

And factor out the lookup as Ryder suggested so it's not duplicated in
the mtk_pcie_config_read()/mtk_pcie_config_write() paths.

Bjorn

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v2 4/5] PCI: mediatek: Add new generation controller support
@ 2017-08-08 20:16             ` Bjorn Helgaas
  0 siblings, 0 replies; 80+ messages in thread
From: Bjorn Helgaas @ 2017-08-08 20:16 UTC (permalink / raw)
  To: Ryder Lee
  Cc: Honghui Zhang, bhelgaas-hpIqsD4AKlfQT0dZR+AlfA,
	robh-+zGGX9k9yNkdnm+yROfE0A, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	matthias.bgg-Re5JQEeQqe8AvxtiuMwx3w,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-pci-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	yingjoe.chen-NuS5LvNUpcJWk0Htik3J/w,
	eddie.huang-NuS5LvNUpcJWk0Htik3J/w,
	hongkun.cao-NuS5LvNUpcJWk0Htik3J/w,
	youlin.pei-NuS5LvNUpcJWk0Htik3J/w,
	yong.wu-NuS5LvNUpcJWk0Htik3J/w, yt.shen-NuS5LvNUpcJWk0Htik3J/w,
	sean.wang-NuS5LvNUpcJWk0Htik3J/w,
	xinping.qian-NuS5LvNUpcJWk0Htik3J/w

On Sat, Aug 05, 2017 at 12:52:43PM +0800, Ryder Lee wrote:
> Hi Honghui, Bjorn,
> 
> On Fri, 2017-08-04 at 08:18 -0500, Bjorn Helgaas wrote:
> > On Fri, Aug 04, 2017 at 04:39:36PM +0800, Honghui Zhang wrote:
> > > On Thu, 2017-08-03 at 17:42 -0500, Bjorn Helgaas wrote:
> > > > > +
> > > > > +static struct mtk_pcie_port *mtk_pcie_find_port(struct mtk_pcie *pcie,
> > > > > +						struct pci_bus *bus, int devfn)
> > > > > +{
> > > > > +	struct pci_dev *dev;
> > > > > +	struct pci_bus *pbus;
> > > > > +	struct mtk_pcie_port *port, *tmp;
> > > > > +
> > > > > +	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
> > > > > +		if (bus->number == 0 && port->index == PCI_SLOT(devfn)) {
> > > > > +			return port;
> > > > > +		} else if (bus->number != 0) {
> > > > > +			pbus = bus;
> > > > > +			do {
> > > > > +				dev = pbus->self;
> > > > > +				if (port->index == PCI_SLOT(dev->devfn))
> > > > > +					return port;
> > > > > +				pbus = dev->bus;
> > > > > +			} while (dev->bus->number != 0);
> > > > > +		}
> > > > > +	}
> > > > > +
> > > > > +	return NULL;
> > > > 
> > > > You should be able to use sysdata to avoid searching the list.
> > > > See drivers/pci/host/pci-aardvark.c, for example.
> > > > 
> > > 
> > > I could put the mtk_pcie * in sysdata, but still need to searching the
> > > list to get the mtk_pcie_port *, how about:
> > > 
> > > 	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
> > > 		if (port->index == PCI_SLOT(devfn))
> > > 			return port;
> > > 	}
> > 
> > No.  Other drivers don't need to search the list.  Please take a look
> > at them and see how they solve this problem.  I don't think your
> > hardware is fundamentally different in a way that means you need to
> > search when the others don't.
> > 
> 
> I'm not directly involved in this generation, but I guess the main
> reason why Honghui need to do that is just because this hardware
> access configuration space via per-port registers, not just for the
> guard.  Currently, We had a host bridge with two ports (two subnodes
> in binding text), thus he tried to tells them apart so that he can
> get the correct registers.
> 
> Some platforms don't need to do that since they just have a single
> port (no more subnodes), the others might have specific/shared
> registers to access configuration space. (e.g. Tegra, MTK legacy IP
> block).  Or, he can split them into two independent nodes, but it
> will break common probing flow by doing so. (I'd prefer to use
> subnodes.)

The PCI core interface (pci_scan_root_bus_bridge()) starts with
sysdata in the struct pci_host_bridge, so every PCI bus under that
host bridge has the same sysdata.  

You have multiple root ports (sounds like two ports in this case)
under that host bridge.  Each port has independent interrupt mappings,
but the MMIO address space routed to the ports is described in the
upper-level host bridge (the "pcie" node in DT).  I assume the I/O and
MMIO routing through the root ports works as described in the
PCI-to-PCI bridge spec, using PCI_MEMORY_BASE, PCI_PREF_MEMORY_BASE,
etc.

If that's the case, I think your current DT "pcie" node is
appropriate, and both ports should have the same sysdata (as they do
in your current patch), and you do need some additional way to get
from that sysdata (the struct mtk_pcie) to the per-port data (the
struct mtk_pcie_port).

Apparently the two root ports of this MT7622/MT2712 controller are
hardwired at device (PCI_SLOT) 0 and 1.  Using a list to look that up
seems like a little overkill, since you could index an array by
PCI_SLOT(), but I guess you could do it either way.

I would probably rename "port->index" to "port->slot" or similar to
make it more obvious that it's not merely the Nth port we found; it's
the one that is hardwired at PCI_SLOT N.

Also, s/mtk_pcie_parse_ports/mtk_pcie_parse_port/, since it parses one
port each time you call it.

And factor out the lookup as Ryder suggested so it's not duplicated in
the mtk_pcie_config_read()/mtk_pcie_config_write() paths.

Bjorn
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v2 4/5] PCI: mediatek: Add new generation controller support
@ 2017-08-08 20:16             ` Bjorn Helgaas
  0 siblings, 0 replies; 80+ messages in thread
From: Bjorn Helgaas @ 2017-08-08 20:16 UTC (permalink / raw)
  To: Ryder Lee
  Cc: youlin.pei, devicetree, hongkun.cao, yt.shen, linux-pci,
	sean.wang, xinping.qian, linux-kernel, robh+dt, matthias.bgg,
	robh, linux-mediatek, yong.wu, Honghui Zhang, bhelgaas,
	yingjoe.chen, eddie.huang, linux-arm-kernel

On Sat, Aug 05, 2017 at 12:52:43PM +0800, Ryder Lee wrote:
> Hi Honghui, Bjorn,
> 
> On Fri, 2017-08-04 at 08:18 -0500, Bjorn Helgaas wrote:
> > On Fri, Aug 04, 2017 at 04:39:36PM +0800, Honghui Zhang wrote:
> > > On Thu, 2017-08-03 at 17:42 -0500, Bjorn Helgaas wrote:
> > > > > +
> > > > > +static struct mtk_pcie_port *mtk_pcie_find_port(struct mtk_pcie *pcie,
> > > > > +						struct pci_bus *bus, int devfn)
> > > > > +{
> > > > > +	struct pci_dev *dev;
> > > > > +	struct pci_bus *pbus;
> > > > > +	struct mtk_pcie_port *port, *tmp;
> > > > > +
> > > > > +	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
> > > > > +		if (bus->number == 0 && port->index == PCI_SLOT(devfn)) {
> > > > > +			return port;
> > > > > +		} else if (bus->number != 0) {
> > > > > +			pbus = bus;
> > > > > +			do {
> > > > > +				dev = pbus->self;
> > > > > +				if (port->index == PCI_SLOT(dev->devfn))
> > > > > +					return port;
> > > > > +				pbus = dev->bus;
> > > > > +			} while (dev->bus->number != 0);
> > > > > +		}
> > > > > +	}
> > > > > +
> > > > > +	return NULL;
> > > > 
> > > > You should be able to use sysdata to avoid searching the list.
> > > > See drivers/pci/host/pci-aardvark.c, for example.
> > > > 
> > > 
> > > I could put the mtk_pcie * in sysdata, but still need to searching the
> > > list to get the mtk_pcie_port *, how about:
> > > 
> > > 	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
> > > 		if (port->index == PCI_SLOT(devfn))
> > > 			return port;
> > > 	}
> > 
> > No.  Other drivers don't need to search the list.  Please take a look
> > at them and see how they solve this problem.  I don't think your
> > hardware is fundamentally different in a way that means you need to
> > search when the others don't.
> > 
> 
> I'm not directly involved in this generation, but I guess the main
> reason why Honghui need to do that is just because this hardware
> access configuration space via per-port registers, not just for the
> guard.  Currently, We had a host bridge with two ports (two subnodes
> in binding text), thus he tried to tells them apart so that he can
> get the correct registers.
> 
> Some platforms don't need to do that since they just have a single
> port (no more subnodes), the others might have specific/shared
> registers to access configuration space. (e.g. Tegra, MTK legacy IP
> block).  Or, he can split them into two independent nodes, but it
> will break common probing flow by doing so. (I'd prefer to use
> subnodes.)

The PCI core interface (pci_scan_root_bus_bridge()) starts with
sysdata in the struct pci_host_bridge, so every PCI bus under that
host bridge has the same sysdata.  

You have multiple root ports (sounds like two ports in this case)
under that host bridge.  Each port has independent interrupt mappings,
but the MMIO address space routed to the ports is described in the
upper-level host bridge (the "pcie" node in DT).  I assume the I/O and
MMIO routing through the root ports works as described in the
PCI-to-PCI bridge spec, using PCI_MEMORY_BASE, PCI_PREF_MEMORY_BASE,
etc.

If that's the case, I think your current DT "pcie" node is
appropriate, and both ports should have the same sysdata (as they do
in your current patch), and you do need some additional way to get
from that sysdata (the struct mtk_pcie) to the per-port data (the
struct mtk_pcie_port).

Apparently the two root ports of this MT7622/MT2712 controller are
hardwired at device (PCI_SLOT) 0 and 1.  Using a list to look that up
seems like a little overkill, since you could index an array by
PCI_SLOT(), but I guess you could do it either way.

I would probably rename "port->index" to "port->slot" or similar to
make it more obvious that it's not merely the Nth port we found; it's
the one that is hardwired at PCI_SLOT N.

Also, s/mtk_pcie_parse_ports/mtk_pcie_parse_port/, since it parses one
port each time you call it.

And factor out the lookup as Ryder suggested so it's not duplicated in
the mtk_pcie_config_read()/mtk_pcie_config_write() paths.

Bjorn

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 80+ messages in thread

* [PATCH v2 4/5] PCI: mediatek: Add new generation controller support
@ 2017-08-08 20:16             ` Bjorn Helgaas
  0 siblings, 0 replies; 80+ messages in thread
From: Bjorn Helgaas @ 2017-08-08 20:16 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, Aug 05, 2017 at 12:52:43PM +0800, Ryder Lee wrote:
> Hi Honghui, Bjorn,
> 
> On Fri, 2017-08-04 at 08:18 -0500, Bjorn Helgaas wrote:
> > On Fri, Aug 04, 2017 at 04:39:36PM +0800, Honghui Zhang wrote:
> > > On Thu, 2017-08-03 at 17:42 -0500, Bjorn Helgaas wrote:
> > > > > +
> > > > > +static struct mtk_pcie_port *mtk_pcie_find_port(struct mtk_pcie *pcie,
> > > > > +						struct pci_bus *bus, int devfn)
> > > > > +{
> > > > > +	struct pci_dev *dev;
> > > > > +	struct pci_bus *pbus;
> > > > > +	struct mtk_pcie_port *port, *tmp;
> > > > > +
> > > > > +	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
> > > > > +		if (bus->number == 0 && port->index == PCI_SLOT(devfn)) {
> > > > > +			return port;
> > > > > +		} else if (bus->number != 0) {
> > > > > +			pbus = bus;
> > > > > +			do {
> > > > > +				dev = pbus->self;
> > > > > +				if (port->index == PCI_SLOT(dev->devfn))
> > > > > +					return port;
> > > > > +				pbus = dev->bus;
> > > > > +			} while (dev->bus->number != 0);
> > > > > +		}
> > > > > +	}
> > > > > +
> > > > > +	return NULL;
> > > > 
> > > > You should be able to use sysdata to avoid searching the list.
> > > > See drivers/pci/host/pci-aardvark.c, for example.
> > > > 
> > > 
> > > I could put the mtk_pcie * in sysdata, but still need to searching the
> > > list to get the mtk_pcie_port *, how about:
> > > 
> > > 	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
> > > 		if (port->index == PCI_SLOT(devfn))
> > > 			return port;
> > > 	}
> > 
> > No.  Other drivers don't need to search the list.  Please take a look
> > at them and see how they solve this problem.  I don't think your
> > hardware is fundamentally different in a way that means you need to
> > search when the others don't.
> > 
> 
> I'm not directly involved in this generation, but I guess the main
> reason why Honghui need to do that is just because this hardware
> access configuration space via per-port registers, not just for the
> guard.  Currently, We had a host bridge with two ports (two subnodes
> in binding text), thus he tried to tells them apart so that he can
> get the correct registers.
> 
> Some platforms don't need to do that since they just have a single
> port (no more subnodes), the others might have specific/shared
> registers to access configuration space. (e.g. Tegra, MTK legacy IP
> block).  Or, he can split them into two independent nodes, but it
> will break common probing flow by doing so. (I'd prefer to use
> subnodes.)

The PCI core interface (pci_scan_root_bus_bridge()) starts with
sysdata in the struct pci_host_bridge, so every PCI bus under that
host bridge has the same sysdata.  

You have multiple root ports (sounds like two ports in this case)
under that host bridge.  Each port has independent interrupt mappings,
but the MMIO address space routed to the ports is described in the
upper-level host bridge (the "pcie" node in DT).  I assume the I/O and
MMIO routing through the root ports works as described in the
PCI-to-PCI bridge spec, using PCI_MEMORY_BASE, PCI_PREF_MEMORY_BASE,
etc.

If that's the case, I think your current DT "pcie" node is
appropriate, and both ports should have the same sysdata (as they do
in your current patch), and you do need some additional way to get
from that sysdata (the struct mtk_pcie) to the per-port data (the
struct mtk_pcie_port).

Apparently the two root ports of this MT7622/MT2712 controller are
hardwired at device (PCI_SLOT) 0 and 1.  Using a list to look that up
seems like a little overkill, since you could index an array by
PCI_SLOT(), but I guess you could do it either way.

I would probably rename "port->index" to "port->slot" or similar to
make it more obvious that it's not merely the Nth port we found; it's
the one that is hardwired at PCI_SLOT N.

Also, s/mtk_pcie_parse_ports/mtk_pcie_parse_port/, since it parses one
port each time you call it.

And factor out the lookup as Ryder suggested so it's not duplicated in
the mtk_pcie_config_read()/mtk_pcie_config_write() paths.

Bjorn

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v2 4/5] PCI: mediatek: Add new generation controller support
  2017-08-04 13:18         ` Bjorn Helgaas
  (?)
@ 2017-08-08 20:19           ` Bjorn Helgaas
  -1 siblings, 0 replies; 80+ messages in thread
From: Bjorn Helgaas @ 2017-08-08 20:19 UTC (permalink / raw)
  To: Honghui Zhang
  Cc: youlin.pei, devicetree, hongkun.cao, ryder.lee, linux-pci,
	sean.wang, xinping.qian, linux-kernel, robh+dt, yt.shen,
	matthias.bgg, robh, linux-mediatek, yong.wu, bhelgaas,
	yingjoe.chen, eddie.huang, linux-arm-kernel

On Fri, Aug 04, 2017 at 08:18:09AM -0500, Bjorn Helgaas wrote:
> On Fri, Aug 04, 2017 at 04:39:36PM +0800, Honghui Zhang wrote:
> > On Thu, 2017-08-03 at 17:42 -0500, Bjorn Helgaas wrote:

> > > > +	port->irq_domain = irq_domain_add_linear(pcie_intc_node, INTX_NUM,
> > > > +						 &intx_domain_ops, port);
> > > 
> > > I think there's an issue here with a 4-element IRQ domain and the
> > > hwirq numbers 1-4 from the of_irq_parse_and_map_pci() path, so INTD
> > > may not work correctly.
> > > 
> > > See
> > > http://lkml.kernel.org/r/20170801212931.GA26498@bhelgaas-glaptop.roam.corp.google.com
> > > and related discussion.
> > 
> > Sorry, I did not get this,
> > I do some test with an intel E350T4 PCIe NICs, it's a x1 lane
> > multi-function device.
> > What I got from the log is below:
> > ->of_irq_parse_and_map_pci
> > 	->of_irq_parse_pci
> > 		->irq_create_of_mapping
> > 			->irq_create_fwspec_mapping
> > 				->irq_domain_translate
> > 				which will go through
> > 				d->ops->translate #the hwirq really start from 0
> > 
> > And I tested every NIC port of the Intel E350T4 with tftp transfer data,
> > seems all are OK with this code.
> 
> OK.  I don't know what d->ops->translate is involved here, but if it
> works, I guess this is OK for now.  We're trying to clean this up and
> make it consistent across all the drivers.  Many of them allocate a
> 5-element IRQ domain, some make a 4-element domain, and on some of
> them INTD doesn't work.  It's a mess.

Paul Burton is cleaning this up.  Can you point out the d->ops->translate
function that's involved here?

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v2 4/5] PCI: mediatek: Add new generation controller support
@ 2017-08-08 20:19           ` Bjorn Helgaas
  0 siblings, 0 replies; 80+ messages in thread
From: Bjorn Helgaas @ 2017-08-08 20:19 UTC (permalink / raw)
  To: Honghui Zhang
  Cc: youlin.pei, devicetree, hongkun.cao, ryder.lee, linux-arm-kernel,
	linux-pci, sean.wang, linux-kernel, matthias.bgg, robh+dt,
	linux-mediatek, yong.wu, yt.shen, yingjoe.chen, eddie.huang,
	bhelgaas, xinping.qian, robh

On Fri, Aug 04, 2017 at 08:18:09AM -0500, Bjorn Helgaas wrote:
> On Fri, Aug 04, 2017 at 04:39:36PM +0800, Honghui Zhang wrote:
> > On Thu, 2017-08-03 at 17:42 -0500, Bjorn Helgaas wrote:

> > > > +	port->irq_domain = irq_domain_add_linear(pcie_intc_node, INTX_NUM,
> > > > +						 &intx_domain_ops, port);
> > > 
> > > I think there's an issue here with a 4-element IRQ domain and the
> > > hwirq numbers 1-4 from the of_irq_parse_and_map_pci() path, so INTD
> > > may not work correctly.
> > > 
> > > See
> > > http://lkml.kernel.org/r/20170801212931.GA26498@bhelgaas-glaptop.roam.corp.google.com
> > > and related discussion.
> > 
> > Sorry, I did not get this,
> > I do some test with an intel E350T4 PCIe NICs, it's a x1 lane
> > multi-function device.
> > What I got from the log is below:
> > ->of_irq_parse_and_map_pci
> > 	->of_irq_parse_pci
> > 		->irq_create_of_mapping
> > 			->irq_create_fwspec_mapping
> > 				->irq_domain_translate
> > 				which will go through
> > 				d->ops->translate #the hwirq really start from 0
> > 
> > And I tested every NIC port of the Intel E350T4 with tftp transfer data,
> > seems all are OK with this code.
> 
> OK.  I don't know what d->ops->translate is involved here, but if it
> works, I guess this is OK for now.  We're trying to clean this up and
> make it consistent across all the drivers.  Many of them allocate a
> 5-element IRQ domain, some make a 4-element domain, and on some of
> them INTD doesn't work.  It's a mess.

Paul Burton is cleaning this up.  Can you point out the d->ops->translate
function that's involved here?

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 80+ messages in thread

* [PATCH v2 4/5] PCI: mediatek: Add new generation controller support
@ 2017-08-08 20:19           ` Bjorn Helgaas
  0 siblings, 0 replies; 80+ messages in thread
From: Bjorn Helgaas @ 2017-08-08 20:19 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Aug 04, 2017 at 08:18:09AM -0500, Bjorn Helgaas wrote:
> On Fri, Aug 04, 2017 at 04:39:36PM +0800, Honghui Zhang wrote:
> > On Thu, 2017-08-03 at 17:42 -0500, Bjorn Helgaas wrote:

> > > > +	port->irq_domain = irq_domain_add_linear(pcie_intc_node, INTX_NUM,
> > > > +						 &intx_domain_ops, port);
> > > 
> > > I think there's an issue here with a 4-element IRQ domain and the
> > > hwirq numbers 1-4 from the of_irq_parse_and_map_pci() path, so INTD
> > > may not work correctly.
> > > 
> > > See
> > > http://lkml.kernel.org/r/20170801212931.GA26498 at bhelgaas-glaptop.roam.corp.google.com
> > > and related discussion.
> > 
> > Sorry, I did not get this,
> > I do some test with an intel E350T4 PCIe NICs, it's a x1 lane
> > multi-function device.
> > What I got from the log is below:
> > ->of_irq_parse_and_map_pci
> > 	->of_irq_parse_pci
> > 		->irq_create_of_mapping
> > 			->irq_create_fwspec_mapping
> > 				->irq_domain_translate
> > 				which will go through
> > 				d->ops->translate #the hwirq really start from 0
> > 
> > And I tested every NIC port of the Intel E350T4 with tftp transfer data,
> > seems all are OK with this code.
> 
> OK.  I don't know what d->ops->translate is involved here, but if it
> works, I guess this is OK for now.  We're trying to clean this up and
> make it consistent across all the drivers.  Many of them allocate a
> 5-element IRQ domain, some make a 4-element domain, and on some of
> them INTD doesn't work.  It's a mess.

Paul Burton is cleaning this up.  Can you point out the d->ops->translate
function that's involved here?

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v2 4/5] PCI: mediatek: Add new generation controller support
  2017-08-08 20:19           ` Bjorn Helgaas
  (?)
@ 2017-08-09  6:49             ` Honghui Zhang
  -1 siblings, 0 replies; 80+ messages in thread
From: Honghui Zhang @ 2017-08-09  6:49 UTC (permalink / raw)
  To: Bjorn Helgaas, paul.burton
  Cc: youlin.pei, devicetree, hongkun.cao, ryder.lee, linux-pci,
	sean.wang, xinping.qian, linux-kernel, robh+dt, yt.shen,
	matthias.bgg, robh, linux-mediatek, yong.wu, bhelgaas,
	yingjoe.chen, eddie.huang, linux-arm-kernel

On Tue, 2017-08-08 at 15:19 -0500, Bjorn Helgaas wrote:
> On Fri, Aug 04, 2017 at 08:18:09AM -0500, Bjorn Helgaas wrote:
> > On Fri, Aug 04, 2017 at 04:39:36PM +0800, Honghui Zhang wrote:
> > > On Thu, 2017-08-03 at 17:42 -0500, Bjorn Helgaas wrote:
> 
> > > > > +	port->irq_domain = irq_domain_add_linear(pcie_intc_node, INTX_NUM,
> > > > > +						 &intx_domain_ops, port);
> > > > 
> > > > I think there's an issue here with a 4-element IRQ domain and the
> > > > hwirq numbers 1-4 from the of_irq_parse_and_map_pci() path, so INTD
> > > > may not work correctly.
> > > > 
> > > > See
> > > > http://lkml.kernel.org/r/20170801212931.GA26498@bhelgaas-glaptop.roam.corp.google.com
> > > > and related discussion.
> > > 
> > > Sorry, I did not get this,
> > > I do some test with an intel E350T4 PCIe NICs, it's a x1 lane
> > > multi-function device.
> > > What I got from the log is below:
> > > ->of_irq_parse_and_map_pci
> > > 	->of_irq_parse_pci
> > > 		->irq_create_of_mapping
> > > 			->irq_create_fwspec_mapping
> > > 				->irq_domain_translate
> > > 				which will go through
> > > 				d->ops->translate #the hwirq really start from 0
> > > 
> > > And I tested every NIC port of the Intel E350T4 with tftp transfer data,
> > > seems all are OK with this code.
> > 
> > OK.  I don't know what d->ops->translate is involved here, but if it
> > works, I guess this is OK for now.  We're trying to clean this up and
> > make it consistent across all the drivers.  Many of them allocate a
> > 5-element IRQ domain, some make a 4-element domain, and on some of
> > them INTD doesn't work.  It's a mess.
> 
> Paul Burton is cleaning this up.  Can you point out the d->ops->translate
> function that's involved here?

Hi, Bjorn,

Sorry for my last reply, I was tracking the wrong logs. The real trick
is here:

->of_irq_parse_and_map_pci
  ->of_irq_parse_pci	#out_irq->args[0] start from 1(1 == INTA)
     ->of_irq_parse_raw

After of_irq_parse_raw finished it's work, the out_irq->args[0] will be
remapped as "interrupt-map" property defines[1], which in my case, it's
start from 0, and then fwspec->param[0] is start from 0 (0 == INTA).

My "interrupt-map" property is defined as below:
interrupt-map = <0 0 0 1 &pcie_intc0 0>,
		<0 0 0 2 &pcie_intc0 1>,
		<0 0 0 3 &pcie_intc0 2>,
		<0 0 0 4 &pcie_intc0 3>;

I do some test with the changes of property defined as below:
interrupt-map = <0 0 0 1 &pcie_intc0 1>,
		<0 0 0 2 &pcie_intc0 2>,
		<0 0 0 3 &pcie_intc0 3>,
		<0 0 0 4 &pcie_intc0 4>;
Then I got the same running complain as Paul have got[2]

So I guess it's the "interrupt-map" property defined in dtsi node play
the key role in this.

[1]http://elixir.free-electrons.com/linux/v4.13-rc4/source/drivers/of/irq.c#L265
[2]https://patchwork.kernel.org/patch/9794355

thanks.

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v2 4/5] PCI: mediatek: Add new generation controller support
@ 2017-08-09  6:49             ` Honghui Zhang
  0 siblings, 0 replies; 80+ messages in thread
From: Honghui Zhang @ 2017-08-09  6:49 UTC (permalink / raw)
  To: Bjorn Helgaas, paul.burton
  Cc: youlin.pei, devicetree, hongkun.cao, ryder.lee, linux-pci,
	sean.wang, xinping.qian, linux-kernel, robh+dt, yt.shen,
	matthias.bgg, robh, linux-mediatek, yong.wu, bhelgaas,
	yingjoe.chen, eddie.huang, linux-arm-kernel

On Tue, 2017-08-08 at 15:19 -0500, Bjorn Helgaas wrote:
> On Fri, Aug 04, 2017 at 08:18:09AM -0500, Bjorn Helgaas wrote:
> > On Fri, Aug 04, 2017 at 04:39:36PM +0800, Honghui Zhang wrote:
> > > On Thu, 2017-08-03 at 17:42 -0500, Bjorn Helgaas wrote:
> 
> > > > > +	port->irq_domain = irq_domain_add_linear(pcie_intc_node, INTX_NUM,
> > > > > +						 &intx_domain_ops, port);
> > > > 
> > > > I think there's an issue here with a 4-element IRQ domain and the
> > > > hwirq numbers 1-4 from the of_irq_parse_and_map_pci() path, so INTD
> > > > may not work correctly.
> > > > 
> > > > See
> > > > http://lkml.kernel.org/r/20170801212931.GA26498@bhelgaas-glaptop.roam.corp.google.com
> > > > and related discussion.
> > > 
> > > Sorry, I did not get this,
> > > I do some test with an intel E350T4 PCIe NICs, it's a x1 lane
> > > multi-function device.
> > > What I got from the log is below:
> > > ->of_irq_parse_and_map_pci
> > > 	->of_irq_parse_pci
> > > 		->irq_create_of_mapping
> > > 			->irq_create_fwspec_mapping
> > > 				->irq_domain_translate
> > > 				which will go through
> > > 				d->ops->translate #the hwirq really start from 0
> > > 
> > > And I tested every NIC port of the Intel E350T4 with tftp transfer data,
> > > seems all are OK with this code.
> > 
> > OK.  I don't know what d->ops->translate is involved here, but if it
> > works, I guess this is OK for now.  We're trying to clean this up and
> > make it consistent across all the drivers.  Many of them allocate a
> > 5-element IRQ domain, some make a 4-element domain, and on some of
> > them INTD doesn't work.  It's a mess.
> 
> Paul Burton is cleaning this up.  Can you point out the d->ops->translate
> function that's involved here?

Hi, Bjorn,

Sorry for my last reply, I was tracking the wrong logs. The real trick
is here:

->of_irq_parse_and_map_pci
  ->of_irq_parse_pci	#out_irq->args[0] start from 1(1 == INTA)
     ->of_irq_parse_raw

After of_irq_parse_raw finished it's work, the out_irq->args[0] will be
remapped as "interrupt-map" property defines[1], which in my case, it's
start from 0, and then fwspec->param[0] is start from 0 (0 == INTA).

My "interrupt-map" property is defined as below:
interrupt-map = <0 0 0 1 &pcie_intc0 0>,
		<0 0 0 2 &pcie_intc0 1>,
		<0 0 0 3 &pcie_intc0 2>,
		<0 0 0 4 &pcie_intc0 3>;

I do some test with the changes of property defined as below:
interrupt-map = <0 0 0 1 &pcie_intc0 1>,
		<0 0 0 2 &pcie_intc0 2>,
		<0 0 0 3 &pcie_intc0 3>,
		<0 0 0 4 &pcie_intc0 4>;
Then I got the same running complain as Paul have got[2]

So I guess it's the "interrupt-map" property defined in dtsi node play
the key role in this.

[1]http://elixir.free-electrons.com/linux/v4.13-rc4/source/drivers/of/irq.c#L265
[2]https://patchwork.kernel.org/patch/9794355

thanks.

^ permalink raw reply	[flat|nested] 80+ messages in thread

* [PATCH v2 4/5] PCI: mediatek: Add new generation controller support
@ 2017-08-09  6:49             ` Honghui Zhang
  0 siblings, 0 replies; 80+ messages in thread
From: Honghui Zhang @ 2017-08-09  6:49 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, 2017-08-08 at 15:19 -0500, Bjorn Helgaas wrote:
> On Fri, Aug 04, 2017 at 08:18:09AM -0500, Bjorn Helgaas wrote:
> > On Fri, Aug 04, 2017 at 04:39:36PM +0800, Honghui Zhang wrote:
> > > On Thu, 2017-08-03 at 17:42 -0500, Bjorn Helgaas wrote:
> 
> > > > > +	port->irq_domain = irq_domain_add_linear(pcie_intc_node, INTX_NUM,
> > > > > +						 &intx_domain_ops, port);
> > > > 
> > > > I think there's an issue here with a 4-element IRQ domain and the
> > > > hwirq numbers 1-4 from the of_irq_parse_and_map_pci() path, so INTD
> > > > may not work correctly.
> > > > 
> > > > See
> > > > http://lkml.kernel.org/r/20170801212931.GA26498 at bhelgaas-glaptop.roam.corp.google.com
> > > > and related discussion.
> > > 
> > > Sorry, I did not get this,
> > > I do some test with an intel E350T4 PCIe NICs, it's a x1 lane
> > > multi-function device.
> > > What I got from the log is below:
> > > ->of_irq_parse_and_map_pci
> > > 	->of_irq_parse_pci
> > > 		->irq_create_of_mapping
> > > 			->irq_create_fwspec_mapping
> > > 				->irq_domain_translate
> > > 				which will go through
> > > 				d->ops->translate #the hwirq really start from 0
> > > 
> > > And I tested every NIC port of the Intel E350T4 with tftp transfer data,
> > > seems all are OK with this code.
> > 
> > OK.  I don't know what d->ops->translate is involved here, but if it
> > works, I guess this is OK for now.  We're trying to clean this up and
> > make it consistent across all the drivers.  Many of them allocate a
> > 5-element IRQ domain, some make a 4-element domain, and on some of
> > them INTD doesn't work.  It's a mess.
> 
> Paul Burton is cleaning this up.  Can you point out the d->ops->translate
> function that's involved here?

Hi, Bjorn,

Sorry for my last reply, I was tracking the wrong logs. The real trick
is here:

->of_irq_parse_and_map_pci
  ->of_irq_parse_pci	#out_irq->args[0] start from 1(1 == INTA)
     ->of_irq_parse_raw

After of_irq_parse_raw finished it's work, the out_irq->args[0] will be
remapped as "interrupt-map" property defines[1], which in my case, it's
start from 0, and then fwspec->param[0] is start from 0 (0 == INTA).

My "interrupt-map" property is defined as below:
interrupt-map = <0 0 0 1 &pcie_intc0 0>,
		<0 0 0 2 &pcie_intc0 1>,
		<0 0 0 3 &pcie_intc0 2>,
		<0 0 0 4 &pcie_intc0 3>;

I do some test with the changes of property defined as below:
interrupt-map = <0 0 0 1 &pcie_intc0 1>,
		<0 0 0 2 &pcie_intc0 2>,
		<0 0 0 3 &pcie_intc0 3>,
		<0 0 0 4 &pcie_intc0 4>;
Then I got the same running complain as Paul have got[2]

So I guess it's the "interrupt-map" property defined in dtsi node play
the key role in this.

[1]http://elixir.free-electrons.com/linux/v4.13-rc4/source/drivers/of/irq.c#L265
[2]https://patchwork.kernel.org/patch/9794355

thanks.

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v2 4/5] PCI: mediatek: Add new generation controller support
  2017-08-09  6:49             ` Honghui Zhang
  (?)
@ 2017-08-09 16:43               ` Paul Burton
  -1 siblings, 0 replies; 80+ messages in thread
From: Paul Burton @ 2017-08-09 16:43 UTC (permalink / raw)
  To: Honghui Zhang, Bjorn Helgaas
  Cc: youlin.pei, devicetree, hongkun.cao, ryder.lee, linux-pci,
	sean.wang, xinping.qian, linux-kernel, robh+dt, yt.shen,
	matthias.bgg, robh, linux-mediatek, yong.wu, bhelgaas,
	yingjoe.chen, eddie.huang, linux-arm-kernel

[-- Attachment #1: Type: text/plain, Size: 4029 bytes --]

Hi Honghui & Bjorn,

On Tuesday, 8 August 2017 23:49:52 PDT Honghui Zhang wrote:
> On Tue, 2017-08-08 at 15:19 -0500, Bjorn Helgaas wrote:
> > On Fri, Aug 04, 2017 at 08:18:09AM -0500, Bjorn Helgaas wrote:
> > > On Fri, Aug 04, 2017 at 04:39:36PM +0800, Honghui Zhang wrote:
> > > > On Thu, 2017-08-03 at 17:42 -0500, Bjorn Helgaas wrote:
> > > > > > +	port->irq_domain = irq_domain_add_linear(pcie_intc_node,
> > > > > > INTX_NUM,
> > > > > > +						 &intx_domain_ops, port);
> > > > > 
> > > > > I think there's an issue here with a 4-element IRQ domain and the
> > > > > hwirq numbers 1-4 from the of_irq_parse_and_map_pci() path, so INTD
> > > > > may not work correctly.
> > > > > 
> > > > > See
> > > > > http://lkml.kernel.org/r/20170801212931.GA26498@bhelgaas-glaptop.roa
> > > > > m.corp.google.com and related discussion.
> > > > 
> > > > Sorry, I did not get this,
> > > > I do some test with an intel E350T4 PCIe NICs, it's a x1 lane
> > > > multi-function device.
> > > > What I got from the log is below:
> > > > ->of_irq_parse_and_map_pci
> > > > 
> > > > 	->of_irq_parse_pci
> > > > 	
> > > > 		->irq_create_of_mapping
> > > > 		
> > > > 			->irq_create_fwspec_mapping
> > > > 			
> > > > 				->irq_domain_translate
> > > > 				which will go through
> > > > 				d->ops->translate #the hwirq really start from 0
> > > > 
> > > > And I tested every NIC port of the Intel E350T4 with tftp transfer
> > > > data,
> > > > seems all are OK with this code.
> > > 
> > > OK.  I don't know what d->ops->translate is involved here, but if it
> > > works, I guess this is OK for now.  We're trying to clean this up and
> > > make it consistent across all the drivers.  Many of them allocate a
> > > 5-element IRQ domain, some make a 4-element domain, and on some of
> > > them INTD doesn't work.  It's a mess.
> > 
> > Paul Burton is cleaning this up.  Can you point out the d->ops->translate
> > function that's involved here?
> 
> Hi, Bjorn,
> 
> Sorry for my last reply, I was tracking the wrong logs. The real trick
> is here:
> 
> ->of_irq_parse_and_map_pci
>   ->of_irq_parse_pci	#out_irq->args[0] start from 1(1 == INTA)
>      ->of_irq_parse_raw
> 
> After of_irq_parse_raw finished it's work, the out_irq->args[0] will be
> remapped as "interrupt-map" property defines[1], which in my case, it's
> start from 0, and then fwspec->param[0] is start from 0 (0 == INTA).
> 
> My "interrupt-map" property is defined as below:
> interrupt-map = <0 0 0 1 &pcie_intc0 0>,
> 		<0 0 0 2 &pcie_intc0 1>,
> 		<0 0 0 3 &pcie_intc0 2>,
> 		<0 0 0 4 &pcie_intc0 3>;
> 
> I do some test with the changes of property defined as below:
> interrupt-map = <0 0 0 1 &pcie_intc0 1>,
> 		<0 0 0 2 &pcie_intc0 2>,
> 		<0 0 0 3 &pcie_intc0 3>,
> 		<0 0 0 4 &pcie_intc0 4>;
> Then I got the same running complain as Paul have got[2]
> 
> So I guess it's the "interrupt-map" property defined in dtsi node play
> the key role in this.
> 
> [1]http://elixir.free-electrons.com/linux/v4.13-rc4/source/drivers/of/irq.c#
> L265 [2]https://patchwork.kernel.org/patch/9794355
> 
> thanks.

That seems like a possibly more sensible way to handle it, so long as you have 
control over all the device trees that the driver may be exposed to.

Bjorn: is this something you want to deal with on a driver by driver basis? 
ie. new drivers just use interrupt-map as above and older ones with existing 
DT bindings use the xlate function? Looking at the drivers & device trees we 
have in-tree it seems we already have a mix of 0-3 & 1-4 ranges in use, so 
we'd just need to use the xlate function for those which currently use 1-4.

I had originally done the same thing with interrupt-map on the MIPS Boston 
board[1] and the Xilinx PCIe driver[2], though that change would break any 
pre-existing device trees that use 1-4 in the interrupt-map property (which is 
sadly what the driver's binding document shows...).

Thanks,
    Paul

[1] https://www.linux-mips.org/archives/linux-mips/2016-08/msg00425.html
[2] https://patchwork.kernel.org/patch/9763191/

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v2 4/5] PCI: mediatek: Add new generation controller support
@ 2017-08-09 16:43               ` Paul Burton
  0 siblings, 0 replies; 80+ messages in thread
From: Paul Burton @ 2017-08-09 16:43 UTC (permalink / raw)
  To: Honghui Zhang, Bjorn Helgaas
  Cc: youlin.pei, devicetree, hongkun.cao, ryder.lee, linux-pci,
	sean.wang, xinping.qian, linux-kernel, robh+dt, yt.shen,
	matthias.bgg, robh, linux-mediatek, yong.wu, bhelgaas,
	yingjoe.chen, eddie.huang, linux-arm-kernel

[-- Attachment #1: Type: text/plain, Size: 4029 bytes --]

Hi Honghui & Bjorn,

On Tuesday, 8 August 2017 23:49:52 PDT Honghui Zhang wrote:
> On Tue, 2017-08-08 at 15:19 -0500, Bjorn Helgaas wrote:
> > On Fri, Aug 04, 2017 at 08:18:09AM -0500, Bjorn Helgaas wrote:
> > > On Fri, Aug 04, 2017 at 04:39:36PM +0800, Honghui Zhang wrote:
> > > > On Thu, 2017-08-03 at 17:42 -0500, Bjorn Helgaas wrote:
> > > > > > +	port->irq_domain = irq_domain_add_linear(pcie_intc_node,
> > > > > > INTX_NUM,
> > > > > > +						 &intx_domain_ops, port);
> > > > > 
> > > > > I think there's an issue here with a 4-element IRQ domain and the
> > > > > hwirq numbers 1-4 from the of_irq_parse_and_map_pci() path, so INTD
> > > > > may not work correctly.
> > > > > 
> > > > > See
> > > > > http://lkml.kernel.org/r/20170801212931.GA26498@bhelgaas-glaptop.roa
> > > > > m.corp.google.com and related discussion.
> > > > 
> > > > Sorry, I did not get this,
> > > > I do some test with an intel E350T4 PCIe NICs, it's a x1 lane
> > > > multi-function device.
> > > > What I got from the log is below:
> > > > ->of_irq_parse_and_map_pci
> > > > 
> > > > 	->of_irq_parse_pci
> > > > 	
> > > > 		->irq_create_of_mapping
> > > > 		
> > > > 			->irq_create_fwspec_mapping
> > > > 			
> > > > 				->irq_domain_translate
> > > > 				which will go through
> > > > 				d->ops->translate #the hwirq really start from 0
> > > > 
> > > > And I tested every NIC port of the Intel E350T4 with tftp transfer
> > > > data,
> > > > seems all are OK with this code.
> > > 
> > > OK.  I don't know what d->ops->translate is involved here, but if it
> > > works, I guess this is OK for now.  We're trying to clean this up and
> > > make it consistent across all the drivers.  Many of them allocate a
> > > 5-element IRQ domain, some make a 4-element domain, and on some of
> > > them INTD doesn't work.  It's a mess.
> > 
> > Paul Burton is cleaning this up.  Can you point out the d->ops->translate
> > function that's involved here?
> 
> Hi, Bjorn,
> 
> Sorry for my last reply, I was tracking the wrong logs. The real trick
> is here:
> 
> ->of_irq_parse_and_map_pci
>   ->of_irq_parse_pci	#out_irq->args[0] start from 1(1 == INTA)
>      ->of_irq_parse_raw
> 
> After of_irq_parse_raw finished it's work, the out_irq->args[0] will be
> remapped as "interrupt-map" property defines[1], which in my case, it's
> start from 0, and then fwspec->param[0] is start from 0 (0 == INTA).
> 
> My "interrupt-map" property is defined as below:
> interrupt-map = <0 0 0 1 &pcie_intc0 0>,
> 		<0 0 0 2 &pcie_intc0 1>,
> 		<0 0 0 3 &pcie_intc0 2>,
> 		<0 0 0 4 &pcie_intc0 3>;
> 
> I do some test with the changes of property defined as below:
> interrupt-map = <0 0 0 1 &pcie_intc0 1>,
> 		<0 0 0 2 &pcie_intc0 2>,
> 		<0 0 0 3 &pcie_intc0 3>,
> 		<0 0 0 4 &pcie_intc0 4>;
> Then I got the same running complain as Paul have got[2]
> 
> So I guess it's the "interrupt-map" property defined in dtsi node play
> the key role in this.
> 
> [1]http://elixir.free-electrons.com/linux/v4.13-rc4/source/drivers/of/irq.c#
> L265 [2]https://patchwork.kernel.org/patch/9794355
> 
> thanks.

That seems like a possibly more sensible way to handle it, so long as you have 
control over all the device trees that the driver may be exposed to.

Bjorn: is this something you want to deal with on a driver by driver basis? 
ie. new drivers just use interrupt-map as above and older ones with existing 
DT bindings use the xlate function? Looking at the drivers & device trees we 
have in-tree it seems we already have a mix of 0-3 & 1-4 ranges in use, so 
we'd just need to use the xlate function for those which currently use 1-4.

I had originally done the same thing with interrupt-map on the MIPS Boston 
board[1] and the Xilinx PCIe driver[2], though that change would break any 
pre-existing device trees that use 1-4 in the interrupt-map property (which is 
sadly what the driver's binding document shows...).

Thanks,
    Paul

[1] https://www.linux-mips.org/archives/linux-mips/2016-08/msg00425.html
[2] https://patchwork.kernel.org/patch/9763191/

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 80+ messages in thread

* [PATCH v2 4/5] PCI: mediatek: Add new generation controller support
@ 2017-08-09 16:43               ` Paul Burton
  0 siblings, 0 replies; 80+ messages in thread
From: Paul Burton @ 2017-08-09 16:43 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Honghui & Bjorn,

On Tuesday, 8 August 2017 23:49:52 PDT Honghui Zhang wrote:
> On Tue, 2017-08-08 at 15:19 -0500, Bjorn Helgaas wrote:
> > On Fri, Aug 04, 2017 at 08:18:09AM -0500, Bjorn Helgaas wrote:
> > > On Fri, Aug 04, 2017 at 04:39:36PM +0800, Honghui Zhang wrote:
> > > > On Thu, 2017-08-03 at 17:42 -0500, Bjorn Helgaas wrote:
> > > > > > +	port->irq_domain = irq_domain_add_linear(pcie_intc_node,
> > > > > > INTX_NUM,
> > > > > > +						 &intx_domain_ops, port);
> > > > > 
> > > > > I think there's an issue here with a 4-element IRQ domain and the
> > > > > hwirq numbers 1-4 from the of_irq_parse_and_map_pci() path, so INTD
> > > > > may not work correctly.
> > > > > 
> > > > > See
> > > > > http://lkml.kernel.org/r/20170801212931.GA26498 at bhelgaas-glaptop.roa
> > > > > m.corp.google.com and related discussion.
> > > > 
> > > > Sorry, I did not get this,
> > > > I do some test with an intel E350T4 PCIe NICs, it's a x1 lane
> > > > multi-function device.
> > > > What I got from the log is below:
> > > > ->of_irq_parse_and_map_pci
> > > > 
> > > > 	->of_irq_parse_pci
> > > > 	
> > > > 		->irq_create_of_mapping
> > > > 		
> > > > 			->irq_create_fwspec_mapping
> > > > 			
> > > > 				->irq_domain_translate
> > > > 				which will go through
> > > > 				d->ops->translate #the hwirq really start from 0
> > > > 
> > > > And I tested every NIC port of the Intel E350T4 with tftp transfer
> > > > data,
> > > > seems all are OK with this code.
> > > 
> > > OK.  I don't know what d->ops->translate is involved here, but if it
> > > works, I guess this is OK for now.  We're trying to clean this up and
> > > make it consistent across all the drivers.  Many of them allocate a
> > > 5-element IRQ domain, some make a 4-element domain, and on some of
> > > them INTD doesn't work.  It's a mess.
> > 
> > Paul Burton is cleaning this up.  Can you point out the d->ops->translate
> > function that's involved here?
> 
> Hi, Bjorn,
> 
> Sorry for my last reply, I was tracking the wrong logs. The real trick
> is here:
> 
> ->of_irq_parse_and_map_pci
>   ->of_irq_parse_pci	#out_irq->args[0] start from 1(1 == INTA)
>      ->of_irq_parse_raw
> 
> After of_irq_parse_raw finished it's work, the out_irq->args[0] will be
> remapped as "interrupt-map" property defines[1], which in my case, it's
> start from 0, and then fwspec->param[0] is start from 0 (0 == INTA).
> 
> My "interrupt-map" property is defined as below:
> interrupt-map = <0 0 0 1 &pcie_intc0 0>,
> 		<0 0 0 2 &pcie_intc0 1>,
> 		<0 0 0 3 &pcie_intc0 2>,
> 		<0 0 0 4 &pcie_intc0 3>;
> 
> I do some test with the changes of property defined as below:
> interrupt-map = <0 0 0 1 &pcie_intc0 1>,
> 		<0 0 0 2 &pcie_intc0 2>,
> 		<0 0 0 3 &pcie_intc0 3>,
> 		<0 0 0 4 &pcie_intc0 4>;
> Then I got the same running complain as Paul have got[2]
> 
> So I guess it's the "interrupt-map" property defined in dtsi node play
> the key role in this.
> 
> [1]http://elixir.free-electrons.com/linux/v4.13-rc4/source/drivers/of/irq.c#
> L265 [2]https://patchwork.kernel.org/patch/9794355
> 
> thanks.

That seems like a possibly more sensible way to handle it, so long as you have 
control over all the device trees that the driver may be exposed to.

Bjorn: is this something you want to deal with on a driver by driver basis? 
ie. new drivers just use interrupt-map as above and older ones with existing 
DT bindings use the xlate function? Looking at the drivers & device trees we 
have in-tree it seems we already have a mix of 0-3 & 1-4 ranges in use, so 
we'd just need to use the xlate function for those which currently use 1-4.

I had originally done the same thing with interrupt-map on the MIPS Boston 
board[1] and the Xilinx PCIe driver[2], though that change would break any 
pre-existing device trees that use 1-4 in the interrupt-map property (which is 
sadly what the driver's binding document shows...).

Thanks,
    Paul

[1] https://www.linux-mips.org/archives/linux-mips/2016-08/msg00425.html
[2] https://patchwork.kernel.org/patch/9763191/
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20170809/cde7d45f/attachment.sig>

^ permalink raw reply	[flat|nested] 80+ messages in thread

end of thread, other threads:[~2017-08-09 16:43 UTC | newest]

Thread overview: 80+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-07-27  2:58 [PATCH v2 0/5] PCI: MediaTek: Add support for new generation host controller honghui.zhang
2017-07-27  2:58 ` honghui.zhang at mediatek.com
2017-07-27  2:58 ` honghui.zhang
2017-07-27  2:58 ` honghui.zhang
2017-07-27  2:58 ` [PATCH v2 1/5] PCI: mediatek: Add a structure to abstract the controller generations honghui.zhang
2017-07-27  2:58   ` honghui.zhang at mediatek.com
2017-07-27  2:58   ` honghui.zhang
2017-07-27  3:19   ` Honghui Zhang
2017-07-27  3:19     ` Honghui Zhang
2017-07-27  3:19     ` Honghui Zhang
2017-07-27  3:19     ` Honghui Zhang
2017-07-27  3:28     ` Honghui Zhang
2017-07-27  3:28       ` Honghui Zhang
2017-07-27  3:28       ` Honghui Zhang
2017-07-27  3:28       ` Honghui Zhang
2017-08-03 22:15   ` Bjorn Helgaas
2017-08-03 22:15     ` Bjorn Helgaas
2017-08-03 22:15     ` Bjorn Helgaas
2017-07-27  2:58 ` [PATCH v2 2/5] PCI: mediatek: switch to use platform_get_resource_byname() honghui.zhang
2017-07-27  2:58   ` honghui.zhang at mediatek.com
2017-07-27  2:58   ` honghui.zhang
2017-07-27  2:58 ` [PATCH v2 3/5] dt-bindings: PCI: rename and cleanup MediaTek binding text honghui.zhang
2017-07-27  2:58   ` honghui.zhang at mediatek.com
2017-07-27  2:58   ` honghui.zhang
2017-07-27  2:58   ` honghui.zhang
2017-08-03 19:10   ` Rob Herring
2017-08-03 19:10     ` Rob Herring
2017-08-03 19:10     ` Rob Herring
2017-08-03 22:17   ` Bjorn Helgaas
2017-08-03 22:17     ` Bjorn Helgaas
2017-08-03 22:17     ` Bjorn Helgaas
2017-07-27  2:58 ` [PATCH v2 4/5] PCI: mediatek: Add new generation controller support honghui.zhang
2017-07-27  2:58   ` honghui.zhang at mediatek.com
2017-07-27  2:58   ` honghui.zhang
2017-08-03 22:42   ` Bjorn Helgaas
2017-08-03 22:42     ` Bjorn Helgaas
2017-08-03 22:42     ` Bjorn Helgaas
2017-08-04  8:39     ` Honghui Zhang
2017-08-04  8:39       ` Honghui Zhang
2017-08-04  8:39       ` Honghui Zhang
2017-08-04 13:18       ` Bjorn Helgaas
2017-08-04 13:18         ` Bjorn Helgaas
2017-08-04 13:18         ` Bjorn Helgaas
2017-08-05  4:52         ` Ryder Lee
2017-08-05  4:52           ` Ryder Lee
2017-08-05  4:52           ` Ryder Lee
2017-08-05  6:16           ` Ryder Lee
2017-08-05  6:16             ` Ryder Lee
2017-08-05  6:16             ` Ryder Lee
2017-08-07  3:40             ` Honghui Zhang
2017-08-07  3:40               ` Honghui Zhang
2017-08-07  3:40               ` Honghui Zhang
2017-08-08 20:16           ` Bjorn Helgaas
2017-08-08 20:16             ` Bjorn Helgaas
2017-08-08 20:16             ` Bjorn Helgaas
2017-08-08 20:16             ` Bjorn Helgaas
2017-08-08 20:19         ` Bjorn Helgaas
2017-08-08 20:19           ` Bjorn Helgaas
2017-08-08 20:19           ` Bjorn Helgaas
2017-08-09  6:49           ` Honghui Zhang
2017-08-09  6:49             ` Honghui Zhang
2017-08-09  6:49             ` Honghui Zhang
2017-08-09 16:43             ` Paul Burton
2017-08-09 16:43               ` Paul Burton
2017-08-09 16:43               ` Paul Burton
2017-07-27  2:58 ` [PATCH v2 5/5] dt-bindings: PCI: add support for new generation controller honghui.zhang
2017-07-27  2:58   ` honghui.zhang at mediatek.com
2017-07-27  2:58   ` honghui.zhang
2017-07-27  2:58   ` honghui.zhang
2017-07-27  3:31   ` Honghui Zhang
2017-07-27  3:31     ` Honghui Zhang
2017-07-27  3:31     ` Honghui Zhang
2017-07-27  3:31     ` Honghui Zhang
2017-07-27  3:38   ` Honghui Zhang
2017-07-27  3:38     ` Honghui Zhang
2017-07-27  3:38     ` Honghui Zhang
2017-07-27  3:38     ` Honghui Zhang
2017-08-03 22:45   ` Bjorn Helgaas
2017-08-03 22:45     ` Bjorn Helgaas
2017-08-03 22:45     ` Bjorn Helgaas

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.