[openwrt/openwrt] ipq4019: patch initialization of Lantiq DSL on FritzBox 7530.

LEDE Commits lede-commits at lists.infradead.org
Sun Jan 19 02:01:39 PST 2025


robimarko pushed a commit to openwrt/openwrt.git, branch openwrt-24.10:
https://git.openwrt.org/f31ab2abef2f4ef36d5c4ee38b97adfbec43a2b9

commit f31ab2abef2f4ef36d5c4ee38b97adfbec43a2b9
Author: Christian Marangi <ansuelsmth at gmail.com>
AuthorDate: Tue May 7 20:44:27 2024 +0200

    ipq4019: patch initialization of Lantiq DSL on FritzBox 7530.
    
    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.
    
    A dedicated compatible is created to activate this in
    the device tree, so this shouldn't affect any devices other than
    FRITZ!Box 7530/7520.
    
    Original investigation was done in https://github.com/janh/openwrt/commit/59f52125178146a9dc44290c11c63e5e029e8044 which used the "avm,host_magic" property to enabled the patch.
    
    Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
    Signed-off-by: Florian Maurer <f.maurer at outlook.de>
    Link: https://github.com/openwrt/openwrt/pull/17622
    Signed-off-by: Robert Marko <robimarko at gmail.com>
    (cherry picked from commit 676dcb1b2cf84142a61d51a15e7a8e1bdc937c23)
---
 ....7-01-PCI-dwc-Add-host_post_init-callback.patch |  42 ++++++
 ...able-ASPM-for-platforms-supporting-1.9.0-.patch | 102 +++++++++++++
 .../boot/dts/qcom/qcom-ipq4019-fritzbox-7530.dts   |   1 +
 ...dd-hack-compatible-for-ipq4019-Lantiq-DSL.patch | 166 +++++++++++++++++++++
 4 files changed, 311 insertions(+)

diff --git a/target/linux/generic/backport-6.6/870-v6.7-01-PCI-dwc-Add-host_post_init-callback.patch b/target/linux/generic/backport-6.6/870-v6.7-01-PCI-dwc-Add-host_post_init-callback.patch
new file mode 100644
index 0000000000..d70c65225e
--- /dev/null
+++ b/target/linux/generic/backport-6.6/870-v6.7-01-PCI-dwc-Add-host_post_init-callback.patch
@@ -0,0 +1,42 @@
+From a78794562fcb2659c976388b1285eddda97e9954 Mon Sep 17 00:00:00 2001
+From: Manivannan Sadhasivam <manivannan.sadhasivam at linaro.org>
+Date: Tue, 10 Oct 2023 21:29:13 +0530
+Subject: [PATCH] PCI: dwc: Add host_post_init() callback
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This callback can be used by the platform drivers to do configuration
+once all the devices are scanned. Like changing LNKCTL of all downstream
+devices to enable ASPM etc...
+
+Link: https://lore.kernel.org/linux-pci/20231010155914.9516-2-manivannan.sadhasivam@linaro.org
+Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam at linaro.org>
+Signed-off-by: Krzysztof Wilczyński <kwilczynski at kernel.org>
+---
+ drivers/pci/controller/dwc/pcie-designware-host.c | 3 +++
+ drivers/pci/controller/dwc/pcie-designware.h      | 1 +
+ 2 files changed, 4 insertions(+)
+
+--- a/drivers/pci/controller/dwc/pcie-designware-host.c
++++ b/drivers/pci/controller/dwc/pcie-designware-host.c
+@@ -502,6 +502,9 @@ int dw_pcie_host_init(struct dw_pcie_rp
+ 	if (ret)
+ 		goto err_stop_link;
+ 
++	if (pp->ops->host_post_init)
++		pp->ops->host_post_init(pp);
++
+ 	return 0;
+ 
+ err_stop_link:
+--- a/drivers/pci/controller/dwc/pcie-designware.h
++++ b/drivers/pci/controller/dwc/pcie-designware.h
+@@ -301,6 +301,7 @@ enum dw_pcie_ltssm {
+ struct dw_pcie_host_ops {
+ 	int (*host_init)(struct dw_pcie_rp *pp);
+ 	void (*host_deinit)(struct dw_pcie_rp *pp);
++	void (*host_post_init)(struct dw_pcie_rp *pp);
+ 	int (*msi_host_init)(struct dw_pcie_rp *pp);
+ 	void (*pme_turn_off)(struct dw_pcie_rp *pp);
+ };
diff --git a/target/linux/generic/backport-6.6/870-v6.7-02-PCI-qcom-Enable-ASPM-for-platforms-supporting-1.9.0-.patch b/target/linux/generic/backport-6.6/870-v6.7-02-PCI-qcom-Enable-ASPM-for-platforms-supporting-1.9.0-.patch
new file mode 100644
index 0000000000..7fdede52f4
--- /dev/null
+++ b/target/linux/generic/backport-6.6/870-v6.7-02-PCI-qcom-Enable-ASPM-for-platforms-supporting-1.9.0-.patch
@@ -0,0 +1,102 @@
+From 9f4f3dfad8cf08208fbb78b1b9cbf957c12618b9 Mon Sep 17 00:00:00 2001
+From: Manivannan Sadhasivam <manivannan.sadhasivam at linaro.org>
+Date: Tue, 10 Oct 2023 21:29:14 +0530
+Subject: [PATCH] PCI: qcom: Enable ASPM for platforms supporting 1.9.0 ops
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+ASPM is supported by Qcom host controllers/bridges on most of the recent
+platforms and so the devices tested so far. But for enabling ASPM by
+default (without using Kconfig, kernel command-line or sysfs), BIOS has
+to enable ASPM on both host bridge and downstream devices during boot.
+
+Unfortunately, none of the BIOS available on Qcom platforms enables
+ASPM. Due to this, the platforms making use of Qcom SoCs draw high power
+during runtime.
+
+To fix this power draw issue, users have to enable ASPM using Kconfig,
+kernel command-line, sysfs or the BIOS has to start enabling ASPM.
+
+The latter may happen in the future, but that won't address the issue on
+current platforms. Also, asking users to enable a feature to get the power
+management right would provide an unpleasant out-of-the-box experience.
+
+So the apt solution is to enable ASPM in the controller driver itself. And
+this is being accomplished by calling pci_enable_link_state() in the newly
+introduced host_post_init() callback for all the devices connected to the
+bus. This function enables all supported link low power states for both
+host bridge and the downstream devices.
+
+Due to limited testing, ASPM is only enabled for platforms making use of
+ops_1_9_0 callbacks.
+
+[kwilczynski: commit log]
+Link: https://lore.kernel.org/linux-pci/20231010155914.9516-3-manivannan.sadhasivam@linaro.org
+Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam at linaro.org>
+Signed-off-by: Krzysztof Wilczyński <kwilczynski at kernel.org>
+---
+ drivers/pci/controller/dwc/pcie-qcom.c | 28 ++++++++++++++++++++++++++
+ 1 file changed, 28 insertions(+)
+
+--- a/drivers/pci/controller/dwc/pcie-qcom.c
++++ b/drivers/pci/controller/dwc/pcie-qcom.c
+@@ -222,6 +222,7 @@ struct qcom_pcie_ops {
+ 	int (*get_resources)(struct qcom_pcie *pcie);
+ 	int (*init)(struct qcom_pcie *pcie);
+ 	int (*post_init)(struct qcom_pcie *pcie);
++	void (*host_post_init)(struct qcom_pcie *pcie);
+ 	void (*deinit)(struct qcom_pcie *pcie);
+ 	void (*ltssm_enable)(struct qcom_pcie *pcie);
+ 	int (*config_sid)(struct qcom_pcie *pcie);
+@@ -966,6 +967,22 @@ static int qcom_pcie_post_init_2_7_0(str
+ 	return 0;
+ }
+ 
++static int qcom_pcie_enable_aspm(struct pci_dev *pdev, void *userdata)
++{
++	/* Downstream devices need to be in D0 state before enabling PCI PM substates */
++	pci_set_power_state(pdev, PCI_D0);
++	pci_enable_link_state(pdev, PCIE_LINK_STATE_ALL);
++
++	return 0;
++}
++
++static void qcom_pcie_host_post_init_2_7_0(struct qcom_pcie *pcie)
++{
++	struct dw_pcie_rp *pp = &pcie->pci->pp;
++
++	pci_walk_bus(pp->bridge->bus, qcom_pcie_enable_aspm, NULL);
++}
++
+ static void qcom_pcie_deinit_2_7_0(struct qcom_pcie *pcie)
+ {
+ 	struct qcom_pcie_resources_2_7_0 *res = &pcie->res.v2_7_0;
+@@ -1224,9 +1241,19 @@ static void qcom_pcie_host_deinit(struct
+ 	pcie->cfg->ops->deinit(pcie);
+ }
+ 
++static void qcom_pcie_host_post_init(struct dw_pcie_rp *pp)
++{
++	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
++	struct qcom_pcie *pcie = to_qcom_pcie(pci);
++
++	if (pcie->cfg->ops->host_post_init)
++		pcie->cfg->ops->host_post_init(pcie);
++}
++
+ static const struct dw_pcie_host_ops qcom_pcie_dw_ops = {
+ 	.host_init	= qcom_pcie_host_init,
+ 	.host_deinit	= qcom_pcie_host_deinit,
++	.host_post_init	= qcom_pcie_host_post_init,
+ };
+ 
+ /* Qcom IP rev.: 2.1.0	Synopsys IP rev.: 4.01a */
+@@ -1288,6 +1315,7 @@ static const struct qcom_pcie_ops ops_1_
+ 	.get_resources = qcom_pcie_get_resources_2_7_0,
+ 	.init = qcom_pcie_init_2_7_0,
+ 	.post_init = qcom_pcie_post_init_2_7_0,
++	.host_post_init = qcom_pcie_host_post_init_2_7_0,
+ 	.deinit = qcom_pcie_deinit_2_7_0,
+ 	.ltssm_enable = qcom_pcie_2_3_2_ltssm_enable,
+ 	.config_sid = qcom_pcie_config_sid_1_9_0,
diff --git a/target/linux/ipq40xx/files-6.6/arch/arm/boot/dts/qcom/qcom-ipq4019-fritzbox-7530.dts b/target/linux/ipq40xx/files-6.6/arch/arm/boot/dts/qcom/qcom-ipq4019-fritzbox-7530.dts
index 39905d4342..8566c7c337 100644
--- a/target/linux/ipq40xx/files-6.6/arch/arm/boot/dts/qcom/qcom-ipq4019-fritzbox-7530.dts
+++ b/target/linux/ipq40xx/files-6.6/arch/arm/boot/dts/qcom/qcom-ipq4019-fritzbox-7530.dts
@@ -307,6 +307,7 @@
 };
 
 &pcie0 {
+	compatible = "qcom,pcie-ipq4019-lantiq-hack";
 	status = "okay";
 
 	perst-gpio = <&tlmm 38 GPIO_ACTIVE_LOW>;
diff --git a/target/linux/ipq40xx/patches-6.6/900-PCI-qcom-add-hack-compatible-for-ipq4019-Lantiq-DSL.patch b/target/linux/ipq40xx/patches-6.6/900-PCI-qcom-add-hack-compatible-for-ipq4019-Lantiq-DSL.patch
new file mode 100644
index 0000000000..af10fd5704
--- /dev/null
+++ b/target/linux/ipq40xx/patches-6.6/900-PCI-qcom-add-hack-compatible-for-ipq4019-Lantiq-DSL.patch
@@ -0,0 +1,166 @@
+From f4f03dca92b45616ef0325051fdc7627c16fdd62 Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth at gmail.com>
+Date: Tue, 7 May 2024 20:21:17 +0200
+Subject: [PATCH] PCI: qcom: add hack compatible for ipq4019 Lantiq DSL
+
+Add hack compatible for ipq4019 Lantiq DSL
+
+This change the PCIe vendor/device ID to the values from Lantiq
+GRX500 SoCs. We also program the ATU to fake the CPU ID as a Lantiq CPU
+by providing to the Lantiq firmware custom crafted value in the address
+the firmware would expect the CPU ID to be readable.
+
+Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
+Signed-off-by: Florian Maurer <f.maurer at outlook.com>
+---
+ drivers/pci/controller/dwc/pcie-qcom.c | 94 +++++++++++++++++++++++++-
+ 1 file changed, 93 insertions(+), 1 deletion(-)
+
+--- a/drivers/pci/controller/dwc/pcie-qcom.c
++++ b/drivers/pci/controller/dwc/pcie-qcom.c
+@@ -184,11 +184,24 @@ struct qcom_pcie_resources_2_3_3 {
+ 
+ #define QCOM_PCIE_2_4_0_MAX_CLOCKS		4
+ #define QCOM_PCIE_2_4_0_MAX_RESETS		12
++/*
++ * 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).
++ */
++#define QCOM_PCIE_2_4_0_CPU_ID_BASE_REG		0x1f107000
++#define QCOM_PCIE_2_4_0_CPU_ID_REG		0x340
++#define QCOM_PCIE_2_4_0_CPU_ID_REG_OFFSET	(QCOM_PCIE_2_4_0_CPU_ID_REG / sizeof(u32))
++#define QCOM_PCIE_2_4_0_CPU_ID_REG_VAL		(0x389 << 5)
++#define QCOM_PCIE_2_4_0_GRX500_VENDOR_ID	0x1bef
++#define QCOM_PCIE_2_4_0_GRX500_DEVICE_ID	0x0030
+ struct qcom_pcie_resources_2_4_0 {
+ 	struct clk_bulk_data clks[QCOM_PCIE_2_4_0_MAX_CLOCKS];
+ 	int num_clks;
+ 	struct reset_control_bulk_data resets[QCOM_PCIE_2_4_0_MAX_RESETS];
+ 	int num_resets;
++	void *lantiq_hack_virt;
++	dma_addr_t lantiq_hack_phys;
+ };
+ 
+ #define QCOM_PCIE_2_7_0_MAX_CLOCKS		15
+@@ -629,12 +642,65 @@ static int qcom_pcie_post_init_2_3_2(str
+ 	return 0;
+ }
+ 
++static void qcom_pcie_host_post_init_2_3_2_lantiq_hack(struct qcom_pcie *pcie)
++{
++	struct qcom_pcie_resources_2_4_0 *res = &pcie->res.v2_4_0;
++	struct dw_pcie *pci = pcie->pci;
++	struct dw_pcie_rp *pp = &pci->pp;
++	struct device *dev = pci->dev;
++	struct resource_entry *entry;
++	int ret, index = 0;
++	u64 addr, phys;
++	u32 *val;
++
++	res->lantiq_hack_virt = dma_alloc_coherent(dev, SZ_4K,
++						   &res->lantiq_hack_phys,
++						   GFP_ATOMIC);
++	if (!res->lantiq_hack_virt) {
++		dev_err(dev, "failed to allocate DMA for lantiq hack\n");
++		return;
++	}
++
++	/* Fake Lantiq CPU ID register */
++	val = (u32 *)res->lantiq_hack_virt;
++	val[QCOM_PCIE_2_4_0_CPU_ID_REG_OFFSET] = QCOM_PCIE_2_4_0_CPU_ID_REG_VAL;
++
++	/* Increment index based on used iATU */
++	resource_list_for_each_entry(entry, &pp->bridge->dma_ranges)
++		if (resource_type(entry->res) == IORESOURCE_MEM)
++			index++;
++
++	/* Check if there is space for an additional iATU */
++	if (index >= pci->num_ib_windows) {
++		dev_err(dev, "No inbound iATU window available for magic\n");
++		return;
++	}
++
++	addr = QCOM_PCIE_2_4_0_CPU_ID_BASE_REG;
++	phys = res->lantiq_hack_phys;
++
++	/* Make it visible to PCIe devices using address translation unit */
++	ret = dw_pcie_prog_inbound_atu(pci, index, PCIE_ATU_TYPE_MEM,
++				       phys, addr, SZ_4K);
++	if (ret) {
++		dev_err(dev, "timeout waiting for IATU for lantiq hack: %d\n", ret);
++		return;
++	}
++
++	/* Set vendor/device ID of GRX500 PCIe host */
++	dw_pcie_dbi_ro_wr_en(pci);
++	dw_pcie_writew_dbi(pci, PCI_VENDOR_ID, QCOM_PCIE_2_4_0_GRX500_VENDOR_ID);
++	dw_pcie_writew_dbi(pci, PCI_DEVICE_ID, QCOM_PCIE_2_4_0_GRX500_DEVICE_ID);
++	dw_pcie_dbi_ro_wr_dis(pci);
++}
++
+ static int qcom_pcie_get_resources_2_4_0(struct qcom_pcie *pcie)
+ {
+ 	struct qcom_pcie_resources_2_4_0 *res = &pcie->res.v2_4_0;
+ 	struct dw_pcie *pci = pcie->pci;
+ 	struct device *dev = pci->dev;
+-	bool is_ipq = of_device_is_compatible(dev->of_node, "qcom,pcie-ipq4019");
++	bool is_ipq = of_device_is_compatible(dev->of_node, "qcom,pcie-ipq4019") || 
++		      of_device_is_compatible(dev->of_node, "qcom,pcie-ipq4019-lantiq-hack");
+ 	int ret;
+ 
+ 	res->clks[0].id = "aux";
+@@ -679,6 +745,17 @@ static void qcom_pcie_deinit_2_4_0(struc
+ 	clk_bulk_disable_unprepare(res->num_clks, res->clks);
+ }
+ 
++static void qcom_pcie_deinit_2_4_0_lantiq_hack(struct qcom_pcie *pcie)
++{
++	struct qcom_pcie_resources_2_4_0 *res = &pcie->res.v2_4_0;
++	struct dw_pcie *pci = pcie->pci;
++	struct device *dev = pci->dev;
++
++	dma_free_coherent(dev, SZ_4K, res->lantiq_hack_virt, res->lantiq_hack_phys);
++
++	qcom_pcie_deinit_2_4_0(pcie);
++}
++
+ static int qcom_pcie_init_2_4_0(struct qcom_pcie *pcie)
+ {
+ 	struct qcom_pcie_resources_2_4_0 *res = &pcie->res.v2_4_0;
+@@ -1292,6 +1369,16 @@ static const struct qcom_pcie_ops ops_2_
+ 	.ltssm_enable = qcom_pcie_2_3_2_ltssm_enable,
+ };
+ 
++/* Qcom IP rev.: 2.4.0	Synopsys IP rev.: 4.20a Lantiq DSL Hack */
++static const struct qcom_pcie_ops ops_2_4_0_lantiq_hack = {
++	.get_resources = qcom_pcie_get_resources_2_4_0,
++	.init = qcom_pcie_init_2_4_0,
++	.post_init = qcom_pcie_post_init_2_3_2,
++	.host_post_init = qcom_pcie_host_post_init_2_3_2_lantiq_hack,
++	.deinit = qcom_pcie_deinit_2_4_0_lantiq_hack,
++	.ltssm_enable = qcom_pcie_2_3_2_ltssm_enable,
++};
++
+ /* Qcom IP rev.: 2.3.3	Synopsys IP rev.: 4.30a */
+ static const struct qcom_pcie_ops ops_2_3_3 = {
+ 	.get_resources = qcom_pcie_get_resources_2_3_3,
+@@ -1354,6 +1441,10 @@ static const struct qcom_pcie_cfg cfg_2_
+ 	.ops = &ops_2_4_0,
+ };
+ 
++static const struct qcom_pcie_cfg cfg_2_4_0_lantiq_hack = {
++	.ops = &ops_2_4_0_lantiq_hack,
++};
++
+ static const struct qcom_pcie_cfg cfg_2_7_0 = {
+ 	.ops = &ops_2_7_0,
+ };
+@@ -1641,6 +1732,7 @@ static const struct of_device_id qcom_pc
+ 	{ .compatible = "qcom,pcie-apq8064", .data = &cfg_2_1_0 },
+ 	{ .compatible = "qcom,pcie-apq8084", .data = &cfg_1_0_0 },
+ 	{ .compatible = "qcom,pcie-ipq4019", .data = &cfg_2_4_0 },
++	{ .compatible = "qcom,pcie-ipq4019-lantiq-hack", .data = &cfg_2_4_0_lantiq_hack },
+ 	{ .compatible = "qcom,pcie-ipq6018", .data = &cfg_2_9_0 },
+ 	{ .compatible = "qcom,pcie-ipq8064", .data = &cfg_2_1_0 },
+ 	{ .compatible = "qcom,pcie-ipq8064-v2", .data = &cfg_2_1_0 },




More information about the lede-commits mailing list