From patchwork Wed Oct 26 01:24:32 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Duc Dang X-Patchwork-Id: 9395789 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 2AA7260235 for ; Wed, 26 Oct 2016 01:35:21 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C537529706 for ; Wed, 26 Oct 2016 01:35:20 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B5AB92976F; Wed, 26 Oct 2016 01:35:20 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.1 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED, T_DKIM_INVALID autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 033F32976A for ; Wed, 26 Oct 2016 01:35:19 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.85_2 #1 (Red Hat Linux)) id 1bzD4E-0006gx-SI; Wed, 26 Oct 2016 01:31:46 +0000 Received: from mail-pf0-x229.google.com ([2607:f8b0:400e:c00::229]) by bombadil.infradead.org with esmtps (Exim 4.85_2 #1 (Red Hat Linux)) id 1bzD47-0006cX-Sf for linux-arm-kernel@lists.infradead.org; Wed, 26 Oct 2016 01:31:41 +0000 Received: by mail-pf0-x229.google.com with SMTP id s8so128977419pfj.2 for ; Tue, 25 Oct 2016 18:31:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=apm.com; s=apm; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=R10Gyijlw8AZoJN9hojfuURXhtKLkKOfC22EjBeG+wY=; b=Z2lpPnQeMLmDb7zEbhWmrHVcILcbHiBbDHrcNngN0xwqgAY944wkXVnVIUCRcbTprg ni48ItfurpeHY1JhG9XHKgrLYU2A7iTGbfGEP9RcEba7K2yBSn9fTX1exuX/CDXWE2sE Wo5Q5ityHeFIJ2Nf7K0DkChJ7tCW2RLPanR5E= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=R10Gyijlw8AZoJN9hojfuURXhtKLkKOfC22EjBeG+wY=; b=Cm18tI8oRbpBBvnUlvMLT2sXHRGIakLkX2iweYY+gN9TDwgNZopWZtImezoxTvQjw/ GcmJq7vcUSOuQI9LI7FusTPGiJIQ0ZzJxiWrLuR38s5vc6GmFu70UpyC3zvzcBJmHhVh IRuCborOqueOnB4jtWPPXqawgg32PG8RrzkhPFJUVVTQ10g8x6HEIWhWSB8l5O/52xsE ZBUyOkRy9Knbg5++TkQ6uMDosf4ghbIel1Z30csyotHTq8ZwJoOqEen4TxYtUACR/hqx gU+85PuFuLN1WdBdw3VSLSzCgdbkq+5EWWWGMtYY7ipdkQQZbb/SBCz2NdVcozoaYOp6 n0aw== X-Gm-Message-State: ABUngvc6BUIc0J+sNYxkz1YacCVkDMj/m4Lj6WfSpLTt0DkAfqG9eVUcAp9budG+asPqShyz X-Received: by 10.98.26.205 with SMTP id a196mr45038877pfa.50.1477445478643; Tue, 25 Oct 2016 18:31:18 -0700 (PDT) Received: from dhdang-workstation-01.amcc.com ([206.80.4.98]) by smtp.gmail.com with ESMTPSA id f67sm36143510pfg.18.2016.10.25.18.31.17 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 25 Oct 2016 18:31:17 -0700 (PDT) From: Duc Dang To: Bjorn Helgaas Subject: [RFC PATCH v2 1/1] PCI/ACPI: xgene: Add ECAM quirk for X-Gene PCIe controller Date: Tue, 25 Oct 2016 18:24:32 -0700 Message-Id: X-Mailer: git-send-email 1.9.1 In-Reply-To: <20160921212258.GE20006@localhost> References: <20160921212258.GE20006@localhost> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20161025_183140_027289_E73983BD X-CRM114-Status: GOOD ( 18.70 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Lorenzo Pieralisi , Jon Masters , Arnd Bergmann , Rafael Wysocki , linux-pci@vger.kernel.org, Duc Dang , patches , Linux Kernel Mailing List , Mark Salter , Tomasz Nowicki , linux-arm MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP PCIe controllers in X-Gene SoCs is not ECAM compliant: software needs to configure additional controller's register to address device at bus:dev:function. This patch depends on "ECAM quirks handling for ARM64 platforms" series (http://www.spinics.net/lists/arm-kernel/msg530692.html, the series was also modified by Bjorn) to address the limitation above for X-Gene PCIe controller. The quirk will only be applied for X-Gene PCIe MCFG table with OEM revison 1, 2, 3 or 4 (PCIe controller v1 and v2 on X-Gene SoCs). Signed-off-by: Duc Dang --- v2 changes: 1. Get rid of pci-xgene-ecam.c file and fold quirk code into pci-xgene.c 2. Redefine fixup array for X-Gene 3. Use devm_ioremap_resource to map csr_base drivers/acpi/pci_mcfg.c | 30 ++++++++ drivers/pci/host/pci-xgene.c | 165 ++++++++++++++++++++++++++++++++++++++++++- include/linux/pci-ecam.h | 5 ++ 3 files changed, 197 insertions(+), 3 deletions(-) diff --git a/drivers/acpi/pci_mcfg.c b/drivers/acpi/pci_mcfg.c index bb2c508..9dfc937 100644 --- a/drivers/acpi/pci_mcfg.c +++ b/drivers/acpi/pci_mcfg.c @@ -96,6 +96,36 @@ struct mcfg_fixup { THUNDER_ECAM_MCFG(2, 12), THUNDER_ECAM_MCFG(2, 13), #endif +#ifdef CONFIG_PCI_XGENE +#define XGENE_V1_ECAM_MCFG(rev, seg) \ + {"APM ", "XGENE ", rev, seg, MCFG_BUS_ANY, \ + &xgene_v1_pcie_ecam_ops } +#define XGENE_V2_1_ECAM_MCFG(rev, seg) \ + {"APM ", "XGENE ", rev, seg, MCFG_BUS_ANY, \ + &xgene_v2_1_pcie_ecam_ops } +#define XGENE_V2_2_ECAM_MCFG(rev, seg) \ + {"APM ", "XGENE ", rev, seg, MCFG_BUS_ANY, \ + &xgene_v2_2_pcie_ecam_ops } + + /* X-Gene SoC with v1 PCIe controller */ + XGENE_V1_ECAM_MCFG(1, 0), + XGENE_V1_ECAM_MCFG(1, 1), + XGENE_V1_ECAM_MCFG(1, 2), + XGENE_V1_ECAM_MCFG(1, 3), + XGENE_V1_ECAM_MCFG(1, 4), + XGENE_V1_ECAM_MCFG(2, 0), + XGENE_V1_ECAM_MCFG(2, 1), + XGENE_V1_ECAM_MCFG(2, 2), + XGENE_V1_ECAM_MCFG(2, 3), + XGENE_V1_ECAM_MCFG(2, 4), + /* X-Gene SoC with v2.1 PCIe controller */ + XGENE_V2_1_ECAM_MCFG(3, 0), + XGENE_V2_1_ECAM_MCFG(3, 1), + /* X-Gene SoC with v2.2 PCIe controller */ + XGENE_V2_2_ECAM_MCFG(4, 0), + XGENE_V2_2_ECAM_MCFG(4, 1), + XGENE_V2_2_ECAM_MCFG(4, 2), +#endif }; static char mcfg_oem_id[ACPI_OEM_ID_SIZE]; diff --git a/drivers/pci/host/pci-xgene.c b/drivers/pci/host/pci-xgene.c index 1de23d7..d6aa642 100644 --- a/drivers/pci/host/pci-xgene.c +++ b/drivers/pci/host/pci-xgene.c @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include #include @@ -64,6 +66,7 @@ /* PCIe IP version */ #define XGENE_PCIE_IP_VER_UNKN 0 #define XGENE_PCIE_IP_VER_1 1 +#define XGENE_PCIE_IP_VER_2 2 struct xgene_pcie_port { struct device_node *node; @@ -97,7 +100,15 @@ static inline u32 pcie_bar_low_val(u32 addr, u32 flags) */ static void __iomem *xgene_pcie_get_cfg_base(struct pci_bus *bus) { - struct xgene_pcie_port *port = bus->sysdata; + struct pci_config_window *cfg; + struct xgene_pcie_port *port; + + if (acpi_disabled) + port = bus->sysdata; + else { + cfg = bus->sysdata; + port = cfg->priv; + } if (bus->number >= (bus->primary + 1)) return port->cfg_base + AXI_EP_CFG_ACCESS; @@ -111,10 +122,18 @@ static void __iomem *xgene_pcie_get_cfg_base(struct pci_bus *bus) */ static void xgene_pcie_set_rtdid_reg(struct pci_bus *bus, uint devfn) { - struct xgene_pcie_port *port = bus->sysdata; + struct pci_config_window *cfg; + struct xgene_pcie_port *port; unsigned int b, d, f; u32 rtdid_val = 0; + if (acpi_disabled) + port = bus->sysdata; + else { + cfg = bus->sysdata; + port = cfg->priv; + } + b = bus->number; d = PCI_SLOT(devfn); f = PCI_FUNC(devfn); @@ -158,7 +177,15 @@ static void __iomem *xgene_pcie_map_bus(struct pci_bus *bus, unsigned int devfn, static int xgene_pcie_config_read32(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *val) { - struct xgene_pcie_port *port = bus->sysdata; + struct pci_config_window *cfg; + struct xgene_pcie_port *port; + + if (acpi_disabled) + port = bus->sysdata; + else { + cfg = bus->sysdata; + port = cfg->priv; + } if (pci_generic_config_read32(bus, devfn, where & ~0x3, 4, val) != PCIBIOS_SUCCESSFUL) @@ -189,6 +216,138 @@ static int xgene_pcie_config_read32(struct pci_bus *bus, unsigned int devfn, .write = pci_generic_config_write32, }; +#ifdef CONFIG_ACPI +static struct resource xgene_v1_csr_res[] = { + [0] = DEFINE_RES_MEM(0x1f2b0000UL, SZ_64K), + [1] = DEFINE_RES_MEM(0x1f2c0000UL, SZ_64K), + [2] = DEFINE_RES_MEM(0x1f2d0000UL, SZ_64K), + [3] = DEFINE_RES_MEM(0x1f500000UL, SZ_64K), + [4] = DEFINE_RES_MEM(0x1f510000UL, SZ_64K), +}; + +static int xgene_v1_pcie_ecam_init(struct pci_config_window *cfg) +{ + struct acpi_device *adev = to_acpi_device(cfg->parent); + struct acpi_pci_root *root = acpi_driver_data(adev); + struct device *dev = cfg->parent; + struct xgene_pcie_port *port; + struct resource *csr; + + port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL); + if (!port) + return -ENOMEM; + + csr = &xgene_v1_csr_res[root->segment]; + port->csr_base = devm_ioremap_resource(dev, csr); + if (IS_ERR(port->csr_base)) { + kfree(port); + return -ENOMEM; + } + + port->cfg_base = cfg->win; + port->version = XGENE_PCIE_IP_VER_1; + + cfg->priv = port; + + return 0; +} + +struct pci_ecam_ops xgene_v1_pcie_ecam_ops = { + .bus_shift = 16, + .init = xgene_v1_pcie_ecam_init, + .pci_ops = { + .map_bus = xgene_pcie_map_bus, + .read = xgene_pcie_config_read32, + .write = pci_generic_config_write, + } +}; + +static struct resource xgene_v2_1_csr_res[] = { + [0] = DEFINE_RES_MEM(0x1f2b0000UL, SZ_64K), + [1] = DEFINE_RES_MEM(0x1f2c0000UL, SZ_64K), +}; + +static int xgene_v2_1_pcie_ecam_init(struct pci_config_window *cfg) +{ + struct acpi_device *adev = to_acpi_device(cfg->parent); + struct acpi_pci_root *root = acpi_driver_data(adev); + struct device *dev = cfg->parent; + struct xgene_pcie_port *port; + struct resource *csr; + + port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL); + if (!port) + return -ENOMEM; + + csr = &xgene_v2_1_csr_res[root->segment]; + port->csr_base = devm_ioremap_resource(dev, csr); + if (IS_ERR(port->csr_base)) { + kfree(port); + return -ENOMEM; + } + + port->cfg_base = cfg->win; + port->version = XGENE_PCIE_IP_VER_2; + + cfg->priv = port; + + return 0; +} + +struct pci_ecam_ops xgene_v2_1_pcie_ecam_ops = { + .bus_shift = 16, + .init = xgene_v2_1_pcie_ecam_init, + .pci_ops = { + .map_bus = xgene_pcie_map_bus, + .read = xgene_pcie_config_read32, + .write = pci_generic_config_write, + } +}; + +static struct resource xgene_v2_2_csr_res[] = { + [0] = DEFINE_RES_MEM(0x1f2b0000UL, SZ_64K), + [1] = DEFINE_RES_MEM(0x1f500000UL, SZ_64K), + [2] = DEFINE_RES_MEM(0x1f2d0000UL, SZ_64K), +}; + +static int xgene_v2_2_pcie_ecam_init(struct pci_config_window *cfg) +{ + struct acpi_device *adev = to_acpi_device(cfg->parent); + struct acpi_pci_root *root = acpi_driver_data(adev); + struct device *dev = cfg->parent; + struct xgene_pcie_port *port; + struct resource *csr; + + port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL); + if (!port) + return -ENOMEM; + + csr = &xgene_v2_2_csr_res[root->segment]; + port->csr_base = devm_ioremap_resource(dev, csr); + if (IS_ERR(port->csr_base)) { + kfree(port); + return -ENOMEM; + } + + port->cfg_base = cfg->win; + port->version = XGENE_PCIE_IP_VER_2; + + cfg->priv = port; + + return 0; +} + +struct pci_ecam_ops xgene_v2_2_pcie_ecam_ops = { + .bus_shift = 16, + .init = xgene_v2_2_pcie_ecam_init, + .pci_ops = { + .map_bus = xgene_pcie_map_bus, + .read = xgene_pcie_config_read32, + .write = pci_generic_config_write, + } +}; +#endif + static u64 xgene_pcie_set_ib_mask(struct xgene_pcie_port *port, u32 addr, u32 flags, u64 size) { diff --git a/include/linux/pci-ecam.h b/include/linux/pci-ecam.h index 35f0e81..40da3e7 100644 --- a/include/linux/pci-ecam.h +++ b/include/linux/pci-ecam.h @@ -65,6 +65,11 @@ void __iomem *pci_ecam_map_bus(struct pci_bus *bus, unsigned int devfn, #ifdef CONFIG_PCI_HOST_THUNDER_ECAM extern struct pci_ecam_ops pci_thunder_ecam_ops; #endif +#ifdef CONFIG_PCI_XGENE +extern struct pci_ecam_ops xgene_v1_pcie_ecam_ops; +extern struct pci_ecam_ops xgene_v2_1_pcie_ecam_ops; +extern struct pci_ecam_ops xgene_v2_2_pcie_ecam_ops; +#endif #ifdef CONFIG_PCI_HOST_GENERIC /* for DT-based PCI controllers that support ECAM */