From patchwork Thu Apr 22 17:04:57 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kunihiko Hayashi X-Patchwork-Id: 12218957 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id C5E2EC433ED for ; Thu, 22 Apr 2021 17:07:29 +0000 (UTC) Received: from desiato.infradead.org (desiato.infradead.org [90.155.92.199]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 27EB4613C9 for ; Thu, 22 Apr 2021 17:07:29 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 27EB4613C9 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=socionext.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=desiato.20200630; h=Sender:Content-Transfer-Encoding :Content-Type:MIME-Version:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:References:In-Reply-To:Message-Id:Date:Subject:Cc:To :From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=wmjp0pL/MXPjfIrvmRKJPkZblE9gB4GDBDo0JheLIGs=; b=fkHv7qSMerg+94fsFhn7gMM6lR iqy8bX2KNl7aYsK+RldKrrxjWRBoSo76s3X515CxJtaoTp7UID0cMSmGAUjxS3n094vOptpP+fxOi GWRV3cw4NDQcT6uBN/2zvWbFOBhZTHHmADaOAoeGZI+oXgHohxX51lIXFGoM+39gtRfskVM1zI6sp +gchTJz3kxtDQbjLd82gV6W8Q1FB13UtS4FdcRjezmb2h//D93rMpfgoAKUYlGDgGTq5qtvUAyhvr lMDGhQNmBNkVSQ+0MgBZ93fzoYCaAET9jDEBg4G5KhIgHMMDoGPBbw/3ZkMzGtlQa6PpRhVXL86ly QbpHcKeQ==; Received: from localhost ([::1] helo=desiato.infradead.org) by desiato.infradead.org with esmtp (Exim 4.94 #2 (Red Hat Linux)) id 1lZclq-00H9WY-6s; Thu, 22 Apr 2021 17:05:42 +0000 Received: from bombadil.infradead.org ([2607:7c80:54:e::133]) by desiato.infradead.org with esmtps (Exim 4.94 #2 (Red Hat Linux)) id 1lZclO-00H9Tr-TD for linux-arm-kernel@desiato.infradead.org; Thu, 22 Apr 2021 17:05:15 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=bombadil.20210309; h=References:In-Reply-To:Message-Id: Date:Subject:Cc:To:From:Sender:Reply-To:MIME-Version:Content-Type: Content-Transfer-Encoding:Content-ID:Content-Description; bh=PBXLeaftA7PlcdYRQK3F7gsIo9w7gahlDpTsFPKCcss=; b=K0iVfje2jUetvRcE9WUuhnnRZ+ 8jCNTMybBfQTtqVCYGlCwFDU6GoQu6iIqCO2vwYup/BzdWXSKaGbxwcKHYlljUvNeQr8HsB1aMvSF RRUTnXrFgaXzDxq/kVgwbOCGVnTHI5ujNnbE7+/f1RngWVsqUBt7hrFhqodVhhZu3kHXJaBoXqbvo GV2YhcVvC/OKi45qVtkrmlhvsqJOnH7r8e3+xezyTb3mlsIpVhVXtJ7hVgk6bja1e48Kcx9h6dyz5 2COkskjZnowDNR0eodoSoCekx1yNxLCLdK4GLhSoQPYFrg6AQDvTqqVkjQUcJaRtKK/UJzBixtgEA fy9RvV1w==; Received: from mx.socionext.com ([202.248.49.38]) by bombadil.infradead.org with esmtp (Exim 4.94 #2 (Red Hat Linux)) id 1lZclM-00Ds38-1y for linux-arm-kernel@lists.infradead.org; Thu, 22 Apr 2021 17:05:13 +0000 Received: from unknown (HELO iyokan2-ex.css.socionext.com) ([172.31.9.54]) by mx.socionext.com with ESMTP; 23 Apr 2021 02:05:11 +0900 Received: from mail.mfilter.local (m-filter-1 [10.213.24.61]) by iyokan2-ex.css.socionext.com (Postfix) with ESMTP id 5B6A9205902A; Fri, 23 Apr 2021 02:05:11 +0900 (JST) Received: from 172.31.9.51 (172.31.9.51) by m-FILTER with ESMTP; Fri, 23 Apr 2021 02:05:11 +0900 Received: from plum.e01.socionext.com (unknown [10.213.132.32]) by kinkan2.css.socionext.com (Postfix) with ESMTP id B095FB1D40; Fri, 23 Apr 2021 02:05:10 +0900 (JST) From: Kunihiko Hayashi To: Bjorn Helgaas , Rob Herring , Lorenzo Pieralisi , Jingoo Han , Gustavo Pimentel , Marc Zyngier Cc: linux-pci@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Jassi Brar , Masami Hiramatsu , Kunihiko Hayashi Subject: [PATCH v11 3/3] PCI: uniphier: Add misc interrupt handler to invoke PME and AER Date: Fri, 23 Apr 2021 02:04:57 +0900 Message-Id: <1619111097-10232-4-git-send-email-hayashi.kunihiko@socionext.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1619111097-10232-1-git-send-email-hayashi.kunihiko@socionext.com> References: <1619111097-10232-1-git-send-email-hayashi.kunihiko@socionext.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210422_100512_232138_5C956A85 X-CRM114-Status: GOOD ( 21.47 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org This patch adds misc interrupt handler to detect and invoke PME/AER event. In UniPhier PCIe controller, PME/AER signals are assigned to the same signal as MSI by the internal logic. These signals should be detected by the internal register, however, DWC MSI handler can't handle these signals. DWC MSI handler calls .msi_host_isr() callback function, that detects PME/AER signals using the internal register and invokes the interrupt with PME/AER IRQ numbers. These IRQ numbers is obtained by uniphier_pcie_port_get_irq() function, that finds the device that matches PME/AER from the devices associated with Root Port, and returns its IRQ number. Cc: Marc Zyngier Cc: Jingoo Han Cc: Gustavo Pimentel Cc: Lorenzo Pieralisi Signed-off-by: Kunihiko Hayashi Reviewed-by: Rob Herring --- drivers/pci/controller/dwc/pcie-uniphier.c | 105 +++++++++++++++++++++++++---- 1 file changed, 91 insertions(+), 14 deletions(-) diff --git a/drivers/pci/controller/dwc/pcie-uniphier.c b/drivers/pci/controller/dwc/pcie-uniphier.c index 7e8bad3..dcd8fa8 100644 --- a/drivers/pci/controller/dwc/pcie-uniphier.c +++ b/drivers/pci/controller/dwc/pcie-uniphier.c @@ -21,6 +21,7 @@ #include #include "pcie-designware.h" +#include "../../pcie/portdrv.h" #define PCL_PINCTRL0 0x002c #define PCL_PERST_PLDN_REGEN BIT(12) @@ -44,7 +45,9 @@ #define PCL_SYS_AUX_PWR_DET BIT(8) #define PCL_RCV_INT 0x8108 +#define PCL_RCV_INT_ALL_INT_MASK GENMASK(28, 25) #define PCL_RCV_INT_ALL_ENABLE GENMASK(20, 17) +#define PCL_RCV_INT_ALL_MSI_MASK GENMASK(12, 9) #define PCL_CFG_BW_MGT_STATUS BIT(4) #define PCL_CFG_LINK_AUTO_BW_STATUS BIT(3) #define PCL_CFG_AER_RC_ERR_MSI_STATUS BIT(2) @@ -68,6 +71,8 @@ struct uniphier_pcie_priv { struct reset_control *rst; struct phy *phy; struct irq_domain *legacy_irq_domain; + int aer_irq; + int pme_irq; }; #define to_uniphier_pcie(x) dev_get_drvdata((x)->dev) @@ -164,7 +169,15 @@ static void uniphier_pcie_stop_link(struct dw_pcie *pci) static void uniphier_pcie_irq_enable(struct uniphier_pcie_priv *priv) { - writel(PCL_RCV_INT_ALL_ENABLE, priv->base + PCL_RCV_INT); + u32 val; + + val = PCL_RCV_INT_ALL_ENABLE; + if (pci_msi_enabled()) + val |= PCL_RCV_INT_ALL_INT_MASK; + else + val |= PCL_RCV_INT_ALL_MSI_MASK; + + writel(val, priv->base + PCL_RCV_INT); writel(PCL_RCV_INTX_ALL_ENABLE, priv->base + PCL_RCV_INTX); } @@ -228,28 +241,51 @@ static const struct irq_domain_ops uniphier_intx_domain_ops = { .map = uniphier_pcie_intx_map, }; -static void uniphier_pcie_irq_handler(struct irq_desc *desc) +static void uniphier_pcie_misc_isr(struct pcie_port *pp, bool is_msi) { - struct pcie_port *pp = irq_desc_get_handler_data(desc); struct dw_pcie *pci = to_dw_pcie_from_pp(pp); struct uniphier_pcie_priv *priv = to_uniphier_pcie(pci); - struct irq_chip *chip = irq_desc_get_chip(desc); - unsigned long reg; - u32 val, bit, virq; + u32 val; - /* INT for debug */ val = readl(priv->base + PCL_RCV_INT); if (val & PCL_CFG_BW_MGT_STATUS) dev_dbg(pci->dev, "Link Bandwidth Management Event\n"); if (val & PCL_CFG_LINK_AUTO_BW_STATUS) dev_dbg(pci->dev, "Link Autonomous Bandwidth Event\n"); - if (val & PCL_CFG_AER_RC_ERR_MSI_STATUS) - dev_dbg(pci->dev, "Root Error\n"); - if (val & PCL_CFG_PME_MSI_STATUS) - dev_dbg(pci->dev, "PME Interrupt\n"); + + if (is_msi) { + if (val & PCL_CFG_AER_RC_ERR_MSI_STATUS) { + dev_dbg(pci->dev, "Root Error Status\n"); + if (priv->aer_irq) + generic_handle_irq(priv->aer_irq); + } + + if (val & PCL_CFG_PME_MSI_STATUS) { + dev_dbg(pci->dev, "PME Interrupt\n"); + if (priv->pme_irq) + generic_handle_irq(priv->pme_irq); + } + } writel(val, priv->base + PCL_RCV_INT); +} + +static void uniphier_pcie_msi_host_isr(struct pcie_port *pp) +{ + uniphier_pcie_misc_isr(pp, true); +} + +static void uniphier_pcie_irq_handler(struct irq_desc *desc) +{ + struct pcie_port *pp = irq_desc_get_handler_data(desc); + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); + struct uniphier_pcie_priv *priv = to_uniphier_pcie(pci); + struct irq_chip *chip = irq_desc_get_chip(desc); + unsigned long reg; + u32 val, bit, irq; + + uniphier_pcie_misc_isr(pp, false); /* INTx */ chained_irq_enter(chip, desc); @@ -258,8 +294,8 @@ static void uniphier_pcie_irq_handler(struct irq_desc *desc) reg = FIELD_GET(PCL_RCV_INTX_ALL_STATUS, val); for_each_set_bit(bit, ®, PCI_NUM_INTX) { - virq = irq_linear_revmap(priv->legacy_irq_domain, bit); - generic_handle_irq(virq); + irq = irq_linear_revmap(priv->legacy_irq_domain, bit); + generic_handle_irq(irq); } chained_irq_exit(chip, desc); @@ -317,8 +353,45 @@ static int uniphier_pcie_host_init(struct pcie_port *pp) return 0; } +static int uniphier_pcie_port_get_irq(struct pcie_port *pp, u32 service) +{ + struct pci_dev *pcidev; + int irq = 0; + + if (!IS_ENABLED(CONFIG_PCIEAER) && !IS_ENABLED(CONFIG_PCIE_PME)) + return 0; + + /* + * Finds the device that matches 'service' from the devices + * associated with Root Port, and returns its IRQ number. + */ + list_for_each_entry(pcidev, &pp->bridge->bus->devices, bus_list) { + irq = pcie_port_service_get_irq(pcidev, service); + if (irq) + break; + } + + return irq; +} + +static int uniphier_pcie_host_init_complete(struct pcie_port *pp) +{ + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); + struct uniphier_pcie_priv *priv = to_uniphier_pcie(pci); + + if (IS_ENABLED(CONFIG_PCIE_PME)) + priv->pme_irq = + uniphier_pcie_port_get_irq(pp, PCIE_PORT_SERVICE_PME); + if (IS_ENABLED(CONFIG_PCIEAER)) + priv->aer_irq = + uniphier_pcie_port_get_irq(pp, PCIE_PORT_SERVICE_AER); + + return 0; +} + static const struct dw_pcie_host_ops uniphier_pcie_host_ops = { .host_init = uniphier_pcie_host_init, + .msi_host_isr = uniphier_pcie_msi_host_isr, }; static int uniphier_pcie_host_enable(struct uniphier_pcie_priv *priv) @@ -398,7 +471,11 @@ static int uniphier_pcie_probe(struct platform_device *pdev) priv->pci.pp.ops = &uniphier_pcie_host_ops; - return dw_pcie_host_init(&priv->pci.pp); + ret = dw_pcie_host_init(&priv->pci.pp); + if (ret) + return ret; + + return uniphier_pcie_host_init_complete(&priv->pci.pp); } static const struct of_device_id uniphier_pcie_match[] = {