From mboxrd@z Thu Jan 1 00:00:00 1970 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 DDA80C43458 for ; Sat, 27 Jun 2026 12:15:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:To:From:Reply-To: Cc:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=n0HAnRoWmxVJhdNy0Aj/UApzioKy1NxiDXgx0VMIzbA=; b=bTgSIKDw4QlYKntADe6EKWr2lR 9F1gkoq8/2iwLqIL2ZRii/h6PQYdAZK50bEihBnSA6opdf5AhBhpDnCAM3h2rNl8+3BRp2Gveyr8U n9G4ahP59XLNYXERhYU58yP43AFmezmJztEIbjMdBaC89FEVIFEyDWvcvOiOLabucnTggxhk05G1L p3b/NEoYg+oVkh13Uy9yYEV15GyGQ48uaw/NfpW5NZqiU+fYTrjNxkNOKFJUoGhYcGyD3ZmKKXnmm QvprlwQvBz+I/uW8/Q4RyqBxDtDZPpg7Q0BdYK2us/4Z78+vfCVDWEn4ZJR0JT2G9YIoprxey5uQG p75WZ57A==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.99.1 #2 (Red Hat Linux)) id 1wdRwO-0000000CRXH-3Beb; Sat, 27 Jun 2026 12:15:20 +0000 Received: from mail-wm1-x32f.google.com ([2a00:1450:4864:20::32f]) by bombadil.infradead.org with esmtps (Exim 4.99.1 #2 (Red Hat Linux)) id 1wdRwC-0000000CROG-0mTF for linux-mediatek@lists.infradead.org; Sat, 27 Jun 2026 12:15:09 +0000 Received: by mail-wm1-x32f.google.com with SMTP id 5b1f17b1804b1-493a5392c60so15165e9.2 for ; Sat, 27 Jun 2026 05:15:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1782562506; x=1783167306; darn=lists.infradead.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=n0HAnRoWmxVJhdNy0Aj/UApzioKy1NxiDXgx0VMIzbA=; b=jkcZMuzCfaN+XBcSETpAYQwXaDAir+BNxdhbpBVXTySlfecNZFk7jG/Pgu1Y8rkDvP BRXx5YUGugs/m1IdjlMxQ/9nLvrLA2yzOcovZHEImqxhVZ0wERWRY+MDT1ZnLNY3WsC2 /ib5nureZ1FLw6Ag+zgytkwY2sslgKKR35RKHv2r5chS67p6T8sV3yyV+ag1UWcKJLae nQvoiE0kEfyXCpJMQZDzn/q0jra58Kvhdm2M4ywV1Noe9lTNH+EJ8C+OhTncH5Vivf8F f6nEDM6+Ru+xTqtm8Q6lpsIfS5JRZrIo2DoRJroqLrAN4XUr3Lfu3h2LWSnnM6PFAnrt JNKQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1782562506; x=1783167306; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=n0HAnRoWmxVJhdNy0Aj/UApzioKy1NxiDXgx0VMIzbA=; b=ntV0oUT8yb2EV6bhlx4uPTKQBvk3tqbWAhLyGuerf03FrqMl8ftMH3FOU0CHcm1lYY QwbiMF9huVHr+kgatJwp1Wdbo+EeBeZ15QeLU086mxLlSr/r+S+e9hYJMmljjjNGGZFn 26wMB87dJjadGZvhKSxSov7fgv10LgnNV+vuJs5kpU6boU0uwVK5BkhNnLtJNaqnw5QO XSBFPvgqOoenO4E7P/jjFihp2b2eCZL6QeJ+ZJInkUC5lIHyRLQbmQyXJE5u4BGI6O2d 4W7wF9iZNxLYebMA6uUXTzYCRN9f91q5oR4yn4gdLKI9JnJIsm0o3lREyM5KXiKpq6bY DY2Q== X-Forwarded-Encrypted: i=1; AFNElJ+DdyG/+jZzVv3UVUn/j03t73sNDp7ilbk6nIgPS8Kf2ViPY9hoOgA2UHkzZtVH3jmbSWLMYNcJZlxWRRa4hQ==@lists.infradead.org X-Gm-Message-State: AOJu0YxTjJ3MRvR7MLadc581leL7vddUx2DGl1AYSeajPy1wiB66xclc jaBl7Ie6LlrPzI9hFQs6ElBtw0QlQKSLYPjdCcmcYUg2wLM/iryZN7wn X-Gm-Gg: AfdE7cnxxy9v24oEy66Fy2jMFbA2F6tIikCyLGjHDCklcdbz0617I5CWgbsdfQiLqEz mphYy4mkvDu8YtMMEMPR0jgnbow+bJvq7iyQnkOfAktRA2Ye9p5oA1dltYwFqVM+o0QKVrSoob/ K7IjWJV9dkjPRpHEe0Z0EcQtmW6d743Gss8rmdyZJf7x27SSMcAJ6eKxcKWrEzsCBiAECU2XO/K zNh0mLj/coN3JDSpI33usDCm3ZEzQICf6GraIT6svD9yzodbaSPrBXdWnB4C5BWk9832t+DGyt0 QVyEq26DwZygEstsg7uwlov+4tmEAh/0Rxezq/stD9ELzd+toacvy4D0CKvyFpzz+/aM8Dhsvt6 7SjK8AIxbn6BbhRprllG0CtpzyV/xd3h4fhNV8k3D7F3O2ERWkEgJGDw7V+bxfNtHCEwCQuUT9r 9DNeAo+PIMdcU4qzjR6peIu2zAw57TXuErkubvtBvVVMEfiz3/FjYcNsF4Y5mfo/iGRtT1bSac X-Received: by 2002:a05:600c:e557:20b0:490:a1dc:e542 with SMTP id 5b1f17b1804b1-49266862d71mr106741475e9.6.1782562506392; Sat, 27 Jun 2026 05:15:06 -0700 (PDT) Received: from Ansuel-XPS24.localdomain (93-34-89-195.ip49.fastwebnet.it. [93.34.89.195]) by smtp.googlemail.com with ESMTPSA id 5b1f17b1804b1-49269002511sm149028265e9.8.2026.06.27.05.15.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 27 Jun 2026 05:15:05 -0700 (PDT) From: Christian Marangi To: Bjorn Helgaas , Lorenzo Pieralisi , =?UTF-8?q?Krzysztof=20Wilczy=C5=84ski?= , Manivannan Sadhasivam , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Ryder Lee , Michael Turquette , Stephen Boyd , Brian Masney , Philipp Zabel , Matthias Brugger , AngeloGioacchino Del Regno , Christian Marangi , Jianjun Wang , linux-pci@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-mediatek@lists.infradead.org, linux-clk@vger.kernel.org, linux-arm-kernel@lists.infradead.org Subject: [PATCH v3 4/4] PCI: mediatek-gen3: Add 2-lanes mode support for Airoha AN7581 Date: Sat, 27 Jun 2026 14:14:45 +0200 Message-ID: <20260627121450.3529133-5-ansuelsmth@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260627121450.3529133-1-ansuelsmth@gmail.com> References: <20260627121450.3529133-1-ansuelsmth@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.9.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20260627_051508_269523_973232EE X-CRM114-Status: GOOD ( 25.39 ) X-BeenThere: linux-mediatek@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-mediatek" Errors-To: linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org The Airoha AN7581 SoC supports configuring the first PCIe0 lane to 2-lanes mode (2x link) by bonding it with the second PCIe lane (PCIe1). This is done by configuring the PCIe MUX in the SCU register. To correctly configure PCIe0 in 2x link, define in DT the following additional property: - additional reg, 'sec-pcie-mac' for the secondary PCIe. - PERSTOUT reset for both main and secondary PCIE0, called 'perstout' and 'sec-perstout' - airoha,scu property to correctly configure the SCU register for the PCIe MUX - 'num-lanes' set to '2' to enable PCIe0 in 2x link In such configuration the EQ preset are configured to the same values. To permit correct configuration of the PCIe line, additional logic is added to assert and deassert the PERSTOUT resets. Signed-off-by: Christian Marangi --- drivers/pci/controller/pcie-mediatek-gen3.c | 104 ++++++++++++++++---- 1 file changed, 87 insertions(+), 17 deletions(-) diff --git a/drivers/pci/controller/pcie-mediatek-gen3.c b/drivers/pci/controller/pcie-mediatek-gen3.c index b0accd828589..ba28d95e5d44 100644 --- a/drivers/pci/controller/pcie-mediatek-gen3.c +++ b/drivers/pci/controller/pcie-mediatek-gen3.c @@ -32,6 +32,11 @@ #include "../pci.h" +/* AN7581 SCU register */ +#define SCU_PCIC 0x88 +#define SCU_PCIC_PCIE_CTRL GENMASK(7, 0) + +/* PCIe register */ #define PCIE_BASE_CFG_REG 0x14 #define PCIE_BASE_CFG_SPEED GENMASK(15, 8) @@ -131,6 +136,7 @@ #define PCIE_ATR_TLP_TYPE_IO PCIE_ATR_TLP_TYPE(2) #define MAX_NUM_PHY_RESETS 3 +#define MAX_NUM_PERSTOUT_RESETS 2 #define PCIE_MTK_RESET_TIME_US 10 @@ -203,9 +209,11 @@ struct mtk_msi_set { struct mtk_gen3_pcie { struct device *dev; void __iomem *base; + void __iomem *sec_base; phys_addr_t reg_base; struct reset_control *mac_reset; struct reset_control_bulk_data phy_resets[MAX_NUM_PHY_RESETS]; + struct reset_control_bulk_data perstout_resets[MAX_NUM_PERSTOUT_RESETS]; struct phy *phy; struct clk_bulk_data *clks; int num_clks; @@ -928,6 +936,14 @@ static int mtk_pcie_parse_port(struct mtk_gen3_pcie *pcie) if (ret) return dev_err_probe(dev, ret, "failed to get PHY bulk reset\n"); + pcie->perstout_resets[0].id = "perstout"; + pcie->perstout_resets[1].id = "sec-perstout"; + + ret = devm_reset_control_bulk_get_optional_exclusive(dev, MAX_NUM_PERSTOUT_RESETS, + pcie->perstout_resets); + if (ret) + return dev_err_probe(dev, ret, "failed to get PERSTOUT bulk reset\n"); + pcie->mac_reset = devm_reset_control_get_optional_exclusive(dev, "mac"); if (IS_ERR(pcie->mac_reset)) return dev_err_probe(dev, PTR_ERR(pcie->mac_reset), "failed to get MAC reset\n"); @@ -949,18 +965,38 @@ static int mtk_pcie_parse_port(struct mtk_gen3_pcie *pcie) pcie->num_lanes = num_lanes; } + /* Map secondary PCIe for 2-lanes mode for EN7581 */ + if (pcie->num_lanes == 2 && device_is_compatible(dev, "airoha,en7581-pcie")) { + regs = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sec-pcie-mac"); + if (!regs) + return -EINVAL; + pcie->sec_base = devm_ioremap_resource(dev, regs); + if (IS_ERR(pcie->sec_base)) + return dev_err_probe(dev, PTR_ERR(pcie->sec_base), "failed to map secondary register base\n"); + } + return 0; } static int mtk_pcie_en7581_power_up(struct mtk_gen3_pcie *pcie) { struct pci_host_bridge *host = pci_host_bridge_from_priv(pcie); + unsigned int num_lanes = max(1, pcie->num_lanes); + struct regmap *pbus_regmap, *scu; struct device *dev = pcie->dev; struct resource_entry *entry; - struct regmap *pbus_regmap; u32 val, args[2], size; resource_size_t addr; - int err; + int i, err; + + if (num_lanes > 2) + return dev_err_probe(dev, -EINVAL, "unsupported num-lanes, maximum 2 lanes supported\n"); + + if (num_lanes == 2) { + scu = syscon_regmap_lookup_by_phandle(dev->of_node, "airoha,scu"); + if (IS_ERR(scu)) + return dev_err_probe(dev, PTR_ERR(scu), "failed to map SCU regmap\n"); + } /* * The controller may have been left out of reset by the bootloader @@ -992,6 +1028,19 @@ static int mtk_pcie_en7581_power_up(struct mtk_gen3_pcie *pcie) size = lower_32_bits(resource_size(entry->res)); regmap_write(pbus_regmap, args[1], GENMASK(31, __fls(size))); + /* Assert PERSTOUT for all relevant lines */ + err = reset_control_bulk_assert(MAX_NUM_PERSTOUT_RESETS, + pcie->perstout_resets); + if (err) { + dev_err(dev, "failed to assert PERSTOUTs\n"); + return err; + } + + /* Configure SCU MUX to disable PCIE1 for 2 lines mode */ + if (num_lanes == 2) + regmap_update_bits(scu, SCU_PCIC, SCU_PCIC_PCIE_CTRL, + FIELD_PREP(SCU_PCIC_PCIE_CTRL, BIT(1))); + /* * Unlike the other MediaTek Gen3 controllers, the Airoha EN7581 * requires PHY initialization and power-on before PHY reset deassert. @@ -1024,18 +1073,6 @@ static int mtk_pcie_en7581_power_up(struct mtk_gen3_pcie *pcie) pm_runtime_enable(dev); pm_runtime_get_sync(dev); - val = FIELD_PREP(PCIE_VAL_LN0_DOWNSTREAM, 0x47) | - FIELD_PREP(PCIE_VAL_LN1_DOWNSTREAM, 0x47) | - FIELD_PREP(PCIE_VAL_LN0_UPSTREAM, 0x41) | - FIELD_PREP(PCIE_VAL_LN1_UPSTREAM, 0x41); - writel_relaxed(val, pcie->base + PCIE_EQ_PRESET_01_REG); - - val = PCIE_K_PHYPARAM_QUERY | PCIE_K_QUERY_TIMEOUT | - FIELD_PREP(PCIE_K_PRESET_TO_USE_16G, 0x80) | - FIELD_PREP(PCIE_K_PRESET_TO_USE, 0x2) | - FIELD_PREP(PCIE_K_FINETUNE_MAX, 0xf); - writel_relaxed(val, pcie->base + PCIE_PIPE4_PIE8_REG); - err = clk_bulk_prepare_enable(pcie->num_clks, pcie->clks); if (err) { dev_err(dev, "failed to prepare clock\n"); @@ -1043,14 +1080,47 @@ static int mtk_pcie_en7581_power_up(struct mtk_gen3_pcie *pcie) } /* - * Airoha EN7581 performs PCIe reset via clk callbacks since it has a - * hw issue with PCIE_PE_RSTB signal. Add wait for the time needed to - * complete the PCIe reset. + * Old Airoha EN7581 clock driver performed PCIe reset via + * clk callbacks since it has a hw issue with PCIE_PE_RSTB signal. + * This is now handled by dedicated PERSTOUT resets with clk + * driver only enabling the refclk. + * + * Wait is still needed for refclk to stabilize */ msleep(PCIE_T_PVPERL_MS); + /* Configure all the lines to the same EQ config */ + for (i = 0; i < num_lanes; i++) { + void __iomem *base = pcie->base; + + if (i == 1) + base = pcie->sec_base; + + val = FIELD_PREP(PCIE_VAL_LN0_DOWNSTREAM, 0x47) | + FIELD_PREP(PCIE_VAL_LN1_DOWNSTREAM, 0x47) | + FIELD_PREP(PCIE_VAL_LN0_UPSTREAM, 0x41) | + FIELD_PREP(PCIE_VAL_LN1_UPSTREAM, 0x41); + writel_relaxed(val, base + PCIE_EQ_PRESET_01_REG); + + val = PCIE_K_PHYPARAM_QUERY | PCIE_K_QUERY_TIMEOUT | + FIELD_PREP(PCIE_K_PRESET_TO_USE_16G, 0x80) | + FIELD_PREP(PCIE_K_PRESET_TO_USE, 0x2) | + FIELD_PREP(PCIE_K_FINETUNE_MAX, 0xf); + writel_relaxed(val, base + PCIE_PIPE4_PIE8_REG); + } + + /* Deassert PERSTOUT for all relevant lines */ + err = reset_control_bulk_deassert(MAX_NUM_PERSTOUT_RESETS, + pcie->perstout_resets); + if (err) { + dev_err(dev, "failed to deassert PERSTOUTs\n"); + goto err_perstout_deassert; + } + return 0; +err_perstout_deassert: + clk_bulk_disable_unprepare(pcie->num_clks, pcie->clks); err_clk_prepare_enable: pm_runtime_put_sync(dev); pm_runtime_disable(dev); -- 2.53.0