From patchwork Fri Oct 13 16:09:04 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Niklas Cassel X-Patchwork-Id: 825568 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pci-owner@vger.kernel.org; receiver=) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yDCTh27Nfz9sPr for ; Sat, 14 Oct 2017 03:14:32 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752693AbdJMQOQ (ORCPT ); Fri, 13 Oct 2017 12:14:16 -0400 Received: from bastet.se.axis.com ([195.60.68.11]:52192 "EHLO bastet.se.axis.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751509AbdJMQJ2 (ORCPT ); Fri, 13 Oct 2017 12:09:28 -0400 Received: from localhost (localhost [127.0.0.1]) by bastet.se.axis.com (Postfix) with ESMTP id 365341847D; Fri, 13 Oct 2017 18:09:27 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at bastet.se.axis.com Received: from bastet.se.axis.com ([IPv6:::ffff:127.0.0.1]) by localhost (bastet.se.axis.com [::ffff:127.0.0.1]) (amavisd-new, port 10024) with LMTP id qakdBF81CC09; Fri, 13 Oct 2017 18:09:25 +0200 (CEST) Received: from boulder03.se.axis.com (boulder03.se.axis.com [10.0.8.17]) by bastet.se.axis.com (Postfix) with ESMTPS id 52A8618419; Fri, 13 Oct 2017 18:09:25 +0200 (CEST) Received: from boulder03.se.axis.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 3D5821E076; Fri, 13 Oct 2017 18:09:25 +0200 (CEST) Received: from boulder03.se.axis.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 31B421E070; Fri, 13 Oct 2017 18:09:25 +0200 (CEST) Received: from seth.se.axis.com (unknown [10.0.2.172]) by boulder03.se.axis.com (Postfix) with ESMTP; Fri, 13 Oct 2017 18:09:25 +0200 (CEST) Received: from lnxartpec1.se.axis.com (lnxartpec1.se.axis.com [10.88.4.10]) by seth.se.axis.com (Postfix) with ESMTP id 240C657C; Fri, 13 Oct 2017 18:09:25 +0200 (CEST) Received: by lnxartpec1.se.axis.com (Postfix, from userid 20283) id 209B2401A0; Fri, 13 Oct 2017 18:09:25 +0200 (CEST) From: Niklas Cassel To: Jingoo Han , Joao Pinto , Bjorn Helgaas Cc: Niklas Cassel , linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 01/10] PCI: dwc: use DMA-API for allocating MSI data Date: Fri, 13 Oct 2017 18:09:04 +0200 Message-Id: <20171013160914.3220-2-niklas.cassel@axis.com> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20171013160914.3220-1-niklas.cassel@axis.com> References: <20171013160914.3220-1-niklas.cassel@axis.com> X-TM-AS-GCONF: 00 Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org Since it is a PCIe endpoint device, rather than the CPU, that is supposed to write to this location, the proper way to get the address to this this location is really to use the DMA API, rather than virt_to_phys. Using virt_to_phys might work on some systems, but by using the DMA API, we know that it will work on all systems. This is essentially the same thing as allocating a buffer in a driver, to which the endpoint will write to. To do this, we use the DMA API. Signed-off-by: Niklas Cassel --- drivers/pci/dwc/pcie-designware-host.c | 23 ++++++++++++++++------- drivers/pci/dwc/pcie-designware.h | 3 ++- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/drivers/pci/dwc/pcie-designware-host.c b/drivers/pci/dwc/pcie-designware-host.c index 81e2157a7cfb..f6d152ea2a03 100644 --- a/drivers/pci/dwc/pcie-designware-host.c +++ b/drivers/pci/dwc/pcie-designware-host.c @@ -83,16 +83,25 @@ irqreturn_t dw_handle_msi_irq(struct pcie_port *pp) void dw_pcie_msi_init(struct pcie_port *pp) { + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); + struct device *dev = pci->dev; + struct page *page; u64 msi_target; - pp->msi_data = __get_free_pages(GFP_KERNEL, 0); - msi_target = virt_to_phys((void *)pp->msi_data); + page = alloc_page(GFP_KERNEL | GFP_DMA32); + pp->msi_data = dma_map_page(dev, page, 0, PAGE_SIZE, DMA_FROM_DEVICE); + if (dma_mapping_error(dev, pp->msi_data)) { + dev_err(dev, "failed to map msi data\n"); + __free_page(page); + return; + } + msi_target = (u64)pp->msi_data; /* program the msi_data */ dw_pcie_wr_own_conf(pp, PCIE_MSI_ADDR_LO, 4, - (u32)(msi_target & 0xffffffff)); + lower_32_bits(msi_target)); dw_pcie_wr_own_conf(pp, PCIE_MSI_ADDR_HI, 4, - (u32)(msi_target >> 32 & 0xffffffff)); + upper_32_bits(msi_target)); } static void dw_pcie_msi_clear_irq(struct pcie_port *pp, int irq) @@ -187,10 +196,10 @@ static void dw_msi_setup_msg(struct pcie_port *pp, unsigned int irq, u32 pos) if (pp->ops->get_msi_addr) msi_target = pp->ops->get_msi_addr(pp); else - msi_target = virt_to_phys((void *)pp->msi_data); + msi_target = (u64)pp->msi_data; - msg.address_lo = (u32)(msi_target & 0xffffffff); - msg.address_hi = (u32)(msi_target >> 32 & 0xffffffff); + msg.address_lo = lower_32_bits(msi_target); + msg.address_hi = upper_32_bits(msi_target); if (pp->ops->get_msi_data) msg.data = pp->ops->get_msi_data(pp, pos); diff --git a/drivers/pci/dwc/pcie-designware.h b/drivers/pci/dwc/pcie-designware.h index e5d9d77b778e..547352a317f8 100644 --- a/drivers/pci/dwc/pcie-designware.h +++ b/drivers/pci/dwc/pcie-designware.h @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -168,7 +169,7 @@ struct pcie_port { const struct dw_pcie_host_ops *ops; int msi_irq; struct irq_domain *irq_domain; - unsigned long msi_data; + dma_addr_t msi_data; DECLARE_BITMAP(msi_irq_in_use, MAX_MSI_IRQS); }; From patchwork Fri Oct 13 16:09:05 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Niklas Cassel X-Patchwork-Id: 825555 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pci-owner@vger.kernel.org; receiver=) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yDCMw5nWpz9s2G for ; Sat, 14 Oct 2017 03:09:32 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751906AbdJMQJ3 (ORCPT ); Fri, 13 Oct 2017 12:09:29 -0400 Received: from bastet.se.axis.com ([195.60.68.11]:52187 "EHLO bastet.se.axis.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751544AbdJMQJ1 (ORCPT ); Fri, 13 Oct 2017 12:09:27 -0400 Received: from localhost (localhost [127.0.0.1]) by bastet.se.axis.com (Postfix) with ESMTP id 6883218602; Fri, 13 Oct 2017 18:09:26 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at bastet.se.axis.com Received: from bastet.se.axis.com ([IPv6:::ffff:127.0.0.1]) by localhost (bastet.se.axis.com [::ffff:127.0.0.1]) (amavisd-new, port 10024) with LMTP id sPws39ZkEpy4; Fri, 13 Oct 2017 18:09:25 +0200 (CEST) Received: from boulder02.se.axis.com (boulder02.se.axis.com [10.0.8.16]) by bastet.se.axis.com (Postfix) with ESMTPS id 99A7F1847D; Fri, 13 Oct 2017 18:09:25 +0200 (CEST) Received: from boulder02.se.axis.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 7BACE1A069; Fri, 13 Oct 2017 18:09:25 +0200 (CEST) Received: from boulder02.se.axis.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 707BD1A066; Fri, 13 Oct 2017 18:09:25 +0200 (CEST) Received: from thoth.se.axis.com (unknown [10.0.2.173]) by boulder02.se.axis.com (Postfix) with ESMTP; Fri, 13 Oct 2017 18:09:25 +0200 (CEST) Received: from lnxartpec1.se.axis.com (lnxartpec1.se.axis.com [10.88.4.10]) by thoth.se.axis.com (Postfix) with ESMTP id 64046DFE; Fri, 13 Oct 2017 18:09:25 +0200 (CEST) Received: by lnxartpec1.se.axis.com (Postfix, from userid 20283) id 60419401A0; Fri, 13 Oct 2017 18:09:25 +0200 (CEST) From: Niklas Cassel To: Jingoo Han , Joao Pinto , Bjorn Helgaas Cc: Niklas Cassel , linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 02/10] PCI: designware-ep: set_msi should only set MMC bits Date: Fri, 13 Oct 2017 18:09:05 +0200 Message-Id: <20171013160914.3220-3-niklas.cassel@axis.com> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20171013160914.3220-1-niklas.cassel@axis.com> References: <20171013160914.3220-1-niklas.cassel@axis.com> X-TM-AS-GCONF: 00 Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org Previously, set_msi wrote all bits in the Message Control register, thus overwriting the 64 bit address capable bit. By clearing the 64 bit address capable bit, we break MSI on systems where the RC has set a 64 bit MSI address. Signed-off-by: Niklas Cassel --- drivers/pci/dwc/pcie-designware-ep.c | 4 +++- drivers/pci/dwc/pcie-designware.h | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/pci/dwc/pcie-designware-ep.c b/drivers/pci/dwc/pcie-designware-ep.c index d53d5f168363..c92ab87fd660 100644 --- a/drivers/pci/dwc/pcie-designware-ep.c +++ b/drivers/pci/dwc/pcie-designware-ep.c @@ -220,7 +220,9 @@ static int dw_pcie_ep_set_msi(struct pci_epc *epc, u8 encode_int) struct dw_pcie_ep *ep = epc_get_drvdata(epc); struct dw_pcie *pci = to_dw_pcie_from_ep(ep); - val = (encode_int << MSI_CAP_MMC_SHIFT); + val = dw_pcie_readw_dbi(pci, MSI_MESSAGE_CONTROL); + val &= ~MSI_CAP_MMC_MASK; + val |= (encode_int << MSI_CAP_MMC_SHIFT) & MSI_CAP_MMC_MASK; dw_pcie_writew_dbi(pci, MSI_MESSAGE_CONTROL, val); return 0; diff --git a/drivers/pci/dwc/pcie-designware.h b/drivers/pci/dwc/pcie-designware.h index 547352a317f8..36183906e1d2 100644 --- a/drivers/pci/dwc/pcie-designware.h +++ b/drivers/pci/dwc/pcie-designware.h @@ -101,6 +101,7 @@ #define MSI_MESSAGE_CONTROL 0x52 #define MSI_CAP_MMC_SHIFT 1 +#define MSI_CAP_MMC_MASK (7 << MSI_CAP_MMC_SHIFT) #define MSI_CAP_MME_SHIFT 4 #define MSI_CAP_MME_MASK (7 << MSI_CAP_MME_SHIFT) #define MSI_MESSAGE_ADDR_L32 0x54 From patchwork Fri Oct 13 16:09:06 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Niklas Cassel X-Patchwork-Id: 825565 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pci-owner@vger.kernel.org; receiver=) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yDCR52dQMz9s2G for ; Sat, 14 Oct 2017 03:12:17 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751341AbdJMQMO (ORCPT ); Fri, 13 Oct 2017 12:12:14 -0400 Received: from bastet.se.axis.com ([195.60.68.11]:52213 "EHLO bastet.se.axis.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751918AbdJMQJa (ORCPT ); Fri, 13 Oct 2017 12:09:30 -0400 Received: from localhost (localhost [127.0.0.1]) by bastet.se.axis.com (Postfix) with ESMTP id 0BBE318600; Fri, 13 Oct 2017 18:09:29 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at bastet.se.axis.com Received: from bastet.se.axis.com ([IPv6:::ffff:127.0.0.1]) by localhost (bastet.se.axis.com [::ffff:127.0.0.1]) (amavisd-new, port 10024) with LMTP id 9lbQf_rJr7C1; Fri, 13 Oct 2017 18:09:25 +0200 (CEST) Received: from boulder03.se.axis.com (boulder03.se.axis.com [10.0.8.17]) by bastet.se.axis.com (Postfix) with ESMTPS id BE810185FF; Fri, 13 Oct 2017 18:09:25 +0200 (CEST) Received: from boulder03.se.axis.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id AA7BC1E078; Fri, 13 Oct 2017 18:09:25 +0200 (CEST) Received: from boulder03.se.axis.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 9F2971E070; Fri, 13 Oct 2017 18:09:25 +0200 (CEST) Received: from seth.se.axis.com (unknown [10.0.2.172]) by boulder03.se.axis.com (Postfix) with ESMTP; Fri, 13 Oct 2017 18:09:25 +0200 (CEST) Received: from lnxartpec1.se.axis.com (lnxartpec1.se.axis.com [10.88.4.10]) by seth.se.axis.com (Postfix) with ESMTP id 924C057C; Fri, 13 Oct 2017 18:09:25 +0200 (CEST) Received: by lnxartpec1.se.axis.com (Postfix, from userid 20283) id 8DDD2401A0; Fri, 13 Oct 2017 18:09:25 +0200 (CEST) From: Niklas Cassel To: Jingoo Han , Joao Pinto , Bjorn Helgaas Cc: Niklas Cassel , linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 03/10] PCI: designware-ep: read-only registers need DBI_RO_WR_EN to be writable Date: Fri, 13 Oct 2017 18:09:06 +0200 Message-Id: <20171013160914.3220-4-niklas.cassel@axis.com> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20171013160914.3220-1-niklas.cassel@axis.com> References: <20171013160914.3220-1-niklas.cassel@axis.com> X-TM-AS-GCONF: 00 Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org Certain registers that pcie-designware-ep tries to write are read-only registers. However, these registers can become read/write if we first enable the DBI_RO_WR_EN bit. Signed-off-by: Niklas Cassel --- drivers/pci/dwc/pcie-designware-ep.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/pci/dwc/pcie-designware-ep.c b/drivers/pci/dwc/pcie-designware-ep.c index c92ab87fd660..3fb34be99715 100644 --- a/drivers/pci/dwc/pcie-designware-ep.c +++ b/drivers/pci/dwc/pcie-designware-ep.c @@ -35,8 +35,10 @@ static void dw_pcie_ep_reset_bar(struct dw_pcie *pci, enum pci_barno bar) u32 reg; reg = PCI_BASE_ADDRESS_0 + (4 * bar); + dw_pcie_dbi_ro_wr_en(pci); dw_pcie_writel_dbi2(pci, reg, 0x0); dw_pcie_writel_dbi(pci, reg, 0x0); + dw_pcie_dbi_ro_wr_dis(pci); } static int dw_pcie_ep_write_header(struct pci_epc *epc, @@ -45,6 +47,7 @@ static int dw_pcie_ep_write_header(struct pci_epc *epc, struct dw_pcie_ep *ep = epc_get_drvdata(epc); struct dw_pcie *pci = to_dw_pcie_from_ep(ep); + dw_pcie_dbi_ro_wr_en(pci); dw_pcie_writew_dbi(pci, PCI_VENDOR_ID, hdr->vendorid); dw_pcie_writew_dbi(pci, PCI_DEVICE_ID, hdr->deviceid); dw_pcie_writeb_dbi(pci, PCI_REVISION_ID, hdr->revid); @@ -58,6 +61,7 @@ static int dw_pcie_ep_write_header(struct pci_epc *epc, dw_pcie_writew_dbi(pci, PCI_SUBSYSTEM_ID, hdr->subsys_id); dw_pcie_writeb_dbi(pci, PCI_INTERRUPT_PIN, hdr->interrupt_pin); + dw_pcie_dbi_ro_wr_dis(pci); return 0; } @@ -142,8 +146,10 @@ static int dw_pcie_ep_set_bar(struct pci_epc *epc, enum pci_barno bar, if (ret) return ret; + dw_pcie_dbi_ro_wr_en(pci); dw_pcie_writel_dbi2(pci, reg, size - 1); dw_pcie_writel_dbi(pci, reg, flags); + dw_pcie_dbi_ro_wr_dis(pci); return 0; } @@ -223,7 +229,9 @@ static int dw_pcie_ep_set_msi(struct pci_epc *epc, u8 encode_int) val = dw_pcie_readw_dbi(pci, MSI_MESSAGE_CONTROL); val &= ~MSI_CAP_MMC_MASK; val |= (encode_int << MSI_CAP_MMC_SHIFT) & MSI_CAP_MMC_MASK; + dw_pcie_dbi_ro_wr_en(pci); dw_pcie_writew_dbi(pci, MSI_MESSAGE_CONTROL, val); + dw_pcie_dbi_ro_wr_dis(pci); return 0; } From patchwork Fri Oct 13 16:09:07 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Niklas Cassel X-Patchwork-Id: 825564 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pci-owner@vger.kernel.org; receiver=) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yDCR44ZTZz9sPr for ; Sat, 14 Oct 2017 03:12:16 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751921AbdJMQJa (ORCPT ); Fri, 13 Oct 2017 12:09:30 -0400 Received: from bastet.se.axis.com ([195.60.68.11]:52201 "EHLO bastet.se.axis.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751656AbdJMQJ3 (ORCPT ); Fri, 13 Oct 2017 12:09:29 -0400 Received: from localhost (localhost [127.0.0.1]) by bastet.se.axis.com (Postfix) with ESMTP id 2838418604; Fri, 13 Oct 2017 18:09:28 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at bastet.se.axis.com Received: from bastet.se.axis.com ([IPv6:::ffff:127.0.0.1]) by localhost (bastet.se.axis.com [::ffff:127.0.0.1]) (amavisd-new, port 10024) with LMTP id nRF0YUikmRUW; Fri, 13 Oct 2017 18:09:26 +0200 (CEST) Received: from boulder02.se.axis.com (boulder02.se.axis.com [10.0.8.16]) by bastet.se.axis.com (Postfix) with ESMTPS id 0282C182E7; Fri, 13 Oct 2017 18:09:26 +0200 (CEST) Received: from boulder02.se.axis.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id E5DFD1A069; Fri, 13 Oct 2017 18:09:25 +0200 (CEST) Received: from boulder02.se.axis.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id DAA9A1A066; Fri, 13 Oct 2017 18:09:25 +0200 (CEST) Received: from thoth.se.axis.com (unknown [10.0.2.173]) by boulder02.se.axis.com (Postfix) with ESMTP; Fri, 13 Oct 2017 18:09:25 +0200 (CEST) Received: from lnxartpec1.se.axis.com (lnxartpec1.se.axis.com [10.88.4.10]) by thoth.se.axis.com (Postfix) with ESMTP id CEA4FDFE; Fri, 13 Oct 2017 18:09:25 +0200 (CEST) Received: by lnxartpec1.se.axis.com (Postfix, from userid 20283) id CAAEC401A0; Fri, 13 Oct 2017 18:09:25 +0200 (CEST) From: Niklas Cassel To: Jingoo Han , Joao Pinto , Bjorn Helgaas Cc: Niklas Cassel , linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 04/10] PCI: designware-ep: pre-allocate memory for MSI in dw_pcie_ep_init Date: Fri, 13 Oct 2017 18:09:07 +0200 Message-Id: <20171013160914.3220-5-niklas.cassel@axis.com> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20171013160914.3220-1-niklas.cassel@axis.com> References: <20171013160914.3220-1-niklas.cassel@axis.com> X-TM-AS-GCONF: 00 Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org Certain SoCs need to map the MSI address in raise_irq. To map an address, you first need to call pci_epc_mem_alloc_addr, however, pci_epc_mem_alloc_addr calls ioremap (which can sleep). Since raise_irq is only called from atomic context, we can't call pci_epc_mem_alloc_addr from raise_irq, instead we pre-allocate a page in dw_pcie_ep_init, so this page can later be used to map/unmap the MSI address in raise_irq. Signed-off-by: Niklas Cassel --- drivers/pci/dwc/pcie-designware-ep.c | 8 ++++++++ drivers/pci/dwc/pcie-designware.h | 2 ++ 2 files changed, 10 insertions(+) diff --git a/drivers/pci/dwc/pcie-designware-ep.c b/drivers/pci/dwc/pcie-designware-ep.c index 3fb34be99715..c291da2a10ba 100644 --- a/drivers/pci/dwc/pcie-designware-ep.c +++ b/drivers/pci/dwc/pcie-designware-ep.c @@ -286,6 +286,8 @@ void dw_pcie_ep_exit(struct dw_pcie_ep *ep) { struct pci_epc *epc = ep->epc; + pci_epc_mem_free_addr(epc, ep->msi_mem_phys, ep->msi_mem, PAGE_SIZE); + pci_epc_mem_exit(epc); } @@ -341,6 +343,12 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep) return ret; } + ep->msi_mem = pci_epc_mem_alloc_addr(epc, &ep->msi_mem_phys, PAGE_SIZE); + if (!ep->msi_mem) { + dev_err(dev, "Failed to reserve memory for MSI\n"); + return -ENOMEM; + } + ep->epc = epc; epc_set_drvdata(epc, ep); dw_pcie_setup(pci); diff --git a/drivers/pci/dwc/pcie-designware.h b/drivers/pci/dwc/pcie-designware.h index 36183906e1d2..f56d040afde4 100644 --- a/drivers/pci/dwc/pcie-designware.h +++ b/drivers/pci/dwc/pcie-designware.h @@ -198,6 +198,8 @@ struct dw_pcie_ep { unsigned long ob_window_map; u32 num_ib_windows; u32 num_ob_windows; + void __iomem *msi_mem; + phys_addr_t msi_mem_phys; }; struct dw_pcie_ops { From patchwork Fri Oct 13 16:09:08 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Niklas Cassel X-Patchwork-Id: 825563 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pci-owner@vger.kernel.org; receiver=) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yDCQl2Dmfz9sPr for ; Sat, 14 Oct 2017 03:11:59 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751656AbdJMQJl (ORCPT ); Fri, 13 Oct 2017 12:09:41 -0400 Received: from bastet.se.axis.com ([195.60.68.11]:52235 "EHLO bastet.se.axis.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751455AbdJMQJi (ORCPT ); Fri, 13 Oct 2017 12:09:38 -0400 Received: from localhost (localhost [127.0.0.1]) by bastet.se.axis.com (Postfix) with ESMTP id 6A51D1860D; Fri, 13 Oct 2017 18:09:37 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at bastet.se.axis.com Received: from bastet.se.axis.com ([IPv6:::ffff:127.0.0.1]) by localhost (bastet.se.axis.com [::ffff:127.0.0.1]) (amavisd-new, port 10024) with LMTP id XB9IZ9yFj2W7; Fri, 13 Oct 2017 18:09:36 +0200 (CEST) Received: from boulder02.se.axis.com (boulder02.se.axis.com [10.0.8.16]) by bastet.se.axis.com (Postfix) with ESMTPS id 62CEC18609; Fri, 13 Oct 2017 18:09:36 +0200 (CEST) Received: from boulder02.se.axis.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 24AFD1A069; Fri, 13 Oct 2017 18:09:36 +0200 (CEST) Received: from boulder02.se.axis.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 19F6E1A066; Fri, 13 Oct 2017 18:09:36 +0200 (CEST) Received: from thoth.se.axis.com (unknown [10.0.2.173]) by boulder02.se.axis.com (Postfix) with ESMTP; Fri, 13 Oct 2017 18:09:36 +0200 (CEST) Received: from lnxartpec1.se.axis.com (lnxartpec1.se.axis.com [10.88.4.10]) by thoth.se.axis.com (Postfix) with ESMTP id 0E615DFE; Fri, 13 Oct 2017 18:09:36 +0200 (CEST) Received: by lnxartpec1.se.axis.com (Postfix, from userid 20283) id 09B23401A0; Fri, 13 Oct 2017 18:09:36 +0200 (CEST) From: Niklas Cassel To: Niklas Cassel , Jesper Nilsson , Bjorn Helgaas Cc: linux-arm-kernel@axis.com, linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 05/10] PCI: artpec6: remove unused defines Date: Fri, 13 Oct 2017 18:09:08 +0200 Message-Id: <20171013160914.3220-6-niklas.cassel@axis.com> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20171013160914.3220-1-niklas.cassel@axis.com> References: <20171013160914.3220-1-niklas.cassel@axis.com> X-TM-AS-GCONF: 00 Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org Commit b015b37e6693 ("PCI: artpec6: Stop enabling writes to DBI read-only registers") removed the only write using these defines, but it did not remove the defines. Remove the defines since they are now unused. Signed-off-by: Niklas Cassel --- drivers/pci/dwc/pcie-artpec6.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/pci/dwc/pcie-artpec6.c b/drivers/pci/dwc/pcie-artpec6.c index 6653619db6a1..4b8ef266dc2f 100644 --- a/drivers/pci/dwc/pcie-artpec6.c +++ b/drivers/pci/dwc/pcie-artpec6.c @@ -37,9 +37,6 @@ struct artpec6_pcie { #define PCIE_PHY_DEBUG_R0 (PL_OFFSET + 0x28) #define PCIE_PHY_DEBUG_R1 (PL_OFFSET + 0x2c) -#define MISC_CONTROL_1_OFF (PL_OFFSET + 0x1bc) -#define DBI_RO_WR_EN 1 - /* ARTPEC-6 specific registers */ #define PCIECFG 0x18 #define PCIECFG_DBG_OEN (1 << 24) From patchwork Fri Oct 13 16:09:09 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Niklas Cassel X-Patchwork-Id: 825561 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pci-owner@vger.kernel.org; receiver=) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yDCQ74q78z9sxR for ; Sat, 14 Oct 2017 03:11:27 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752701AbdJMQLA (ORCPT ); Fri, 13 Oct 2017 12:11:00 -0400 Received: from bastet.se.axis.com ([195.60.68.11]:52245 "EHLO bastet.se.axis.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752158AbdJMQJm (ORCPT ); Fri, 13 Oct 2017 12:09:42 -0400 Received: from localhost (localhost [127.0.0.1]) by bastet.se.axis.com (Postfix) with ESMTP id BE0BB18600; Fri, 13 Oct 2017 18:09:40 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at bastet.se.axis.com Received: from bastet.se.axis.com ([IPv6:::ffff:127.0.0.1]) by localhost (bastet.se.axis.com [::ffff:127.0.0.1]) (amavisd-new, port 10024) with LMTP id AZvZExEemd18; Fri, 13 Oct 2017 18:09:36 +0200 (CEST) Received: from boulder02.se.axis.com (boulder02.se.axis.com [10.0.8.16]) by bastet.se.axis.com (Postfix) with ESMTPS id 97FB718602; Fri, 13 Oct 2017 18:09:36 +0200 (CEST) Received: from boulder02.se.axis.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 52A181A07C; Fri, 13 Oct 2017 18:09:36 +0200 (CEST) Received: from boulder02.se.axis.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 47DD31A066; Fri, 13 Oct 2017 18:09:36 +0200 (CEST) Received: from seth.se.axis.com (unknown [10.0.2.172]) by boulder02.se.axis.com (Postfix) with ESMTP; Fri, 13 Oct 2017 18:09:36 +0200 (CEST) Received: from lnxartpec1.se.axis.com (lnxartpec1.se.axis.com [10.88.4.10]) by seth.se.axis.com (Postfix) with ESMTP id 3B22657C; Fri, 13 Oct 2017 18:09:36 +0200 (CEST) Received: by lnxartpec1.se.axis.com (Postfix, from userid 20283) id 37996401A0; Fri, 13 Oct 2017 18:09:36 +0200 (CEST) From: Niklas Cassel To: Niklas Cassel , Jesper Nilsson , Bjorn Helgaas Cc: linux-arm-kernel@axis.com, linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 06/10] PCI: dwc: artpec6: use BIT and GENMASK macros Date: Fri, 13 Oct 2017 18:09:09 +0200 Message-Id: <20171013160914.3220-7-niklas.cassel@axis.com> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20171013160914.3220-1-niklas.cassel@axis.com> References: <20171013160914.3220-1-niklas.cassel@axis.com> X-TM-AS-GCONF: 00 Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org This greatly improves readability. Signed-off-by: Niklas Cassel --- drivers/pci/dwc/pcie-artpec6.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/pci/dwc/pcie-artpec6.c b/drivers/pci/dwc/pcie-artpec6.c index 4b8ef266dc2f..18075e0fab80 100644 --- a/drivers/pci/dwc/pcie-artpec6.c +++ b/drivers/pci/dwc/pcie-artpec6.c @@ -39,28 +39,28 @@ struct artpec6_pcie { /* ARTPEC-6 specific registers */ #define PCIECFG 0x18 -#define PCIECFG_DBG_OEN (1 << 24) -#define PCIECFG_CORE_RESET_REQ (1 << 21) -#define PCIECFG_LTSSM_ENABLE (1 << 20) -#define PCIECFG_CLKREQ_B (1 << 11) -#define PCIECFG_REFCLK_ENABLE (1 << 10) -#define PCIECFG_PLL_ENABLE (1 << 9) -#define PCIECFG_PCLK_ENABLE (1 << 8) -#define PCIECFG_RISRCREN (1 << 4) -#define PCIECFG_MODE_TX_DRV_EN (1 << 3) -#define PCIECFG_CISRREN (1 << 2) -#define PCIECFG_MACRO_ENABLE (1 << 0) +#define PCIECFG_DBG_OEN BIT(24) +#define PCIECFG_CORE_RESET_REQ BIT(21) +#define PCIECFG_LTSSM_ENABLE BIT(20) +#define PCIECFG_CLKREQ_B BIT(11) +#define PCIECFG_REFCLK_ENABLE BIT(10) +#define PCIECFG_PLL_ENABLE BIT(9) +#define PCIECFG_PCLK_ENABLE BIT(8) +#define PCIECFG_RISRCREN BIT(4) +#define PCIECFG_MODE_TX_DRV_EN BIT(3) +#define PCIECFG_CISRREN BIT(2) +#define PCIECFG_MACRO_ENABLE BIT(0) #define NOCCFG 0x40 -#define NOCCFG_ENABLE_CLK_PCIE (1 << 4) -#define NOCCFG_POWER_PCIE_IDLEACK (1 << 3) -#define NOCCFG_POWER_PCIE_IDLE (1 << 2) -#define NOCCFG_POWER_PCIE_IDLEREQ (1 << 1) +#define NOCCFG_ENABLE_CLK_PCIE BIT(4) +#define NOCCFG_POWER_PCIE_IDLEACK BIT(3) +#define NOCCFG_POWER_PCIE_IDLE BIT(2) +#define NOCCFG_POWER_PCIE_IDLEREQ BIT(1) #define PHY_STATUS 0x118 -#define PHY_COSPLLLOCK (1 << 0) +#define PHY_COSPLLLOCK BIT(0) -#define ARTPEC6_CPU_TO_BUS_ADDR 0x0fffffff +#define ARTPEC6_CPU_TO_BUS_ADDR GENMASK(27, 0) static u32 artpec6_pcie_readl(struct artpec6_pcie *artpec6_pcie, u32 offset) { From patchwork Fri Oct 13 16:09:10 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Niklas Cassel X-Patchwork-Id: 825562 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pci-owner@vger.kernel.org; receiver=) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yDCQG5g6lz9s2G for ; Sat, 14 Oct 2017 03:11:34 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752241AbdJMQJm (ORCPT ); Fri, 13 Oct 2017 12:09:42 -0400 Received: from bastet.se.axis.com ([195.60.68.11]:52237 "EHLO bastet.se.axis.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751503AbdJMQJj (ORCPT ); Fri, 13 Oct 2017 12:09:39 -0400 Received: from localhost (localhost [127.0.0.1]) by bastet.se.axis.com (Postfix) with ESMTP id 2F0A7182E7; Fri, 13 Oct 2017 18:09:38 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at bastet.se.axis.com Received: from bastet.se.axis.com ([IPv6:::ffff:127.0.0.1]) by localhost (bastet.se.axis.com [::ffff:127.0.0.1]) (amavisd-new, port 10024) with LMTP id uSzKZ9FKnEJe; Fri, 13 Oct 2017 18:09:37 +0200 (CEST) Received: from boulder02.se.axis.com (boulder02.se.axis.com [10.0.8.16]) by bastet.se.axis.com (Postfix) with ESMTPS id A8AA61860A; Fri, 13 Oct 2017 18:09:36 +0200 (CEST) Received: from boulder02.se.axis.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 82AE61A080; Fri, 13 Oct 2017 18:09:36 +0200 (CEST) Received: from boulder02.se.axis.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 77F6E1A066; Fri, 13 Oct 2017 18:09:36 +0200 (CEST) Received: from thoth.se.axis.com (unknown [10.0.2.173]) by boulder02.se.axis.com (Postfix) with ESMTP; Fri, 13 Oct 2017 18:09:36 +0200 (CEST) Received: from lnxartpec1.se.axis.com (lnxartpec1.se.axis.com [10.88.4.10]) by thoth.se.axis.com (Postfix) with ESMTP id 6BDE8DFE; Fri, 13 Oct 2017 18:09:36 +0200 (CEST) Received: by lnxartpec1.se.axis.com (Postfix, from userid 20283) id 672D7401A0; Fri, 13 Oct 2017 18:09:36 +0200 (CEST) From: Niklas Cassel To: Niklas Cassel , Jesper Nilsson , Bjorn Helgaas Cc: linux-arm-kernel@axis.com, linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 07/10] PCI: dwc: artpec6: split artpec6_pcie_establish_link to smaller functions Date: Fri, 13 Oct 2017 18:09:10 +0200 Message-Id: <20171013160914.3220-8-niklas.cassel@axis.com> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20171013160914.3220-1-niklas.cassel@axis.com> References: <20171013160914.3220-1-niklas.cassel@axis.com> X-TM-AS-GCONF: 00 Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org This is done to better match other drivers such as dra7xx and imx6, but also to prepare for endpoint mode support. Signed-off-by: Niklas Cassel --- drivers/pci/dwc/pcie-artpec6.c | 59 +++++++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 27 deletions(-) diff --git a/drivers/pci/dwc/pcie-artpec6.c b/drivers/pci/dwc/pcie-artpec6.c index 18075e0fab80..c5d7f98dc6b2 100644 --- a/drivers/pci/dwc/pcie-artpec6.c +++ b/drivers/pci/dwc/pcie-artpec6.c @@ -80,18 +80,11 @@ static u64 artpec6_pcie_cpu_addr_fixup(u64 pci_addr) return pci_addr & ARTPEC6_CPU_TO_BUS_ADDR; } -static int artpec6_pcie_establish_link(struct artpec6_pcie *artpec6_pcie) +static void artpec6_pcie_init_phy(struct artpec6_pcie *artpec6_pcie) { - struct dw_pcie *pci = artpec6_pcie->pci; - struct pcie_port *pp = &pci->pp; u32 val; unsigned int retries; - /* Hold DW core in reset */ - val = artpec6_pcie_readl(artpec6_pcie, PCIECFG); - val |= PCIECFG_CORE_RESET_REQ; - artpec6_pcie_writel(artpec6_pcie, PCIECFG, val); - val = artpec6_pcie_readl(artpec6_pcie, PCIECFG); val |= PCIECFG_RISRCREN | /* Receiver term. 50 Ohm */ PCIECFG_MODE_TX_DRV_EN | @@ -131,30 +124,18 @@ static int artpec6_pcie_establish_link(struct artpec6_pcie *artpec6_pcie) val = readl(artpec6_pcie->phy_base + PHY_STATUS); retries--; } while (retries && !(val & PHY_COSPLLLOCK)); +} - /* Take DW core out of reset */ - val = artpec6_pcie_readl(artpec6_pcie, PCIECFG); - val &= ~PCIECFG_CORE_RESET_REQ; - artpec6_pcie_writel(artpec6_pcie, PCIECFG, val); - usleep_range(100, 200); - - /* setup root complex */ - dw_pcie_setup_rc(pp); +static int artpec6_pcie_establish_link(struct dw_pcie *pci) +{ + struct artpec6_pcie *artpec6_pcie = to_artpec6_pcie(pci); + u32 val; - /* assert LTSSM enable */ val = artpec6_pcie_readl(artpec6_pcie, PCIECFG); val |= PCIECFG_LTSSM_ENABLE; artpec6_pcie_writel(artpec6_pcie, PCIECFG, val); - /* check if the link is up or not */ - if (!dw_pcie_wait_for_link(pci)) - return 0; - - dev_dbg(pci->dev, "DEBUG_R0: 0x%08x, DEBUG_R1: 0x%08x\n", - dw_pcie_readl_dbi(pci, PCIE_PHY_DEBUG_R0), - dw_pcie_readl_dbi(pci, PCIE_PHY_DEBUG_R1)); - - return -ETIMEDOUT; + return 0; } static void artpec6_pcie_enable_interrupts(struct artpec6_pcie *artpec6_pcie) @@ -166,12 +147,36 @@ static void artpec6_pcie_enable_interrupts(struct artpec6_pcie *artpec6_pcie) dw_pcie_msi_init(pp); } +static void artpec6_pcie_assert_core_reset(struct artpec6_pcie *artpec6_pcie) +{ + u32 val; + + val = artpec6_pcie_readl(artpec6_pcie, PCIECFG); + val |= PCIECFG_CORE_RESET_REQ; + artpec6_pcie_writel(artpec6_pcie, PCIECFG, val); +} + +static void artpec6_pcie_deassert_core_reset(struct artpec6_pcie *artpec6_pcie) +{ + u32 val; + + val = artpec6_pcie_readl(artpec6_pcie, PCIECFG); + val &= ~PCIECFG_CORE_RESET_REQ; + artpec6_pcie_writel(artpec6_pcie, PCIECFG, val); + usleep_range(100, 200); +} + static int artpec6_pcie_host_init(struct pcie_port *pp) { struct dw_pcie *pci = to_dw_pcie_from_pp(pp); struct artpec6_pcie *artpec6_pcie = to_artpec6_pcie(pci); - artpec6_pcie_establish_link(artpec6_pcie); + artpec6_pcie_assert_core_reset(artpec6_pcie); + artpec6_pcie_init_phy(artpec6_pcie); + artpec6_pcie_deassert_core_reset(artpec6_pcie); + dw_pcie_setup_rc(pp); + artpec6_pcie_establish_link(pci); + dw_pcie_wait_for_link(pci); artpec6_pcie_enable_interrupts(artpec6_pcie); return 0; From patchwork Fri Oct 13 16:09:11 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Niklas Cassel X-Patchwork-Id: 825558 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pci-owner@vger.kernel.org; receiver=) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yDCNn1rHxz9sPr for ; Sat, 14 Oct 2017 03:10:17 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752465AbdJMQJs (ORCPT ); Fri, 13 Oct 2017 12:09:48 -0400 Received: from bastet.se.axis.com ([195.60.68.11]:52268 "EHLO bastet.se.axis.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752392AbdJMQJq (ORCPT ); Fri, 13 Oct 2017 12:09:46 -0400 Received: from localhost (localhost [127.0.0.1]) by bastet.se.axis.com (Postfix) with ESMTP id C9A3718604; Fri, 13 Oct 2017 18:09:44 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at bastet.se.axis.com Received: from bastet.se.axis.com ([IPv6:::ffff:127.0.0.1]) by localhost (bastet.se.axis.com [::ffff:127.0.0.1]) (amavisd-new, port 10024) with LMTP id NFvj3ZyEn-PY; Fri, 13 Oct 2017 18:09:42 +0200 (CEST) Received: from boulder03.se.axis.com (boulder03.se.axis.com [10.0.8.17]) by bastet.se.axis.com (Postfix) with ESMTPS id A77B118419; Fri, 13 Oct 2017 18:09:41 +0200 (CEST) Received: from boulder03.se.axis.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 851831E070; Fri, 13 Oct 2017 18:09:41 +0200 (CEST) Received: from boulder03.se.axis.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 773AE1E078; Fri, 13 Oct 2017 18:09:41 +0200 (CEST) Received: from seth.se.axis.com (unknown [10.0.2.172]) by boulder03.se.axis.com (Postfix) with ESMTP; Fri, 13 Oct 2017 18:09:41 +0200 (CEST) Received: from lnxartpec1.se.axis.com (lnxartpec1.se.axis.com [10.88.4.10]) by seth.se.axis.com (Postfix) with ESMTP id 69A1C57C; Fri, 13 Oct 2017 18:09:41 +0200 (CEST) Received: by lnxartpec1.se.axis.com (Postfix, from userid 20283) id 6449F401A0; Fri, 13 Oct 2017 18:09:41 +0200 (CEST) From: Niklas Cassel To: Niklas Cassel , Jesper Nilsson , Bjorn Helgaas , Rob Herring , Mark Rutland , Kishon Vijay Abraham I , Jingoo Han , Xiaowei Song , Peter Robinson , Tomasz Nowicki , Gabriele Paoloni , Duc Dang Cc: linux-arm-kernel@axis.com, linux-pci@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 08/10] PCI: dwc: artpec6: add support for endpoint mode Date: Fri, 13 Oct 2017 18:09:11 +0200 Message-Id: <20171013160914.3220-9-niklas.cassel@axis.com> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20171013160914.3220-1-niklas.cassel@axis.com> References: <20171013160914.3220-1-niklas.cassel@axis.com> X-TM-AS-GCONF: 00 Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org Signed-off-by: Niklas Cassel Acked-by: Rob Herring --- .../devicetree/bindings/pci/axis,artpec6-pcie.txt | 3 +- drivers/pci/dwc/Kconfig | 41 +++-- drivers/pci/dwc/Makefile | 4 +- drivers/pci/dwc/pcie-artpec6.c | 202 ++++++++++++++++++++- 4 files changed, 233 insertions(+), 17 deletions(-) diff --git a/Documentation/devicetree/bindings/pci/axis,artpec6-pcie.txt b/Documentation/devicetree/bindings/pci/axis,artpec6-pcie.txt index 4e4aee4439ea..33eef7ae5a23 100644 --- a/Documentation/devicetree/bindings/pci/axis,artpec6-pcie.txt +++ b/Documentation/devicetree/bindings/pci/axis,artpec6-pcie.txt @@ -4,7 +4,8 @@ This PCIe host controller is based on the Synopsys DesignWare PCIe IP and thus inherits all the common properties defined in designware-pcie.txt. Required properties: -- compatible: "axis,artpec6-pcie", "snps,dw-pcie" +- compatible: "axis,artpec6-pcie", "snps,dw-pcie" for ARTPEC-6 in RC mode; + "axis,artpec6-pcie-ep", "snps,dw-pcie" for ARTPEC-6 in EP mode; - reg: base addresses and lengths of the PCIe controller (DBI), the PHY controller, and configuration address space. - reg-names: Must include the following entries: diff --git a/drivers/pci/dwc/Kconfig b/drivers/pci/dwc/Kconfig index 22ec82fcdea2..e333283fb1ed 100644 --- a/drivers/pci/dwc/Kconfig +++ b/drivers/pci/dwc/Kconfig @@ -14,6 +14,36 @@ config PCIE_DW_EP depends on PCI_ENDPOINT select PCIE_DW +config PCIE_ARTPEC6 + bool "Axis ARTPEC-6 PCIe controller" + depends on (PCI && PCI_MSI_IRQ_DOMAIN) || PCI_ENDPOINT + depends on MACH_ARTPEC6 + help + Say Y here to enable PCIe controller support on Axis ARTPEC-6 + SoCs. This PCIe controller uses the DesignWare core. + +if PCIE_ARTPEC6 + +config PCIE_ARTPEC6_HOST + bool "Axis ARTPEC-6 Host Mode" + depends on PCI + depends on PCI_MSI_IRQ_DOMAIN + select PCIEPORTBUS + select PCIE_DW_HOST + help + Enables support for the PCIe controller in the ARTPEC-6 SoC to work in + host mode. + +config PCIE_ARTPEC6_EP + bool "Axis ARTPEC-6 Endpoint Mode" + depends on PCI_ENDPOINT + select PCIE_DW_EP + help + Enables support for the PCIe controller in the ARTPEC-6 SoC to work in + endpoint mode. + +endif + config PCI_DRA7XX bool "TI DRA7xx PCIe controller" depends on SOC_DRA7XX || COMPILE_TEST @@ -148,17 +178,6 @@ config PCIE_ARMADA_8K DesignWare hardware and therefore the driver re-uses the DesignWare core functions to implement the driver. -config PCIE_ARTPEC6 - bool "Axis ARTPEC-6 PCIe controller" - depends on PCI - depends on MACH_ARTPEC6 - depends on PCI_MSI_IRQ_DOMAIN - select PCIEPORTBUS - select PCIE_DW_HOST - help - Say Y here to enable PCIe controller support on Axis ARTPEC-6 - SoCs. This PCIe controller uses the DesignWare core. - config PCIE_KIRIN depends on OF && ARM64 bool "HiSilicon Kirin series SoCs PCIe controllers" diff --git a/drivers/pci/dwc/Makefile b/drivers/pci/dwc/Makefile index c61be9738cce..ac98242b83a9 100644 --- a/drivers/pci/dwc/Makefile +++ b/drivers/pci/dwc/Makefile @@ -2,6 +2,9 @@ obj-$(CONFIG_PCIE_DW) += pcie-designware.o obj-$(CONFIG_PCIE_DW_HOST) += pcie-designware-host.o obj-$(CONFIG_PCIE_DW_EP) += pcie-designware-ep.o obj-$(CONFIG_PCIE_DW_PLAT) += pcie-designware-plat.o +ifneq ($(filter y,$(CONFIG_PCIE_ARTPEC6_HOST) $(CONFIG_PCIE_ARTPEC6_EP)),) + obj-$(CONFIG_PCIE_ARTPEC6) += pcie-artpec6.o +endif ifneq ($(filter y,$(CONFIG_PCI_DRA7XX_HOST) $(CONFIG_PCI_DRA7XX_EP)),) obj-$(CONFIG_PCI_DRA7XX) += pci-dra7xx.o endif @@ -12,7 +15,6 @@ obj-$(CONFIG_PCI_KEYSTONE) += pci-keystone-dw.o pci-keystone.o obj-$(CONFIG_PCI_LAYERSCAPE) += pci-layerscape.o obj-$(CONFIG_PCIE_QCOM) += pcie-qcom.o obj-$(CONFIG_PCIE_ARMADA_8K) += pcie-armada8k.o -obj-$(CONFIG_PCIE_ARTPEC6) += pcie-artpec6.o obj-$(CONFIG_PCIE_KIRIN) += pcie-kirin.o # The following drivers are for devices that use the generic ACPI diff --git a/drivers/pci/dwc/pcie-artpec6.c b/drivers/pci/dwc/pcie-artpec6.c index c5d7f98dc6b2..21ea9ffef784 100644 --- a/drivers/pci/dwc/pcie-artpec6.c +++ b/drivers/pci/dwc/pcie-artpec6.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -30,8 +31,15 @@ struct artpec6_pcie { struct dw_pcie *pci; struct regmap *regmap; /* DT axis,syscon-pcie */ void __iomem *phy_base; /* DT phy */ + enum dw_pcie_device_mode mode; }; +struct artpec_pcie_of_data { + enum dw_pcie_device_mode mode; +}; + +static const struct of_device_id artpec6_pcie_of_match[]; + /* PCIe Port Logic registers (memory-mapped) */ #define PL_OFFSET 0x700 #define PCIE_PHY_DEBUG_R0 (PL_OFFSET + 0x28) @@ -42,6 +50,7 @@ struct artpec6_pcie { #define PCIECFG_DBG_OEN BIT(24) #define PCIECFG_CORE_RESET_REQ BIT(21) #define PCIECFG_LTSSM_ENABLE BIT(20) +#define PCIECFG_DEVICE_TYPE_MASK GENMASK(19, 16) #define PCIECFG_CLKREQ_B BIT(11) #define PCIECFG_REFCLK_ENABLE BIT(10) #define PCIECFG_PLL_ENABLE BIT(9) @@ -126,6 +135,16 @@ static void artpec6_pcie_init_phy(struct artpec6_pcie *artpec6_pcie) } while (retries && !(val & PHY_COSPLLLOCK)); } +static void artpec6_pcie_stop_link(struct dw_pcie *pci) +{ + struct artpec6_pcie *artpec6_pcie = to_artpec6_pcie(pci); + u32 val; + + val = artpec6_pcie_readl(artpec6_pcie, PCIECFG); + val &= ~PCIECFG_LTSSM_ENABLE; + artpec6_pcie_writel(artpec6_pcie, PCIECFG, val); +} + static int artpec6_pcie_establish_link(struct dw_pcie *pci) { struct artpec6_pcie *artpec6_pcie = to_artpec6_pcie(pci); @@ -195,6 +214,136 @@ static irqreturn_t artpec6_pcie_msi_handler(int irq, void *arg) return dw_handle_msi_irq(pp); } +static void dw_pcie_ep_reset_bar(struct dw_pcie *pci, enum pci_barno bar) +{ + u32 reg; + + reg = PCI_BASE_ADDRESS_0 + (4 * bar); + dw_pcie_dbi_ro_wr_en(pci); + dw_pcie_writel_dbi2(pci, reg, 0x0); + dw_pcie_writel_dbi(pci, reg, 0x0); + dw_pcie_dbi_ro_wr_dis(pci); +} + +static void artpec6_pcie_ep_init(struct dw_pcie_ep *ep) +{ + struct dw_pcie *pci = to_dw_pcie_from_ep(ep); + struct artpec6_pcie *artpec6_pcie = to_artpec6_pcie(pci); + enum pci_barno bar; + + artpec6_pcie_assert_core_reset(artpec6_pcie); + artpec6_pcie_init_phy(artpec6_pcie); + artpec6_pcie_deassert_core_reset(artpec6_pcie); + + for (bar = BAR_0; bar <= BAR_5; bar++) + dw_pcie_ep_reset_bar(pci, bar); +} + +static int artpec6_pcie_raise_msi_irq(struct dw_pcie_ep *ep, + u8 interrupt_num) +{ + struct dw_pcie *pci = to_dw_pcie_from_ep(ep); + struct pci_epc *epc = ep->epc; + u32 cap_addr, cap_value, cap_id, next_ptr, msg_ctrl, msg_data; + u32 msg_addr_lower, msg_addr_upper; + u64 msg_addr; + bool has_upper; + int ret; + + /* Raise MSI per the PCI Local Bus Specification Revision 3.0, 6.8.1. */ + cap_addr = dw_pcie_readl_dbi(pci, PCI_CAPABILITY_LIST); + while (1) { + cap_value = dw_pcie_readl_dbi(pci, cap_addr); + cap_id = cap_value & GENMASK(7, 0); + if (cap_id == PCI_CAP_ID_MSI) + break; + next_ptr = (cap_value & GENMASK(15, 8)) >> 8; + if (next_ptr == 0) { + dev_err(pci->dev, "No MSI cap found!\n"); + return -EINVAL; + } + cap_addr = next_ptr; + } + msg_ctrl = (cap_value & GENMASK(31, 16)) >> 16; + has_upper = !!(msg_ctrl & BIT(7)); + msg_addr_lower = dw_pcie_readl_dbi(pci, cap_addr + 0x4); + if (has_upper) { + msg_addr_upper = dw_pcie_readl_dbi(pci, cap_addr + 0x8); + msg_data = dw_pcie_readl_dbi(pci, cap_addr + 0xc) & + GENMASK(15, 0); + } else { + msg_addr_upper = 0; + msg_data = dw_pcie_readl_dbi(pci, cap_addr + 0x8) & + GENMASK(15, 0); + } + msg_addr = ((u64) msg_addr_upper) << 32 | msg_addr_lower; + ret = epc->ops->map_addr(epc, ep->msi_mem_phys, msg_addr, PAGE_SIZE); + if (ret) + return ret; + + writel(msg_data | (interrupt_num - 1), ep->msi_mem); + + epc->ops->unmap_addr(epc, ep->msi_mem_phys); + + return 0; +} + +static int artpec6_pcie_raise_irq(struct dw_pcie_ep *ep, + enum pci_epc_irq_type type, u8 interrupt_num) +{ + struct dw_pcie *pci = to_dw_pcie_from_ep(ep); + + switch (type) { + case PCI_EPC_IRQ_LEGACY: + dev_err(pci->dev, "EP cannot trigger legacy IRQs\n"); + return -EINVAL; + case PCI_EPC_IRQ_MSI: + return artpec6_pcie_raise_msi_irq(ep, interrupt_num); + default: + dev_err(pci->dev, "UNKNOWN IRQ type\n"); + } + + return 0; +} + +static struct dw_pcie_ep_ops pcie_ep_ops = { + .ep_init = artpec6_pcie_ep_init, + .raise_irq = artpec6_pcie_raise_irq, +}; + +static int artpec6_add_pcie_ep(struct artpec6_pcie *artpec6_pcie, + struct platform_device *pdev) +{ + int ret; + struct dw_pcie_ep *ep; + struct resource *res; + struct device *dev = &pdev->dev; + struct dw_pcie *pci = artpec6_pcie->pci; + + ep = &pci->ep; + ep->ops = &pcie_ep_ops; + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi2"); + pci->dbi_base2 = devm_ioremap(dev, res->start, resource_size(res)); + if (IS_ERR(pci->dbi_base2)) + return PTR_ERR(pci->dbi_base2); + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "addr_space"); + if (!res) + return -EINVAL; + + ep->phys_base = res->start; + ep->addr_size = resource_size(res); + + ret = dw_pcie_ep_init(ep); + if (ret) { + dev_err(dev, "failed to initialize endpoint\n"); + return ret; + } + + return 0; +} + static int artpec6_add_pcie_port(struct artpec6_pcie *artpec6_pcie, struct platform_device *pdev) { @@ -234,6 +383,8 @@ static int artpec6_add_pcie_port(struct artpec6_pcie *artpec6_pcie, static const struct dw_pcie_ops dw_pcie_ops = { .cpu_addr_fixup = artpec6_pcie_cpu_addr_fixup, + .start_link = artpec6_pcie_establish_link, + .stop_link = artpec6_pcie_stop_link, }; static int artpec6_pcie_probe(struct platform_device *pdev) @@ -244,6 +395,16 @@ static int artpec6_pcie_probe(struct platform_device *pdev) struct resource *dbi_base; struct resource *phy_base; int ret; + const struct of_device_id *match; + const struct artpec_pcie_of_data *data; + enum dw_pcie_device_mode mode; + + match = of_match_device(artpec6_pcie_of_match, dev); + if (!match) + return -EINVAL; + + data = (struct artpec_pcie_of_data *)match->data; + mode = (enum dw_pcie_device_mode)data->mode; artpec6_pcie = devm_kzalloc(dev, sizeof(*artpec6_pcie), GFP_KERNEL); if (!artpec6_pcie) @@ -257,6 +418,7 @@ static int artpec6_pcie_probe(struct platform_device *pdev) pci->ops = &dw_pcie_ops; artpec6_pcie->pci = pci; + artpec6_pcie->mode = mode; dbi_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi"); pci->dbi_base = devm_ioremap_resource(dev, dbi_base); @@ -276,15 +438,47 @@ static int artpec6_pcie_probe(struct platform_device *pdev) platform_set_drvdata(pdev, artpec6_pcie); - ret = artpec6_add_pcie_port(artpec6_pcie, pdev); - if (ret < 0) - return ret; + switch (artpec6_pcie->mode) { + case DW_PCIE_RC_TYPE: + ret = artpec6_add_pcie_port(artpec6_pcie, pdev); + if (ret < 0) + return ret; + break; + case DW_PCIE_EP_TYPE: { + u32 val; + + val = artpec6_pcie_readl(artpec6_pcie, PCIECFG); + val &= ~PCIECFG_DEVICE_TYPE_MASK; + artpec6_pcie_writel(artpec6_pcie, PCIECFG, val); + ret = artpec6_add_pcie_ep(artpec6_pcie, pdev); + if (ret < 0) + return ret; + break; + } + default: + dev_err(dev, "INVALID device type %d\n", artpec6_pcie->mode); + } return 0; } +static const struct artpec_pcie_of_data artpec6_pcie_rc_of_data = { + .mode = DW_PCIE_RC_TYPE, +}; + +static const struct artpec_pcie_of_data artpec6_pcie_ep_of_data = { + .mode = DW_PCIE_EP_TYPE, +}; + static const struct of_device_id artpec6_pcie_of_match[] = { - { .compatible = "axis,artpec6-pcie", }, + { + .compatible = "axis,artpec6-pcie", + .data = &artpec6_pcie_rc_of_data, + }, + { + .compatible = "axis,artpec6-pcie-ep", + .data = &artpec6_pcie_ep_of_data, + }, {}, }; From patchwork Fri Oct 13 16:09:12 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Niklas Cassel X-Patchwork-Id: 825560 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pci-owner@vger.kernel.org; receiver=) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yDCPH3ynfz9t38 for ; Sat, 14 Oct 2017 03:10:43 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751549AbdJMQK2 (ORCPT ); Fri, 13 Oct 2017 12:10:28 -0400 Received: from bastet.se.axis.com ([195.60.68.11]:52255 "EHLO bastet.se.axis.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751455AbdJMQJo (ORCPT ); Fri, 13 Oct 2017 12:09:44 -0400 Received: from localhost (localhost [127.0.0.1]) by bastet.se.axis.com (Postfix) with ESMTP id 30048185FF; Fri, 13 Oct 2017 18:09:43 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at bastet.se.axis.com Received: from bastet.se.axis.com ([IPv6:::ffff:127.0.0.1]) by localhost (bastet.se.axis.com [::ffff:127.0.0.1]) (amavisd-new, port 10024) with LMTP id ndngnZ5JeHXa; Fri, 13 Oct 2017 18:09:42 +0200 (CEST) Received: from boulder03.se.axis.com (boulder03.se.axis.com [10.0.8.17]) by bastet.se.axis.com (Postfix) with ESMTPS id EDA67185C7; Fri, 13 Oct 2017 18:09:41 +0200 (CEST) Received: from boulder03.se.axis.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id D9B901E078; Fri, 13 Oct 2017 18:09:41 +0200 (CEST) Received: from boulder03.se.axis.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id CD8A71E076; Fri, 13 Oct 2017 18:09:41 +0200 (CEST) Received: from seth.se.axis.com (unknown [10.0.2.172]) by boulder03.se.axis.com (Postfix) with ESMTP; Fri, 13 Oct 2017 18:09:41 +0200 (CEST) Received: from lnxartpec1.se.axis.com (lnxartpec1.se.axis.com [10.88.4.10]) by seth.se.axis.com (Postfix) with ESMTP id BFB5057C; Fri, 13 Oct 2017 18:09:41 +0200 (CEST) Received: by lnxartpec1.se.axis.com (Postfix, from userid 20283) id BC3C8401A0; Fri, 13 Oct 2017 18:09:41 +0200 (CEST) From: Niklas Cassel To: Kishon Vijay Abraham I , Bjorn Helgaas , Niklas Cassel , Jesper Nilsson , Jingoo Han , Joao Pinto Cc: linux-omap@vger.kernel.org, linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@axis.com Subject: [PATCH 09/10] PCI: dwc: make cpu_addr_fixup take struct dw_pcie as argument Date: Fri, 13 Oct 2017 18:09:12 +0200 Message-Id: <20171013160914.3220-10-niklas.cassel@axis.com> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20171013160914.3220-1-niklas.cassel@axis.com> References: <20171013160914.3220-1-niklas.cassel@axis.com> X-TM-AS-GCONF: 00 Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org There is no need to hard code the cpu to bus fixup address. By calculating the sum of sizes of config, io and mem, from device tree, we know how big the PCIe window is. The bus address has to be inside of this range, so all bits in the cpu address that are higher than this range, are the ones that we need to clear to get the local bus address. Also for ARTPEC-7, hard coding the cpu fixup address is not possible, since it uses a High Address Bits Look Up Table, which means that it can, at runtime, map the PCIe window to an arbitrary address in the 32-bit address space. This also fixes a bug for ARTPEC-6, where the cpu_fixup_address previously masked one bit too many. (Another reason why it should be calculated from device tree.) Signed-off-by: Niklas Cassel --- drivers/pci/dwc/pci-dra7xx.c | 2 +- drivers/pci/dwc/pcie-artpec6.c | 42 +++++++++++++++++++++++++++++++++++---- drivers/pci/dwc/pcie-designware.c | 2 +- drivers/pci/dwc/pcie-designware.h | 2 +- 4 files changed, 41 insertions(+), 7 deletions(-) diff --git a/drivers/pci/dwc/pci-dra7xx.c b/drivers/pci/dwc/pci-dra7xx.c index 34427a6a15af..a93bafc72fa0 100644 --- a/drivers/pci/dwc/pci-dra7xx.c +++ b/drivers/pci/dwc/pci-dra7xx.c @@ -109,7 +109,7 @@ static inline void dra7xx_pcie_writel(struct dra7xx_pcie *pcie, u32 offset, writel(value, pcie->base + offset); } -static u64 dra7xx_pcie_cpu_addr_fixup(u64 pci_addr) +static u64 dra7xx_pcie_cpu_addr_fixup(struct dw_pcie *pci, u64 pci_addr) { return pci_addr & DRA7XX_CPU_TO_BUS_ADDR; } diff --git a/drivers/pci/dwc/pcie-artpec6.c b/drivers/pci/dwc/pcie-artpec6.c index 21ea9ffef784..1e113dbea1da 100644 --- a/drivers/pci/dwc/pcie-artpec6.c +++ b/drivers/pci/dwc/pcie-artpec6.c @@ -32,6 +32,7 @@ struct artpec6_pcie { struct regmap *regmap; /* DT axis,syscon-pcie */ void __iomem *phy_base; /* DT phy */ enum dw_pcie_device_mode mode; + u64 cpu_fixup_mask; }; struct artpec_pcie_of_data { @@ -69,8 +70,6 @@ static const struct of_device_id artpec6_pcie_of_match[]; #define PHY_STATUS 0x118 #define PHY_COSPLLLOCK BIT(0) -#define ARTPEC6_CPU_TO_BUS_ADDR GENMASK(27, 0) - static u32 artpec6_pcie_readl(struct artpec6_pcie *artpec6_pcie, u32 offset) { u32 val; @@ -84,9 +83,42 @@ static void artpec6_pcie_writel(struct artpec6_pcie *artpec6_pcie, u32 offset, u regmap_write(artpec6_pcie->regmap, offset, val); } -static u64 artpec6_pcie_cpu_addr_fixup(u64 pci_addr) +static void artpec6_pcie_calc_cpu_fixup_mask(struct artpec6_pcie *artpec6_pcie) { - return pci_addr & ARTPEC6_CPU_TO_BUS_ADDR; + struct dw_pcie *pci = artpec6_pcie->pci; + struct pcie_port *pp = &pci->pp; + struct dw_pcie_ep *ep = &pci->ep; + u64 size; + u64 mask; + int msb; + + switch (artpec6_pcie->mode) { + case DW_PCIE_RC_TYPE: + size = pp->cfg0_size + pp->cfg1_size + pp->io_size + + pp->mem_size; + break; + case DW_PCIE_EP_TYPE: + size = ep->addr_size; + break; + default: + dev_err(pci->dev, "UNKNOWN device type\n"); + return; + } + /* Calculate the mask (which can have potential holes). */ + mask = size - 1; + /* Find the mask's msb. */ + msb = fls64(mask); + /* Use the msb to generate a new mask without any holes. */ + mask = (1ULL << msb) - 1; + artpec6_pcie->cpu_fixup_mask = mask; + dev_dbg(pci->dev, "Using cpu fixup mask: 0x%llx\n", mask); +} + +static u64 artpec6_pcie_cpu_addr_fixup(struct dw_pcie *pci, u64 pci_addr) +{ + struct artpec6_pcie *artpec6_pcie = to_artpec6_pcie(pci); + + return pci_addr & artpec6_pcie->cpu_fixup_mask; } static void artpec6_pcie_init_phy(struct artpec6_pcie *artpec6_pcie) @@ -190,6 +222,7 @@ static int artpec6_pcie_host_init(struct pcie_port *pp) struct dw_pcie *pci = to_dw_pcie_from_pp(pp); struct artpec6_pcie *artpec6_pcie = to_artpec6_pcie(pci); + artpec6_pcie_calc_cpu_fixup_mask(artpec6_pcie); artpec6_pcie_assert_core_reset(artpec6_pcie); artpec6_pcie_init_phy(artpec6_pcie); artpec6_pcie_deassert_core_reset(artpec6_pcie); @@ -231,6 +264,7 @@ static void artpec6_pcie_ep_init(struct dw_pcie_ep *ep) struct artpec6_pcie *artpec6_pcie = to_artpec6_pcie(pci); enum pci_barno bar; + artpec6_pcie_calc_cpu_fixup_mask(artpec6_pcie); artpec6_pcie_assert_core_reset(artpec6_pcie); artpec6_pcie_init_phy(artpec6_pcie); artpec6_pcie_deassert_core_reset(artpec6_pcie); diff --git a/drivers/pci/dwc/pcie-designware.c b/drivers/pci/dwc/pcie-designware.c index 88abdddee2ad..800be7a4f087 100644 --- a/drivers/pci/dwc/pcie-designware.c +++ b/drivers/pci/dwc/pcie-designware.c @@ -149,7 +149,7 @@ void dw_pcie_prog_outbound_atu(struct dw_pcie *pci, int index, int type, u32 retries, val; if (pci->ops->cpu_addr_fixup) - cpu_addr = pci->ops->cpu_addr_fixup(cpu_addr); + cpu_addr = pci->ops->cpu_addr_fixup(pci, cpu_addr); if (pci->iatu_unroll_enabled) { dw_pcie_prog_outbound_atu_unroll(pci, index, type, cpu_addr, diff --git a/drivers/pci/dwc/pcie-designware.h b/drivers/pci/dwc/pcie-designware.h index f56d040afde4..897e190f8e24 100644 --- a/drivers/pci/dwc/pcie-designware.h +++ b/drivers/pci/dwc/pcie-designware.h @@ -203,7 +203,7 @@ struct dw_pcie_ep { }; struct dw_pcie_ops { - u64 (*cpu_addr_fixup)(u64 cpu_addr); + u64 (*cpu_addr_fixup)(struct dw_pcie *pcie, u64 cpu_addr); u32 (*read_dbi)(struct dw_pcie *pcie, void __iomem *base, u32 reg, size_t size); void (*write_dbi)(struct dw_pcie *pcie, void __iomem *base, u32 reg, From patchwork Fri Oct 13 16:09:13 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Niklas Cassel X-Patchwork-Id: 825556 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pci-owner@vger.kernel.org; receiver=) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yDCNh5Fcyz9t30 for ; Sat, 14 Oct 2017 03:10:12 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752545AbdJMQJ6 (ORCPT ); Fri, 13 Oct 2017 12:09:58 -0400 Received: from bastet.se.axis.com ([195.60.68.11]:52331 "EHLO bastet.se.axis.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752392AbdJMQJz (ORCPT ); Fri, 13 Oct 2017 12:09:55 -0400 Received: from localhost (localhost [127.0.0.1]) by bastet.se.axis.com (Postfix) with ESMTP id 399E518418; Fri, 13 Oct 2017 18:09:54 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at bastet.se.axis.com Received: from bastet.se.axis.com ([IPv6:::ffff:127.0.0.1]) by localhost (bastet.se.axis.com [::ffff:127.0.0.1]) (amavisd-new, port 10024) with LMTP id n2p9hBz_J0Pw; Fri, 13 Oct 2017 18:09:52 +0200 (CEST) Received: from boulder03.se.axis.com (boulder03.se.axis.com [10.0.8.17]) by bastet.se.axis.com (Postfix) with ESMTPS id 3CF96182E7; Fri, 13 Oct 2017 18:09:52 +0200 (CEST) Received: from boulder03.se.axis.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 277E61E076; Fri, 13 Oct 2017 18:09:52 +0200 (CEST) Received: from boulder03.se.axis.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 1B58C1E070; Fri, 13 Oct 2017 18:09:52 +0200 (CEST) Received: from seth.se.axis.com (unknown [10.0.2.172]) by boulder03.se.axis.com (Postfix) with ESMTP; Fri, 13 Oct 2017 18:09:52 +0200 (CEST) Received: from lnxartpec1.se.axis.com (lnxartpec1.se.axis.com [10.88.4.10]) by seth.se.axis.com (Postfix) with ESMTP id 0E52557C; Fri, 13 Oct 2017 18:09:52 +0200 (CEST) Received: by lnxartpec1.se.axis.com (Postfix, from userid 20283) id 0ABF2401A0; Fri, 13 Oct 2017 18:09:52 +0200 (CEST) From: Niklas Cassel To: Niklas Cassel , Jesper Nilsson , Bjorn Helgaas , Rob Herring , Mark Rutland Cc: linux-arm-kernel@axis.com, linux-pci@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 10/10] PCI: dwc: artpec6: add support for the ARTPEC-7 SoC Date: Fri, 13 Oct 2017 18:09:13 +0200 Message-Id: <20171013160914.3220-11-niklas.cassel@axis.com> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20171013160914.3220-1-niklas.cassel@axis.com> References: <20171013160914.3220-1-niklas.cassel@axis.com> X-TM-AS-GCONF: 00 Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org The ARTPEC-6 SoC and the ARTPEC-7 SoC are very similar. Unfortunately, some fields in the PCIECFG and PCIESTAT register have changed. Signed-off-by: Niklas Cassel Acked-by: Rob Herring --- .../devicetree/bindings/pci/axis,artpec6-pcie.txt | 2 + drivers/pci/dwc/pcie-artpec6.c | 162 ++++++++++++++++++++- 2 files changed, 161 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/pci/axis,artpec6-pcie.txt b/Documentation/devicetree/bindings/pci/axis,artpec6-pcie.txt index 33eef7ae5a23..979dc7b6cfe8 100644 --- a/Documentation/devicetree/bindings/pci/axis,artpec6-pcie.txt +++ b/Documentation/devicetree/bindings/pci/axis,artpec6-pcie.txt @@ -6,6 +6,8 @@ and thus inherits all the common properties defined in designware-pcie.txt. Required properties: - compatible: "axis,artpec6-pcie", "snps,dw-pcie" for ARTPEC-6 in RC mode; "axis,artpec6-pcie-ep", "snps,dw-pcie" for ARTPEC-6 in EP mode; + "axis,artpec7-pcie", "snps,dw-pcie" for ARTPEC-7 in RC mode; + "axis,artpec7-pcie-ep", "snps,dw-pcie" for ARTPEC-7 in EP mode; - reg: base addresses and lengths of the PCIe controller (DBI), the PHY controller, and configuration address space. - reg-names: Must include the following entries: diff --git a/drivers/pci/dwc/pcie-artpec6.c b/drivers/pci/dwc/pcie-artpec6.c index 1e113dbea1da..80f504babbae 100644 --- a/drivers/pci/dwc/pcie-artpec6.c +++ b/drivers/pci/dwc/pcie-artpec6.c @@ -27,15 +27,22 @@ #define to_artpec6_pcie(x) dev_get_drvdata((x)->dev) +enum artpec_pcie_variants { + ARTPEC6, + ARTPEC7, +}; + struct artpec6_pcie { struct dw_pcie *pci; struct regmap *regmap; /* DT axis,syscon-pcie */ void __iomem *phy_base; /* DT phy */ + enum artpec_pcie_variants variant; enum dw_pcie_device_mode mode; u64 cpu_fixup_mask; }; struct artpec_pcie_of_data { + enum artpec_pcie_variants variant; enum dw_pcie_device_mode mode; }; @@ -46,6 +53,13 @@ static const struct of_device_id artpec6_pcie_of_match[]; #define PCIE_PHY_DEBUG_R0 (PL_OFFSET + 0x28) #define PCIE_PHY_DEBUG_R1 (PL_OFFSET + 0x2c) +#define ACK_F_ASPM_CTRL_OFF (PL_OFFSET + 0xc) +#define ACK_N_FTS_MASK GENMASK(15, 8) +#define ACK_N_FTS(x) (((x) << 8) & ACK_N_FTS_MASK) + +#define FAST_TRAINING_SEQ_MASK GENMASK(7, 0) +#define FAST_TRAINING_SEQ(x) (((x) << 0) & FAST_TRAINING_SEQ_MASK) + /* ARTPEC-6 specific registers */ #define PCIECFG 0x18 #define PCIECFG_DBG_OEN BIT(24) @@ -60,6 +74,13 @@ static const struct of_device_id artpec6_pcie_of_match[]; #define PCIECFG_MODE_TX_DRV_EN BIT(3) #define PCIECFG_CISRREN BIT(2) #define PCIECFG_MACRO_ENABLE BIT(0) +/* ARTPEC-7 specific fields */ +#define PCIECFG_REFCLKSEL BIT(23) +#define PCIECFG_NOC_RESET BIT(3) + +#define PCIESTAT 0x1c +/* ARTPEC-7 specific fields */ +#define PCIESTAT_EXTREFCLK BIT(3) #define NOCCFG 0x40 #define NOCCFG_ENABLE_CLK_PCIE BIT(4) @@ -70,6 +91,12 @@ static const struct of_device_id artpec6_pcie_of_match[]; #define PHY_STATUS 0x118 #define PHY_COSPLLLOCK BIT(0) +#define PHY_TX_ASIC_OUT 0x1014 +#define PHY_TX_ASIC_OUT_TX_ACK BIT(0) + +#define PHY_RX_ASIC_OUT 0x101b +#define PHY_RX_ASIC_OUT_ACK BIT(0) + static u32 artpec6_pcie_readl(struct artpec6_pcie *artpec6_pcie, u32 offset) { u32 val; @@ -121,7 +148,7 @@ static u64 artpec6_pcie_cpu_addr_fixup(struct dw_pcie *pci, u64 pci_addr) return pci_addr & artpec6_pcie->cpu_fixup_mask; } -static void artpec6_pcie_init_phy(struct artpec6_pcie *artpec6_pcie) +static void artpec6_pcie_init_phy_a6(struct artpec6_pcie *artpec6_pcie) { u32 val; unsigned int retries; @@ -167,6 +194,96 @@ static void artpec6_pcie_init_phy(struct artpec6_pcie *artpec6_pcie) } while (retries && !(val & PHY_COSPLLLOCK)); } +static void artpec6_pcie_init_phy_a7(struct artpec6_pcie *artpec6_pcie) +{ + struct dw_pcie *pci = artpec6_pcie->pci; + u32 val; + u16 phy_status_tx, phy_status_rx; + unsigned int retries; + bool extrefclk; + + /* Check if external reference clock is connected */ + val = artpec6_pcie_readl(artpec6_pcie, PCIESTAT); + extrefclk = !!(val & PCIESTAT_EXTREFCLK); + dev_dbg(pci->dev, "Using reference clock: %s\n", + extrefclk ? "external" : "internal"); + + val = artpec6_pcie_readl(artpec6_pcie, PCIECFG); + val |= PCIECFG_RISRCREN | /* Receiver term. 50 Ohm */ + PCIECFG_PCLK_ENABLE; + if (extrefclk) + val |= PCIECFG_REFCLKSEL; + else + val &= ~PCIECFG_REFCLKSEL; + artpec6_pcie_writel(artpec6_pcie, PCIECFG, val); + usleep_range(10, 20); + + val = artpec6_pcie_readl(artpec6_pcie, NOCCFG); + val |= NOCCFG_ENABLE_CLK_PCIE; + artpec6_pcie_writel(artpec6_pcie, NOCCFG, val); + usleep_range(20, 30); + + val = artpec6_pcie_readl(artpec6_pcie, NOCCFG); + val &= ~NOCCFG_POWER_PCIE_IDLEREQ; + artpec6_pcie_writel(artpec6_pcie, NOCCFG, val); + + retries = 50; + do { + usleep_range(1000, 2000); + val = artpec6_pcie_readl(artpec6_pcie, NOCCFG); + retries--; + } while (retries && + (val & (NOCCFG_POWER_PCIE_IDLEACK | NOCCFG_POWER_PCIE_IDLE))); + + retries = 50; + do { + usleep_range(1000, 2000); + phy_status_tx = readw(artpec6_pcie->phy_base + PHY_TX_ASIC_OUT); + phy_status_rx = readw(artpec6_pcie->phy_base + PHY_RX_ASIC_OUT); + retries--; + } while (retries && ((phy_status_tx & PHY_TX_ASIC_OUT_TX_ACK) || + (phy_status_rx & PHY_RX_ASIC_OUT_ACK))); +} + +static void artpec6_pcie_init_phy(struct artpec6_pcie *artpec6_pcie) +{ + switch (artpec6_pcie->variant) { + case ARTPEC6: + artpec6_pcie_init_phy_a6(artpec6_pcie); + break; + case ARTPEC7: + artpec6_pcie_init_phy_a7(artpec6_pcie); + break; + } +} + +static void artpec6_pcie_set_nfts(struct artpec6_pcie *artpec6_pcie) +{ + struct dw_pcie *pci = artpec6_pcie->pci; + u32 val; + + if (artpec6_pcie->variant != ARTPEC7) + return; + + /* + * Increase the N_FTS (Number of Fast Training Sequences) + * to be transmitted when transitioning from L0s to L0. + */ + val = dw_pcie_readl_dbi(pci, ACK_F_ASPM_CTRL_OFF); + val &= ~ACK_N_FTS_MASK; + val |= ACK_N_FTS(180); + dw_pcie_writel_dbi(pci, ACK_F_ASPM_CTRL_OFF, val); + + /* + * Set the Number of Fast Training Sequences that the core + * advertises as its N_FTS during Gen2 or Gen3 link training. + */ + val = dw_pcie_readl_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL); + val &= ~FAST_TRAINING_SEQ_MASK; + val |= FAST_TRAINING_SEQ(180); + dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, val); +} + static void artpec6_pcie_stop_link(struct dw_pcie *pci) { struct artpec6_pcie *artpec6_pcie = to_artpec6_pcie(pci); @@ -203,7 +320,14 @@ static void artpec6_pcie_assert_core_reset(struct artpec6_pcie *artpec6_pcie) u32 val; val = artpec6_pcie_readl(artpec6_pcie, PCIECFG); - val |= PCIECFG_CORE_RESET_REQ; + switch (artpec6_pcie->variant) { + case ARTPEC6: + val |= PCIECFG_CORE_RESET_REQ; + break; + case ARTPEC7: + val &= ~PCIECFG_NOC_RESET; + break; + } artpec6_pcie_writel(artpec6_pcie, PCIECFG, val); } @@ -212,7 +336,14 @@ static void artpec6_pcie_deassert_core_reset(struct artpec6_pcie *artpec6_pcie) u32 val; val = artpec6_pcie_readl(artpec6_pcie, PCIECFG); - val &= ~PCIECFG_CORE_RESET_REQ; + switch (artpec6_pcie->variant) { + case ARTPEC6: + val &= ~PCIECFG_CORE_RESET_REQ; + break; + case ARTPEC7: + val |= PCIECFG_NOC_RESET; + break; + } artpec6_pcie_writel(artpec6_pcie, PCIECFG, val); usleep_range(100, 200); } @@ -226,6 +357,7 @@ static int artpec6_pcie_host_init(struct pcie_port *pp) artpec6_pcie_assert_core_reset(artpec6_pcie); artpec6_pcie_init_phy(artpec6_pcie); artpec6_pcie_deassert_core_reset(artpec6_pcie); + artpec6_pcie_set_nfts(artpec6_pcie); dw_pcie_setup_rc(pp); artpec6_pcie_establish_link(pci); dw_pcie_wait_for_link(pci); @@ -268,6 +400,7 @@ static void artpec6_pcie_ep_init(struct dw_pcie_ep *ep) artpec6_pcie_assert_core_reset(artpec6_pcie); artpec6_pcie_init_phy(artpec6_pcie); artpec6_pcie_deassert_core_reset(artpec6_pcie); + artpec6_pcie_set_nfts(artpec6_pcie); for (bar = BAR_0; bar <= BAR_5; bar++) dw_pcie_ep_reset_bar(pci, bar); @@ -431,6 +564,7 @@ static int artpec6_pcie_probe(struct platform_device *pdev) int ret; const struct of_device_id *match; const struct artpec_pcie_of_data *data; + enum artpec_pcie_variants variant; enum dw_pcie_device_mode mode; match = of_match_device(artpec6_pcie_of_match, dev); @@ -438,6 +572,7 @@ static int artpec6_pcie_probe(struct platform_device *pdev) return -EINVAL; data = (struct artpec_pcie_of_data *)match->data; + variant = (enum artpec_pcie_variants)data->variant; mode = (enum dw_pcie_device_mode)data->mode; artpec6_pcie = devm_kzalloc(dev, sizeof(*artpec6_pcie), GFP_KERNEL); @@ -452,6 +587,7 @@ static int artpec6_pcie_probe(struct platform_device *pdev) pci->ops = &dw_pcie_ops; artpec6_pcie->pci = pci; + artpec6_pcie->variant = variant; artpec6_pcie->mode = mode; dbi_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi"); @@ -497,10 +633,22 @@ static int artpec6_pcie_probe(struct platform_device *pdev) } static const struct artpec_pcie_of_data artpec6_pcie_rc_of_data = { + .variant = ARTPEC6, .mode = DW_PCIE_RC_TYPE, }; static const struct artpec_pcie_of_data artpec6_pcie_ep_of_data = { + .variant = ARTPEC6, + .mode = DW_PCIE_EP_TYPE, +}; + +static const struct artpec_pcie_of_data artpec7_pcie_rc_of_data = { + .variant = ARTPEC7, + .mode = DW_PCIE_RC_TYPE, +}; + +static const struct artpec_pcie_of_data artpec7_pcie_ep_of_data = { + .variant = ARTPEC7, .mode = DW_PCIE_EP_TYPE, }; @@ -513,6 +661,14 @@ static const struct of_device_id artpec6_pcie_of_match[] = { .compatible = "axis,artpec6-pcie-ep", .data = &artpec6_pcie_ep_of_data, }, + { + .compatible = "axis,artpec7-pcie", + .data = &artpec7_pcie_rc_of_data, + }, + { + .compatible = "axis,artpec7-pcie-ep", + .data = &artpec7_pcie_ep_of_data, + }, {}, };