* [PATCH v5 0/2] Add PCIe host driver support for Mediatek SoCs @ 2017-05-21 3:42 ` Ryder Lee 0 siblings, 0 replies; 23+ messages in thread From: Ryder Lee @ 2017-05-21 3:42 UTC (permalink / raw) To: Bjorn Helgaas, Rob Herring, Arnd Bergmann Cc: linux-pci, devicetree, linux-mediatek, linux-arm-kernel, linux-kernel, Red Hung, Ryder Lee Hi, This patch series add Mediatek Gen2 PCIe host controller driver and dt-binding document. It can be found on MT7623 series SoCs. This driver was validated using Broadcom Tigon3 and Intel(R) 82575/82576 gigabit ethernet card. Changes since v5: - rebase to Linux 4.12-rc1. - remove redundant module.h header and MODULE macros. Changes since v4: - move the per-port registers to the parent node. - use a valid compatible for hifsys controller. - use the 'sysirq' instead of 'gic' as a correct 'interrupt-parent' of the interrupt-map properties. 'sysirq' is an interrupt-controller that could help us to reverse GIC SPIs polarity so that we could properly set irq type to level low without any extra properties. It was a mistake to select wrong interrupt-parent on the previous versions. Now, we could remove unnecessary interrupt properties entirely from binding. Changes since v3: - correct sub-nodes unit addresses. Changes since v2: - modify Kconfig to avoid kbuild test error on some architecture. - change compatible string. - revise binding document: add missing interrupt-names. remove the board dts example and drop 'status' properties. remove unnecessary descriptions bout standard PCI bus binding. Changes since v1: - add .suppress_bind_attrs. - remove unnecessary *_valid_device() pattern. - remove PCI_PROBE_ONLY. - use the regular readl() instead of readl_relaxed(). - add .map_bus() and change to use pci_generic_config_read/pci_generic_config_write. - revise dt-binding document and move nonstandard properties to root node. - change compatible string. - use interrupt-map property and replace mtk_pcie_map_irq() with of_irq_parse_and_map_pci(). - use the new pci_register_host_bridge() method instead of pci_scan_root_bus()* Ryder Lee (2): PCI: mediatek: Add Mediatek PCIe host controller support dt-bindings: pcie: Add documentation for Mediatek PCIe .../bindings/pci/mediatek,mt7623-pcie.txt | 130 +++++ drivers/pci/host/Kconfig | 11 + drivers/pci/host/Makefile | 1 + drivers/pci/host/pcie-mediatek.c | 553 +++++++++++++++++++++ 4 files changed, 695 insertions(+) create mode 100644 Documentation/devicetree/bindings/pci/mediatek,mt7623-pcie.txt create mode 100644 drivers/pci/host/pcie-mediatek.c -- 1.9.1 ^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH v5 0/2] Add PCIe host driver support for Mediatek SoCs @ 2017-05-21 3:42 ` Ryder Lee 0 siblings, 0 replies; 23+ messages in thread From: Ryder Lee @ 2017-05-21 3:42 UTC (permalink / raw) To: linux-arm-kernel Hi, This patch series add Mediatek Gen2 PCIe host controller driver and dt-binding document. It can be found on MT7623 series SoCs. This driver was validated using Broadcom Tigon3 and Intel(R) 82575/82576 gigabit ethernet card. Changes since v5: - rebase to Linux 4.12-rc1. - remove redundant module.h header and MODULE macros. Changes since v4: - move the per-port registers to the parent node. - use a valid compatible for hifsys controller. - use the 'sysirq' instead of 'gic' as a correct 'interrupt-parent' of the interrupt-map properties. 'sysirq' is an interrupt-controller that could help us to reverse GIC SPIs polarity so that we could properly set irq type to level low without any extra properties. It was a mistake to select wrong interrupt-parent on the previous versions. Now, we could remove unnecessary interrupt properties entirely from binding. Changes since v3: - correct sub-nodes unit addresses. Changes since v2: - modify Kconfig to avoid kbuild test error on some architecture. - change compatible string. - revise binding document: add missing interrupt-names. remove the board dts example and drop 'status' properties. remove unnecessary descriptions bout standard PCI bus binding. Changes since v1: - add .suppress_bind_attrs. - remove unnecessary *_valid_device() pattern. - remove PCI_PROBE_ONLY. - use the regular readl() instead of readl_relaxed(). - add .map_bus() and change to use pci_generic_config_read/pci_generic_config_write. - revise dt-binding document and move nonstandard properties to root node. - change compatible string. - use interrupt-map property and replace mtk_pcie_map_irq() with of_irq_parse_and_map_pci(). - use the new pci_register_host_bridge() method instead of pci_scan_root_bus()* Ryder Lee (2): PCI: mediatek: Add Mediatek PCIe host controller support dt-bindings: pcie: Add documentation for Mediatek PCIe .../bindings/pci/mediatek,mt7623-pcie.txt | 130 +++++ drivers/pci/host/Kconfig | 11 + drivers/pci/host/Makefile | 1 + drivers/pci/host/pcie-mediatek.c | 553 +++++++++++++++++++++ 4 files changed, 695 insertions(+) create mode 100644 Documentation/devicetree/bindings/pci/mediatek,mt7623-pcie.txt create mode 100644 drivers/pci/host/pcie-mediatek.c -- 1.9.1 ^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH v5 0/2] Add PCIe host driver support for Mediatek SoCs @ 2017-05-21 3:42 ` Ryder Lee 0 siblings, 0 replies; 23+ messages in thread From: Ryder Lee @ 2017-05-21 3:42 UTC (permalink / raw) To: Bjorn Helgaas, Rob Herring, Arnd Bergmann Cc: devicetree, Red Hung, linux-pci, linux-kernel, Ryder Lee, linux-mediatek, linux-arm-kernel Hi, This patch series add Mediatek Gen2 PCIe host controller driver and dt-binding document. It can be found on MT7623 series SoCs. This driver was validated using Broadcom Tigon3 and Intel(R) 82575/82576 gigabit ethernet card. Changes since v5: - rebase to Linux 4.12-rc1. - remove redundant module.h header and MODULE macros. Changes since v4: - move the per-port registers to the parent node. - use a valid compatible for hifsys controller. - use the 'sysirq' instead of 'gic' as a correct 'interrupt-parent' of the interrupt-map properties. 'sysirq' is an interrupt-controller that could help us to reverse GIC SPIs polarity so that we could properly set irq type to level low without any extra properties. It was a mistake to select wrong interrupt-parent on the previous versions. Now, we could remove unnecessary interrupt properties entirely from binding. Changes since v3: - correct sub-nodes unit addresses. Changes since v2: - modify Kconfig to avoid kbuild test error on some architecture. - change compatible string. - revise binding document: add missing interrupt-names. remove the board dts example and drop 'status' properties. remove unnecessary descriptions bout standard PCI bus binding. Changes since v1: - add .suppress_bind_attrs. - remove unnecessary *_valid_device() pattern. - remove PCI_PROBE_ONLY. - use the regular readl() instead of readl_relaxed(). - add .map_bus() and change to use pci_generic_config_read/pci_generic_config_write. - revise dt-binding document and move nonstandard properties to root node. - change compatible string. - use interrupt-map property and replace mtk_pcie_map_irq() with of_irq_parse_and_map_pci(). - use the new pci_register_host_bridge() method instead of pci_scan_root_bus()* Ryder Lee (2): PCI: mediatek: Add Mediatek PCIe host controller support dt-bindings: pcie: Add documentation for Mediatek PCIe .../bindings/pci/mediatek,mt7623-pcie.txt | 130 +++++ drivers/pci/host/Kconfig | 11 + drivers/pci/host/Makefile | 1 + drivers/pci/host/pcie-mediatek.c | 553 +++++++++++++++++++++ 4 files changed, 695 insertions(+) create mode 100644 Documentation/devicetree/bindings/pci/mediatek,mt7623-pcie.txt create mode 100644 drivers/pci/host/pcie-mediatek.c -- 1.9.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] 23+ messages in thread
* [PATCH v5 0/2] Add PCIe host driver support for Mediatek SoCs @ 2017-05-21 3:42 ` Ryder Lee 0 siblings, 0 replies; 23+ messages in thread From: Ryder Lee @ 2017-05-21 3:42 UTC (permalink / raw) To: Bjorn Helgaas, Rob Herring, Arnd Bergmann Cc: linux-pci, devicetree, linux-mediatek, linux-arm-kernel, linux-kernel, Red Hung, Ryder Lee Hi, This patch series add Mediatek Gen2 PCIe host controller driver and dt-binding document. It can be found on MT7623 series SoCs. This driver was validated using Broadcom Tigon3 and Intel(R) 82575/82576 gigabit ethernet card. Changes since v5: - rebase to Linux 4.12-rc1. - remove redundant module.h header and MODULE macros. Changes since v4: - move the per-port registers to the parent node. - use a valid compatible for hifsys controller. - use the 'sysirq' instead of 'gic' as a correct 'interrupt-parent' of the interrupt-map properties. 'sysirq' is an interrupt-controller that could help us to reverse GIC SPIs polarity so that we could properly set irq type to level low without any extra properties. It was a mistake to select wrong interrupt-parent on the previous versions. Now, we could remove unnecessary interrupt properties entirely from binding. Changes since v3: - correct sub-nodes unit addresses. Changes since v2: - modify Kconfig to avoid kbuild test error on some architecture. - change compatible string. - revise binding document: add missing interrupt-names. remove the board dts example and drop 'status' properties. remove unnecessary descriptions bout standard PCI bus binding. Changes since v1: - add .suppress_bind_attrs. - remove unnecessary *_valid_device() pattern. - remove PCI_PROBE_ONLY. - use the regular readl() instead of readl_relaxed(). - add .map_bus() and change to use pci_generic_config_read/pci_generic_config_write. - revise dt-binding document and move nonstandard properties to root node. - change compatible string. - use interrupt-map property and replace mtk_pcie_map_irq() with of_irq_parse_and_map_pci(). - use the new pci_register_host_bridge() method instead of pci_scan_root_bus()* Ryder Lee (2): PCI: mediatek: Add Mediatek PCIe host controller support dt-bindings: pcie: Add documentation for Mediatek PCIe .../bindings/pci/mediatek,mt7623-pcie.txt | 130 +++++ drivers/pci/host/Kconfig | 11 + drivers/pci/host/Makefile | 1 + drivers/pci/host/pcie-mediatek.c | 553 +++++++++++++++++++++ 4 files changed, 695 insertions(+) create mode 100644 Documentation/devicetree/bindings/pci/mediatek,mt7623-pcie.txt create mode 100644 drivers/pci/host/pcie-mediatek.c -- 1.9.1 ^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH v5 1/2] PCI: mediatek: Add Mediatek PCIe host controller support 2017-05-21 3:42 ` Ryder Lee (?) (?) @ 2017-05-21 3:42 ` Ryder Lee -1 siblings, 0 replies; 23+ messages in thread From: Ryder Lee @ 2017-05-21 3:42 UTC (permalink / raw) To: Bjorn Helgaas, Rob Herring, Arnd Bergmann Cc: linux-pci, devicetree, linux-mediatek, linux-arm-kernel, linux-kernel, Red Hung, Ryder Lee Add support for the Mediatek PCIe Gen2 controller which can be found on MT7623 series SoCs. Signed-off-by: Ryder Lee <ryder.lee@mediatek.com> --- drivers/pci/host/Kconfig | 11 + drivers/pci/host/Makefile | 1 + drivers/pci/host/pcie-mediatek.c | 553 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 565 insertions(+) create mode 100644 drivers/pci/host/pcie-mediatek.c diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig index 7f47cd5..d7d7c47 100644 --- a/drivers/pci/host/Kconfig +++ b/drivers/pci/host/Kconfig @@ -180,6 +180,17 @@ config PCIE_ROCKCHIP There is 1 internal PCIe port available to support GEN2 with 4 slots. +config PCIE_MEDIATEK + bool "Mediatek PCIe controller" + depends on ARM && (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. + config VMD depends on PCI_MSI && X86_64 && SRCU tristate "Intel Volume Management Device Driver" diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile index cab8795..b10d104 100644 --- a/drivers/pci/host/Makefile +++ b/drivers/pci/host/Makefile @@ -18,6 +18,7 @@ obj-$(CONFIG_PCIE_IPROC_BCMA) += pcie-iproc-bcma.o obj-$(CONFIG_PCIE_ALTERA) += pcie-altera.o obj-$(CONFIG_PCIE_ALTERA_MSI) += pcie-altera-msi.o obj-$(CONFIG_PCIE_ROCKCHIP) += pcie-rockchip.o +obj-$(CONFIG_PCIE_MEDIATEK) += pcie-mediatek.o obj-$(CONFIG_VMD) += vmd.o # The following drivers are for devices that use the generic ACPI diff --git a/drivers/pci/host/pcie-mediatek.c b/drivers/pci/host/pcie-mediatek.c new file mode 100644 index 0000000..0cc7943 --- /dev/null +++ b/drivers/pci/host/pcie-mediatek.c @@ -0,0 +1,553 @@ +/* + * Mediatek PCIe host controller driver. + * + * Copyright (c) 2017 MediaTek Inc. + * Author: Ryder Lee <ryder.lee@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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/kernel.h> +#include <linux/of_address.h> +#include <linux/of_pci.h> +#include <linux/of_platform.h> +#include <linux/pci.h> +#include <linux/phy/phy.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> +#include <linux/reset.h> + +/* PCIe shared registers */ +#define PCIE_SYS_CFG 0x00 +#define PCIE_INT_ENABLE 0x0c +#define PCIE_CFG_ADDR 0x20 +#define PCIE_CFG_DATA 0x24 + +/* PCIe per port registers */ +#define PCIE_BAR0_SETUP 0x10 +#define PCIE_BAR1_SETUP 0x14 +#define PCIE_BAR0_MEM_BASE 0x18 +#define PCIE_CLASS 0x34 +#define PCIE_LINK_STATUS 0x50 + +#define PCIE_PORT_INT_EN(x) BIT(20 + (x)) +#define PCIE_PORT_PERST(x) BIT(1 + (x)) +#define PCIE_PORT_LINKUP BIT(0) +#define PCIE_BAR_MAP_MAX GENMASK(31, 16) + +#define PCIE_BAR_ENABLE BIT(0) +#define PCIE_REVISION_ID BIT(0) +#define PCIE_CLASS_CODE (0x60400 << 8) +#define PCIE_CONF_REG(regn) (((regn) & GENMASK(7, 2)) | \ + ((((regn) >> 8) & GENMASK(3, 0)) << 24)) +#define PCIE_CONF_FUN(fun) (((fun) << 8) & GENMASK(10, 8)) +#define PCIE_CONF_DEV(dev) (((dev) << 11) & GENMASK(15, 11)) +#define PCIE_CONF_BUS(bus) (((bus) << 16) & GENMASK(23, 16)) +#define PCIE_CONF_ADDR(regn, fun, dev, bus) \ + (PCIE_CONF_REG(regn) | PCIE_CONF_FUN(fun) | \ + PCIE_CONF_DEV(dev) | PCIE_CONF_BUS(bus)) + +/* Mediatek specific configuration registers */ +#define PCIE_FTS_NUM 0x70c +#define PCIE_FTS_NUM_MASK GENMASK(15, 8) +#define PCIE_FTS_NUM_L0(x) ((x) & 0xff << 8) + +#define PCIE_FC_CREDIT 0x73c +#define PCIE_FC_CREDIT_MASK (GENMASK(31, 31) | GENMASK(28, 16)) +#define PCIE_FC_CREDIT_VAL(x) ((x) << 16) + +/** + * struct mtk_pcie_port - PCIe port information + * @base: IO mapped register base + * @list: port list + * @pcie: pointer to PCIe host info + * @reset: pointer to port reset control + * @sys_ck: pointer to bus clock + * @phy: pointer to phy control block + * @lane: lane count + * @index: port index + */ +struct mtk_pcie_port { + void __iomem *base; + struct list_head list; + struct mtk_pcie *pcie; + struct reset_control *reset; + struct clk *sys_ck; + struct phy *phy; + u32 lane; + u32 index; +}; + +/** + * struct mtk_pcie - PCIe host information + * @dev: pointer to PCIe device + * @base: IO mapped register Base + * @free_ck: free-run reference clock + * @io: IO resource + * @pio: PIO resource + * @mem: non-prefetchable memory resource + * @busn: bus range + * @offset: IO / Memory offset + * @ports: pointer to PCIe port information + */ +struct mtk_pcie { + struct device *dev; + void __iomem *base; + struct clk *free_ck; + + struct resource io; + struct resource pio; + struct resource mem; + struct resource busn; + struct { + resource_size_t mem; + resource_size_t io; + } offset; + struct list_head ports; +}; + +static inline bool mtk_pcie_link_is_up(struct mtk_pcie_port *port) +{ + return !!(readl(port->base + PCIE_LINK_STATUS) & + PCIE_PORT_LINKUP); +} + +static void mtk_pcie_port_free(struct mtk_pcie_port *port) +{ + struct mtk_pcie *pcie = port->pcie; + struct device *dev = pcie->dev; + + devm_iounmap(dev, port->base); + list_del(&port->list); + devm_kfree(dev, port); +} + +static void mtk_pcie_put_resources(struct mtk_pcie *pcie) +{ + struct device *dev = pcie->dev; + struct mtk_pcie_port *port, *tmp; + + list_for_each_entry_safe(port, tmp, &pcie->ports, list) { + phy_power_off(port->phy); + clk_disable_unprepare(port->sys_ck); + mtk_pcie_port_free(port); + } + + clk_disable_unprepare(pcie->free_ck); + pm_runtime_put_sync(dev); + pm_runtime_disable(dev); +} + +static void __iomem *mtk_pcie_map_bus(struct pci_bus *bus, + unsigned int devfn, int where) +{ + struct pci_host_bridge *host = pci_find_host_bridge(bus); + struct mtk_pcie *pcie = pci_host_bridge_priv(host); + + writel(PCIE_CONF_ADDR(where, PCI_FUNC(devfn), PCI_SLOT(devfn), + bus->number), pcie->base + PCIE_CFG_ADDR); + + return pcie->base + PCIE_CFG_DATA + (where & 3); +} + +static struct pci_ops mtk_pcie_ops = { + .map_bus = mtk_pcie_map_bus, + .read = pci_generic_config_read, + .write = pci_generic_config_write, +}; + +static void mtk_pcie_configure_rc(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; + + /* enable interrupt */ + val = readl(pcie->base + PCIE_INT_ENABLE); + val |= PCIE_PORT_INT_EN(port->index); + writel(val, pcie->base + PCIE_INT_ENABLE); + + /* map to all DDR region. We need to set it before cfg operation. */ + writel(PCIE_BAR_MAP_MAX | PCIE_BAR_ENABLE, + port->base + PCIE_BAR0_SETUP); + + /* configure class Code and revision ID */ + writel(PCIE_CLASS_CODE | PCIE_REVISION_ID, + port->base + PCIE_CLASS); + + /* configure FC credit */ + writel(PCIE_CONF_ADDR(PCIE_FC_CREDIT, func, slot, 0), + pcie->base + PCIE_CFG_ADDR); + val = readl(pcie->base + PCIE_CFG_DATA); + val &= ~PCIE_FC_CREDIT_MASK; + val |= PCIE_FC_CREDIT_VAL(0x806c); + writel(PCIE_CONF_ADDR(PCIE_FC_CREDIT, func, slot, 0), + pcie->base + PCIE_CFG_ADDR); + writel(val, pcie->base + PCIE_CFG_DATA); + + /* configure RC FTS number to 250 when it leaves L0s */ + writel(PCIE_CONF_ADDR(PCIE_FTS_NUM, func, slot, 0), + pcie->base + PCIE_CFG_ADDR); + val = readl(pcie->base + PCIE_CFG_DATA); + val &= ~PCIE_FTS_NUM_MASK; + val |= PCIE_FTS_NUM_L0(0x50); + 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); +} + +static int mtk_pcie_enable_ports(struct mtk_pcie_port *port) +{ + struct device *dev = port->pcie->dev; + int err; + + err = clk_prepare_enable(port->sys_ck); + if (err) { + dev_err(dev, "failed to enable port%d clock\n", port->index); + goto err_sys_clk; + } + + reset_control_assert(port->reset); + reset_control_deassert(port->reset); + + err = phy_power_on(port->phy); + if (err) { + dev_err(dev, "failed to power on port%d phy\n", port->index); + goto err_phy_on; + } + + mtk_pcie_assert_ports(port); + + /* if link up, then setup root port configuration space */ + if (mtk_pcie_link_is_up(port)) { + mtk_pcie_configure_rc(port); + return 0; + } + + dev_info(dev, "Port%d link down\n", port->index); + + phy_power_off(port->phy); +err_phy_on: + clk_disable_unprepare(port->sys_ck); + mtk_pcie_port_free(port); +err_sys_clk: + return err; +} + +static int mtk_pcie_parse_ports(struct mtk_pcie *pcie, + struct mtk_pcie_port **p, + struct device_node *node, + int index) +{ + struct mtk_pcie_port *port; + struct resource *regs; + struct device *dev = pcie->dev; + struct platform_device *pdev = to_platform_device(dev); + char name[10]; + int err; + + *p = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL); + if (!*p) + return -ENOMEM; + + port = *p; + + err = of_property_read_u32(node, "num-lanes", &port->lane); + if (err) { + dev_err(dev, "missing num-lanes property\n"); + return err; + } + + regs = platform_get_resource(pdev, IORESOURCE_MEM, index + 1); + port->base = devm_ioremap_resource(dev, regs); + if (IS_ERR(port->base)) { + dev_err(dev, "failed to map port%d base\n", index); + return PTR_ERR(port->base); + } + + 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); + return PTR_ERR(port->sys_ck); + } + + snprintf(name, sizeof(name), "pcie-rst%d", index); + port->reset = devm_reset_control_get(dev, name); + if (IS_ERR(port->reset)) { + dev_err(dev, "failed to get port%d reset\n", index); + return PTR_ERR(port->reset); + } + + snprintf(name, sizeof(name), "pcie-phy%d", index); + port->phy = devm_phy_get(dev, name); + if (IS_ERR(port->phy)) { + dev_err(dev, "failed to get port%d phy\n", index); + return PTR_ERR(port->phy); + } + + port->index = index; + port->pcie = pcie; + + INIT_LIST_HEAD(&port->list); + list_add_tail(&port->list, &pcie->ports); + + return 0; +} + +static int mtk_pcie_handle_shared_resource(struct mtk_pcie *pcie) +{ + struct device *dev = pcie->dev; + struct platform_device *pdev = to_platform_device(dev); + 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); + } + + pcie->free_ck = devm_clk_get(dev, "free_ck"); + if (IS_ERR(pcie->free_ck)) { + dev_err(dev, "failed to get free_ck\n"); + return PTR_ERR(pcie->free_ck); + } + + pm_runtime_enable(dev); + err = pm_runtime_get_sync(dev); + if (err) + goto err_pm; + + /* enable top level clock */ + err = clk_prepare_enable(pcie->free_ck); + if (err) { + dev_err(dev, "failed to enable free_ck\n"); + goto err_free_ck; + } + + return 0; + +err_free_ck: + pm_runtime_put_sync(dev); +err_pm: + pm_runtime_disable(dev); + + return err; +} + +static int mtk_pcie_parse_and_add_res(struct mtk_pcie *pcie) +{ + struct device *dev = pcie->dev; + struct device_node *node = dev->of_node, *child; + struct of_pci_range_parser parser; + struct of_pci_range range; + struct resource res; + int err, linkup = 0; + + /* parse shared resources */ + err = mtk_pcie_handle_shared_resource(pcie); + if (err) + return err; + + if (of_pci_range_parser_init(&parser, node)) { + dev_err(dev, "missing \"ranges\" property\n"); + return -EINVAL; + } + + for_each_of_pci_range(&parser, &range) { + err = of_pci_range_to_resource(&range, node, &res); + if (err < 0) + return err; + + switch (res.flags & IORESOURCE_TYPE_BITS) { + case IORESOURCE_IO: + pcie->offset.io = res.start - range.pci_addr; + + memcpy(&pcie->pio, &res, sizeof(res)); + pcie->pio.name = node->full_name; + + pcie->io.start = range.cpu_addr; + pcie->io.end = range.cpu_addr + range.size - 1; + pcie->io.flags = IORESOURCE_MEM; + pcie->io.name = "I/O"; + + memcpy(&res, &pcie->io, sizeof(res)); + break; + + case IORESOURCE_MEM: + pcie->offset.mem = res.start - range.pci_addr; + + memcpy(&pcie->mem, &res, sizeof(res)); + pcie->mem.name = "non-prefetchable"; + break; + } + } + + err = of_pci_parse_bus_range(node, &pcie->busn); + if (err < 0) { + dev_err(dev, "failed to parse ranges property: %d\n", err); + pcie->busn.name = node->name; + pcie->busn.start = 0; + pcie->busn.end = 0xff; + pcie->busn.flags = IORESOURCE_BUS; + } + + for_each_child_of_node(node, child) { + struct mtk_pcie_port *port; + int index; + + err = of_pci_get_devfn(child); + if (err < 0) { + dev_err(dev, "failed to parse devfn: %d\n", err); + return err; + } + + index = PCI_SLOT(err); + + if (!of_device_is_available(child)) + continue; + + err = mtk_pcie_parse_ports(pcie, &port, child, index); + if (err) + return err; + + /* enable each port, and then check link status */ + err = mtk_pcie_enable_ports(port); + if (!err) + linkup++; + } + + return !linkup; +} + +static int mtk_pcie_request_resources(struct mtk_pcie *pcie) +{ + struct pci_host_bridge *host = pci_host_bridge_from_priv(pcie); + struct list_head *windows = &host->windows; + struct device *dev = pcie->dev; + int err; + + pci_add_resource_offset(windows, &pcie->pio, pcie->offset.io); + pci_add_resource_offset(windows, &pcie->mem, pcie->offset.mem); + pci_add_resource(windows, &pcie->busn); + + err = devm_request_pci_bus_resources(dev, windows); + if (err < 0) + return err; + + pci_remap_iospace(&pcie->pio, pcie->io.start); + + return 0; +} + +static int mtk_pcie_register_host(struct pci_host_bridge *host) +{ + struct mtk_pcie *pcie = pci_host_bridge_priv(host); + struct pci_bus *child; + int err; + + pci_add_flags(PCI_REASSIGN_ALL_RSRC | PCI_REASSIGN_ALL_BUS); + host->busnr = pcie->busn.start; + host->dev.parent = pcie->dev; + host->ops = &mtk_pcie_ops; + + err = pci_register_host_bridge(host); + if (err < 0) + return err; + + pci_scan_child_bus(host->bus); + + pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci); + pci_bus_size_bridges(host->bus); + pci_bus_assign_resources(host->bus); + + list_for_each_entry(child, &host->bus->children, node) + pcie_bus_configure_settings(child); + + pci_bus_add_devices(host->bus); + + return 0; +} + +static int mtk_pcie_probe(struct platform_device *pdev) +{ + struct mtk_pcie *pcie; + struct pci_host_bridge *host; + int err; + + host = pci_alloc_host_bridge(sizeof(*pcie)); + if (!host) + return -ENOMEM; + + pcie = pci_host_bridge_priv(host); + + pcie->dev = &pdev->dev; + platform_set_drvdata(pdev, pcie); + INIT_LIST_HEAD(&pcie->ports); + + err = mtk_pcie_parse_and_add_res(pcie); + if (err) + return err; + + err = mtk_pcie_request_resources(pcie); + if (err) + goto put_resources; + + err = mtk_pcie_register_host(host); + if (err) + goto put_resources; + + return 0; + +put_resources: + mtk_pcie_put_resources(pcie); + return err; +} + +static const struct of_device_id mtk_pcie_ids[] = { + { .compatible = "mediatek,mt7623-pcie"}, + { .compatible = "mediatek,mt2701-pcie"}, + {}, +}; + +static struct platform_driver mtk_pcie_driver = { + .probe = mtk_pcie_probe, + .driver = { + .name = "mtk-pcie", + .of_match_table = mtk_pcie_ids, + .suppress_bind_attrs = true, + }, +}; +builtin_platform_driver(mtk_pcie_driver); -- 1.9.1 ^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v5 1/2] PCI: mediatek: Add Mediatek PCIe host controller support @ 2017-05-21 3:42 ` Ryder Lee 0 siblings, 0 replies; 23+ messages in thread From: Ryder Lee @ 2017-05-21 3:42 UTC (permalink / raw) To: linux-arm-kernel Add support for the Mediatek PCIe Gen2 controller which can be found on MT7623 series SoCs. Signed-off-by: Ryder Lee <ryder.lee@mediatek.com> --- drivers/pci/host/Kconfig | 11 + drivers/pci/host/Makefile | 1 + drivers/pci/host/pcie-mediatek.c | 553 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 565 insertions(+) create mode 100644 drivers/pci/host/pcie-mediatek.c diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig index 7f47cd5..d7d7c47 100644 --- a/drivers/pci/host/Kconfig +++ b/drivers/pci/host/Kconfig @@ -180,6 +180,17 @@ config PCIE_ROCKCHIP There is 1 internal PCIe port available to support GEN2 with 4 slots. +config PCIE_MEDIATEK + bool "Mediatek PCIe controller" + depends on ARM && (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. + config VMD depends on PCI_MSI && X86_64 && SRCU tristate "Intel Volume Management Device Driver" diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile index cab8795..b10d104 100644 --- a/drivers/pci/host/Makefile +++ b/drivers/pci/host/Makefile @@ -18,6 +18,7 @@ obj-$(CONFIG_PCIE_IPROC_BCMA) += pcie-iproc-bcma.o obj-$(CONFIG_PCIE_ALTERA) += pcie-altera.o obj-$(CONFIG_PCIE_ALTERA_MSI) += pcie-altera-msi.o obj-$(CONFIG_PCIE_ROCKCHIP) += pcie-rockchip.o +obj-$(CONFIG_PCIE_MEDIATEK) += pcie-mediatek.o obj-$(CONFIG_VMD) += vmd.o # The following drivers are for devices that use the generic ACPI diff --git a/drivers/pci/host/pcie-mediatek.c b/drivers/pci/host/pcie-mediatek.c new file mode 100644 index 0000000..0cc7943 --- /dev/null +++ b/drivers/pci/host/pcie-mediatek.c @@ -0,0 +1,553 @@ +/* + * Mediatek PCIe host controller driver. + * + * Copyright (c) 2017 MediaTek Inc. + * Author: Ryder Lee <ryder.lee@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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/kernel.h> +#include <linux/of_address.h> +#include <linux/of_pci.h> +#include <linux/of_platform.h> +#include <linux/pci.h> +#include <linux/phy/phy.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> +#include <linux/reset.h> + +/* PCIe shared registers */ +#define PCIE_SYS_CFG 0x00 +#define PCIE_INT_ENABLE 0x0c +#define PCIE_CFG_ADDR 0x20 +#define PCIE_CFG_DATA 0x24 + +/* PCIe per port registers */ +#define PCIE_BAR0_SETUP 0x10 +#define PCIE_BAR1_SETUP 0x14 +#define PCIE_BAR0_MEM_BASE 0x18 +#define PCIE_CLASS 0x34 +#define PCIE_LINK_STATUS 0x50 + +#define PCIE_PORT_INT_EN(x) BIT(20 + (x)) +#define PCIE_PORT_PERST(x) BIT(1 + (x)) +#define PCIE_PORT_LINKUP BIT(0) +#define PCIE_BAR_MAP_MAX GENMASK(31, 16) + +#define PCIE_BAR_ENABLE BIT(0) +#define PCIE_REVISION_ID BIT(0) +#define PCIE_CLASS_CODE (0x60400 << 8) +#define PCIE_CONF_REG(regn) (((regn) & GENMASK(7, 2)) | \ + ((((regn) >> 8) & GENMASK(3, 0)) << 24)) +#define PCIE_CONF_FUN(fun) (((fun) << 8) & GENMASK(10, 8)) +#define PCIE_CONF_DEV(dev) (((dev) << 11) & GENMASK(15, 11)) +#define PCIE_CONF_BUS(bus) (((bus) << 16) & GENMASK(23, 16)) +#define PCIE_CONF_ADDR(regn, fun, dev, bus) \ + (PCIE_CONF_REG(regn) | PCIE_CONF_FUN(fun) | \ + PCIE_CONF_DEV(dev) | PCIE_CONF_BUS(bus)) + +/* Mediatek specific configuration registers */ +#define PCIE_FTS_NUM 0x70c +#define PCIE_FTS_NUM_MASK GENMASK(15, 8) +#define PCIE_FTS_NUM_L0(x) ((x) & 0xff << 8) + +#define PCIE_FC_CREDIT 0x73c +#define PCIE_FC_CREDIT_MASK (GENMASK(31, 31) | GENMASK(28, 16)) +#define PCIE_FC_CREDIT_VAL(x) ((x) << 16) + +/** + * struct mtk_pcie_port - PCIe port information + * @base: IO mapped register base + * @list: port list + * @pcie: pointer to PCIe host info + * @reset: pointer to port reset control + * @sys_ck: pointer to bus clock + * @phy: pointer to phy control block + * @lane: lane count + * @index: port index + */ +struct mtk_pcie_port { + void __iomem *base; + struct list_head list; + struct mtk_pcie *pcie; + struct reset_control *reset; + struct clk *sys_ck; + struct phy *phy; + u32 lane; + u32 index; +}; + +/** + * struct mtk_pcie - PCIe host information + * @dev: pointer to PCIe device + * @base: IO mapped register Base + * @free_ck: free-run reference clock + * @io: IO resource + * @pio: PIO resource + * @mem: non-prefetchable memory resource + * @busn: bus range + * @offset: IO / Memory offset + * @ports: pointer to PCIe port information + */ +struct mtk_pcie { + struct device *dev; + void __iomem *base; + struct clk *free_ck; + + struct resource io; + struct resource pio; + struct resource mem; + struct resource busn; + struct { + resource_size_t mem; + resource_size_t io; + } offset; + struct list_head ports; +}; + +static inline bool mtk_pcie_link_is_up(struct mtk_pcie_port *port) +{ + return !!(readl(port->base + PCIE_LINK_STATUS) & + PCIE_PORT_LINKUP); +} + +static void mtk_pcie_port_free(struct mtk_pcie_port *port) +{ + struct mtk_pcie *pcie = port->pcie; + struct device *dev = pcie->dev; + + devm_iounmap(dev, port->base); + list_del(&port->list); + devm_kfree(dev, port); +} + +static void mtk_pcie_put_resources(struct mtk_pcie *pcie) +{ + struct device *dev = pcie->dev; + struct mtk_pcie_port *port, *tmp; + + list_for_each_entry_safe(port, tmp, &pcie->ports, list) { + phy_power_off(port->phy); + clk_disable_unprepare(port->sys_ck); + mtk_pcie_port_free(port); + } + + clk_disable_unprepare(pcie->free_ck); + pm_runtime_put_sync(dev); + pm_runtime_disable(dev); +} + +static void __iomem *mtk_pcie_map_bus(struct pci_bus *bus, + unsigned int devfn, int where) +{ + struct pci_host_bridge *host = pci_find_host_bridge(bus); + struct mtk_pcie *pcie = pci_host_bridge_priv(host); + + writel(PCIE_CONF_ADDR(where, PCI_FUNC(devfn), PCI_SLOT(devfn), + bus->number), pcie->base + PCIE_CFG_ADDR); + + return pcie->base + PCIE_CFG_DATA + (where & 3); +} + +static struct pci_ops mtk_pcie_ops = { + .map_bus = mtk_pcie_map_bus, + .read = pci_generic_config_read, + .write = pci_generic_config_write, +}; + +static void mtk_pcie_configure_rc(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; + + /* enable interrupt */ + val = readl(pcie->base + PCIE_INT_ENABLE); + val |= PCIE_PORT_INT_EN(port->index); + writel(val, pcie->base + PCIE_INT_ENABLE); + + /* map to all DDR region. We need to set it before cfg operation. */ + writel(PCIE_BAR_MAP_MAX | PCIE_BAR_ENABLE, + port->base + PCIE_BAR0_SETUP); + + /* configure class Code and revision ID */ + writel(PCIE_CLASS_CODE | PCIE_REVISION_ID, + port->base + PCIE_CLASS); + + /* configure FC credit */ + writel(PCIE_CONF_ADDR(PCIE_FC_CREDIT, func, slot, 0), + pcie->base + PCIE_CFG_ADDR); + val = readl(pcie->base + PCIE_CFG_DATA); + val &= ~PCIE_FC_CREDIT_MASK; + val |= PCIE_FC_CREDIT_VAL(0x806c); + writel(PCIE_CONF_ADDR(PCIE_FC_CREDIT, func, slot, 0), + pcie->base + PCIE_CFG_ADDR); + writel(val, pcie->base + PCIE_CFG_DATA); + + /* configure RC FTS number to 250 when it leaves L0s */ + writel(PCIE_CONF_ADDR(PCIE_FTS_NUM, func, slot, 0), + pcie->base + PCIE_CFG_ADDR); + val = readl(pcie->base + PCIE_CFG_DATA); + val &= ~PCIE_FTS_NUM_MASK; + val |= PCIE_FTS_NUM_L0(0x50); + 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); +} + +static int mtk_pcie_enable_ports(struct mtk_pcie_port *port) +{ + struct device *dev = port->pcie->dev; + int err; + + err = clk_prepare_enable(port->sys_ck); + if (err) { + dev_err(dev, "failed to enable port%d clock\n", port->index); + goto err_sys_clk; + } + + reset_control_assert(port->reset); + reset_control_deassert(port->reset); + + err = phy_power_on(port->phy); + if (err) { + dev_err(dev, "failed to power on port%d phy\n", port->index); + goto err_phy_on; + } + + mtk_pcie_assert_ports(port); + + /* if link up, then setup root port configuration space */ + if (mtk_pcie_link_is_up(port)) { + mtk_pcie_configure_rc(port); + return 0; + } + + dev_info(dev, "Port%d link down\n", port->index); + + phy_power_off(port->phy); +err_phy_on: + clk_disable_unprepare(port->sys_ck); + mtk_pcie_port_free(port); +err_sys_clk: + return err; +} + +static int mtk_pcie_parse_ports(struct mtk_pcie *pcie, + struct mtk_pcie_port **p, + struct device_node *node, + int index) +{ + struct mtk_pcie_port *port; + struct resource *regs; + struct device *dev = pcie->dev; + struct platform_device *pdev = to_platform_device(dev); + char name[10]; + int err; + + *p = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL); + if (!*p) + return -ENOMEM; + + port = *p; + + err = of_property_read_u32(node, "num-lanes", &port->lane); + if (err) { + dev_err(dev, "missing num-lanes property\n"); + return err; + } + + regs = platform_get_resource(pdev, IORESOURCE_MEM, index + 1); + port->base = devm_ioremap_resource(dev, regs); + if (IS_ERR(port->base)) { + dev_err(dev, "failed to map port%d base\n", index); + return PTR_ERR(port->base); + } + + 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); + return PTR_ERR(port->sys_ck); + } + + snprintf(name, sizeof(name), "pcie-rst%d", index); + port->reset = devm_reset_control_get(dev, name); + if (IS_ERR(port->reset)) { + dev_err(dev, "failed to get port%d reset\n", index); + return PTR_ERR(port->reset); + } + + snprintf(name, sizeof(name), "pcie-phy%d", index); + port->phy = devm_phy_get(dev, name); + if (IS_ERR(port->phy)) { + dev_err(dev, "failed to get port%d phy\n", index); + return PTR_ERR(port->phy); + } + + port->index = index; + port->pcie = pcie; + + INIT_LIST_HEAD(&port->list); + list_add_tail(&port->list, &pcie->ports); + + return 0; +} + +static int mtk_pcie_handle_shared_resource(struct mtk_pcie *pcie) +{ + struct device *dev = pcie->dev; + struct platform_device *pdev = to_platform_device(dev); + 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); + } + + pcie->free_ck = devm_clk_get(dev, "free_ck"); + if (IS_ERR(pcie->free_ck)) { + dev_err(dev, "failed to get free_ck\n"); + return PTR_ERR(pcie->free_ck); + } + + pm_runtime_enable(dev); + err = pm_runtime_get_sync(dev); + if (err) + goto err_pm; + + /* enable top level clock */ + err = clk_prepare_enable(pcie->free_ck); + if (err) { + dev_err(dev, "failed to enable free_ck\n"); + goto err_free_ck; + } + + return 0; + +err_free_ck: + pm_runtime_put_sync(dev); +err_pm: + pm_runtime_disable(dev); + + return err; +} + +static int mtk_pcie_parse_and_add_res(struct mtk_pcie *pcie) +{ + struct device *dev = pcie->dev; + struct device_node *node = dev->of_node, *child; + struct of_pci_range_parser parser; + struct of_pci_range range; + struct resource res; + int err, linkup = 0; + + /* parse shared resources */ + err = mtk_pcie_handle_shared_resource(pcie); + if (err) + return err; + + if (of_pci_range_parser_init(&parser, node)) { + dev_err(dev, "missing \"ranges\" property\n"); + return -EINVAL; + } + + for_each_of_pci_range(&parser, &range) { + err = of_pci_range_to_resource(&range, node, &res); + if (err < 0) + return err; + + switch (res.flags & IORESOURCE_TYPE_BITS) { + case IORESOURCE_IO: + pcie->offset.io = res.start - range.pci_addr; + + memcpy(&pcie->pio, &res, sizeof(res)); + pcie->pio.name = node->full_name; + + pcie->io.start = range.cpu_addr; + pcie->io.end = range.cpu_addr + range.size - 1; + pcie->io.flags = IORESOURCE_MEM; + pcie->io.name = "I/O"; + + memcpy(&res, &pcie->io, sizeof(res)); + break; + + case IORESOURCE_MEM: + pcie->offset.mem = res.start - range.pci_addr; + + memcpy(&pcie->mem, &res, sizeof(res)); + pcie->mem.name = "non-prefetchable"; + break; + } + } + + err = of_pci_parse_bus_range(node, &pcie->busn); + if (err < 0) { + dev_err(dev, "failed to parse ranges property: %d\n", err); + pcie->busn.name = node->name; + pcie->busn.start = 0; + pcie->busn.end = 0xff; + pcie->busn.flags = IORESOURCE_BUS; + } + + for_each_child_of_node(node, child) { + struct mtk_pcie_port *port; + int index; + + err = of_pci_get_devfn(child); + if (err < 0) { + dev_err(dev, "failed to parse devfn: %d\n", err); + return err; + } + + index = PCI_SLOT(err); + + if (!of_device_is_available(child)) + continue; + + err = mtk_pcie_parse_ports(pcie, &port, child, index); + if (err) + return err; + + /* enable each port, and then check link status */ + err = mtk_pcie_enable_ports(port); + if (!err) + linkup++; + } + + return !linkup; +} + +static int mtk_pcie_request_resources(struct mtk_pcie *pcie) +{ + struct pci_host_bridge *host = pci_host_bridge_from_priv(pcie); + struct list_head *windows = &host->windows; + struct device *dev = pcie->dev; + int err; + + pci_add_resource_offset(windows, &pcie->pio, pcie->offset.io); + pci_add_resource_offset(windows, &pcie->mem, pcie->offset.mem); + pci_add_resource(windows, &pcie->busn); + + err = devm_request_pci_bus_resources(dev, windows); + if (err < 0) + return err; + + pci_remap_iospace(&pcie->pio, pcie->io.start); + + return 0; +} + +static int mtk_pcie_register_host(struct pci_host_bridge *host) +{ + struct mtk_pcie *pcie = pci_host_bridge_priv(host); + struct pci_bus *child; + int err; + + pci_add_flags(PCI_REASSIGN_ALL_RSRC | PCI_REASSIGN_ALL_BUS); + host->busnr = pcie->busn.start; + host->dev.parent = pcie->dev; + host->ops = &mtk_pcie_ops; + + err = pci_register_host_bridge(host); + if (err < 0) + return err; + + pci_scan_child_bus(host->bus); + + pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci); + pci_bus_size_bridges(host->bus); + pci_bus_assign_resources(host->bus); + + list_for_each_entry(child, &host->bus->children, node) + pcie_bus_configure_settings(child); + + pci_bus_add_devices(host->bus); + + return 0; +} + +static int mtk_pcie_probe(struct platform_device *pdev) +{ + struct mtk_pcie *pcie; + struct pci_host_bridge *host; + int err; + + host = pci_alloc_host_bridge(sizeof(*pcie)); + if (!host) + return -ENOMEM; + + pcie = pci_host_bridge_priv(host); + + pcie->dev = &pdev->dev; + platform_set_drvdata(pdev, pcie); + INIT_LIST_HEAD(&pcie->ports); + + err = mtk_pcie_parse_and_add_res(pcie); + if (err) + return err; + + err = mtk_pcie_request_resources(pcie); + if (err) + goto put_resources; + + err = mtk_pcie_register_host(host); + if (err) + goto put_resources; + + return 0; + +put_resources: + mtk_pcie_put_resources(pcie); + return err; +} + +static const struct of_device_id mtk_pcie_ids[] = { + { .compatible = "mediatek,mt7623-pcie"}, + { .compatible = "mediatek,mt2701-pcie"}, + {}, +}; + +static struct platform_driver mtk_pcie_driver = { + .probe = mtk_pcie_probe, + .driver = { + .name = "mtk-pcie", + .of_match_table = mtk_pcie_ids, + .suppress_bind_attrs = true, + }, +}; +builtin_platform_driver(mtk_pcie_driver); -- 1.9.1 ^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v5 1/2] PCI: mediatek: Add Mediatek PCIe host controller support @ 2017-05-21 3:42 ` Ryder Lee 0 siblings, 0 replies; 23+ messages in thread From: Ryder Lee @ 2017-05-21 3:42 UTC (permalink / raw) To: Bjorn Helgaas, Rob Herring, Arnd Bergmann Cc: devicetree, Red Hung, linux-pci, linux-kernel, Ryder Lee, linux-mediatek, linux-arm-kernel Add support for the Mediatek PCIe Gen2 controller which can be found on MT7623 series SoCs. Signed-off-by: Ryder Lee <ryder.lee@mediatek.com> --- drivers/pci/host/Kconfig | 11 + drivers/pci/host/Makefile | 1 + drivers/pci/host/pcie-mediatek.c | 553 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 565 insertions(+) create mode 100644 drivers/pci/host/pcie-mediatek.c diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig index 7f47cd5..d7d7c47 100644 --- a/drivers/pci/host/Kconfig +++ b/drivers/pci/host/Kconfig @@ -180,6 +180,17 @@ config PCIE_ROCKCHIP There is 1 internal PCIe port available to support GEN2 with 4 slots. +config PCIE_MEDIATEK + bool "Mediatek PCIe controller" + depends on ARM && (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. + config VMD depends on PCI_MSI && X86_64 && SRCU tristate "Intel Volume Management Device Driver" diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile index cab8795..b10d104 100644 --- a/drivers/pci/host/Makefile +++ b/drivers/pci/host/Makefile @@ -18,6 +18,7 @@ obj-$(CONFIG_PCIE_IPROC_BCMA) += pcie-iproc-bcma.o obj-$(CONFIG_PCIE_ALTERA) += pcie-altera.o obj-$(CONFIG_PCIE_ALTERA_MSI) += pcie-altera-msi.o obj-$(CONFIG_PCIE_ROCKCHIP) += pcie-rockchip.o +obj-$(CONFIG_PCIE_MEDIATEK) += pcie-mediatek.o obj-$(CONFIG_VMD) += vmd.o # The following drivers are for devices that use the generic ACPI diff --git a/drivers/pci/host/pcie-mediatek.c b/drivers/pci/host/pcie-mediatek.c new file mode 100644 index 0000000..0cc7943 --- /dev/null +++ b/drivers/pci/host/pcie-mediatek.c @@ -0,0 +1,553 @@ +/* + * Mediatek PCIe host controller driver. + * + * Copyright (c) 2017 MediaTek Inc. + * Author: Ryder Lee <ryder.lee@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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/kernel.h> +#include <linux/of_address.h> +#include <linux/of_pci.h> +#include <linux/of_platform.h> +#include <linux/pci.h> +#include <linux/phy/phy.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> +#include <linux/reset.h> + +/* PCIe shared registers */ +#define PCIE_SYS_CFG 0x00 +#define PCIE_INT_ENABLE 0x0c +#define PCIE_CFG_ADDR 0x20 +#define PCIE_CFG_DATA 0x24 + +/* PCIe per port registers */ +#define PCIE_BAR0_SETUP 0x10 +#define PCIE_BAR1_SETUP 0x14 +#define PCIE_BAR0_MEM_BASE 0x18 +#define PCIE_CLASS 0x34 +#define PCIE_LINK_STATUS 0x50 + +#define PCIE_PORT_INT_EN(x) BIT(20 + (x)) +#define PCIE_PORT_PERST(x) BIT(1 + (x)) +#define PCIE_PORT_LINKUP BIT(0) +#define PCIE_BAR_MAP_MAX GENMASK(31, 16) + +#define PCIE_BAR_ENABLE BIT(0) +#define PCIE_REVISION_ID BIT(0) +#define PCIE_CLASS_CODE (0x60400 << 8) +#define PCIE_CONF_REG(regn) (((regn) & GENMASK(7, 2)) | \ + ((((regn) >> 8) & GENMASK(3, 0)) << 24)) +#define PCIE_CONF_FUN(fun) (((fun) << 8) & GENMASK(10, 8)) +#define PCIE_CONF_DEV(dev) (((dev) << 11) & GENMASK(15, 11)) +#define PCIE_CONF_BUS(bus) (((bus) << 16) & GENMASK(23, 16)) +#define PCIE_CONF_ADDR(regn, fun, dev, bus) \ + (PCIE_CONF_REG(regn) | PCIE_CONF_FUN(fun) | \ + PCIE_CONF_DEV(dev) | PCIE_CONF_BUS(bus)) + +/* Mediatek specific configuration registers */ +#define PCIE_FTS_NUM 0x70c +#define PCIE_FTS_NUM_MASK GENMASK(15, 8) +#define PCIE_FTS_NUM_L0(x) ((x) & 0xff << 8) + +#define PCIE_FC_CREDIT 0x73c +#define PCIE_FC_CREDIT_MASK (GENMASK(31, 31) | GENMASK(28, 16)) +#define PCIE_FC_CREDIT_VAL(x) ((x) << 16) + +/** + * struct mtk_pcie_port - PCIe port information + * @base: IO mapped register base + * @list: port list + * @pcie: pointer to PCIe host info + * @reset: pointer to port reset control + * @sys_ck: pointer to bus clock + * @phy: pointer to phy control block + * @lane: lane count + * @index: port index + */ +struct mtk_pcie_port { + void __iomem *base; + struct list_head list; + struct mtk_pcie *pcie; + struct reset_control *reset; + struct clk *sys_ck; + struct phy *phy; + u32 lane; + u32 index; +}; + +/** + * struct mtk_pcie - PCIe host information + * @dev: pointer to PCIe device + * @base: IO mapped register Base + * @free_ck: free-run reference clock + * @io: IO resource + * @pio: PIO resource + * @mem: non-prefetchable memory resource + * @busn: bus range + * @offset: IO / Memory offset + * @ports: pointer to PCIe port information + */ +struct mtk_pcie { + struct device *dev; + void __iomem *base; + struct clk *free_ck; + + struct resource io; + struct resource pio; + struct resource mem; + struct resource busn; + struct { + resource_size_t mem; + resource_size_t io; + } offset; + struct list_head ports; +}; + +static inline bool mtk_pcie_link_is_up(struct mtk_pcie_port *port) +{ + return !!(readl(port->base + PCIE_LINK_STATUS) & + PCIE_PORT_LINKUP); +} + +static void mtk_pcie_port_free(struct mtk_pcie_port *port) +{ + struct mtk_pcie *pcie = port->pcie; + struct device *dev = pcie->dev; + + devm_iounmap(dev, port->base); + list_del(&port->list); + devm_kfree(dev, port); +} + +static void mtk_pcie_put_resources(struct mtk_pcie *pcie) +{ + struct device *dev = pcie->dev; + struct mtk_pcie_port *port, *tmp; + + list_for_each_entry_safe(port, tmp, &pcie->ports, list) { + phy_power_off(port->phy); + clk_disable_unprepare(port->sys_ck); + mtk_pcie_port_free(port); + } + + clk_disable_unprepare(pcie->free_ck); + pm_runtime_put_sync(dev); + pm_runtime_disable(dev); +} + +static void __iomem *mtk_pcie_map_bus(struct pci_bus *bus, + unsigned int devfn, int where) +{ + struct pci_host_bridge *host = pci_find_host_bridge(bus); + struct mtk_pcie *pcie = pci_host_bridge_priv(host); + + writel(PCIE_CONF_ADDR(where, PCI_FUNC(devfn), PCI_SLOT(devfn), + bus->number), pcie->base + PCIE_CFG_ADDR); + + return pcie->base + PCIE_CFG_DATA + (where & 3); +} + +static struct pci_ops mtk_pcie_ops = { + .map_bus = mtk_pcie_map_bus, + .read = pci_generic_config_read, + .write = pci_generic_config_write, +}; + +static void mtk_pcie_configure_rc(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; + + /* enable interrupt */ + val = readl(pcie->base + PCIE_INT_ENABLE); + val |= PCIE_PORT_INT_EN(port->index); + writel(val, pcie->base + PCIE_INT_ENABLE); + + /* map to all DDR region. We need to set it before cfg operation. */ + writel(PCIE_BAR_MAP_MAX | PCIE_BAR_ENABLE, + port->base + PCIE_BAR0_SETUP); + + /* configure class Code and revision ID */ + writel(PCIE_CLASS_CODE | PCIE_REVISION_ID, + port->base + PCIE_CLASS); + + /* configure FC credit */ + writel(PCIE_CONF_ADDR(PCIE_FC_CREDIT, func, slot, 0), + pcie->base + PCIE_CFG_ADDR); + val = readl(pcie->base + PCIE_CFG_DATA); + val &= ~PCIE_FC_CREDIT_MASK; + val |= PCIE_FC_CREDIT_VAL(0x806c); + writel(PCIE_CONF_ADDR(PCIE_FC_CREDIT, func, slot, 0), + pcie->base + PCIE_CFG_ADDR); + writel(val, pcie->base + PCIE_CFG_DATA); + + /* configure RC FTS number to 250 when it leaves L0s */ + writel(PCIE_CONF_ADDR(PCIE_FTS_NUM, func, slot, 0), + pcie->base + PCIE_CFG_ADDR); + val = readl(pcie->base + PCIE_CFG_DATA); + val &= ~PCIE_FTS_NUM_MASK; + val |= PCIE_FTS_NUM_L0(0x50); + 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); +} + +static int mtk_pcie_enable_ports(struct mtk_pcie_port *port) +{ + struct device *dev = port->pcie->dev; + int err; + + err = clk_prepare_enable(port->sys_ck); + if (err) { + dev_err(dev, "failed to enable port%d clock\n", port->index); + goto err_sys_clk; + } + + reset_control_assert(port->reset); + reset_control_deassert(port->reset); + + err = phy_power_on(port->phy); + if (err) { + dev_err(dev, "failed to power on port%d phy\n", port->index); + goto err_phy_on; + } + + mtk_pcie_assert_ports(port); + + /* if link up, then setup root port configuration space */ + if (mtk_pcie_link_is_up(port)) { + mtk_pcie_configure_rc(port); + return 0; + } + + dev_info(dev, "Port%d link down\n", port->index); + + phy_power_off(port->phy); +err_phy_on: + clk_disable_unprepare(port->sys_ck); + mtk_pcie_port_free(port); +err_sys_clk: + return err; +} + +static int mtk_pcie_parse_ports(struct mtk_pcie *pcie, + struct mtk_pcie_port **p, + struct device_node *node, + int index) +{ + struct mtk_pcie_port *port; + struct resource *regs; + struct device *dev = pcie->dev; + struct platform_device *pdev = to_platform_device(dev); + char name[10]; + int err; + + *p = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL); + if (!*p) + return -ENOMEM; + + port = *p; + + err = of_property_read_u32(node, "num-lanes", &port->lane); + if (err) { + dev_err(dev, "missing num-lanes property\n"); + return err; + } + + regs = platform_get_resource(pdev, IORESOURCE_MEM, index + 1); + port->base = devm_ioremap_resource(dev, regs); + if (IS_ERR(port->base)) { + dev_err(dev, "failed to map port%d base\n", index); + return PTR_ERR(port->base); + } + + 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); + return PTR_ERR(port->sys_ck); + } + + snprintf(name, sizeof(name), "pcie-rst%d", index); + port->reset = devm_reset_control_get(dev, name); + if (IS_ERR(port->reset)) { + dev_err(dev, "failed to get port%d reset\n", index); + return PTR_ERR(port->reset); + } + + snprintf(name, sizeof(name), "pcie-phy%d", index); + port->phy = devm_phy_get(dev, name); + if (IS_ERR(port->phy)) { + dev_err(dev, "failed to get port%d phy\n", index); + return PTR_ERR(port->phy); + } + + port->index = index; + port->pcie = pcie; + + INIT_LIST_HEAD(&port->list); + list_add_tail(&port->list, &pcie->ports); + + return 0; +} + +static int mtk_pcie_handle_shared_resource(struct mtk_pcie *pcie) +{ + struct device *dev = pcie->dev; + struct platform_device *pdev = to_platform_device(dev); + 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); + } + + pcie->free_ck = devm_clk_get(dev, "free_ck"); + if (IS_ERR(pcie->free_ck)) { + dev_err(dev, "failed to get free_ck\n"); + return PTR_ERR(pcie->free_ck); + } + + pm_runtime_enable(dev); + err = pm_runtime_get_sync(dev); + if (err) + goto err_pm; + + /* enable top level clock */ + err = clk_prepare_enable(pcie->free_ck); + if (err) { + dev_err(dev, "failed to enable free_ck\n"); + goto err_free_ck; + } + + return 0; + +err_free_ck: + pm_runtime_put_sync(dev); +err_pm: + pm_runtime_disable(dev); + + return err; +} + +static int mtk_pcie_parse_and_add_res(struct mtk_pcie *pcie) +{ + struct device *dev = pcie->dev; + struct device_node *node = dev->of_node, *child; + struct of_pci_range_parser parser; + struct of_pci_range range; + struct resource res; + int err, linkup = 0; + + /* parse shared resources */ + err = mtk_pcie_handle_shared_resource(pcie); + if (err) + return err; + + if (of_pci_range_parser_init(&parser, node)) { + dev_err(dev, "missing \"ranges\" property\n"); + return -EINVAL; + } + + for_each_of_pci_range(&parser, &range) { + err = of_pci_range_to_resource(&range, node, &res); + if (err < 0) + return err; + + switch (res.flags & IORESOURCE_TYPE_BITS) { + case IORESOURCE_IO: + pcie->offset.io = res.start - range.pci_addr; + + memcpy(&pcie->pio, &res, sizeof(res)); + pcie->pio.name = node->full_name; + + pcie->io.start = range.cpu_addr; + pcie->io.end = range.cpu_addr + range.size - 1; + pcie->io.flags = IORESOURCE_MEM; + pcie->io.name = "I/O"; + + memcpy(&res, &pcie->io, sizeof(res)); + break; + + case IORESOURCE_MEM: + pcie->offset.mem = res.start - range.pci_addr; + + memcpy(&pcie->mem, &res, sizeof(res)); + pcie->mem.name = "non-prefetchable"; + break; + } + } + + err = of_pci_parse_bus_range(node, &pcie->busn); + if (err < 0) { + dev_err(dev, "failed to parse ranges property: %d\n", err); + pcie->busn.name = node->name; + pcie->busn.start = 0; + pcie->busn.end = 0xff; + pcie->busn.flags = IORESOURCE_BUS; + } + + for_each_child_of_node(node, child) { + struct mtk_pcie_port *port; + int index; + + err = of_pci_get_devfn(child); + if (err < 0) { + dev_err(dev, "failed to parse devfn: %d\n", err); + return err; + } + + index = PCI_SLOT(err); + + if (!of_device_is_available(child)) + continue; + + err = mtk_pcie_parse_ports(pcie, &port, child, index); + if (err) + return err; + + /* enable each port, and then check link status */ + err = mtk_pcie_enable_ports(port); + if (!err) + linkup++; + } + + return !linkup; +} + +static int mtk_pcie_request_resources(struct mtk_pcie *pcie) +{ + struct pci_host_bridge *host = pci_host_bridge_from_priv(pcie); + struct list_head *windows = &host->windows; + struct device *dev = pcie->dev; + int err; + + pci_add_resource_offset(windows, &pcie->pio, pcie->offset.io); + pci_add_resource_offset(windows, &pcie->mem, pcie->offset.mem); + pci_add_resource(windows, &pcie->busn); + + err = devm_request_pci_bus_resources(dev, windows); + if (err < 0) + return err; + + pci_remap_iospace(&pcie->pio, pcie->io.start); + + return 0; +} + +static int mtk_pcie_register_host(struct pci_host_bridge *host) +{ + struct mtk_pcie *pcie = pci_host_bridge_priv(host); + struct pci_bus *child; + int err; + + pci_add_flags(PCI_REASSIGN_ALL_RSRC | PCI_REASSIGN_ALL_BUS); + host->busnr = pcie->busn.start; + host->dev.parent = pcie->dev; + host->ops = &mtk_pcie_ops; + + err = pci_register_host_bridge(host); + if (err < 0) + return err; + + pci_scan_child_bus(host->bus); + + pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci); + pci_bus_size_bridges(host->bus); + pci_bus_assign_resources(host->bus); + + list_for_each_entry(child, &host->bus->children, node) + pcie_bus_configure_settings(child); + + pci_bus_add_devices(host->bus); + + return 0; +} + +static int mtk_pcie_probe(struct platform_device *pdev) +{ + struct mtk_pcie *pcie; + struct pci_host_bridge *host; + int err; + + host = pci_alloc_host_bridge(sizeof(*pcie)); + if (!host) + return -ENOMEM; + + pcie = pci_host_bridge_priv(host); + + pcie->dev = &pdev->dev; + platform_set_drvdata(pdev, pcie); + INIT_LIST_HEAD(&pcie->ports); + + err = mtk_pcie_parse_and_add_res(pcie); + if (err) + return err; + + err = mtk_pcie_request_resources(pcie); + if (err) + goto put_resources; + + err = mtk_pcie_register_host(host); + if (err) + goto put_resources; + + return 0; + +put_resources: + mtk_pcie_put_resources(pcie); + return err; +} + +static const struct of_device_id mtk_pcie_ids[] = { + { .compatible = "mediatek,mt7623-pcie"}, + { .compatible = "mediatek,mt2701-pcie"}, + {}, +}; + +static struct platform_driver mtk_pcie_driver = { + .probe = mtk_pcie_probe, + .driver = { + .name = "mtk-pcie", + .of_match_table = mtk_pcie_ids, + .suppress_bind_attrs = true, + }, +}; +builtin_platform_driver(mtk_pcie_driver); -- 1.9.1 _______________________________________________ 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] 23+ messages in thread
* [PATCH v5 1/2] PCI: mediatek: Add Mediatek PCIe host controller support @ 2017-05-21 3:42 ` Ryder Lee 0 siblings, 0 replies; 23+ messages in thread From: Ryder Lee @ 2017-05-21 3:42 UTC (permalink / raw) To: Bjorn Helgaas, Rob Herring, Arnd Bergmann Cc: linux-pci, devicetree, linux-mediatek, linux-arm-kernel, linux-kernel, Red Hung, Ryder Lee Add support for the Mediatek PCIe Gen2 controller which can be found on MT7623 series SoCs. Signed-off-by: Ryder Lee <ryder.lee@mediatek.com> --- drivers/pci/host/Kconfig | 11 + drivers/pci/host/Makefile | 1 + drivers/pci/host/pcie-mediatek.c | 553 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 565 insertions(+) create mode 100644 drivers/pci/host/pcie-mediatek.c diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig index 7f47cd5..d7d7c47 100644 --- a/drivers/pci/host/Kconfig +++ b/drivers/pci/host/Kconfig @@ -180,6 +180,17 @@ config PCIE_ROCKCHIP There is 1 internal PCIe port available to support GEN2 with 4 slots. +config PCIE_MEDIATEK + bool "Mediatek PCIe controller" + depends on ARM && (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. + config VMD depends on PCI_MSI && X86_64 && SRCU tristate "Intel Volume Management Device Driver" diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile index cab8795..b10d104 100644 --- a/drivers/pci/host/Makefile +++ b/drivers/pci/host/Makefile @@ -18,6 +18,7 @@ obj-$(CONFIG_PCIE_IPROC_BCMA) += pcie-iproc-bcma.o obj-$(CONFIG_PCIE_ALTERA) += pcie-altera.o obj-$(CONFIG_PCIE_ALTERA_MSI) += pcie-altera-msi.o obj-$(CONFIG_PCIE_ROCKCHIP) += pcie-rockchip.o +obj-$(CONFIG_PCIE_MEDIATEK) += pcie-mediatek.o obj-$(CONFIG_VMD) += vmd.o # The following drivers are for devices that use the generic ACPI diff --git a/drivers/pci/host/pcie-mediatek.c b/drivers/pci/host/pcie-mediatek.c new file mode 100644 index 0000000..0cc7943 --- /dev/null +++ b/drivers/pci/host/pcie-mediatek.c @@ -0,0 +1,553 @@ +/* + * Mediatek PCIe host controller driver. + * + * Copyright (c) 2017 MediaTek Inc. + * Author: Ryder Lee <ryder.lee@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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/kernel.h> +#include <linux/of_address.h> +#include <linux/of_pci.h> +#include <linux/of_platform.h> +#include <linux/pci.h> +#include <linux/phy/phy.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> +#include <linux/reset.h> + +/* PCIe shared registers */ +#define PCIE_SYS_CFG 0x00 +#define PCIE_INT_ENABLE 0x0c +#define PCIE_CFG_ADDR 0x20 +#define PCIE_CFG_DATA 0x24 + +/* PCIe per port registers */ +#define PCIE_BAR0_SETUP 0x10 +#define PCIE_BAR1_SETUP 0x14 +#define PCIE_BAR0_MEM_BASE 0x18 +#define PCIE_CLASS 0x34 +#define PCIE_LINK_STATUS 0x50 + +#define PCIE_PORT_INT_EN(x) BIT(20 + (x)) +#define PCIE_PORT_PERST(x) BIT(1 + (x)) +#define PCIE_PORT_LINKUP BIT(0) +#define PCIE_BAR_MAP_MAX GENMASK(31, 16) + +#define PCIE_BAR_ENABLE BIT(0) +#define PCIE_REVISION_ID BIT(0) +#define PCIE_CLASS_CODE (0x60400 << 8) +#define PCIE_CONF_REG(regn) (((regn) & GENMASK(7, 2)) | \ + ((((regn) >> 8) & GENMASK(3, 0)) << 24)) +#define PCIE_CONF_FUN(fun) (((fun) << 8) & GENMASK(10, 8)) +#define PCIE_CONF_DEV(dev) (((dev) << 11) & GENMASK(15, 11)) +#define PCIE_CONF_BUS(bus) (((bus) << 16) & GENMASK(23, 16)) +#define PCIE_CONF_ADDR(regn, fun, dev, bus) \ + (PCIE_CONF_REG(regn) | PCIE_CONF_FUN(fun) | \ + PCIE_CONF_DEV(dev) | PCIE_CONF_BUS(bus)) + +/* Mediatek specific configuration registers */ +#define PCIE_FTS_NUM 0x70c +#define PCIE_FTS_NUM_MASK GENMASK(15, 8) +#define PCIE_FTS_NUM_L0(x) ((x) & 0xff << 8) + +#define PCIE_FC_CREDIT 0x73c +#define PCIE_FC_CREDIT_MASK (GENMASK(31, 31) | GENMASK(28, 16)) +#define PCIE_FC_CREDIT_VAL(x) ((x) << 16) + +/** + * struct mtk_pcie_port - PCIe port information + * @base: IO mapped register base + * @list: port list + * @pcie: pointer to PCIe host info + * @reset: pointer to port reset control + * @sys_ck: pointer to bus clock + * @phy: pointer to phy control block + * @lane: lane count + * @index: port index + */ +struct mtk_pcie_port { + void __iomem *base; + struct list_head list; + struct mtk_pcie *pcie; + struct reset_control *reset; + struct clk *sys_ck; + struct phy *phy; + u32 lane; + u32 index; +}; + +/** + * struct mtk_pcie - PCIe host information + * @dev: pointer to PCIe device + * @base: IO mapped register Base + * @free_ck: free-run reference clock + * @io: IO resource + * @pio: PIO resource + * @mem: non-prefetchable memory resource + * @busn: bus range + * @offset: IO / Memory offset + * @ports: pointer to PCIe port information + */ +struct mtk_pcie { + struct device *dev; + void __iomem *base; + struct clk *free_ck; + + struct resource io; + struct resource pio; + struct resource mem; + struct resource busn; + struct { + resource_size_t mem; + resource_size_t io; + } offset; + struct list_head ports; +}; + +static inline bool mtk_pcie_link_is_up(struct mtk_pcie_port *port) +{ + return !!(readl(port->base + PCIE_LINK_STATUS) & + PCIE_PORT_LINKUP); +} + +static void mtk_pcie_port_free(struct mtk_pcie_port *port) +{ + struct mtk_pcie *pcie = port->pcie; + struct device *dev = pcie->dev; + + devm_iounmap(dev, port->base); + list_del(&port->list); + devm_kfree(dev, port); +} + +static void mtk_pcie_put_resources(struct mtk_pcie *pcie) +{ + struct device *dev = pcie->dev; + struct mtk_pcie_port *port, *tmp; + + list_for_each_entry_safe(port, tmp, &pcie->ports, list) { + phy_power_off(port->phy); + clk_disable_unprepare(port->sys_ck); + mtk_pcie_port_free(port); + } + + clk_disable_unprepare(pcie->free_ck); + pm_runtime_put_sync(dev); + pm_runtime_disable(dev); +} + +static void __iomem *mtk_pcie_map_bus(struct pci_bus *bus, + unsigned int devfn, int where) +{ + struct pci_host_bridge *host = pci_find_host_bridge(bus); + struct mtk_pcie *pcie = pci_host_bridge_priv(host); + + writel(PCIE_CONF_ADDR(where, PCI_FUNC(devfn), PCI_SLOT(devfn), + bus->number), pcie->base + PCIE_CFG_ADDR); + + return pcie->base + PCIE_CFG_DATA + (where & 3); +} + +static struct pci_ops mtk_pcie_ops = { + .map_bus = mtk_pcie_map_bus, + .read = pci_generic_config_read, + .write = pci_generic_config_write, +}; + +static void mtk_pcie_configure_rc(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; + + /* enable interrupt */ + val = readl(pcie->base + PCIE_INT_ENABLE); + val |= PCIE_PORT_INT_EN(port->index); + writel(val, pcie->base + PCIE_INT_ENABLE); + + /* map to all DDR region. We need to set it before cfg operation. */ + writel(PCIE_BAR_MAP_MAX | PCIE_BAR_ENABLE, + port->base + PCIE_BAR0_SETUP); + + /* configure class Code and revision ID */ + writel(PCIE_CLASS_CODE | PCIE_REVISION_ID, + port->base + PCIE_CLASS); + + /* configure FC credit */ + writel(PCIE_CONF_ADDR(PCIE_FC_CREDIT, func, slot, 0), + pcie->base + PCIE_CFG_ADDR); + val = readl(pcie->base + PCIE_CFG_DATA); + val &= ~PCIE_FC_CREDIT_MASK; + val |= PCIE_FC_CREDIT_VAL(0x806c); + writel(PCIE_CONF_ADDR(PCIE_FC_CREDIT, func, slot, 0), + pcie->base + PCIE_CFG_ADDR); + writel(val, pcie->base + PCIE_CFG_DATA); + + /* configure RC FTS number to 250 when it leaves L0s */ + writel(PCIE_CONF_ADDR(PCIE_FTS_NUM, func, slot, 0), + pcie->base + PCIE_CFG_ADDR); + val = readl(pcie->base + PCIE_CFG_DATA); + val &= ~PCIE_FTS_NUM_MASK; + val |= PCIE_FTS_NUM_L0(0x50); + 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); +} + +static int mtk_pcie_enable_ports(struct mtk_pcie_port *port) +{ + struct device *dev = port->pcie->dev; + int err; + + err = clk_prepare_enable(port->sys_ck); + if (err) { + dev_err(dev, "failed to enable port%d clock\n", port->index); + goto err_sys_clk; + } + + reset_control_assert(port->reset); + reset_control_deassert(port->reset); + + err = phy_power_on(port->phy); + if (err) { + dev_err(dev, "failed to power on port%d phy\n", port->index); + goto err_phy_on; + } + + mtk_pcie_assert_ports(port); + + /* if link up, then setup root port configuration space */ + if (mtk_pcie_link_is_up(port)) { + mtk_pcie_configure_rc(port); + return 0; + } + + dev_info(dev, "Port%d link down\n", port->index); + + phy_power_off(port->phy); +err_phy_on: + clk_disable_unprepare(port->sys_ck); + mtk_pcie_port_free(port); +err_sys_clk: + return err; +} + +static int mtk_pcie_parse_ports(struct mtk_pcie *pcie, + struct mtk_pcie_port **p, + struct device_node *node, + int index) +{ + struct mtk_pcie_port *port; + struct resource *regs; + struct device *dev = pcie->dev; + struct platform_device *pdev = to_platform_device(dev); + char name[10]; + int err; + + *p = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL); + if (!*p) + return -ENOMEM; + + port = *p; + + err = of_property_read_u32(node, "num-lanes", &port->lane); + if (err) { + dev_err(dev, "missing num-lanes property\n"); + return err; + } + + regs = platform_get_resource(pdev, IORESOURCE_MEM, index + 1); + port->base = devm_ioremap_resource(dev, regs); + if (IS_ERR(port->base)) { + dev_err(dev, "failed to map port%d base\n", index); + return PTR_ERR(port->base); + } + + 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); + return PTR_ERR(port->sys_ck); + } + + snprintf(name, sizeof(name), "pcie-rst%d", index); + port->reset = devm_reset_control_get(dev, name); + if (IS_ERR(port->reset)) { + dev_err(dev, "failed to get port%d reset\n", index); + return PTR_ERR(port->reset); + } + + snprintf(name, sizeof(name), "pcie-phy%d", index); + port->phy = devm_phy_get(dev, name); + if (IS_ERR(port->phy)) { + dev_err(dev, "failed to get port%d phy\n", index); + return PTR_ERR(port->phy); + } + + port->index = index; + port->pcie = pcie; + + INIT_LIST_HEAD(&port->list); + list_add_tail(&port->list, &pcie->ports); + + return 0; +} + +static int mtk_pcie_handle_shared_resource(struct mtk_pcie *pcie) +{ + struct device *dev = pcie->dev; + struct platform_device *pdev = to_platform_device(dev); + 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); + } + + pcie->free_ck = devm_clk_get(dev, "free_ck"); + if (IS_ERR(pcie->free_ck)) { + dev_err(dev, "failed to get free_ck\n"); + return PTR_ERR(pcie->free_ck); + } + + pm_runtime_enable(dev); + err = pm_runtime_get_sync(dev); + if (err) + goto err_pm; + + /* enable top level clock */ + err = clk_prepare_enable(pcie->free_ck); + if (err) { + dev_err(dev, "failed to enable free_ck\n"); + goto err_free_ck; + } + + return 0; + +err_free_ck: + pm_runtime_put_sync(dev); +err_pm: + pm_runtime_disable(dev); + + return err; +} + +static int mtk_pcie_parse_and_add_res(struct mtk_pcie *pcie) +{ + struct device *dev = pcie->dev; + struct device_node *node = dev->of_node, *child; + struct of_pci_range_parser parser; + struct of_pci_range range; + struct resource res; + int err, linkup = 0; + + /* parse shared resources */ + err = mtk_pcie_handle_shared_resource(pcie); + if (err) + return err; + + if (of_pci_range_parser_init(&parser, node)) { + dev_err(dev, "missing \"ranges\" property\n"); + return -EINVAL; + } + + for_each_of_pci_range(&parser, &range) { + err = of_pci_range_to_resource(&range, node, &res); + if (err < 0) + return err; + + switch (res.flags & IORESOURCE_TYPE_BITS) { + case IORESOURCE_IO: + pcie->offset.io = res.start - range.pci_addr; + + memcpy(&pcie->pio, &res, sizeof(res)); + pcie->pio.name = node->full_name; + + pcie->io.start = range.cpu_addr; + pcie->io.end = range.cpu_addr + range.size - 1; + pcie->io.flags = IORESOURCE_MEM; + pcie->io.name = "I/O"; + + memcpy(&res, &pcie->io, sizeof(res)); + break; + + case IORESOURCE_MEM: + pcie->offset.mem = res.start - range.pci_addr; + + memcpy(&pcie->mem, &res, sizeof(res)); + pcie->mem.name = "non-prefetchable"; + break; + } + } + + err = of_pci_parse_bus_range(node, &pcie->busn); + if (err < 0) { + dev_err(dev, "failed to parse ranges property: %d\n", err); + pcie->busn.name = node->name; + pcie->busn.start = 0; + pcie->busn.end = 0xff; + pcie->busn.flags = IORESOURCE_BUS; + } + + for_each_child_of_node(node, child) { + struct mtk_pcie_port *port; + int index; + + err = of_pci_get_devfn(child); + if (err < 0) { + dev_err(dev, "failed to parse devfn: %d\n", err); + return err; + } + + index = PCI_SLOT(err); + + if (!of_device_is_available(child)) + continue; + + err = mtk_pcie_parse_ports(pcie, &port, child, index); + if (err) + return err; + + /* enable each port, and then check link status */ + err = mtk_pcie_enable_ports(port); + if (!err) + linkup++; + } + + return !linkup; +} + +static int mtk_pcie_request_resources(struct mtk_pcie *pcie) +{ + struct pci_host_bridge *host = pci_host_bridge_from_priv(pcie); + struct list_head *windows = &host->windows; + struct device *dev = pcie->dev; + int err; + + pci_add_resource_offset(windows, &pcie->pio, pcie->offset.io); + pci_add_resource_offset(windows, &pcie->mem, pcie->offset.mem); + pci_add_resource(windows, &pcie->busn); + + err = devm_request_pci_bus_resources(dev, windows); + if (err < 0) + return err; + + pci_remap_iospace(&pcie->pio, pcie->io.start); + + return 0; +} + +static int mtk_pcie_register_host(struct pci_host_bridge *host) +{ + struct mtk_pcie *pcie = pci_host_bridge_priv(host); + struct pci_bus *child; + int err; + + pci_add_flags(PCI_REASSIGN_ALL_RSRC | PCI_REASSIGN_ALL_BUS); + host->busnr = pcie->busn.start; + host->dev.parent = pcie->dev; + host->ops = &mtk_pcie_ops; + + err = pci_register_host_bridge(host); + if (err < 0) + return err; + + pci_scan_child_bus(host->bus); + + pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci); + pci_bus_size_bridges(host->bus); + pci_bus_assign_resources(host->bus); + + list_for_each_entry(child, &host->bus->children, node) + pcie_bus_configure_settings(child); + + pci_bus_add_devices(host->bus); + + return 0; +} + +static int mtk_pcie_probe(struct platform_device *pdev) +{ + struct mtk_pcie *pcie; + struct pci_host_bridge *host; + int err; + + host = pci_alloc_host_bridge(sizeof(*pcie)); + if (!host) + return -ENOMEM; + + pcie = pci_host_bridge_priv(host); + + pcie->dev = &pdev->dev; + platform_set_drvdata(pdev, pcie); + INIT_LIST_HEAD(&pcie->ports); + + err = mtk_pcie_parse_and_add_res(pcie); + if (err) + return err; + + err = mtk_pcie_request_resources(pcie); + if (err) + goto put_resources; + + err = mtk_pcie_register_host(host); + if (err) + goto put_resources; + + return 0; + +put_resources: + mtk_pcie_put_resources(pcie); + return err; +} + +static const struct of_device_id mtk_pcie_ids[] = { + { .compatible = "mediatek,mt7623-pcie"}, + { .compatible = "mediatek,mt2701-pcie"}, + {}, +}; + +static struct platform_driver mtk_pcie_driver = { + .probe = mtk_pcie_probe, + .driver = { + .name = "mtk-pcie", + .of_match_table = mtk_pcie_ids, + .suppress_bind_attrs = true, + }, +}; +builtin_platform_driver(mtk_pcie_driver); -- 1.9.1 ^ permalink raw reply related [flat|nested] 23+ messages in thread
* Re: [PATCH v5 1/2] PCI: mediatek: Add Mediatek PCIe host controller support @ 2017-06-28 19:53 ` Bjorn Helgaas 0 siblings, 0 replies; 23+ messages in thread From: Bjorn Helgaas @ 2017-06-28 19:53 UTC (permalink / raw) To: Ryder Lee Cc: Bjorn Helgaas, Rob Herring, Arnd Bergmann, devicetree, Red Hung, linux-pci, linux-kernel, linux-mediatek, linux-arm-kernel On Sun, May 21, 2017 at 11:42:24AM +0800, Ryder Lee wrote: > Add support for the Mediatek PCIe Gen2 controller which can > be found on MT7623 series SoCs. > > Signed-off-by: Ryder Lee <ryder.lee@mediatek.com> > --- > drivers/pci/host/Kconfig | 11 + > drivers/pci/host/Makefile | 1 + > drivers/pci/host/pcie-mediatek.c | 553 +++++++++++++++++++++++++++++++++++++++ > 3 files changed, 565 insertions(+) > create mode 100644 drivers/pci/host/pcie-mediatek.c >... > +static int mtk_pcie_register_host(struct pci_host_bridge *host) > +{ > + struct mtk_pcie *pcie = pci_host_bridge_priv(host); > + struct pci_bus *child; > + int err; > + > + pci_add_flags(PCI_REASSIGN_ALL_RSRC | PCI_REASSIGN_ALL_BUS); Do you really need the PCI_REASSIGN_ALL_RSRC and PCI_REASSIGN_ALL_BUS flags? I'd like to get rid of them because we should automatically assign resources if the firmware hasn't done it. Bjorn ^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH v5 1/2] PCI: mediatek: Add Mediatek PCIe host controller support @ 2017-06-28 19:53 ` Bjorn Helgaas 0 siblings, 0 replies; 23+ messages in thread From: Bjorn Helgaas @ 2017-06-28 19:53 UTC (permalink / raw) To: linux-arm-kernel On Sun, May 21, 2017 at 11:42:24AM +0800, Ryder Lee wrote: > Add support for the Mediatek PCIe Gen2 controller which can > be found on MT7623 series SoCs. > > Signed-off-by: Ryder Lee <ryder.lee@mediatek.com> > --- > drivers/pci/host/Kconfig | 11 + > drivers/pci/host/Makefile | 1 + > drivers/pci/host/pcie-mediatek.c | 553 +++++++++++++++++++++++++++++++++++++++ > 3 files changed, 565 insertions(+) > create mode 100644 drivers/pci/host/pcie-mediatek.c >... > +static int mtk_pcie_register_host(struct pci_host_bridge *host) > +{ > + struct mtk_pcie *pcie = pci_host_bridge_priv(host); > + struct pci_bus *child; > + int err; > + > + pci_add_flags(PCI_REASSIGN_ALL_RSRC | PCI_REASSIGN_ALL_BUS); Do you really need the PCI_REASSIGN_ALL_RSRC and PCI_REASSIGN_ALL_BUS flags? I'd like to get rid of them because we should automatically assign resources if the firmware hasn't done it. Bjorn ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v5 1/2] PCI: mediatek: Add Mediatek PCIe host controller support @ 2017-06-28 19:53 ` Bjorn Helgaas 0 siblings, 0 replies; 23+ messages in thread From: Bjorn Helgaas @ 2017-06-28 19:53 UTC (permalink / raw) To: Ryder Lee Cc: devicetree, Red Hung, Arnd Bergmann, linux-pci, linux-kernel, Rob Herring, linux-mediatek, Bjorn Helgaas, linux-arm-kernel On Sun, May 21, 2017 at 11:42:24AM +0800, Ryder Lee wrote: > Add support for the Mediatek PCIe Gen2 controller which can > be found on MT7623 series SoCs. > > Signed-off-by: Ryder Lee <ryder.lee@mediatek.com> > --- > drivers/pci/host/Kconfig | 11 + > drivers/pci/host/Makefile | 1 + > drivers/pci/host/pcie-mediatek.c | 553 +++++++++++++++++++++++++++++++++++++++ > 3 files changed, 565 insertions(+) > create mode 100644 drivers/pci/host/pcie-mediatek.c >... > +static int mtk_pcie_register_host(struct pci_host_bridge *host) > +{ > + struct mtk_pcie *pcie = pci_host_bridge_priv(host); > + struct pci_bus *child; > + int err; > + > + pci_add_flags(PCI_REASSIGN_ALL_RSRC | PCI_REASSIGN_ALL_BUS); Do you really need the PCI_REASSIGN_ALL_RSRC and PCI_REASSIGN_ALL_BUS flags? I'd like to get rid of them because we should automatically assign resources if the firmware hasn't done it. 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] 23+ messages in thread
* Re: [PATCH v5 1/2] PCI: mediatek: Add Mediatek PCIe host controller support @ 2017-06-28 19:53 ` Bjorn Helgaas 0 siblings, 0 replies; 23+ messages in thread From: Bjorn Helgaas @ 2017-06-28 19:53 UTC (permalink / raw) To: Ryder Lee Cc: Bjorn Helgaas, Rob Herring, Arnd Bergmann, devicetree-u79uwXL29TY76Z2rM5mHXA, Red Hung, linux-pci-u79uwXL29TY76Z2rM5mHXA, linux-kernel-u79uwXL29TY76Z2rM5mHXA, linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r On Sun, May 21, 2017 at 11:42:24AM +0800, Ryder Lee wrote: > Add support for the Mediatek PCIe Gen2 controller which can > be found on MT7623 series SoCs. > > Signed-off-by: Ryder Lee <ryder.lee-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org> > --- > drivers/pci/host/Kconfig | 11 + > drivers/pci/host/Makefile | 1 + > drivers/pci/host/pcie-mediatek.c | 553 +++++++++++++++++++++++++++++++++++++++ > 3 files changed, 565 insertions(+) > create mode 100644 drivers/pci/host/pcie-mediatek.c >... > +static int mtk_pcie_register_host(struct pci_host_bridge *host) > +{ > + struct mtk_pcie *pcie = pci_host_bridge_priv(host); > + struct pci_bus *child; > + int err; > + > + pci_add_flags(PCI_REASSIGN_ALL_RSRC | PCI_REASSIGN_ALL_BUS); Do you really need the PCI_REASSIGN_ALL_RSRC and PCI_REASSIGN_ALL_BUS flags? I'd like to get rid of them because we should automatically assign resources if the firmware hasn't done it. 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] 23+ messages in thread
* Re: [PATCH v5 1/2] PCI: mediatek: Add Mediatek PCIe host controller support @ 2017-06-29 2:00 ` Ryder Lee 0 siblings, 0 replies; 23+ messages in thread From: Ryder Lee @ 2017-06-29 2:00 UTC (permalink / raw) To: Bjorn Helgaas Cc: Bjorn Helgaas, Rob Herring, Arnd Bergmann, devicetree, Red Hung, linux-pci, linux-kernel, linux-mediatek, linux-arm-kernel On Wed, 2017-06-28 at 14:53 -0500, Bjorn Helgaas wrote: > On Sun, May 21, 2017 at 11:42:24AM +0800, Ryder Lee wrote: > > Add support for the Mediatek PCIe Gen2 controller which can > > be found on MT7623 series SoCs. > > > > Signed-off-by: Ryder Lee <ryder.lee@mediatek.com> > > --- > > drivers/pci/host/Kconfig | 11 + > > drivers/pci/host/Makefile | 1 + > > drivers/pci/host/pcie-mediatek.c | 553 +++++++++++++++++++++++++++++++++++++++ > > 3 files changed, 565 insertions(+) > > create mode 100644 drivers/pci/host/pcie-mediatek.c > >... > > > +static int mtk_pcie_register_host(struct pci_host_bridge *host) > > +{ > > + struct mtk_pcie *pcie = pci_host_bridge_priv(host); > > + struct pci_bus *child; > > + int err; > > + > > + pci_add_flags(PCI_REASSIGN_ALL_RSRC | PCI_REASSIGN_ALL_BUS); > > Do you really need the PCI_REASSIGN_ALL_RSRC and PCI_REASSIGN_ALL_BUS > flags? I'd like to get rid of them because we should automatically > assign resources if the firmware hasn't done it. > > Bjorn You're right! These flags are not needed and should be removed. Thanks for catching that. Ryder ^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH v5 1/2] PCI: mediatek: Add Mediatek PCIe host controller support @ 2017-06-29 2:00 ` Ryder Lee 0 siblings, 0 replies; 23+ messages in thread From: Ryder Lee @ 2017-06-29 2:00 UTC (permalink / raw) To: linux-arm-kernel On Wed, 2017-06-28 at 14:53 -0500, Bjorn Helgaas wrote: > On Sun, May 21, 2017 at 11:42:24AM +0800, Ryder Lee wrote: > > Add support for the Mediatek PCIe Gen2 controller which can > > be found on MT7623 series SoCs. > > > > Signed-off-by: Ryder Lee <ryder.lee@mediatek.com> > > --- > > drivers/pci/host/Kconfig | 11 + > > drivers/pci/host/Makefile | 1 + > > drivers/pci/host/pcie-mediatek.c | 553 +++++++++++++++++++++++++++++++++++++++ > > 3 files changed, 565 insertions(+) > > create mode 100644 drivers/pci/host/pcie-mediatek.c > >... > > > +static int mtk_pcie_register_host(struct pci_host_bridge *host) > > +{ > > + struct mtk_pcie *pcie = pci_host_bridge_priv(host); > > + struct pci_bus *child; > > + int err; > > + > > + pci_add_flags(PCI_REASSIGN_ALL_RSRC | PCI_REASSIGN_ALL_BUS); > > Do you really need the PCI_REASSIGN_ALL_RSRC and PCI_REASSIGN_ALL_BUS > flags? I'd like to get rid of them because we should automatically > assign resources if the firmware hasn't done it. > > Bjorn You're right! These flags are not needed and should be removed. Thanks for catching that. Ryder ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v5 1/2] PCI: mediatek: Add Mediatek PCIe host controller support @ 2017-06-29 2:00 ` Ryder Lee 0 siblings, 0 replies; 23+ messages in thread From: Ryder Lee @ 2017-06-29 2:00 UTC (permalink / raw) To: Bjorn Helgaas Cc: Bjorn Helgaas, Rob Herring, Arnd Bergmann, devicetree-u79uwXL29TY76Z2rM5mHXA, Red Hung, linux-pci-u79uwXL29TY76Z2rM5mHXA, linux-kernel-u79uwXL29TY76Z2rM5mHXA, linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r On Wed, 2017-06-28 at 14:53 -0500, Bjorn Helgaas wrote: > On Sun, May 21, 2017 at 11:42:24AM +0800, Ryder Lee wrote: > > Add support for the Mediatek PCIe Gen2 controller which can > > be found on MT7623 series SoCs. > > > > Signed-off-by: Ryder Lee <ryder.lee-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org> > > --- > > drivers/pci/host/Kconfig | 11 + > > drivers/pci/host/Makefile | 1 + > > drivers/pci/host/pcie-mediatek.c | 553 +++++++++++++++++++++++++++++++++++++++ > > 3 files changed, 565 insertions(+) > > create mode 100644 drivers/pci/host/pcie-mediatek.c > >... > > > +static int mtk_pcie_register_host(struct pci_host_bridge *host) > > +{ > > + struct mtk_pcie *pcie = pci_host_bridge_priv(host); > > + struct pci_bus *child; > > + int err; > > + > > + pci_add_flags(PCI_REASSIGN_ALL_RSRC | PCI_REASSIGN_ALL_BUS); > > Do you really need the PCI_REASSIGN_ALL_RSRC and PCI_REASSIGN_ALL_BUS > flags? I'd like to get rid of them because we should automatically > assign resources if the firmware hasn't done it. > > Bjorn You're right! These flags are not needed and should be removed. Thanks for catching that. Ryder -- 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] 23+ messages in thread
* [PATCH v5 2/2] dt-bindings: pcie: Add documentation for Mediatek PCIe 2017-05-21 3:42 ` Ryder Lee (?) (?) @ 2017-05-21 3:42 ` Ryder Lee -1 siblings, 0 replies; 23+ messages in thread From: Ryder Lee @ 2017-05-21 3:42 UTC (permalink / raw) To: Bjorn Helgaas, Rob Herring, Arnd Bergmann Cc: linux-pci, devicetree, linux-mediatek, linux-arm-kernel, linux-kernel, Red Hung, Ryder Lee Add documentation for PCIe host driver available in MT7623 series SoCs. Signed-off-by: Ryder Lee <ryder.lee@mediatek.com> Acked-by: Rob Herring <robh@kernel.org> --- .../bindings/pci/mediatek,mt7623-pcie.txt | 130 +++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 Documentation/devicetree/bindings/pci/mediatek,mt7623-pcie.txt diff --git a/Documentation/devicetree/bindings/pci/mediatek,mt7623-pcie.txt b/Documentation/devicetree/bindings/pci/mediatek,mt7623-pcie.txt new file mode 100644 index 0000000..ae4a3f4 --- /dev/null +++ b/Documentation/devicetree/bindings/pci/mediatek,mt7623-pcie.txt @@ -0,0 +1,130 @@ +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. + +Required properties: +- compatible: Should contain "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: + - 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 +- 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. +- power-domains: A phandle and power domain specifier pair to the power domain + which is responsible for collapsing and restoring power to the peripheral. +- bus-range: Range of bus numbers associated with this controller. +- ranges: Ranges for the PCI memory and I/O regions. + +In addition, the device tree node must have sub-nodes describing each +PCIe port interface, having the following mandatory properties: + +Required properties: +- device_type: Must be "pci" +- reg: Only the first four bytes are used to refer to the correct bus number + and device number. +- #address-cells: Must be 3 +- #size-cells: Must be 2 +- #interrupt-cells: 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. +- ranges: Sub-ranges distributed from the PCIe controller node. An empty + property is sufficient. +- num-lanes: Number of lanes to use for this port. + +Examples: + + hifsys: syscon@1a000000 { + compatible = "mediatek,mt7623-hifsys", + "mediatek,mt2701-hifsys", + "syscon"; + reg = <0 0x1a000000 0 0x1000>; + #clock-cells = <1>; + #reset-cells = <1>; + }; + + pcie: pcie-controller@1a140000 { + compatible = "mediatek,mt7623-pcie"; + device_type = "pci"; + reg = <0 0x1a140000 0 0x1000>, /* PCIe shared registers */ + <0 0x1a142000 0 0x1000>, /* Port0 registers */ + <0 0x1a143000 0 0x1000>, /* Port1 registers */ + <0 0x1a144000 0 0x1000>; /* Port2 registers */ + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + interrupt-map-mask = <0xf800 0 0 0>; + interrupt-map = <0x0000 0 0 0 &sysirq GIC_SPI 193 IRQ_TYPE_LEVEL_LOW>, + <0x0800 0 0 0 &sysirq GIC_SPI 194 IRQ_TYPE_LEVEL_LOW>, + <0x1000 0 0 0 &sysirq GIC_SPI 195 IRQ_TYPE_LEVEL_LOW>; + clocks = <&topckgen CLK_TOP_ETHIF_SEL>, + <&hifsys CLK_HIFSYS_PCIE0>, + <&hifsys CLK_HIFSYS_PCIE1>, + <&hifsys CLK_HIFSYS_PCIE2>; + clock-names = "free_ck", "sys_ck0", "sys_ck1", "sys_ck2"; + resets = <&hifsys MT2701_HIFSYS_PCIE0_RST>, + <&hifsys MT2701_HIFSYS_PCIE1_RST>, + <&hifsys MT2701_HIFSYS_PCIE2_RST>; + reset-names = "pcie-rst0", "pcie-rst1", "pcie-rst2"; + phys = <&pcie0_phy>, <&pcie1_phy>, <&pcie2_phy>; + phy-names = "pcie-phy0", "pcie-phy1", "pcie-phy2"; + power-domains = <&scpsys MT2701_POWER_DOMAIN_HIF>; + bus-range = <0x00 0xff>; + ranges = <0x81000000 0 0x1a160000 0 0x1a160000 0 0x00010000 /* I/O space */ + 0x83000000 0 0x60000000 0 0x60000000 0 0x10000000>; /* memory space */ + + pcie@0,0 { + device_type = "pci"; + reg = <0x0000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &sysirq GIC_SPI 193 IRQ_TYPE_LEVEL_LOW>; + ranges; + num-lanes = <1>; + }; + + pcie@1,0 { + device_type = "pci"; + reg = <0x0800 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &sysirq GIC_SPI 194 IRQ_TYPE_LEVEL_LOW>; + ranges; + num-lanes = <1>; + }; + + pcie@2,0 { + device_type = "pci"; + reg = <0x1000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &sysirq GIC_SPI 195 IRQ_TYPE_LEVEL_LOW>; + ranges; + num-lanes = <1>; + }; + }; -- 1.9.1 ^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v5 2/2] dt-bindings: pcie: Add documentation for Mediatek PCIe @ 2017-05-21 3:42 ` Ryder Lee 0 siblings, 0 replies; 23+ messages in thread From: Ryder Lee @ 2017-05-21 3:42 UTC (permalink / raw) To: linux-arm-kernel Add documentation for PCIe host driver available in MT7623 series SoCs. Signed-off-by: Ryder Lee <ryder.lee@mediatek.com> Acked-by: Rob Herring <robh@kernel.org> --- .../bindings/pci/mediatek,mt7623-pcie.txt | 130 +++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 Documentation/devicetree/bindings/pci/mediatek,mt7623-pcie.txt diff --git a/Documentation/devicetree/bindings/pci/mediatek,mt7623-pcie.txt b/Documentation/devicetree/bindings/pci/mediatek,mt7623-pcie.txt new file mode 100644 index 0000000..ae4a3f4 --- /dev/null +++ b/Documentation/devicetree/bindings/pci/mediatek,mt7623-pcie.txt @@ -0,0 +1,130 @@ +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. + +Required properties: +- compatible: Should contain "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: + - 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 +- 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. +- power-domains: A phandle and power domain specifier pair to the power domain + which is responsible for collapsing and restoring power to the peripheral. +- bus-range: Range of bus numbers associated with this controller. +- ranges: Ranges for the PCI memory and I/O regions. + +In addition, the device tree node must have sub-nodes describing each +PCIe port interface, having the following mandatory properties: + +Required properties: +- device_type: Must be "pci" +- reg: Only the first four bytes are used to refer to the correct bus number + and device number. +- #address-cells: Must be 3 +- #size-cells: Must be 2 +- #interrupt-cells: 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. +- ranges: Sub-ranges distributed from the PCIe controller node. An empty + property is sufficient. +- num-lanes: Number of lanes to use for this port. + +Examples: + + hifsys: syscon at 1a000000 { + compatible = "mediatek,mt7623-hifsys", + "mediatek,mt2701-hifsys", + "syscon"; + reg = <0 0x1a000000 0 0x1000>; + #clock-cells = <1>; + #reset-cells = <1>; + }; + + pcie: pcie-controller at 1a140000 { + compatible = "mediatek,mt7623-pcie"; + device_type = "pci"; + reg = <0 0x1a140000 0 0x1000>, /* PCIe shared registers */ + <0 0x1a142000 0 0x1000>, /* Port0 registers */ + <0 0x1a143000 0 0x1000>, /* Port1 registers */ + <0 0x1a144000 0 0x1000>; /* Port2 registers */ + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + interrupt-map-mask = <0xf800 0 0 0>; + interrupt-map = <0x0000 0 0 0 &sysirq GIC_SPI 193 IRQ_TYPE_LEVEL_LOW>, + <0x0800 0 0 0 &sysirq GIC_SPI 194 IRQ_TYPE_LEVEL_LOW>, + <0x1000 0 0 0 &sysirq GIC_SPI 195 IRQ_TYPE_LEVEL_LOW>; + clocks = <&topckgen CLK_TOP_ETHIF_SEL>, + <&hifsys CLK_HIFSYS_PCIE0>, + <&hifsys CLK_HIFSYS_PCIE1>, + <&hifsys CLK_HIFSYS_PCIE2>; + clock-names = "free_ck", "sys_ck0", "sys_ck1", "sys_ck2"; + resets = <&hifsys MT2701_HIFSYS_PCIE0_RST>, + <&hifsys MT2701_HIFSYS_PCIE1_RST>, + <&hifsys MT2701_HIFSYS_PCIE2_RST>; + reset-names = "pcie-rst0", "pcie-rst1", "pcie-rst2"; + phys = <&pcie0_phy>, <&pcie1_phy>, <&pcie2_phy>; + phy-names = "pcie-phy0", "pcie-phy1", "pcie-phy2"; + power-domains = <&scpsys MT2701_POWER_DOMAIN_HIF>; + bus-range = <0x00 0xff>; + ranges = <0x81000000 0 0x1a160000 0 0x1a160000 0 0x00010000 /* I/O space */ + 0x83000000 0 0x60000000 0 0x60000000 0 0x10000000>; /* memory space */ + + pcie at 0,0 { + device_type = "pci"; + reg = <0x0000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &sysirq GIC_SPI 193 IRQ_TYPE_LEVEL_LOW>; + ranges; + num-lanes = <1>; + }; + + pcie at 1,0 { + device_type = "pci"; + reg = <0x0800 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &sysirq GIC_SPI 194 IRQ_TYPE_LEVEL_LOW>; + ranges; + num-lanes = <1>; + }; + + pcie at 2,0 { + device_type = "pci"; + reg = <0x1000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &sysirq GIC_SPI 195 IRQ_TYPE_LEVEL_LOW>; + ranges; + num-lanes = <1>; + }; + }; -- 1.9.1 ^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v5 2/2] dt-bindings: pcie: Add documentation for Mediatek PCIe @ 2017-05-21 3:42 ` Ryder Lee 0 siblings, 0 replies; 23+ messages in thread From: Ryder Lee @ 2017-05-21 3:42 UTC (permalink / raw) To: Bjorn Helgaas, Rob Herring, Arnd Bergmann Cc: devicetree, Red Hung, linux-pci, linux-kernel, Ryder Lee, linux-mediatek, linux-arm-kernel Add documentation for PCIe host driver available in MT7623 series SoCs. Signed-off-by: Ryder Lee <ryder.lee@mediatek.com> Acked-by: Rob Herring <robh@kernel.org> --- .../bindings/pci/mediatek,mt7623-pcie.txt | 130 +++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 Documentation/devicetree/bindings/pci/mediatek,mt7623-pcie.txt diff --git a/Documentation/devicetree/bindings/pci/mediatek,mt7623-pcie.txt b/Documentation/devicetree/bindings/pci/mediatek,mt7623-pcie.txt new file mode 100644 index 0000000..ae4a3f4 --- /dev/null +++ b/Documentation/devicetree/bindings/pci/mediatek,mt7623-pcie.txt @@ -0,0 +1,130 @@ +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. + +Required properties: +- compatible: Should contain "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: + - 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 +- 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. +- power-domains: A phandle and power domain specifier pair to the power domain + which is responsible for collapsing and restoring power to the peripheral. +- bus-range: Range of bus numbers associated with this controller. +- ranges: Ranges for the PCI memory and I/O regions. + +In addition, the device tree node must have sub-nodes describing each +PCIe port interface, having the following mandatory properties: + +Required properties: +- device_type: Must be "pci" +- reg: Only the first four bytes are used to refer to the correct bus number + and device number. +- #address-cells: Must be 3 +- #size-cells: Must be 2 +- #interrupt-cells: 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. +- ranges: Sub-ranges distributed from the PCIe controller node. An empty + property is sufficient. +- num-lanes: Number of lanes to use for this port. + +Examples: + + hifsys: syscon@1a000000 { + compatible = "mediatek,mt7623-hifsys", + "mediatek,mt2701-hifsys", + "syscon"; + reg = <0 0x1a000000 0 0x1000>; + #clock-cells = <1>; + #reset-cells = <1>; + }; + + pcie: pcie-controller@1a140000 { + compatible = "mediatek,mt7623-pcie"; + device_type = "pci"; + reg = <0 0x1a140000 0 0x1000>, /* PCIe shared registers */ + <0 0x1a142000 0 0x1000>, /* Port0 registers */ + <0 0x1a143000 0 0x1000>, /* Port1 registers */ + <0 0x1a144000 0 0x1000>; /* Port2 registers */ + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + interrupt-map-mask = <0xf800 0 0 0>; + interrupt-map = <0x0000 0 0 0 &sysirq GIC_SPI 193 IRQ_TYPE_LEVEL_LOW>, + <0x0800 0 0 0 &sysirq GIC_SPI 194 IRQ_TYPE_LEVEL_LOW>, + <0x1000 0 0 0 &sysirq GIC_SPI 195 IRQ_TYPE_LEVEL_LOW>; + clocks = <&topckgen CLK_TOP_ETHIF_SEL>, + <&hifsys CLK_HIFSYS_PCIE0>, + <&hifsys CLK_HIFSYS_PCIE1>, + <&hifsys CLK_HIFSYS_PCIE2>; + clock-names = "free_ck", "sys_ck0", "sys_ck1", "sys_ck2"; + resets = <&hifsys MT2701_HIFSYS_PCIE0_RST>, + <&hifsys MT2701_HIFSYS_PCIE1_RST>, + <&hifsys MT2701_HIFSYS_PCIE2_RST>; + reset-names = "pcie-rst0", "pcie-rst1", "pcie-rst2"; + phys = <&pcie0_phy>, <&pcie1_phy>, <&pcie2_phy>; + phy-names = "pcie-phy0", "pcie-phy1", "pcie-phy2"; + power-domains = <&scpsys MT2701_POWER_DOMAIN_HIF>; + bus-range = <0x00 0xff>; + ranges = <0x81000000 0 0x1a160000 0 0x1a160000 0 0x00010000 /* I/O space */ + 0x83000000 0 0x60000000 0 0x60000000 0 0x10000000>; /* memory space */ + + pcie@0,0 { + device_type = "pci"; + reg = <0x0000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &sysirq GIC_SPI 193 IRQ_TYPE_LEVEL_LOW>; + ranges; + num-lanes = <1>; + }; + + pcie@1,0 { + device_type = "pci"; + reg = <0x0800 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &sysirq GIC_SPI 194 IRQ_TYPE_LEVEL_LOW>; + ranges; + num-lanes = <1>; + }; + + pcie@2,0 { + device_type = "pci"; + reg = <0x1000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &sysirq GIC_SPI 195 IRQ_TYPE_LEVEL_LOW>; + ranges; + num-lanes = <1>; + }; + }; -- 1.9.1 _______________________________________________ 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] 23+ messages in thread
* [PATCH v5 2/2] dt-bindings: pcie: Add documentation for Mediatek PCIe @ 2017-05-21 3:42 ` Ryder Lee 0 siblings, 0 replies; 23+ messages in thread From: Ryder Lee @ 2017-05-21 3:42 UTC (permalink / raw) To: Bjorn Helgaas, Rob Herring, Arnd Bergmann Cc: linux-pci, devicetree, linux-mediatek, linux-arm-kernel, linux-kernel, Red Hung, Ryder Lee Add documentation for PCIe host driver available in MT7623 series SoCs. Signed-off-by: Ryder Lee <ryder.lee@mediatek.com> Acked-by: Rob Herring <robh@kernel.org> --- .../bindings/pci/mediatek,mt7623-pcie.txt | 130 +++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 Documentation/devicetree/bindings/pci/mediatek,mt7623-pcie.txt diff --git a/Documentation/devicetree/bindings/pci/mediatek,mt7623-pcie.txt b/Documentation/devicetree/bindings/pci/mediatek,mt7623-pcie.txt new file mode 100644 index 0000000..ae4a3f4 --- /dev/null +++ b/Documentation/devicetree/bindings/pci/mediatek,mt7623-pcie.txt @@ -0,0 +1,130 @@ +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. + +Required properties: +- compatible: Should contain "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: + - 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 +- 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. +- power-domains: A phandle and power domain specifier pair to the power domain + which is responsible for collapsing and restoring power to the peripheral. +- bus-range: Range of bus numbers associated with this controller. +- ranges: Ranges for the PCI memory and I/O regions. + +In addition, the device tree node must have sub-nodes describing each +PCIe port interface, having the following mandatory properties: + +Required properties: +- device_type: Must be "pci" +- reg: Only the first four bytes are used to refer to the correct bus number + and device number. +- #address-cells: Must be 3 +- #size-cells: Must be 2 +- #interrupt-cells: 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. +- ranges: Sub-ranges distributed from the PCIe controller node. An empty + property is sufficient. +- num-lanes: Number of lanes to use for this port. + +Examples: + + hifsys: syscon@1a000000 { + compatible = "mediatek,mt7623-hifsys", + "mediatek,mt2701-hifsys", + "syscon"; + reg = <0 0x1a000000 0 0x1000>; + #clock-cells = <1>; + #reset-cells = <1>; + }; + + pcie: pcie-controller@1a140000 { + compatible = "mediatek,mt7623-pcie"; + device_type = "pci"; + reg = <0 0x1a140000 0 0x1000>, /* PCIe shared registers */ + <0 0x1a142000 0 0x1000>, /* Port0 registers */ + <0 0x1a143000 0 0x1000>, /* Port1 registers */ + <0 0x1a144000 0 0x1000>; /* Port2 registers */ + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + interrupt-map-mask = <0xf800 0 0 0>; + interrupt-map = <0x0000 0 0 0 &sysirq GIC_SPI 193 IRQ_TYPE_LEVEL_LOW>, + <0x0800 0 0 0 &sysirq GIC_SPI 194 IRQ_TYPE_LEVEL_LOW>, + <0x1000 0 0 0 &sysirq GIC_SPI 195 IRQ_TYPE_LEVEL_LOW>; + clocks = <&topckgen CLK_TOP_ETHIF_SEL>, + <&hifsys CLK_HIFSYS_PCIE0>, + <&hifsys CLK_HIFSYS_PCIE1>, + <&hifsys CLK_HIFSYS_PCIE2>; + clock-names = "free_ck", "sys_ck0", "sys_ck1", "sys_ck2"; + resets = <&hifsys MT2701_HIFSYS_PCIE0_RST>, + <&hifsys MT2701_HIFSYS_PCIE1_RST>, + <&hifsys MT2701_HIFSYS_PCIE2_RST>; + reset-names = "pcie-rst0", "pcie-rst1", "pcie-rst2"; + phys = <&pcie0_phy>, <&pcie1_phy>, <&pcie2_phy>; + phy-names = "pcie-phy0", "pcie-phy1", "pcie-phy2"; + power-domains = <&scpsys MT2701_POWER_DOMAIN_HIF>; + bus-range = <0x00 0xff>; + ranges = <0x81000000 0 0x1a160000 0 0x1a160000 0 0x00010000 /* I/O space */ + 0x83000000 0 0x60000000 0 0x60000000 0 0x10000000>; /* memory space */ + + pcie@0,0 { + device_type = "pci"; + reg = <0x0000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &sysirq GIC_SPI 193 IRQ_TYPE_LEVEL_LOW>; + ranges; + num-lanes = <1>; + }; + + pcie@1,0 { + device_type = "pci"; + reg = <0x0800 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &sysirq GIC_SPI 194 IRQ_TYPE_LEVEL_LOW>; + ranges; + num-lanes = <1>; + }; + + pcie@2,0 { + device_type = "pci"; + reg = <0x1000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &sysirq GIC_SPI 195 IRQ_TYPE_LEVEL_LOW>; + ranges; + num-lanes = <1>; + }; + }; -- 1.9.1 ^ permalink raw reply related [flat|nested] 23+ messages in thread
* Re: [PATCH v5 0/2] Add PCIe host driver support for Mediatek SoCs @ 2017-05-24 21:56 ` Bjorn Helgaas 0 siblings, 0 replies; 23+ messages in thread From: Bjorn Helgaas @ 2017-05-24 21:56 UTC (permalink / raw) To: Ryder Lee Cc: Bjorn Helgaas, Rob Herring, Arnd Bergmann, devicetree, Red Hung, linux-pci, linux-kernel, linux-mediatek, linux-arm-kernel On Sun, May 21, 2017 at 11:42:23AM +0800, Ryder Lee wrote: > Hi, > > This patch series add Mediatek Gen2 PCIe host controller driver and > dt-binding document. It can be found on MT7623 series SoCs. > > This driver was validated using Broadcom Tigon3 and Intel(R) 82575/82576 > gigabit ethernet card. > > > Changes since v5: > - rebase to Linux 4.12-rc1. > - remove redundant module.h header and MODULE macros. > > Changes since v4: > - move the per-port registers to the parent node. > - use a valid compatible for hifsys controller. > - use the 'sysirq' instead of 'gic' as a correct 'interrupt-parent' of the > interrupt-map properties. > > 'sysirq' is an interrupt-controller that could help us to reverse GIC SPIs polarity > so that we could properly set irq type to level low without any extra properties. > It was a mistake to select wrong interrupt-parent on the previous versions. > Now, we could remove unnecessary interrupt properties entirely from binding. > > Changes since v3: > - correct sub-nodes unit addresses. > > Changes since v2: > - modify Kconfig to avoid kbuild test error on some architecture. > - change compatible string. > - revise binding document: > add missing interrupt-names. > remove the board dts example and drop 'status' properties. > remove unnecessary descriptions bout standard PCI bus binding. > > Changes since v1: > - add .suppress_bind_attrs. > - remove unnecessary *_valid_device() pattern. > - remove PCI_PROBE_ONLY. > - use the regular readl() instead of readl_relaxed(). > - add .map_bus() and change to use pci_generic_config_read/pci_generic_config_write. > - revise dt-binding document and move nonstandard properties to root node. > - change compatible string. > - use interrupt-map property and replace mtk_pcie_map_irq() with of_irq_parse_and_map_pci(). > - use the new pci_register_host_bridge() method instead of pci_scan_root_bus()* > > Ryder Lee (2): > PCI: mediatek: Add Mediatek PCIe host controller support > dt-bindings: pcie: Add documentation for Mediatek PCIe > > .../bindings/pci/mediatek,mt7623-pcie.txt | 130 +++++ > drivers/pci/host/Kconfig | 11 + > drivers/pci/host/Makefile | 1 + > drivers/pci/host/pcie-mediatek.c | 553 +++++++++++++++++++++ > 4 files changed, 695 insertions(+) > create mode 100644 Documentation/devicetree/bindings/pci/mediatek,mt7623-pcie.txt > create mode 100644 drivers/pci/host/pcie-mediatek.c Applied to pci/host-mediatek for v4.13, thanks! ^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH v5 0/2] Add PCIe host driver support for Mediatek SoCs @ 2017-05-24 21:56 ` Bjorn Helgaas 0 siblings, 0 replies; 23+ messages in thread From: Bjorn Helgaas @ 2017-05-24 21:56 UTC (permalink / raw) To: linux-arm-kernel On Sun, May 21, 2017 at 11:42:23AM +0800, Ryder Lee wrote: > Hi, > > This patch series add Mediatek Gen2 PCIe host controller driver and > dt-binding document. It can be found on MT7623 series SoCs. > > This driver was validated using Broadcom Tigon3 and Intel(R) 82575/82576 > gigabit ethernet card. > > > Changes since v5: > - rebase to Linux 4.12-rc1. > - remove redundant module.h header and MODULE macros. > > Changes since v4: > - move the per-port registers to the parent node. > - use a valid compatible for hifsys controller. > - use the 'sysirq' instead of 'gic' as a correct 'interrupt-parent' of the > interrupt-map properties. > > 'sysirq' is an interrupt-controller that could help us to reverse GIC SPIs polarity > so that we could properly set irq type to level low without any extra properties. > It was a mistake to select wrong interrupt-parent on the previous versions. > Now, we could remove unnecessary interrupt properties entirely from binding. > > Changes since v3: > - correct sub-nodes unit addresses. > > Changes since v2: > - modify Kconfig to avoid kbuild test error on some architecture. > - change compatible string. > - revise binding document: > add missing interrupt-names. > remove the board dts example and drop 'status' properties. > remove unnecessary descriptions bout standard PCI bus binding. > > Changes since v1: > - add .suppress_bind_attrs. > - remove unnecessary *_valid_device() pattern. > - remove PCI_PROBE_ONLY. > - use the regular readl() instead of readl_relaxed(). > - add .map_bus() and change to use pci_generic_config_read/pci_generic_config_write. > - revise dt-binding document and move nonstandard properties to root node. > - change compatible string. > - use interrupt-map property and replace mtk_pcie_map_irq() with of_irq_parse_and_map_pci(). > - use the new pci_register_host_bridge() method instead of pci_scan_root_bus()* > > Ryder Lee (2): > PCI: mediatek: Add Mediatek PCIe host controller support > dt-bindings: pcie: Add documentation for Mediatek PCIe > > .../bindings/pci/mediatek,mt7623-pcie.txt | 130 +++++ > drivers/pci/host/Kconfig | 11 + > drivers/pci/host/Makefile | 1 + > drivers/pci/host/pcie-mediatek.c | 553 +++++++++++++++++++++ > 4 files changed, 695 insertions(+) > create mode 100644 Documentation/devicetree/bindings/pci/mediatek,mt7623-pcie.txt > create mode 100644 drivers/pci/host/pcie-mediatek.c Applied to pci/host-mediatek for v4.13, thanks! ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v5 0/2] Add PCIe host driver support for Mediatek SoCs @ 2017-05-24 21:56 ` Bjorn Helgaas 0 siblings, 0 replies; 23+ messages in thread From: Bjorn Helgaas @ 2017-05-24 21:56 UTC (permalink / raw) To: Ryder Lee Cc: devicetree, Red Hung, Arnd Bergmann, linux-pci, linux-kernel, Rob Herring, linux-mediatek, Bjorn Helgaas, linux-arm-kernel On Sun, May 21, 2017 at 11:42:23AM +0800, Ryder Lee wrote: > Hi, > > This patch series add Mediatek Gen2 PCIe host controller driver and > dt-binding document. It can be found on MT7623 series SoCs. > > This driver was validated using Broadcom Tigon3 and Intel(R) 82575/82576 > gigabit ethernet card. > > > Changes since v5: > - rebase to Linux 4.12-rc1. > - remove redundant module.h header and MODULE macros. > > Changes since v4: > - move the per-port registers to the parent node. > - use a valid compatible for hifsys controller. > - use the 'sysirq' instead of 'gic' as a correct 'interrupt-parent' of the > interrupt-map properties. > > 'sysirq' is an interrupt-controller that could help us to reverse GIC SPIs polarity > so that we could properly set irq type to level low without any extra properties. > It was a mistake to select wrong interrupt-parent on the previous versions. > Now, we could remove unnecessary interrupt properties entirely from binding. > > Changes since v3: > - correct sub-nodes unit addresses. > > Changes since v2: > - modify Kconfig to avoid kbuild test error on some architecture. > - change compatible string. > - revise binding document: > add missing interrupt-names. > remove the board dts example and drop 'status' properties. > remove unnecessary descriptions bout standard PCI bus binding. > > Changes since v1: > - add .suppress_bind_attrs. > - remove unnecessary *_valid_device() pattern. > - remove PCI_PROBE_ONLY. > - use the regular readl() instead of readl_relaxed(). > - add .map_bus() and change to use pci_generic_config_read/pci_generic_config_write. > - revise dt-binding document and move nonstandard properties to root node. > - change compatible string. > - use interrupt-map property and replace mtk_pcie_map_irq() with of_irq_parse_and_map_pci(). > - use the new pci_register_host_bridge() method instead of pci_scan_root_bus()* > > Ryder Lee (2): > PCI: mediatek: Add Mediatek PCIe host controller support > dt-bindings: pcie: Add documentation for Mediatek PCIe > > .../bindings/pci/mediatek,mt7623-pcie.txt | 130 +++++ > drivers/pci/host/Kconfig | 11 + > drivers/pci/host/Makefile | 1 + > drivers/pci/host/pcie-mediatek.c | 553 +++++++++++++++++++++ > 4 files changed, 695 insertions(+) > create mode 100644 Documentation/devicetree/bindings/pci/mediatek,mt7623-pcie.txt > create mode 100644 drivers/pci/host/pcie-mediatek.c Applied to pci/host-mediatek for v4.13, thanks! _______________________________________________ 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] 23+ messages in thread
* Re: [PATCH v5 0/2] Add PCIe host driver support for Mediatek SoCs @ 2017-05-24 21:56 ` Bjorn Helgaas 0 siblings, 0 replies; 23+ messages in thread From: Bjorn Helgaas @ 2017-05-24 21:56 UTC (permalink / raw) To: Ryder Lee Cc: Bjorn Helgaas, Rob Herring, Arnd Bergmann, devicetree-u79uwXL29TY76Z2rM5mHXA, Red Hung, linux-pci-u79uwXL29TY76Z2rM5mHXA, linux-kernel-u79uwXL29TY76Z2rM5mHXA, linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r On Sun, May 21, 2017 at 11:42:23AM +0800, Ryder Lee wrote: > Hi, > > This patch series add Mediatek Gen2 PCIe host controller driver and > dt-binding document. It can be found on MT7623 series SoCs. > > This driver was validated using Broadcom Tigon3 and Intel(R) 82575/82576 > gigabit ethernet card. > > > Changes since v5: > - rebase to Linux 4.12-rc1. > - remove redundant module.h header and MODULE macros. > > Changes since v4: > - move the per-port registers to the parent node. > - use a valid compatible for hifsys controller. > - use the 'sysirq' instead of 'gic' as a correct 'interrupt-parent' of the > interrupt-map properties. > > 'sysirq' is an interrupt-controller that could help us to reverse GIC SPIs polarity > so that we could properly set irq type to level low without any extra properties. > It was a mistake to select wrong interrupt-parent on the previous versions. > Now, we could remove unnecessary interrupt properties entirely from binding. > > Changes since v3: > - correct sub-nodes unit addresses. > > Changes since v2: > - modify Kconfig to avoid kbuild test error on some architecture. > - change compatible string. > - revise binding document: > add missing interrupt-names. > remove the board dts example and drop 'status' properties. > remove unnecessary descriptions bout standard PCI bus binding. > > Changes since v1: > - add .suppress_bind_attrs. > - remove unnecessary *_valid_device() pattern. > - remove PCI_PROBE_ONLY. > - use the regular readl() instead of readl_relaxed(). > - add .map_bus() and change to use pci_generic_config_read/pci_generic_config_write. > - revise dt-binding document and move nonstandard properties to root node. > - change compatible string. > - use interrupt-map property and replace mtk_pcie_map_irq() with of_irq_parse_and_map_pci(). > - use the new pci_register_host_bridge() method instead of pci_scan_root_bus()* > > Ryder Lee (2): > PCI: mediatek: Add Mediatek PCIe host controller support > dt-bindings: pcie: Add documentation for Mediatek PCIe > > .../bindings/pci/mediatek,mt7623-pcie.txt | 130 +++++ > drivers/pci/host/Kconfig | 11 + > drivers/pci/host/Makefile | 1 + > drivers/pci/host/pcie-mediatek.c | 553 +++++++++++++++++++++ > 4 files changed, 695 insertions(+) > create mode 100644 Documentation/devicetree/bindings/pci/mediatek,mt7623-pcie.txt > create mode 100644 drivers/pci/host/pcie-mediatek.c Applied to pci/host-mediatek for v4.13, thanks! -- 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] 23+ messages in thread
end of thread, other threads:[~2017-06-29 2:00 UTC | newest] Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2017-05-21 3:42 [PATCH v5 0/2] Add PCIe host driver support for Mediatek SoCs Ryder Lee 2017-05-21 3:42 ` Ryder Lee 2017-05-21 3:42 ` Ryder Lee 2017-05-21 3:42 ` Ryder Lee 2017-05-21 3:42 ` [PATCH v5 1/2] PCI: mediatek: Add Mediatek PCIe host controller support Ryder Lee 2017-05-21 3:42 ` Ryder Lee 2017-05-21 3:42 ` Ryder Lee 2017-05-21 3:42 ` Ryder Lee 2017-06-28 19:53 ` Bjorn Helgaas 2017-06-28 19:53 ` Bjorn Helgaas 2017-06-28 19:53 ` Bjorn Helgaas 2017-06-28 19:53 ` Bjorn Helgaas 2017-06-29 2:00 ` Ryder Lee 2017-06-29 2:00 ` Ryder Lee 2017-06-29 2:00 ` Ryder Lee 2017-05-21 3:42 ` [PATCH v5 2/2] dt-bindings: pcie: Add documentation for Mediatek PCIe Ryder Lee 2017-05-21 3:42 ` Ryder Lee 2017-05-21 3:42 ` Ryder Lee 2017-05-21 3:42 ` Ryder Lee 2017-05-24 21:56 ` [PATCH v5 0/2] Add PCIe host driver support for Mediatek SoCs Bjorn Helgaas 2017-05-24 21:56 ` Bjorn Helgaas 2017-05-24 21:56 ` Bjorn Helgaas 2017-05-24 21:56 ` 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.