From patchwork Tue Sep 27 14:19:19 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marek_Beh=C3=BAn?= X-Patchwork-Id: 12990699 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id ECAB9C54EE9 for ; Tue, 27 Sep 2022 14:21:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version: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=Zyn61S0k79yknZ+BoGqKT8m6mBJHtAL8dSmzhxiRiYI=; b=g1bdOOCmB4r/85 OXhrStcSxR3x7x/xUKJ0wXe32QskZFbLIjbT+V6u1431GZxrghBjpCcFegWK8w7I9GzatLe7r6Scd 4hXW0xBPypIONO1ppuAFni846uLeQ3nHlV4AGcHd6ifeuvcWNMbsDLf7cp94VlLwp79HMpl61JFRV ZxTwxksFI9XY1hPpKdmqsmfRllHPoR/ok1Wc+UUSZzTXs79XhZ23j7gK64PYoQTbcGqcBPbEDPaSl Wi8Nij+GNfhh/JfEFBacaobc8QxN733Hlz5QJZr2nx4IoUCadYLYB117WC4KfT0GBnOgNIcFysjnG mXfrFU0A0j7ZKFV1BsgQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1odBRO-00BBBQ-H2; Tue, 27 Sep 2022 14:20:06 +0000 Received: from dfw.source.kernel.org ([139.178.84.217]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1odBQw-00BB1g-DD for linux-arm-kernel@lists.infradead.org; Tue, 27 Sep 2022 14:19:40 +0000 Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 9BF13619FE; Tue, 27 Sep 2022 14:19:37 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8122FC433C1; Tue, 27 Sep 2022 14:19:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1664288377; bh=PUps/ldFkt1/yI6ZmwNvDNq7YAuTSGdZNC88IA2kSQk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=YY7vZap89PBZyec+jMI/NGAhNvUYS9qfnkV7j3mcoBw/lfgS9yHkMvQ5SFGDOVqwH I6L+zLrrMY9JKRxBuBiqy0IJjLzpAqHmAKVEP3eU2QXHs6FjHcTZxwK10L3SZr0gTW oF/U4kzwL8lY0/zzvLwGGIyMh9mx8GLPuRO1QwUdxfkQGn54aN1SvCeft0adKCxpYC aYS1FoA5koY7GS/LUteWRKL8p1IxJ38bmuXHzgIDga/FHsv8GwOgk+PW7jCf7b1Q8T eHUQs/ZqYjHChb8846B4C07EJ6Tv/cIiH9da1IUqp+5dZxLe1PaO3m1wuOD+7hK7wN xSRoiPiXHxxGg== From: =?utf-8?q?Marek_Beh=C3=BAn?= To: Lorenzo Pieralisi Cc: Bjorn Helgaas , Gregory CLEMENT , pali@kernel.org, =?utf-8?q?K?= =?utf-8?q?rzysztof_Wilczy=C5=84ski?= , linux-pci@vger.kernel.org, linux-arm-kernel@lists.infradead.org, =?utf-8?q?Marek_Beh=C3=BAn?= Subject: [PATCH v2 03/10] PCI: aardvark: Send Set_Slot_Power_Limit message Date: Tue, 27 Sep 2022 16:19:19 +0200 Message-Id: <20220927141926.8895-4-kabel@kernel.org> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220927141926.8895-1-kabel@kernel.org> References: <20220927141926.8895-1-kabel@kernel.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220927_071938_564451_07AC1672 X-CRM114-Status: GOOD ( 20.21 ) 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: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org From: Pali Rohár Emulate Slot PowerLimit Scale and Value bits in the Slot Capabilities register of the emulated bridge and if slot power limit value is defined, send that Set_Slot_Power_Limit message via Message Generation Control Register in Link Up handler on link up event. Slot power limit value is read from device-tree property 'slot-power-limit-milliwatt'. If this property is not specified, we treat it as "Slot Capabilities register has not yet been initialized". According to PCIe Base specification 3.0, when transitioning from a non-DL_Up Status to a DL_Up Status, the Port must initiate the transmission of a Set_Slot_Power_Limit Message to the other component on the Link to convey the value programmed in the Slot Power Limit Scale and Value fields of the Slot Capabilities register. This transmission is optional if the Slot Capabilities register has not yet been initialized. Signed-off-by: Pali Rohár Signed-off-by: Marek Behún --- drivers/pci/controller/pci-aardvark.c | 51 ++++++++++++++++++++++++--- 1 file changed, 47 insertions(+), 4 deletions(-) diff --git a/drivers/pci/controller/pci-aardvark.c b/drivers/pci/controller/pci-aardvark.c index 31da28ebc5d1..03e318bc171f 100644 --- a/drivers/pci/controller/pci-aardvark.c +++ b/drivers/pci/controller/pci-aardvark.c @@ -213,6 +213,11 @@ enum { }; #define VENDOR_ID_REG (LMI_BASE_ADDR + 0x44) +#define PME_MSG_GEN_CTRL (LMI_BASE_ADDR + 0x220) +#define SEND_SET_SLOT_POWER_LIMIT BIT(13) +#define SEND_PME_TURN_OFF BIT(14) +#define SLOT_POWER_LIMIT_DATA_SHIFT 16 +#define SLOT_POWER_LIMIT_DATA_MASK GENMASK(25, 16) /* PCIe core controller registers */ #define CTRL_CORE_BASE_ADDR 0x18000 @@ -285,6 +290,8 @@ struct advk_pcie { raw_spinlock_t msi_irq_lock; DECLARE_BITMAP(msi_used, MSI_IRQ_NUM); struct mutex msi_used_lock; + u8 slot_power_limit_value; + u8 slot_power_limit_scale; int link_gen; bool link_was_up; struct timer_list link_irq_timer; @@ -317,8 +324,9 @@ static inline bool advk_pcie_link_up(struct advk_pcie *pcie) { /* check if LTSSM is in normal operation - some L* state */ u8 ltssm_state = advk_pcie_ltssm_state(pcie); + u16 slotsta, slotctl; + u32 slotpwr, val; bool link_is_up; - u16 slotsta; link_is_up = ltssm_state >= LTSSM_L0 && ltssm_state < LTSSM_DISABLED; @@ -332,6 +340,27 @@ static inline bool advk_pcie_link_up(struct advk_pcie *pcie) pcie->bridge.pcie_conf.slotsta = cpu_to_le16(slotsta); mod_timer(&pcie->link_irq_timer, jiffies + 1); + + /* + * According to PCIe Base specification 3.0, when transitioning + * from a non-DL_Up Status to a DL_Up Status, the Port must + * initiate the transmission of a Set_Slot_Power_Limit Message + * to the other component on the Link to convey the value + * programmed in the Slot Power Limit Scale and Value fields of + * the Slot Capabilities register. This transmission is optional + * if the Slot Capabilities register has not yet been + * initialized. + */ + slotctl = le16_to_cpu(pcie->bridge.pcie_conf.slotctl); + slotpwr = FIELD_GET(PCI_EXP_SLTCAP_SPLV | PCI_EXP_SLTCAP_SPLS, + le32_to_cpu(pcie->bridge.pcie_conf.slotcap)); + if (!(slotctl & PCI_EXP_SLTCTL_ASPL_DISABLE) && slotpwr) { + val = advk_readl(pcie, PME_MSG_GEN_CTRL); + val &= ~SLOT_POWER_LIMIT_DATA_MASK; + val |= slotpwr << SLOT_POWER_LIMIT_DATA_SHIFT; + val |= SEND_SET_SLOT_POWER_LIMIT; + advk_writel(pcie, val, PME_MSG_GEN_CTRL); + } } return link_is_up; @@ -944,8 +973,9 @@ advk_pci_bridge_emul_pcie_conf_write(struct pci_bridge_emul *bridge, case PCI_EXP_SLTCTL: { u16 slotctl = le16_to_cpu(bridge->pcie_conf.slotctl); - /* Only emulation of HPIE and DLLSCE bits is provided */ - slotctl &= PCI_EXP_SLTCTL_HPIE | PCI_EXP_SLTCTL_DLLSCE; + /* Only emulation of HPIE, DLLSCE and ASPLD bits is provided */ + slotctl &= PCI_EXP_SLTCTL_HPIE | PCI_EXP_SLTCTL_DLLSCE | + PCI_EXP_SLTCTL_ASPL_DISABLE; bridge->pcie_conf.slotctl = cpu_to_le16(slotctl); break; } @@ -1109,9 +1139,13 @@ static int advk_sw_pci_bridge_init(struct advk_pcie *pcie) * Set physical slot number to 1 since there is only one port and zero * value is reserved for ports within the same silicon as Root Port * which is not our case. + * + * Set slot power limit. */ slotcap = PCI_EXP_SLTCAP_NCCS | PCI_EXP_SLTCAP_HPC | - FIELD_PREP(PCI_EXP_SLTCAP_PSN, 1); + FIELD_PREP(PCI_EXP_SLTCAP_PSN, 1) | + FIELD_PREP(PCI_EXP_SLTCAP_SPLV, pcie->slot_power_limit_value) | + FIELD_PREP(PCI_EXP_SLTCAP_SPLS, pcie->slot_power_limit_scale); bridge->pcie_conf.slotcap = cpu_to_le32(slotcap); bridge->pcie_conf.slotsta = cpu_to_le16(PCI_EXP_SLTSTA_PDS); @@ -1837,6 +1871,7 @@ static int advk_pcie_probe(struct platform_device *pdev) struct advk_pcie *pcie; struct pci_host_bridge *bridge; struct resource_entry *entry; + u32 slot_power_limit; int ret, irq; bridge = devm_pci_alloc_host_bridge(dev, sizeof(struct advk_pcie)); @@ -1957,6 +1992,14 @@ static int advk_pcie_probe(struct platform_device *pdev) else pcie->link_gen = ret; + slot_power_limit = of_pci_get_slot_power_limit(dev->of_node, + &pcie->slot_power_limit_value, + &pcie->slot_power_limit_scale); + if (slot_power_limit) + dev_info(dev, "Slot Power Limit: %u.%uW\n", + slot_power_limit / 1000, + (slot_power_limit / 100) % 10); + ret = advk_pcie_setup_phy(pcie); if (ret) return ret;