From: John Crispin <blogic@openwrt.org>
To: Bjorn Helgaas <bhelgaas@google.com>
Cc: linux-pci@vger.kernel.org, linux-mediatek@lists.infradead.org
Subject: [PATCH 2/2] PCI: mediatek: add support for PCIE found on MT7623/MT2701
Date: Thu, 7 Jan 2016 22:06:13 +0100 [thread overview]
Message-ID: <1452200773-50794-2-git-send-email-blogic@openwrt.org> (raw)
In-Reply-To: <1452200773-50794-1-git-send-email-blogic@openwrt.org>
Add PCIE controller support on MediaTek MT2701/MT7623. The driver supports
a single Root complex (RC) with 3 Root Ports. The SoCs supports a Gen2
1-lan Link on each port.
Signed-off-by: John Crispin <blogic@openwrt.org>
---
arch/arm/mach-mediatek/Kconfig | 1 +
drivers/pci/host/Kconfig | 11 +
drivers/pci/host/Makefile | 1 +
drivers/pci/host/pcie-mediatek.c | 604 ++++++++++++++++++++++++++++++++++++++
4 files changed, 617 insertions(+)
create mode 100644 drivers/pci/host/pcie-mediatek.c
diff --git a/arch/arm/mach-mediatek/Kconfig b/arch/arm/mach-mediatek/Kconfig
index 7fb605e..a7fef77 100644
--- a/arch/arm/mach-mediatek/Kconfig
+++ b/arch/arm/mach-mediatek/Kconfig
@@ -24,6 +24,7 @@ config MACH_MT6592
config MACH_MT7623
bool "MediaTek MT7623 SoCs support"
default ARCH_MEDIATEK
+ select MIGHT_HAVE_PCI
config MACH_MT8127
bool "MediaTek MT8127 SoCs support"
diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
index f131ba9..912f0e1 100644
--- a/drivers/pci/host/Kconfig
+++ b/drivers/pci/host/Kconfig
@@ -172,4 +172,15 @@ config PCI_HISI
help
Say Y here if you want PCIe controller support on HiSilicon HIP05 SoC
+config PCIE_MTK
+ bool "Mediatek PCIe Controller"
+ depends on MACH_MT2701 || MACH_MT7623
+ depends on OF
+ depends on PCI
+ help
+ Say Y here if you want to enable PCI controller support on Mediatek MT7623.
+ MT7623 PCIe supports single Root complex (RC) with 3 Root Ports.
+ Each port supports a Gen2 1-lan Link.
+ PCIe include one Host/PCI bridge and 3 PCIe MAC.
+
endmenu
diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile
index 9d4d3c6..3b53374 100644
--- a/drivers/pci/host/Makefile
+++ b/drivers/pci/host/Makefile
@@ -20,3 +20,4 @@ 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_PCI_HISI) += pcie-hisi.o
+obj-$(CONFIG_PCIE_MTK) += pcie-mediatek.o
diff --git a/drivers/pci/host/pcie-mediatek.c b/drivers/pci/host/pcie-mediatek.c
new file mode 100644
index 0000000..6bd283a
--- /dev/null
+++ b/drivers/pci/host/pcie-mediatek.c
@@ -0,0 +1,604 @@
+/*
+ * Mediatek MT2701/MT7623 SoC PCIE support
+ *
+ * Copyright (C) 2015 Mediatek
+ * Copyright (C) 2015 Ziv Huang <ziv.huang@mediatek.com>
+ * Copyright (C) 2015 John Crispin <blogic@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <asm/irq.h>
+#include <asm/mach/pci.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_pci.h>
+#include <linux/of_platform.h>
+#include <linux/of_irq.h>
+#include <linux/reset.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/pm_runtime.h>
+#include <linux/clk.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+
+#define MEMORY_BASE 0x80000000
+
+/* PCIE Registers */
+#define PCICFG 0x00
+#define PCIINT 0x08
+#define PCIENA 0x0c
+#define CFGADDR 0x20
+#define CFGDATA 0x24
+#define MEMBASE 0x28
+#define IOBASE 0x2c
+
+/* per Port Registers */
+#define BAR0SETUP 0x10
+#define IMBASEBAR0 0x18
+#define PCIE_CLASS 0x34
+#define PCIE_SISTAT 0x50
+
+#define MTK_PCIE_HIGH_PERF BIT(14)
+#define PCIEP0_BASE 0x2000
+#define PCIEP1_BASE 0x3000
+#define PCIEP2_BASE 0x4000
+
+#define PHY_P0_CTL 0x9000
+#define PHY_P1_CTL 0xa000
+#define PHY_P2_CTL 0x4000
+
+#define RSTCTL_PCIE0_RST BIT(24)
+#define RSTCTL_PCIE1_RST BIT(25)
+#define RSTCTL_PCIE2_RST BIT(26)
+
+#define HIFSYS_SYSCFG1 0x14
+#define HIFSYS_SYSCFG1_PHY2_MASK (0x3 << 20)
+
+static struct mtk_pcie_port {
+ int id;
+ int enable;
+ u32 base;
+ u32 perst_n;
+ u32 interrupt_en;
+ int irq;
+ u32 link;
+ void __iomem *phy_base;
+ struct reset_control *rstc;
+} mtk_pcie_port[] = {
+ { 0, 0, PCIEP0_BASE, BIT(1), BIT(20) },
+ { 1, 0, PCIEP1_BASE, BIT(2), BIT(21) },
+ { 2, 0, PCIEP2_BASE, BIT(3), BIT(22) },
+};
+#define MAX_PORT_NUM ARRAY_SIZE(mtk_pcie_port)
+#define mtk_foreach_port(p) \
+ for ((p) = mtk_pcie_port; \
+ (p) != &mtk_pcie_port[MAX_PORT_NUM]; (p)++)
+
+struct mtk_pcie {
+ struct device *dev;
+ void __iomem *pcie_base;
+ struct regmap *hifsys;
+
+ struct resource io;
+ struct resource pio;
+ struct resource mem;
+ struct resource prefetch;
+ struct resource busn;
+
+ u32 io_bus_addr;
+ u32 mem_bus_addr;
+
+ struct clk *clk;
+ int pcie_card_link;
+};
+
+static const struct mtk_phy_init {
+ uint32_t reg;
+ uint32_t mask;
+ uint32_t val;
+} mtk_phy_init[] = {
+ { 0xc00, 0x33000, 0x22000 },
+ { 0xb04, 0xe0000000, 0x40000000 },
+ { 0xb00, 0xe, 0x4 },
+ { 0xc3C, 0xffff0000, 0x3c0000 },
+ { 0xc48, 0xffff, 0x36 },
+ { 0xc0c, 0x30000000, 0x10000000 },
+ { 0xc08, 0x3800c0, 0xc0 },
+ { 0xc10, 0xf0000, 0x20000 },
+ { 0xc0c, 0xf000, 0x1000 },
+ { 0xc14, 0xf0000, 0xa0000 },
+};
+
+static struct mtk_pcie *sys_to_pcie(struct pci_sys_data *sys)
+{
+ return sys->private_data;
+}
+
+static void pcie_w32(struct mtk_pcie *pcie, u32 val, unsigned reg)
+{
+ iowrite32(val, pcie->pcie_base + reg);
+}
+
+static u32 pcie_r32(struct mtk_pcie *pcie, unsigned reg)
+{
+ return ioread32(pcie->pcie_base + reg);
+}
+
+static void pcie_m32(struct mtk_pcie *pcie, u32 mask, u32 val, unsigned reg)
+{
+ u32 v = pcie_r32(pcie, reg);
+
+ v &= mask;
+ v |= val;
+ pcie_w32(pcie, v, reg);
+}
+
+static int pcie_config_read(struct pci_bus *bus, unsigned int devfn, int where,
+ int size, u32 *val)
+{
+ struct mtk_pcie *pcie = sys_to_pcie(bus->sysdata);
+ unsigned int slot = PCI_SLOT(devfn);
+ u8 func = PCI_FUNC(devfn);
+ u32 address;
+ u32 data;
+ u32 num = 0;
+
+ if (bus)
+ num = bus->number;
+
+ address = (((where & 0xf00) >> 8) << 24) |
+ (num << 16) |
+ (slot << 11) |
+ (func << 8) |
+ (where & 0xfc);
+
+ pcie_m32(pcie, 0xf0000000, address, CFGADDR);
+ data = pcie_r32(pcie, CFGDATA);
+
+ switch (size) {
+ case 1:
+ *val = (data >> ((where & 3) << 3)) & 0xff;
+ break;
+ case 2:
+ *val = (data >> ((where & 3) << 3)) & 0xffff;
+ break;
+ case 4:
+ *val = data;
+ break;
+ }
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int pcie_config_write(struct pci_bus *bus, unsigned int devfn, int where,
+ int size, u32 val)
+{
+ struct mtk_pcie *pcie = sys_to_pcie(bus->sysdata);
+ unsigned int slot = PCI_SLOT(devfn);
+ u8 func = PCI_FUNC(devfn);
+ u32 address;
+ u32 data;
+ u32 num = 0;
+
+ if (bus)
+ num = bus->number;
+
+ address = (((where & 0xf00) >> 8) << 24) |
+ (num << 16) | (slot << 11) | (func << 8) | (where & 0xfc);
+ pcie_m32(pcie, 0xf0000000, address, CFGADDR);
+ data = pcie_r32(pcie, CFGDATA);
+
+ switch (size) {
+ case 1:
+ data = (data & ~(0xff << ((where & 3) << 3))) |
+ (val << ((where & 3) << 3));
+ break;
+ case 2:
+ data = (data & ~(0xffff << ((where & 3) << 3))) |
+ (val << ((where & 3) << 3));
+ break;
+ case 4:
+ data = val;
+ break;
+ }
+ pcie_w32(pcie, data, CFGDATA);
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops mtk_pcie_ops = {
+ .read = pcie_config_read,
+ .write = pcie_config_write,
+};
+
+static int __init mtk_pcie_setup(int nr, struct pci_sys_data *sys)
+{
+ struct mtk_pcie *pcie = sys_to_pcie(sys);
+
+ if (!pcie->pcie_card_link)
+ return -1;
+
+ request_resource(&ioport_resource, &pcie->pio);
+ request_resource(&iomem_resource, &pcie->mem);
+
+ pci_add_resource_offset(&sys->resources, &pcie->mem, sys->mem_offset);
+ pci_add_resource_offset(&sys->resources, &pcie->pio, sys->io_offset);
+ pci_add_resource(&sys->resources, &pcie->busn);
+
+ return 1;
+}
+
+static struct pci_bus * __init mtk_pcie_scan_bus(int nr,
+ struct pci_sys_data *sys)
+{
+ struct mtk_pcie *pcie = sys_to_pcie(sys);
+ struct pci_bus *bus;
+
+ if (!pcie->pcie_card_link)
+ return NULL;
+
+ bus = pci_create_root_bus(pcie->dev, sys->busnr, &mtk_pcie_ops, sys,
+ &sys->resources);
+ if (!bus)
+ return NULL;
+
+ pci_scan_child_bus(bus);
+
+ return bus;
+}
+
+static int __init mtk_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+ struct mtk_pcie *pcie = sys_to_pcie(dev->bus->sysdata);
+ struct mtk_pcie_port *port;
+ int irq = -1;
+
+ if (!pcie->pcie_card_link)
+ return irq;
+
+ mtk_foreach_port(port)
+ if (port->id == slot)
+ irq = port->irq;
+
+ return irq;
+}
+
+static void mtk_pcie_configure_phy(struct mtk_pcie *pcie,
+ struct mtk_pcie_port *port)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(mtk_phy_init); i++) {
+ void __iomem *phy_addr = port->phy_base + mtk_phy_init[i].reg;
+ u32 val = ioread32(phy_addr);
+
+ val &= ~mtk_phy_init[i].mask;
+ val |= mtk_phy_init[i].val;
+ iowrite32(val, phy_addr);
+ }
+ usleep_range(5000, 6000);
+}
+
+static void mtk_pcie_configure_rc(struct mtk_pcie *pcie,
+ struct mtk_pcie_port *port,
+ struct pci_bus *bus)
+{
+ u32 val = 0;
+
+ pcie_config_write(bus,
+ port->id << 3,
+ PCI_BASE_ADDRESS_0, 4, MEMORY_BASE);
+
+ pcie_config_read(bus,
+ port->id << 3, PCI_BASE_ADDRESS_0, 4, &val);
+
+ /* Configure RC Credit */
+ pcie_config_read(bus, port->id << 3, 0x73c, 4, &val);
+ val &= ~(0x9fff) << 16;
+ val |= 0x806c << 16;
+ pcie_config_write(bus, port->id << 3, 0x73c, 4, val);
+
+ /* Configure RC FTS number */
+ pcie_config_read(bus, port->id << 3, 0x70c, 4, &val);
+ val &= ~(0xff3) << 8;
+ val |= 0x50 << 8;
+ pcie_config_write(bus, port->id << 3, 0x70c, 4, val);
+}
+
+static void mtk_pcie_preinit(struct mtk_pcie *pcie)
+{
+ struct mtk_pcie_port *port;
+ u32 val = 0;
+ struct pci_bus bus;
+ struct pci_sys_data sys;
+
+ memset(&bus, 0, sizeof(bus));
+ memset(&sys, 0, sizeof(sys));
+ bus.sysdata = (void *)&sys;
+ sys.private_data = (void *)pcie;
+
+ pcibios_min_io = 0;
+ pcibios_min_mem = 0;
+
+ /* The PHY on Port 2 is shared with USB */
+ if (mtk_pcie_port[2].enable)
+ regmap_update_bits(pcie->hifsys, HIFSYS_SYSCFG1,
+ HIFSYS_SYSCFG1_PHY2_MASK, 0x0);
+
+ /* PCIe RC Reset */
+ mtk_foreach_port(port)
+ if (port->enable)
+ reset_control_assert(port->rstc);
+ usleep_range(1000, 2000);
+ mtk_foreach_port(port)
+ if (port->enable)
+ reset_control_deassert(port->rstc);
+ usleep_range(1000, 2000);
+
+ /* Configure PCIe PHY */
+ mtk_foreach_port(port)
+ if (port->enable)
+ mtk_pcie_configure_phy(pcie, port);
+
+ /* PCIe EP reset */
+ val = 0;
+ mtk_foreach_port(port)
+ if (port->enable)
+ val |= port->perst_n;
+ pcie_w32(pcie, pcie_r32(pcie, PCICFG) | val, PCICFG);
+ usleep_range(1000, 2000);
+ pcie_w32(pcie, pcie_r32(pcie, PCICFG) & ~val, PCICFG);
+ usleep_range(1000, 2000);
+ msleep(100);
+
+ /* check the link status */
+ val = 0;
+ mtk_foreach_port(port) {
+ if (port->enable) {
+ if ((pcie_r32(pcie, port->base + PCIE_SISTAT) & 0x1))
+ port->link = 1;
+ else
+ reset_control_assert(port->rstc);
+ }
+ }
+
+ mtk_foreach_port(port)
+ if (port->link)
+ pcie->pcie_card_link++;
+
+ if (!pcie->pcie_card_link)
+ return;
+
+ pcie_w32(pcie, pcie->mem_bus_addr, MEMBASE);
+ pcie_w32(pcie, pcie->io_bus_addr, IOBASE);
+
+ mtk_foreach_port(port) {
+ if (port->link) {
+ pcie_m32(pcie, 0, port->interrupt_en, PCIENA);
+ pcie_w32(pcie, 0x7fff0001, port->base + BAR0SETUP);
+ pcie_w32(pcie, MEMORY_BASE, port->base + IMBASEBAR0);
+ pcie_w32(pcie, 0x06040001, port->base + PCIE_CLASS);
+ }
+ }
+
+ mtk_foreach_port(port)
+ if (port->link)
+ mtk_pcie_configure_rc(pcie, port, &bus);
+}
+
+static int mtk_pcie_parse_dt(struct mtk_pcie *pcie)
+{
+ struct device_node *np = pcie->dev->of_node, *port;
+ struct of_pci_range_parser parser;
+ struct of_pci_range range;
+ struct resource res;
+ int err;
+
+ pcie->hifsys = syscon_regmap_lookup_by_phandle(np, "mediatek,hifsys");
+ if (IS_ERR(pcie->hifsys)) {
+ dev_err(pcie->dev, "missing \"mediatek,hifsys\" phandle\n");
+ return PTR_ERR(pcie->hifsys);
+ }
+
+ if (of_pci_range_parser_init(&parser, np)) {
+ dev_err(pcie->dev, "missing \"ranges\" property\n");
+ return -EINVAL;
+ }
+
+ for_each_of_pci_range(&parser, &range) {
+ err = of_pci_range_to_resource(&range, np, &res);
+ if (err < 0) {
+ dev_err(pcie->dev, "failed to read resource range\n");
+ return err;
+ }
+
+ switch (res.flags & IORESOURCE_TYPE_BITS) {
+ case IORESOURCE_IO:
+ memcpy(&pcie->pio, &res, sizeof(res));
+ pcie->pio.start = (resource_size_t)range.pci_addr;
+ pcie->pio.end = (resource_size_t)
+ (range.pci_addr + range.size - 1);
+ pcie->io_bus_addr = (resource_size_t)range.cpu_addr;
+ break;
+
+ case IORESOURCE_MEM:
+ if (res.flags & IORESOURCE_PREFETCH) {
+ memcpy(&pcie->prefetch, &res, sizeof(res));
+ pcie->prefetch.name = "prefetchable";
+ pcie->prefetch.start =
+ (resource_size_t)range.pci_addr;
+ pcie->prefetch.end = (resource_size_t)
+ (range.pci_addr + range.size - 1);
+ } else {
+ memcpy(&pcie->mem, &res, sizeof(res));
+ pcie->mem.name = "non-prefetchable";
+ pcie->mem.start = (resource_size_t)
+ range.pci_addr;
+ pcie->prefetch.end = (resource_size_t)
+ (range.pci_addr + range.size - 1);
+ pcie->mem_bus_addr = (resource_size_t)
+ range.cpu_addr;
+ }
+ break;
+ }
+ }
+
+ err = of_pci_parse_bus_range(np, &pcie->busn);
+ if (err < 0) {
+ dev_err(pcie->dev, "failed to parse ranges property: %d\n",
+ err);
+ pcie->busn.name = np->name;
+ pcie->busn.start = 0;
+ pcie->busn.end = 0xff;
+ pcie->busn.flags = IORESOURCE_BUS;
+ }
+
+ /* parse root ports */
+ for_each_child_of_node(np, port) {
+ unsigned int index;
+ char rst[] = "pcie0";
+
+ err = of_pci_get_devfn(port);
+ if (err < 0) {
+ dev_err(pcie->dev, "failed to parse address: %d\n",
+ err);
+ return err;
+ }
+
+ index = PCI_SLOT(err);
+
+ if (index > MAX_PORT_NUM) {
+ dev_err(pcie->dev, "invalid port number: %d\n", index);
+ continue;
+ }
+ index--;
+
+ if (!of_device_is_available(port))
+ continue;
+
+ rst[4] += index;
+ mtk_pcie_port[index].rstc = devm_reset_control_get(pcie->dev,
+ rst);
+ if (!IS_ERR(mtk_pcie_port[index].rstc))
+ mtk_pcie_port[index].enable = 1;
+ }
+ return 0;
+}
+
+static int mtk_pcie_get_resources(struct mtk_pcie *pcie)
+{
+ struct platform_device *pdev = to_platform_device(pcie->dev);
+ struct mtk_pcie_port *port;
+ struct resource *res;
+
+ pcie->clk = devm_clk_get(&pdev->dev, "pcie");
+ if (IS_ERR(pcie->clk)) {
+ dev_err(&pdev->dev, "Failed to get pcie clk\n");
+ return PTR_ERR(pcie->clk);
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ pcie->pcie_base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(pcie->pcie_base)) {
+ dev_err(&pdev->dev, "Failed to get pcie range\n");
+ return PTR_ERR(pcie->pcie_base);
+ }
+
+ mtk_foreach_port(port) {
+ if (!port->enable)
+ continue;
+ res = platform_get_resource(pdev, IORESOURCE_MEM, port->id + 1);
+ port->phy_base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(port->phy_base)) {
+ dev_err(&pdev->dev, "Failed to get pcie phy%d range\n",
+ port->id);
+ return PTR_ERR(port->phy_base);
+ }
+ port->irq = platform_get_irq(pdev, port->id);
+ }
+
+ return clk_prepare_enable(pcie->clk);
+}
+
+static int mtk_pcie_probe(struct platform_device *pdev)
+{
+ struct mtk_pcie *pcie;
+ struct hw_pci hw;
+ int ret;
+
+ pcie = devm_kzalloc(&pdev->dev, sizeof(*pcie), GFP_KERNEL);
+ if (!pcie)
+ return -ENOMEM;
+
+ pcie->dev = &pdev->dev;
+ ret = mtk_pcie_parse_dt(pcie);
+ if (ret < 0)
+ return ret;
+
+ pm_runtime_enable(&pdev->dev);
+ pm_runtime_get_sync(&pdev->dev);
+
+ ret = mtk_pcie_get_resources(pcie);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "failed to request resources: %d\n", ret);
+ goto err_out;
+ }
+
+ mtk_pcie_preinit(pcie);
+
+ memset(&hw, 0, sizeof(hw));
+ hw.nr_controllers = 1;
+ hw.private_data = (void **)&pcie;
+ hw.setup = mtk_pcie_setup;
+ hw.map_irq = mtk_pcie_map_irq;
+ hw.scan = mtk_pcie_scan_bus;
+
+ pci_common_init_dev(pcie->dev, &hw);
+ platform_set_drvdata(pdev, pcie);
+
+ return 0;
+
+err_out:
+ clk_disable_unprepare(pcie->clk);
+ pm_runtime_put_sync(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+
+ return ret;
+}
+
+static const struct of_device_id mtk_pcie_ids[] = {
+ { .compatible = "mediatek,mt2701-pcie" },
+ { .compatible = "mediatek,mt7623-pcie" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, mtk_pcie_ids);
+
+static struct platform_driver mtk_pcie_driver = {
+ .probe = mtk_pcie_probe,
+ .driver = {
+ .name = "mediatek-pcie",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(mtk_pcie_ids),
+ },
+};
+
+static int __init mtk_pcie_init(void)
+{
+ return platform_driver_register(&mtk_pcie_driver);
+}
+
+module_init(mtk_pcie_init);
--
1.7.10.4
next prev parent reply other threads:[~2016-01-08 15:17 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-01-07 21:06 [PATCH 1/2] dt-bindings: add MedieTak PCIE binding documentation John Crispin
2016-01-07 21:06 ` John Crispin [this message]
2016-01-09 0:18 ` [PATCH 2/2] PCI: mediatek: add support for PCIE found on MT7623/MT2701 Bjorn Helgaas
2016-01-09 11:21 ` John Crispin
2016-01-09 0:20 ` [PATCH 1/2] dt-bindings: add MedieTak PCIE binding documentation Bjorn Helgaas
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1452200773-50794-2-git-send-email-blogic@openwrt.org \
--to=blogic@openwrt.org \
--cc=bhelgaas@google.com \
--cc=linux-mediatek@lists.infradead.org \
--cc=linux-pci@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is 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.