mirror of
https://github.com/openwrt/openwrt.git
synced 2026-10-13 00:17:02 +04:00
qualcommax: usb: dwc3: 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.
This fixes USB2 mode on the IPQ50xx platform.
link: https://lore.kernel.org/r/20260906-ipq-flatten-usb-v3-1-13e4e0f63123@outlook.com
link: https://lore.kernel.org/r/20260906-ipq-flatten-usb-v3-2-13e4e0f63123@outlook.com
Fixes: 409bf967e4 ("qualcommax: ipq50xx: add support for USB3")
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
Link: https://github.com/openwrt/openwrt/pull/25038
Signed-off-by: Robert Marko <robimarko@gmail.com>
This commit is contained in:
1 parent
980becf1da
commit
cf3fe920b9
2 files changed
+152
No files matched your search
+98
@@ -0,0 +1,98 @@
|
||||
From 93a8fd3d8d04be9935a2897ef90e7f1100e69830 Mon Sep 17 00:00:00 2001
|
||||
From: George Moussalem <george.moussalem@outlook.com>
|
||||
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 <varadarajan.narayanan@oss.qualcomm.com>
|
||||
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
|
||||
---
|
||||
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);
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
From f598a5a7837caa3daef086fb42534572e4e9b540 Mon Sep 17 00:00:00 2001
|
||||
From: George Moussalem <george.moussalem@outlook.com>
|
||||
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 <varadarajan.narayanan@oss.qualcomm.com>
|
||||
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
|
||||
---
|
||||
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;
|
||||
Reference in new issue
Block a user