From patchwork Mon Jan 30 22:40:20 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Hoffmann X-Patchwork-Id: 1734517 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.openwrt.org (client-ip=2607:7c80:54:3::133; helo=bombadil.infradead.org; envelope-from=openwrt-devel-bounces+incoming=patchwork.ozlabs.org@lists.openwrt.org; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; secure) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20210309 header.b=foTPoae9; dkim=fail reason="signature verification failed" (2048-bit key; secure) header.d=3e8.eu header.i=@3e8.eu header.a=rsa-sha256 header.s=mail20211217 header.b=U13BPPUH; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:3::133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4P5NW65zf2z23hg for ; Tue, 31 Jan 2023 09:43:14 +1100 (AEDT) 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: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:In-Reply-To:References: List-Owner; bh=mGr6Lt6gonbhI9LVw2ShD7wxgaJu4xcs1iYqQe3y+tM=; b=foTPoae9TTyXfH FAcpQquQNvIugxAHLKuj2N67+4DsZIw/7rObjbt68jN8tBoqEaDIFDTU/29OfzuG72oSHybHc69HA 70GLjSE56IWmfCXPe57H19utHTPUB5XiFyIKpnKI+JOiZaYVyNek/2L80zxk8BZi5nZfapN5NlkHh 33FaQ+iKFqAXUVbND4X3OyqBfBqCycY38U8p5lcrpJ5LxBhHUaAwvamXM8HxsmTiSp8OhbkWqU0kw iBvnu8FIkYPHAT+4FLsHsYkqIDFEygSPNW28NKqOoHIV2jQvNbn/Fq3SuAe2xPPeTtW0vLOZV/ocr X2n+bGE2w0m2QFNHPuQw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1pMcpp-005fda-1d; Mon, 30 Jan 2023 22:41:09 +0000 Received: from srv4.3e8.eu ([193.25.101.238]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1pMcpg-005fbO-Fk for openwrt-devel@lists.openwrt.org; Mon, 30 Jan 2023 22:41:06 +0000 Received: from localhost.localdomain (p200300c6cf2a62a066f0c3dfd7cd766d.dip0.t-ipconnect.de [IPv6:2003:c6:cf2a:62a0:66f0:c3df:d7cd:766d]) (using TLSv1.3 with cipher TLS_CHACHA20_POLY1305_SHA256 (256/256 bits)) (No client certificate requested) by srv4.3e8.eu (Postfix) with ESMTPSA id 0B665600C7; Mon, 30 Jan 2023 23:40:40 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=3e8.eu; s=mail20211217; t=1675118441; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding; bh=qfL0g7412AD0A3PixFwxYydSlzHVK9oIG7RNFN1xDuA=; b=U13BPPUHAWW+ko1sSGIw7aJfa7irBwRf4q7F1hJEUzA8llnSDsPAsoGvBRlY+7zvL1Cn4p ecN83ZJkjrUKVSC01fZLZ2ThM3gwFl4AIMI29cavMJHKbFCWZ9yxKJBb6lCiJArCYZPOwI 08D2i7tw0fYumzSBlKLJYcD+ytDJ6sdxUTjusiTVfUc/Nyw2h8wqEfO2jp4610l59uNDoH DPWrs6bXuU+v4e5diOW6vR0GaRNA3VlPEV2fuoqzBUhSELo6skbyrUPcmixJeZDeQqY7gD PLZU2Ux3rqtL7k95akJSskun8es5QwTrFwKFhppVwp+TX682pjRXweRwXlLiHQ== From: Jan Hoffmann To: openwrt-devel@lists.openwrt.org Cc: Jan Hoffmann Subject: [PATCH] ipq40xx: add PCIe magic hack to improve VRX518 compatibility Date: Mon, 30 Jan 2023 23:40:20 +0100 Message-Id: <20230130224020.473703-1-jan@3e8.eu> X-Mailer: git-send-email 2.39.1 MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20230130_144101_430836_0BCDEB0B X-CRM114-Status: GOOD ( 23.60 ) X-Spam-Score: -0.2 (/) X-Spam-Report: Spam detection software, running on the system "bombadil.infradead.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: Some VRX518 modems fail to initialize properly with the error message "dc_ep_clk_on failed". As a result, the DSL data path doesn't work. This hack, which is based on code from the FRITZ!Box 7530 GPL archive, fixes the issue. It changes the PCIe vendor/device ID to values matching a Lantiq SoC. It also appears to emulate a Lantiq CPU ID [...] Content analysis details: (-0.2 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_PASS SPF: sender matches SPF record -0.0 SPF_HELO_PASS SPF: HELO matches SPF record -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain X-BeenThere: openwrt-devel@lists.openwrt.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: OpenWrt Development List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "openwrt-devel" Errors-To: openwrt-devel-bounces+incoming=patchwork.ozlabs.org@lists.openwrt.org Some VRX518 modems fail to initialize properly with the error message "dc_ep_clk_on failed". As a result, the DSL data path doesn't work. This hack, which is based on code from the FRITZ!Box 7530 GPL archive, fixes the issue. It changes the PCIe vendor/device ID to values matching a Lantiq SoC. It also appears to emulate a Lantiq CPU ID register for connected PCIe devices, by remapping the matching address area to a specially crafted buffer using the address translation unit. The hack is only active if the "avm,host_magic" property is specified in the device tree, so this shouldn't affect any devices other than FRITZ!Box 7530/7520. Signed-off-by: Jan Hoffmann Tested-by: Felix Maurer --- .../boot/dts/qcom-ipq4019-fritzbox-7530.dts | 2 + .../997-pcie-qcom-host-magic.patch | 215 ++++++++++++++++++ 2 files changed, 217 insertions(+) create mode 100644 target/linux/ipq40xx/patches-5.15/997-pcie-qcom-host-magic.patch diff --git a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-fritzbox-7530.dts b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-fritzbox-7530.dts index 336da52f2724..bc167616d3dc 100644 --- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-fritzbox-7530.dts +++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-fritzbox-7530.dts @@ -306,6 +306,8 @@ perst-gpio = <&tlmm 38 GPIO_ACTIVE_LOW>; wake-gpio = <&tlmm 50 GPIO_ACTIVE_LOW>; + avm,host_magic; + bridge@0,0 { reg = <0x00000000 0 0 0 0>; #address-cells = <3>; diff --git a/target/linux/ipq40xx/patches-5.15/997-pcie-qcom-host-magic.patch b/target/linux/ipq40xx/patches-5.15/997-pcie-qcom-host-magic.patch new file mode 100644 index 000000000000..f427bccd2f4a --- /dev/null +++ b/target/linux/ipq40xx/patches-5.15/997-pcie-qcom-host-magic.patch @@ -0,0 +1,215 @@ +This hack is based on code from the FRITZ!Box 7530 GPL archive for +firmware version 07.50. + +If the device tree contains the "avm,host_magic" property, it changes +the PCIe vendor/device ID to the values from Lantiq GRX500 SoCs. It also +programs the ATU to present a buffer containing a magic value to PCIe +devices. This appears to emulate a Lantiq CPU ID register. + +Without this hack, some VRX518 modems fail to initialize properly (error +"dc_ep_clk_on failed"), and the DSL data path doesn't work. +--- a/drivers/pci/controller/dwc/pcie-qcom.c ++++ b/drivers/pci/controller/dwc/pcie-qcom.c +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + + #include "../../pci.h" + #include "pcie-designware.h" +@@ -102,6 +103,8 @@ + + #define QCOM_PCIE_CRC8_POLYNOMIAL (BIT(2) | BIT(1) | BIT(0)) + ++#define PCIE_MAGIC_SIZE 0x10000 ++ + struct qcom_pcie_resources_2_1_0 { + struct clk_bulk_data clks[QCOM_PCIE_2_1_0_MAX_CLOCKS]; + struct reset_control *pci_reset; +@@ -197,6 +200,8 @@ struct qcom_pcie { + struct phy *phy; + struct gpio_desc *reset; + const struct qcom_pcie_ops *ops; ++ void *magic_cpu_addr; ++ dma_addr_t magic_dma_handle; + }; + + #define to_qcom_pcie(x) dev_get_drvdata((x)->dev) +@@ -1388,8 +1393,141 @@ err_deinit: + return ret; + } + ++static int qcom_pcie_magic_prog_atu(struct qcom_pcie *pcie, ++ u32 addr, u32 limit, u32 phys) ++{ ++ struct dw_pcie *pci = pcie->pci; ++ struct device *dev = pci->dev; ++ u32 retries, val; ++ int index; ++ ++ if (!pci->num_ib_windows) { ++ dev_err(dev, "No inbound ATU window available for magic\n"); ++ return -1; ++ } ++ ++ /* ++ * Use highest window index and reduce window count so the driver ++ * won't overwrite the entry later. ++ */ ++ index = --pci->num_ib_windows; ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(6,0,0) ++ if (pci->iatu_unroll_enabled) { ++ dev_err(dev, "Programming ATU for magic not implemented for this hardware\n"); ++ return -1; ++ } ++ ++ dw_pcie_writel_dbi(pci, PCIE_ATU_VIEWPORT, ++ PCIE_ATU_REGION_INBOUND | index); ++ ++ dw_pcie_writel_dbi(pci, PCIE_ATU_LOWER_BASE, addr); ++ dw_pcie_writel_dbi(pci, PCIE_ATU_UPPER_BASE, 0); ++ dw_pcie_writel_dbi(pci, PCIE_ATU_LIMIT, limit); ++ dw_pcie_writel_dbi(pci, PCIE_ATU_LOWER_TARGET, phys); ++ dw_pcie_writel_dbi(pci, PCIE_ATU_UPPER_TARGET, 0); ++ ++ dw_pcie_writel_dbi(pci, PCIE_ATU_CR1, PCIE_ATU_TYPE_MEM); ++ dw_pcie_writel_dbi(pci, PCIE_ATU_CR2, PCIE_ATU_ENABLE); ++ ++ for (retries = 0; retries < LINK_WAIT_MAX_IATU_RETRIES; retries++) { ++ val = dw_pcie_readl_dbi(pci, PCIE_ATU_CR2); ++ if (val & PCIE_ATU_ENABLE) ++ return 0; ++ ++ mdelay(LINK_WAIT_IATU); ++ } ++#else ++ dw_pcie_writel_atu_ib(pci, index, PCIE_ATU_LOWER_BASE, addr); ++ dw_pcie_writel_atu_ib(pci, index, PCIE_ATU_UPPER_BASE, 0); ++ dw_pcie_writel_atu_ib(pci, index, PCIE_ATU_LIMIT, limit); ++ dw_pcie_writel_atu_ib(pci, index, PCIE_ATU_LOWER_TARGET, phys); ++ dw_pcie_writel_atu_ib(pci, index, PCIE_ATU_UPPER_TARGET, 0); ++ ++ dw_pcie_writel_atu_ib(pci, index, PCIE_ATU_REGION_CTRL1, ++ PCIE_ATU_TYPE_MEM); ++ dw_pcie_writel_atu_ib(pci, index, PCIE_ATU_REGION_CTRL2, ++ PCIE_ATU_ENABLE); ++ ++ for (retries = 0; retries < LINK_WAIT_MAX_IATU_RETRIES; retries++) { ++ val = dw_pcie_readl_atu_ib(pci, index, PCIE_ATU_REGION_CTRL2); ++ if (val & PCIE_ATU_ENABLE) ++ return 0; ++ ++ mdelay(LINK_WAIT_IATU); ++ } ++#endif ++ ++ dev_err(dev, "Failed to program ATU for magic\n"); ++ return -1; ++} ++ ++static void qcom_pcie_magic_deinit(struct qcom_pcie *pcie) ++{ ++ struct dw_pcie *pci = pcie->pci; ++ struct device *dev = pci->dev; ++ ++ if (pcie->magic_cpu_addr) { ++ dma_free_coherent(dev, PCIE_MAGIC_SIZE, ++ pcie->magic_cpu_addr, ++ pcie->magic_dma_handle); ++ ++ pcie->magic_cpu_addr = NULL; ++ } ++} ++ ++static void qcom_pcie_magic_init(struct qcom_pcie *pcie) ++{ ++ struct dw_pcie *pci = pcie->pci; ++ struct device *dev = pci->dev; ++ u32 *virt; ++ u32 phys; ++ int ret; ++ ++ if (!of_property_read_bool(dev->of_node, "avm,host_magic")) ++ return; ++ ++ dev_info(dev, "Applying PCIe host magic\n"); ++ ++ virt = dma_alloc_coherent(dev, PCIE_MAGIC_SIZE, &phys, GFP_ATOMIC); ++ BUG_ON(virt == NULL); ++ ++ pcie->magic_cpu_addr = virt; ++ pcie->magic_dma_handle = phys; ++ ++ /* ++ * This value is the manufacturer ID of Lantiq. The address where ++ * it will be visible for the PCIe device matches the location of ++ * CPU ID registers on Lantiq SocS (MPS base address is 0x1f107000). ++ */ ++ virt[0x7340/4] = 0x389 << 5; ++ ++ /* Make it visible to PCIe devices using address translation unit */ ++ ret = qcom_pcie_magic_prog_atu(pcie, 0x1f100000, 0x1f10ffff, phys); ++ ++ dw_pcie_dbi_ro_wr_en(pci); ++ ++ /* Set vendor/device ID of GRX500 PCIe host */ ++ dw_pcie_writew_dbi(pci, PCI_VENDOR_ID, 0x1bef); ++ dw_pcie_writew_dbi(pci, PCI_DEVICE_ID, 0x0030); ++ ++ dw_pcie_dbi_ro_wr_dis(pci); ++ ++ if (ret) ++ qcom_pcie_magic_deinit(pcie); ++} ++ ++static void qcom_pcie_atu_hack(struct pcie_port *pp) ++{ ++ struct dw_pcie *pci = to_dw_pcie_from_pp(pp); ++ struct qcom_pcie *pcie = to_qcom_pcie(pci); ++ ++ qcom_pcie_magic_init(pcie); ++} ++ + static const struct dw_pcie_host_ops qcom_pcie_dw_ops = { + .host_init = qcom_pcie_host_init, ++ .atu_hack = qcom_pcie_atu_hack, + }; + + /* Qcom IP rev.: 2.1.0 Synopsys IP rev.: 4.01a */ +@@ -1536,6 +1674,7 @@ static int qcom_pcie_probe(struct platfo + + err_phy_exit: + phy_exit(pcie->phy); ++ qcom_pcie_magic_deinit(pcie); + err_pm_runtime_put: + pm_runtime_put(dev); + pm_runtime_disable(dev); +--- a/drivers/pci/controller/dwc/pcie-designware-host.c ++++ b/drivers/pci/controller/dwc/pcie-designware-host.c +@@ -400,6 +400,14 @@ int dw_pcie_host_init(struct pcie_port * + } + dw_pcie_iatu_detect(pci); + ++ /* ++ * This needs to be called after ATU detection, but before the driver ++ * sets up any ATU entries, to avoid any ATU entry programmed in the ++ * hack being overwritten by the driver later. ++ */ ++ if (pp->ops->atu_hack) ++ pp->ops->atu_hack(pp); ++ + dw_pcie_setup_rc(pp); + + if (!dw_pcie_link_up(pci) && pci->ops && pci->ops->start_link) { +--- a/drivers/pci/controller/dwc/pcie-designware.h ++++ b/drivers/pci/controller/dwc/pcie-designware.h +@@ -174,6 +174,7 @@ enum dw_pcie_device_mode { + + struct dw_pcie_host_ops { + int (*host_init)(struct pcie_port *pp); ++ void (*atu_hack)(struct pcie_port *pp); + int (*msi_host_init)(struct pcie_port *pp); + }; +