diff --git a/target/linux/qualcommax/patches-6.18/0140-usb-dwc3-core-Allow-glue-layer-to-pass-reference-clo.patch b/target/linux/qualcommax/patches-6.18/0140-usb-dwc3-core-Allow-glue-layer-to-pass-reference-clo.patch new file mode 100644 index 00000000000..142defd46ce --- /dev/null +++ b/target/linux/qualcommax/patches-6.18/0140-usb-dwc3-core-Allow-glue-layer-to-pass-reference-clo.patch @@ -0,0 +1,98 @@ +From 93a8fd3d8d04be9935a2897ef90e7f1100e69830 Mon Sep 17 00:00:00 2001 +From: George Moussalem +Date: Sat, 22 Aug 2026 16:09:48 +0400 +Subject: [PATCH v3 01/10] usb: dwc3: core: Allow glue layer to pass reference + clock rate + +Add ability to pass the reference clock rate from the glue layer to the +DWC3 core driver. The core calculates the reference clock period and +frame length adjustment based on the reference clock rate. + +In the flattened snsp-dwc3 model, it is currently not possible to pass a +reference clock that differs from the default since: +commit 613a2e655d4d ("usb: dwc3: core: Expose core driver as library") + +The new glue layers (incl. Qualcomm's) set the ignore_clocks_and_resets +flag in dwc3_probe_data to true, which disables the core driver's clock +management, thus it also doesn't acquire the reference clock from the +devicetree needed in dwc3_ref_clk_period. + +There's an existing DT property 'snps,ref-clock-period-ns', but that's +been deprecated. In addition, basing the rate from the period is often +not accurate enough to derive the frame length adjustment value. + +This prevents moving chipsets such as IPQ5018, IPQ6018, IPQ5332, IPQ5424 +and IPQ9574 with a reference clock rate that computes values for the +period and frame length adjustment different from the hardware default +from moving to the flattened model. + +So, add ability to set the reference clock rate in dwc3_probe_data, then +have the core obtain the clock rate and use that to calculate the +required period and frame length adjustment. + +Reviewed-by: Varadarajan Narayanan +Signed-off-by: George Moussalem +--- + drivers/usb/dwc3/core.c | 6 ++++++ + drivers/usb/dwc3/core.h | 2 ++ + drivers/usb/dwc3/glue.h | 4 ++++ + 3 files changed, 12 insertions(+) + +--- a/drivers/usb/dwc3/core.c ++++ b/drivers/usb/dwc3/core.c +@@ -419,6 +419,9 @@ static void dwc3_ref_clk_period(struct d + } else if (dwc->ref_clk_per) { + period = dwc->ref_clk_per; + rate = NSEC_PER_SEC / period; ++ } else if (dwc->ref_clk_rate) { ++ rate = dwc->ref_clk_rate; ++ period = NSEC_PER_SEC / rate; + } else { + return; + } +@@ -2262,6 +2265,9 @@ int dwc3_core_probe(const struct dwc3_pr + goto err_put_psy; + } + ++ if (data->ref_clk_rate > 0) ++ dwc->ref_clk_rate = data->ref_clk_rate; ++ + ret = reset_control_deassert(dwc->reset); + if (ret) + goto err_put_psy; +--- a/drivers/usb/dwc3/core.h ++++ b/drivers/usb/dwc3/core.h +@@ -1033,6 +1033,7 @@ struct dwc3_glue_ops { + * @regs_size: address space size + * @fladj: frame length adjustment + * @ref_clk_per: reference clock period configuration ++ * @ref_clk_rate: reference clock rate provided by glue layer + * @irq_gadget: peripheral controller's IRQ number + * @otg_irq: IRQ number for OTG IRQs + * @current_otg_role: current role of operation while using the OTG block +@@ -1254,6 +1255,7 @@ struct dwc3 { + + u32 fladj; + u32 ref_clk_per; ++ unsigned long ref_clk_rate; + u32 irq_gadget; + u32 otg_irq; + u32 current_otg_role; +--- a/drivers/usb/dwc3/glue.h ++++ b/drivers/usb/dwc3/glue.h +@@ -15,11 +15,15 @@ + * @res: resource for the DWC3 core mmio region + * @ignore_clocks_and_resets: clocks and resets defined for the device should + * be ignored by the DWC3 core, as they are managed by the glue ++ * @ref_clk_rate: optional reference clock rate for the DWC3 core to compute the ++ * period and frame length adjustment required if these values ++ * differ from the hardware default. + */ + struct dwc3_probe_data { + struct dwc3 *dwc; + struct resource *res; + bool ignore_clocks_and_resets; ++ unsigned long ref_clk_rate; + }; + + int dwc3_core_probe(const struct dwc3_probe_data *data); diff --git a/target/linux/qualcommax/patches-6.18/0141-usb-dwc3-qcom-Add-support-for-selecting-UTMI-as-refe.patch b/target/linux/qualcommax/patches-6.18/0141-usb-dwc3-qcom-Add-support-for-selecting-UTMI-as-refe.patch new file mode 100644 index 00000000000..1a397fbaad1 --- /dev/null +++ b/target/linux/qualcommax/patches-6.18/0141-usb-dwc3-qcom-Add-support-for-selecting-UTMI-as-refe.patch @@ -0,0 +1,54 @@ +From f598a5a7837caa3daef086fb42534572e4e9b540 Mon Sep 17 00:00:00 2001 +From: George Moussalem +Date: Sat, 22 Aug 2026 16:59:57 +0400 +Subject: [PATCH v3 02/10] usb: dwc3: qcom: Add support for selecting UTMI as + reference clock + +On many Qualcomm chipsets, the UTMI clock is used as the reference clock +(ex. IPQ5018, IPQ6018, and IPQ9574 and more). Since moving to the new +flattened snps-dwc3 model, it is no longer possible to pass the +reference clock to the dwc3 core driver. + +The clock rate is used by the dwc3 core to compute the reference clock +period and frame length adjustment. This is needed when the reference +clock rate used computes values that deviate from the hardware defaults. +Above mentioned SoCs require values different from the defaults and, as +such, the core initializes with the wrong values which leads to +non-functional USB operation. + +In Qualcomm chipsets, if available, the UTMI clock is used as the +reference clock. Therefore, acquire the reference clock by name +('mock_utmi') and pass its clock rate to the core using the probe_data +structure. + +Reviewed-by: Varadarajan Narayanan +Signed-off-by: George Moussalem +--- + drivers/usb/dwc3/dwc3-qcom.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +--- a/drivers/usb/dwc3/dwc3-qcom.c ++++ b/drivers/usb/dwc3/dwc3-qcom.c +@@ -617,6 +617,7 @@ static int dwc3_qcom_probe(struct platfo + int ret; + bool ignore_pipe_clk; + bool wakeup_source; ++ struct clk *ref_clk; + + qcom = devm_kzalloc(&pdev->dev, sizeof(*qcom), GFP_KERNEL); + if (!qcom) +@@ -698,6 +699,14 @@ static int dwc3_qcom_probe(struct platfo + qcom->current_role = USB_ROLE_DEVICE; + } + ++ ref_clk = devm_clk_get_optional(dev, "mock_utmi"); ++ if (IS_ERR(ref_clk)) { ++ ret = dev_err_probe(dev, PTR_ERR(ref_clk), "failed to get ref clock\n"); ++ goto clk_disable; ++ } else if (ref_clk) { ++ probe_data.ref_clk_rate = clk_get_rate(ref_clk); ++ } ++ + qcom->dwc.glue_ops = &dwc3_qcom_glue_ops; + + qcom->dwc.dev = dev;