Received: by 10.223.164.202 with SMTP id h10csp3819052wrb; Mon, 20 Nov 2017 05:37:01 -0800 (PST) X-Google-Smtp-Source: AGs4zMYzDKN8KplX2BbSBN6KoiEpyEX8ivKVcxo1QBCPHlONvDpSA86N0qxOBxGsFIEgpKOQoMEN X-Received: by 10.99.188.9 with SMTP id q9mr13666012pge.104.1511185021456; Mon, 20 Nov 2017 05:37:01 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1511185021; cv=none; d=google.com; s=arc-20160816; b=lxaNkVgHsTLRCg/B3xSMW9p/t7B8bJ1FFzQzZajHCKxCICPJ7gY+hr7+dXHqlsV/aE uJw8/gk8e3u9UdUFs+bug1BV+DYwfwlIKp11EeNIB7Ynq+TSnzd/nYBa+NAxtzkFNplT 1nNeFgcrz/Yfl46Gn0PCaIQplevA0OTwvkq7TulrBEYH9U1a+lYv4vvNhedLTLEvu+o1 hEh+rANsbJHGsQ9wh9kA2gHvnnwqOdq5Nb+pA+UtQozwZcm++0RbmriXX9VxqMWW3wH8 1fYOWqNeI52lI0pbAwPJKxd1Ove2NgkqpoUVuKEdItrCvYSVpnztZ3ZMxVSm6BCaOoPh zjxQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:arc-authentication-results; bh=xkGOrREI8b+0iWoA+t2MQJXWTlEa6a45xlsiAgC6Ev4=; b=HGgtGhDhLhAfkvhivcmKqsirePY3sALDeF1rnST9VuEUn6aWp7qHagHcQ4NfBDEpIx 1xC5Z6Jze2IW9YiysdeupfgrvTqc6xa1Z72L661o7H9LONpr48qz/VIxizy8oO/PzwtH 7gaS9Nm4xu8E3Iqa96SBgoGEy/bOImnW2GPbbm+sy2YcOzTZU6J0kVDOCUWNVfCvYpje 2x81YLcohMLRk49zyvCCP130guuCpuU7NBfIKLnu2A61Kv5ixuY/oImT/Y2nRmdvNBkH +p2gl5adJY4x6+ygd1nYjnuhR5kDSe4BouMAB5HCgbpACU4Zz/eQ/mP9PCqWdVs1wCA3 oHAw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id a67si8063410pgc.233.2017.11.20.05.36.51; Mon, 20 Nov 2017 05:37:01 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751707AbdKTNfM (ORCPT + 66 others); Mon, 20 Nov 2017 08:35:12 -0500 Received: from bastet.se.axis.com ([195.60.68.11]:39638 "EHLO bastet.se.axis.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751123AbdKTNdm (ORCPT ); Mon, 20 Nov 2017 08:33:42 -0500 Received: from localhost (localhost [127.0.0.1]) by bastet.se.axis.com (Postfix) with ESMTP id 64F18180E6; Mon, 20 Nov 2017 14:33:41 +0100 (CET) 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 vsiA2kJQ8chH; Mon, 20 Nov 2017 14:33:40 +0100 (CET) Received: from boulder02.se.axis.com (boulder02.se.axis.com [10.0.8.16]) by bastet.se.axis.com (Postfix) with ESMTPS id 4D68C183B0; Mon, 20 Nov 2017 14:33:40 +0100 (CET) Received: from boulder02.se.axis.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 0B1311A08C; Mon, 20 Nov 2017 14:33:40 +0100 (CET) Received: from boulder02.se.axis.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id F34141A070; Mon, 20 Nov 2017 14:33:39 +0100 (CET) Received: from thoth.se.axis.com (unknown [10.0.2.173]) by boulder02.se.axis.com (Postfix) with ESMTP; Mon, 20 Nov 2017 14:33:39 +0100 (CET) Received: from lnxartpec1.se.axis.com (lnxartpec1.se.axis.com [10.88.4.10]) by thoth.se.axis.com (Postfix) with ESMTP id E74EB19AA; Mon, 20 Nov 2017 14:33:39 +0100 (CET) Received: by lnxartpec1.se.axis.com (Postfix, from userid 20283) id E2A89400FE; Mon, 20 Nov 2017 14:33:39 +0100 (CET) From: Niklas Cassel To: Lorenzo Pieralisi , Bjorn Helgaas , Niklas Cassel , Jesper Nilsson Cc: linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@axis.com Subject: [PATCH v5 14/18] PCI: dwc: artpec6: Add support for endpoint mode Date: Mon, 20 Nov 2017 14:32:17 +0100 Message-Id: <20171120133222.27771-15-niklas.cassel@axis.com> X-Mailer: git-send-email 2.14.2 In-Reply-To: <20171120133222.27771-1-niklas.cassel@axis.com> References: <20171120133222.27771-1-niklas.cassel@axis.com> X-TM-AS-GCONF: 00 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The PCIe controller integrated in ARTPEC-6 SoCs is capable of operating in endpoint mode. Add endpoint mode support to the artpec6 driver. Signed-off-by: Niklas Cassel --- drivers/pci/dwc/Kconfig | 23 +++++-- drivers/pci/dwc/pcie-artpec6.c | 152 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 164 insertions(+), 11 deletions(-) diff --git a/drivers/pci/dwc/Kconfig b/drivers/pci/dwc/Kconfig index 3954353e3e2e..0fb96c7754de 100644 --- a/drivers/pci/dwc/Kconfig +++ b/drivers/pci/dwc/Kconfig @@ -148,15 +148,28 @@ config PCIE_ARMADA_8K DesignWare core functions to implement the driver. config PCIE_ARTPEC6 - bool "Axis ARTPEC-6 PCIe controller" - depends on PCI + bool + +config PCIE_ARTPEC6_HOST + bool "Axis ARTPEC-6 PCIe controller Host Mode" depends on MACH_ARTPEC6 - depends on PCI_MSI_IRQ_DOMAIN + depends on PCI && PCI_MSI_IRQ_DOMAIN select PCIEPORTBUS select PCIE_DW_HOST + select PCIE_ARTPEC6 + help + Enables support for the PCIe controller in the ARTPEC-6 SoC to work in + host mode. This uses the DesignWare core. + +config PCIE_ARTPEC6_EP + bool "Axis ARTPEC-6 PCIe controller Endpoint Mode" + depends on MACH_ARTPEC6 + depends on PCI_ENDPOINT + select PCIE_DW_EP + select PCIE_ARTPEC6 help - Say Y here to enable PCIe controller support on Axis ARTPEC-6 - SoCs. This PCIe controller uses the DesignWare core. + Enables support for the PCIe controller in the ARTPEC-6 SoC to work in + endpoint mode. This uses the DesignWare core. config PCIE_KIRIN depends on OF && ARM64 diff --git a/drivers/pci/dwc/pcie-artpec6.c b/drivers/pci/dwc/pcie-artpec6.c index b2783b475c2a..e7de4e4649eb 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 @@ -40,6 +48,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) @@ -90,6 +99,22 @@ static int artpec6_pcie_establish_link(struct dw_pcie *pci) return 0; } +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 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 void artpec6_pcie_init_phy(struct artpec6_pcie *artpec6_pcie) { u32 val; @@ -230,10 +255,76 @@ static int artpec6_add_pcie_port(struct artpec6_pcie *artpec6_pcie, return 0; } -static const struct dw_pcie_ops dw_pcie_ops = { - .cpu_addr_fixup = artpec6_pcie_cpu_addr_fixup, +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_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 dw_pcie_ep_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_pcie_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -242,6 +333,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) @@ -255,6 +356,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); @@ -274,15 +376,53 @@ 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: + if (!IS_ENABLED(CONFIG_PCIE_ARTPEC6_HOST)) + return -ENODEV; + + ret = artpec6_add_pcie_port(artpec6_pcie, pdev); + if (ret < 0) + return ret; + break; + case DW_PCIE_EP_TYPE: { + u32 val; + + if (!IS_ENABLED(CONFIG_PCIE_ARTPEC6_EP)) + return -ENODEV; + + 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, + }, {}, }; -- 2.14.2 From 1584610570535318990@xxx Mon Nov 20 18:26:42 +0000 2017 X-GM-THRID: 1584610570535318990 X-Gmail-Labels: Inbox,Category Forums,HistoricalUnread