From: Honghui Zhang <[email protected]>
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.
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
...{mediatek,mt7623-pcie.txt => mediatek-pcie.txt} | 113 +++-
drivers/pci/host/Kconfig | 5 +-
drivers/pci/host/pcie-mediatek.c | 578 +++++++++++++++++++--
3 files changed, 629 insertions(+), 67 deletions(-)
rename Documentation/devicetree/bindings/pci/{mediatek,mt7623-pcie.txt => mediatek-pcie.txt} (59%)
--
2.6.4
From: Ryder Lee <[email protected]>
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 <[email protected]>
---
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 d6ac342..5e0a2ee2 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
From: Ryder Lee <[email protected]>
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 <[email protected]>
Signed-off-by: Honghui Zhang <[email protected]>
---
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..d6ac342 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,mt7623-pcie", .data = &mtk_pcie_soc_v1 },
+ { .compatible = "mediatek,mt2701-pcie", .data = &mtk_pcie_soc_v1 },
{},
};
--
2.6.4
From: Ryder Lee <[email protected]>
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 <[email protected]>
---
...{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..294f4a3 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,mt7623-pcie"
+ "mediatek,mt2701-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
From: Ryder Lee <[email protected]>
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. More specifically, the newer (future) chips will be
developed based on this generation, thus we use a generic compatible to
avoid having an endless list of compatibles with no differences for the
same hardware.
Signed-off-by: Ryder Lee <[email protected]>
Signed-off-by: Honghui Zhang <[email protected]>
---
drivers/pci/host/Kconfig | 5 +-
drivers/pci/host/pcie-mediatek.c | 480 ++++++++++++++++++++++++++++++++++++++-
2 files changed, 479 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 5e0a2ee2..63e117a 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 <[email protected]>
+ * : Honghui Zhang <[email protected]>
*
* 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,15 +67,79 @@
#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 AHB2PCIE_BASE0_L 0x438
+#define AHB2PCIE_BASE0_H 0x43c
+#define PCIE2AXI_WIN 0x448
+#define WIN_ENABLE BIT(7)
+#define AHB2PCIE_BASEL(base) (base & GENMASK(31, 0))
+#define AHB2PCIE_BASEH(base) (base >> 32)
+#define BASE_SIZE(sz) (sz & GENMASK(4, 0))
+#define PCIE2AXI_SIZE 0xffffffff
+
+#define CFG_HEADER_0 0x460
+#define CFG_HEADER_1 0x464
+#define CFG_HEADER_2 0x468
+#define CFG_RDWR_TYPE_0 0x4
+#define CFG_RD_FMT 0x0
+#define CFG_WR_FMT 0x2
+
+/* PCIe V2 Configuration Transaction Header */
+#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_CFG_WDATA 0x470
+#define APP_TLP_REQ 0x488
+#define APP_CFG_REQ BIT(0)
+#define APP_CPL_STATUS GENMASK(7, 5)
+#define PCIE_CFG_RDATA 0x48c
+#define PCIE_RSTCR 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 PCIE_PIPE_RST_EN BIT(13)
+#define PCIE_MAC_RST_EN BIT(14)
+#define PCIE_CONF_RST_EN BIT(15)
+#define PCIE_LINKDOWN_RST_EN (PCIE_PIPE_RST_EN | PCIE_MAC_RST_EN | \
+ PCIE_CONF_RST_EN)
+#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
+ * @setup_irq: pointer to initialize irq functions
* @startup: pointer to controller setting functions
*/
struct mtk_pcie_soc {
struct pci_ops *ops;
+ int (*setup_irq)(struct mtk_pcie_port *port, struct device_node *node);
int (*startup)(struct mtk_pcie_port *port);
};
@@ -82,10 +149,19 @@ 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: the irq number
+ * @irq_domain: legacy intx irq domain
*/
struct mtk_pcie_port {
void __iomem *base;
@@ -93,9 +169,16 @@ 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;
+ u32 irq;
+ struct irq_domain *irq_domain;
};
/**
@@ -156,6 +239,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 +252,285 @@ 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 + APP_TLP_REQ, val,
+ !(val & APP_CFG_REQ), 10,
+ 100 * USEC_PER_MSEC);
+ if (err)
+ return PCIBIOS_SET_FAILED;
+
+ if (readl(port->base + 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);
+
+ *val = 0;
+
+ /* Write PCIe Configuration Transaction Header for cfgrd */
+ writel(CFG_HEADER_DW0(CFG_RDWR_TYPE_0, CFG_RD_FMT),
+ port->base + CFG_HEADER_0);
+ writel(CFG_HEADER_DW1(where, size), port->base + CFG_HEADER_1);
+ writel(CFG_HEADER_DW2(where, PCI_FUNC(devfn),
+ PCI_SLOT(devfn), bus), port->base + CFG_HEADER_2);
+
+ /* Triget h/w to transmit Cfgrd TLP */
+ reg = readl(port->base + APP_TLP_REQ);
+ writel(reg | APP_CFG_REQ, port->base + 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);
+
+ if (size == 1)
+ *val = (*val >> shift) & 0xff;
+ else if (size == 2)
+ *val = (*val >> shift) & 0xffff;
+ else if (size == 3)
+ *val = (*val >> shift) & 0xffffff;
+
+ 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_RDWR_TYPE_0, CFG_WR_FMT),
+ port->base + CFG_HEADER_0);
+ writel(CFG_HEADER_DW1(where, size), port->base + CFG_HEADER_1);
+ writel(CFG_HEADER_DW2(where, PCI_FUNC(devfn),
+ PCI_SLOT(devfn), bus), port->base + CFG_HEADER_2);
+ /* 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 + APP_TLP_REQ);
+ val |= APP_CFG_REQ;
+ writel(val, port->base + 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;
+
+ /* Some V2 platforms need to enable LTSSM 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_RSTCR);
+
+ /*
+ * Enable rc internal reset.
+ * The reset will work when the link is from link up to link down.
+ */
+ writel(PCIE_LINKDOWN_RST_EN, port->base + PCIE_RSTCR);
+
+ /* De-assert phy, pe, pipe, mac and configuration reset */
+ val = readl(port->base + PCIE_RSTCR);
+ val |= PCIE_PHY_RSTB | PCIE_PERSTB | PCIE_PIPE_SRSTB |
+ PCIE_MAC_SRSTB | PCIE_CRSTB;
+ writel(val, port->base + PCIE_RSTCR);
+
+ /* 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 for memory */
+ if (mem->flags & IORESOURCE_MEM) {
+ size = mem->end - mem->start;
+ val = AHB2PCIE_BASEL(mem->start) | BASE_SIZE(fls(size));
+ writel(val, port->base + AHB2PCIE_BASE0_L);
+
+ val = AHB2PCIE_BASEH(mem->start);
+ writel(val, port->base + AHB2PCIE_BASE0_H);
+ }
+
+ /* Set PCIe to axi translation memory space.*/
+ val = fls(PCIE2AXI_SIZE) | WIN_ENABLE;
+ writel(val, port->base + PCIE2AXI_WIN);
+
+ 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;
+ 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(port->pcie->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, index = port->index;
+
+ port->irq = platform_get_irq(pdev, index);
+ err = devm_request_irq(dev, port->irq, mtk_pcie_intr_handler,
+ IRQF_SHARED, "mtk-pcie", port);
+ if (err) {
+ dev_err(dev, "unable to request irq %d\n", port->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 +617,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 +673,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 +722,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 +786,11 @@ 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 +1020,16 @@ static struct mtk_pcie_soc mtk_pcie_soc_v1 = {
.startup = mtk_pcie_startup_ports,
};
+static struct mtk_pcie_soc mtk_pcie_soc_v2 = {
+ .setup_irq = mtk_pcie_setup_irq,
+ .ops = &mtk_pcie_ops_v2,
+ .startup = mtk_pcie_startup_ports_v2,
+};
+
static const struct of_device_id mtk_pcie_ids[] = {
{ .compatible = "mediatek,mt7623-pcie", .data = &mtk_pcie_soc_v1 },
{ .compatible = "mediatek,mt2701-pcie", .data = &mtk_pcie_soc_v1 },
+ { .compatible = "mediatek,generic-pcie-v2", .data = &mtk_pcie_soc_v2 },
{},
};
--
2.6.4
From: Ryder Lee <[email protected]>
Add support for MediaTek new generation controller and update related
properities.
Signed-off-by: Ryder Lee <[email protected]>
Signed-off-by: Honghui Zhang <[email protected]>
---
.../devicetree/bindings/pci/mediatek-pcie.txt | 84 ++++++++++++++++++++--
1 file changed, 79 insertions(+), 5 deletions(-)
diff --git a/Documentation/devicetree/bindings/pci/mediatek-pcie.txt b/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
index 294f4a3..a1f3767 100644
--- a/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
+++ b/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
@@ -4,17 +4,27 @@ Required properties:
- compatible: Should contain one of the following string:
"mediatek,mt7623-pcie"
"mediatek,mt2701-pcie"
+ "mediatek,generic-pcie-v2"
- 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
+ - sys_ckN :transaction layer and data link layer clock
+ The "sys_ck" might be divided into the following parts in some v2 chips:
+ - ahb_ckN :AHB slave interface operating clock for CSR access and RC
+ initiated MMIO access
+ - 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 :pe2_mac_bridge and pe2_mac_core operating clock when
+ pcie_mac_ck/pcie_pipe_ck is turned off
+ 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 +43,9 @@ 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 mediatek generic-pcie-v2:
+-interrupts: A list of interrupt outputs of the controller.
+
In addition, the device tree node must have sub-nodes describing each
PCIe port interface, having the following mandatory properties:
@@ -50,7 +63,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 +81,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 +141,63 @@ Examples:
num-lanes = <1>;
};
};
+
+Examples for mt2712:
+ pcie: pcie@0x11700000 {
+ 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", "ahb0", "ahb1";
+ 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
Hi Ryder,
[auto build test WARNING on pci/next]
[also build test WARNING on v4.13-rc1 next-20170721]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/honghui-zhang-mediatek-com/PCI-MediaTek-Add-support-for-new-generation-host-controller/20170723-040107
base: https://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git next
config: arm-allmodconfig (attached as .config)
compiler: arm-linux-gnueabi-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
wget https://raw.githubusercontent.com/01org/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=arm
All warnings (new ones prefixed by >>):
drivers/pci/host/pcie-mediatek.c: In function 'mtk_pcie_startup_ports_v2':
>> drivers/pci/host/pcie-mediatek.c:86:36: warning: right shift count >= width of type [-Wshift-count-overflow]
#define AHB2PCIE_BASEH(base) (base >> 32)
^
>> drivers/pci/host/pcie-mediatek.c:440:9: note: in expansion of macro 'AHB2PCIE_BASEH'
val = AHB2PCIE_BASEH(mem->start);
^~~~~~~~~~~~~~
drivers/pci/host/pcie-mediatek.c: In function 'mtk_pcie_parse_ports':
>> drivers/pci/host/pcie-mediatek.c:789:2: warning: this 'if' clause does not guard... [-Wmisleading-indentation]
if (pcie->soc->setup_irq)
^~
drivers/pci/host/pcie-mediatek.c:791:3: note: ...this statement, but the latter is misleadingly indented as if it is guarded by the 'if'
if (err)
^~
vim +86 drivers/pci/host/pcie-mediatek.c
74
75 /* PCIe V2 per-port registers */
76 #define PCIE_INT_MASK 0x420
77 #define INTX_MASK GENMASK(19, 16)
78 #define INTX_SHIFT 16
79 #define INTX_NUM 4
80 #define PCIE_INT_STATUS 0x424
81 #define AHB2PCIE_BASE0_L 0x438
82 #define AHB2PCIE_BASE0_H 0x43c
83 #define PCIE2AXI_WIN 0x448
84 #define WIN_ENABLE BIT(7)
85 #define AHB2PCIE_BASEL(base) (base & GENMASK(31, 0))
> 86 #define AHB2PCIE_BASEH(base) (base >> 32)
87 #define BASE_SIZE(sz) (sz & GENMASK(4, 0))
88 #define PCIE2AXI_SIZE 0xffffffff
89
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
On Fri, Jul 21, 2017 at 10:34:49AM +0800, [email protected] wrote:
> From: Ryder Lee <[email protected]>
>
> Add support for MediaTek new generation controller and update related
> properities.
>
> Signed-off-by: Ryder Lee <[email protected]>
> Signed-off-by: Honghui Zhang <[email protected]>
> ---
> .../devicetree/bindings/pci/mediatek-pcie.txt | 84 ++++++++++++++++++++--
> 1 file changed, 79 insertions(+), 5 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/pci/mediatek-pcie.txt b/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
> index 294f4a3..a1f3767 100644
> --- a/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
> +++ b/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
> @@ -4,17 +4,27 @@ Required properties:
> - compatible: Should contain one of the following string:
> "mediatek,mt7623-pcie"
> "mediatek,mt2701-pcie"
> + "mediatek,generic-pcie-v2"
No, please use SoC specific compatible strings.
> - 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
> + - sys_ckN :transaction layer and data link layer clock
> + The "sys_ck" might be divided into the following parts in some v2 chips:
Please be specific about what clocks apply to which compatible. Each
valid combination of clocks should correspond to at least one
compatible.
> + - ahb_ckN :AHB slave interface operating clock for CSR access and RC
> + initiated MMIO access
> + - 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 :pe2_mac_bridge and pe2_mac_core operating clock when
> + pcie_mac_ck/pcie_pipe_ck is turned off
> + 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 +43,9 @@ 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 mediatek generic-pcie-v2:
> +-interrupts: A list of interrupt outputs of the controller.
> +
How mnay interrupts? Not sure why you moved this in the previous patch
if all versions have some interrupts.
> In addition, the device tree node must have sub-nodes describing each
> PCIe port interface, having the following mandatory properties:
>
> @@ -50,7 +63,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 +81,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 +141,63 @@ Examples:
> num-lanes = <1>;
> };
> };
> +
> +Examples for mt2712:
> + pcie: pcie@0x11700000 {
Drop the '0x'.
> + 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", "ahb0", "ahb1";
> + 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
>
> --
> To unsubscribe from this list: send the line "unsubscribe devicetree" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
On Mon, 2017-07-24 at 15:26 -0500, Rob Herring wrote:
> On Fri, Jul 21, 2017 at 10:34:49AM +0800, [email protected] wrote:
> > From: Ryder Lee <[email protected]>
> >
> > Add support for MediaTek new generation controller and update related
> > properities.
> >
> > Signed-off-by: Ryder Lee <[email protected]>
> > Signed-off-by: Honghui Zhang <[email protected]>
> > ---
> > .../devicetree/bindings/pci/mediatek-pcie.txt | 84 ++++++++++++++++++++--
> > 1 file changed, 79 insertions(+), 5 deletions(-)
> >
> > diff --git a/Documentation/devicetree/bindings/pci/mediatek-pcie.txt b/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
> > index 294f4a3..a1f3767 100644
> > --- a/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
> > +++ b/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
> > @@ -4,17 +4,27 @@ Required properties:
> > - compatible: Should contain one of the following string:
> > "mediatek,mt7623-pcie"
> > "mediatek,mt2701-pcie"
> > + "mediatek,generic-pcie-v2"
>
> No, please use SoC specific compatible strings.
>
Thanks, I will rewrite it as below:
"mediatek,mt2701-pcie"
"mediatek,mt7623-pcie"
"mediatek,mt2712-pcie"
"mediatek,mt7622-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
> > + - sys_ckN :transaction layer and data link layer clock
> > + The "sys_ck" might be divided into the following parts in some v2 chips:
>
> Please be specific about what clocks apply to which compatible. Each
> valid combination of clocks should correspond to at least one
> compatible.
>
Thanks, I will change it in the next version.
> > + - ahb_ckN :AHB slave interface operating clock for CSR access and RC
> > + initiated MMIO access
> > + - 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 :pe2_mac_bridge and pe2_mac_core operating clock when
> > + pcie_mac_ck/pcie_pipe_ck is turned off
> > + 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 +43,9 @@ 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 mediatek generic-pcie-v2:
> > +-interrupts: A list of interrupt outputs of the controller.
> > +
>
> How mnay interrupts? Not sure why you moved this in the previous patch
> if all versions have some interrupts.
>
There would be 1 interrupt per port for the new SoCs.
The legacy controller(7623, 2701) does not have a interrupt status
register to identify the interrupt source, so we use interrupt-map to
bind the interrupt to each port, thus we do not need the "interrupt"
property.
But the new SoCs doest not have this problem, and support msi. So we use
the standard "interrupt" property.
How about:
Requirted properties for "medaitek,mt2712-pcie" and
"mediatek,mt7622-pcie"
-interrupts: A list for interrupt outputs of the controller, there must
be one interrupt for each port.
> > In addition, the device tree node must have sub-nodes describing each
> > PCIe port interface, having the following mandatory properties:
> >
> > @@ -50,7 +63,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 +81,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 +141,63 @@ Examples:
> > num-lanes = <1>;
> > };
> > };
> > +
> > +Examples for mt2712:
> > + pcie: pcie@0x11700000 {
>
> Drop the '0x'.
OK, thanks.
>
> > + 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", "ahb0", "ahb1";
> > + 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
> >
> > --
> > To unsubscribe from this list: send the line "unsubscribe devicetree" in
> > the body of a message to [email protected]
> > More majordomo info at http://vger.kernel.org/majordomo-info.html