Add multi pd support to set performance state for cx domain
to maintain minimum corner voltage for USB clocks.
Add corresponding dt bindings, driver changes and dt changes.
changes in v2:
make cx as mandatory power domain.
Added error handling and detach function.Used attach_by_id function.
Changed rpmhd_opp_svs to rmphd_opp_nom for cx domain.
Sandeep Maheswaram (3):
dt-bindings: usb: qcom,dwc3: Add multi-pd bindings for dwc3 qcom
usb: dwc3: qcom: Add multi-pd support
arm64: dts: qcom: sc7280: Add cx power domain support
.../devicetree/bindings/usb/qcom,dwc3.yaml | 8 +-
arch/arm64/boot/dts/qcom/sc7280.dtsi | 3 +-
drivers/usb/dwc3/dwc3-qcom.c | 87 ++++++++++++++++++++++
3 files changed, 96 insertions(+), 2 deletions(-)
--
2.7.4
Add multi pd support to set performance state for cx domain
to maintain minimum corner voltage for USB clocks.
Signed-off-by: Sandeep Maheswaram <[email protected]>
---
v2:
Added error handling and detach function.Used attach_by_id function.
drivers/usb/dwc3/dwc3-qcom.c | 87 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 87 insertions(+)
diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c
index 9abbd01..efbd34a 100644
--- a/drivers/usb/dwc3/dwc3-qcom.c
+++ b/drivers/usb/dwc3/dwc3-qcom.c
@@ -17,6 +17,7 @@
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/phy/phy.h>
+#include <linux/pm_domain.h>
#include <linux/usb/of.h>
#include <linux/reset.h>
#include <linux/iopoll.h>
@@ -89,6 +90,14 @@ struct dwc3_qcom {
bool pm_suspended;
struct icc_path *icc_path_ddr;
struct icc_path *icc_path_apps;
+
+ /* power domain for cx */
+ struct device *pd_cx;
+ struct device_link *pd_link_cx;
+
+ /* power domain for usb gdsc */
+ struct device *pd_usb_gdsc;
+ struct device_link *pd_link_usb_gdsc;
};
static inline void dwc3_qcom_setbits(void __iomem *base, u32 offset, u32 val)
@@ -521,6 +530,79 @@ static int dwc3_qcom_setup_irq(struct platform_device *pdev)
return 0;
}
+static int dwc3_qcom_attach_pd(struct device *dev)
+{
+ struct dwc3_qcom *qcom = dev_get_drvdata(dev);
+ int ret;
+
+ /* Do nothing when in a single power domain */
+ if (dev->pm_domain)
+ return 0;
+
+ qcom->pd_cx = dev_pm_domain_attach_by_id(dev, 0);
+ if (IS_ERR_OR_NULL(qcom->pd_cx)) {
+ dev_err(dev, "Failed to attach cx pd.\n");
+
+ if (!qcom->pd_cx)
+ return -EINVAL;
+ else
+ return PTR_ERR(qcom->pd_cx);
+ }
+
+ qcom->pd_link_cx = device_link_add(dev, qcom->pd_cx,
+ DL_FLAG_STATELESS |
+ DL_FLAG_PM_RUNTIME |
+ DL_FLAG_RPM_ACTIVE);
+ if (!qcom->pd_link_cx) {
+ dev_err(dev, "Failed to add device_link to cx pd.\n");
+ ret = -EINVAL;
+ goto detach_cx_pd;
+ }
+
+ qcom->pd_usb_gdsc = dev_pm_domain_attach_by_id(dev, 1);
+ if (IS_ERR_OR_NULL(qcom->pd_usb_gdsc)) {
+ dev_err(dev, "Failed to attach usb gdsc pd.\n");
+ if (!qcom->pd_usb_gdsc)
+ ret = -EINVAL;
+ else
+ ret = PTR_ERR(qcom->pd_usb_gdsc);
+ goto del_cx_link;
+ }
+
+ qcom->pd_link_usb_gdsc = device_link_add(dev, qcom->pd_usb_gdsc,
+ DL_FLAG_STATELESS |
+ DL_FLAG_PM_RUNTIME |
+ DL_FLAG_RPM_ACTIVE);
+ if (!qcom->pd_link_usb_gdsc) {
+ dev_err(dev, "Failed to add device_link to usb gdsc pd.\n");
+ ret = -EINVAL;
+ goto detach_gdsc_pd;
+ }
+
+ return 0;
+
+detach_gdsc_pd:
+ dev_pm_domain_detach(qcom->pd_usb_gdsc, true);
+del_cx_link:
+ device_link_del(qcom->pd_link_cx);
+detach_cx_pd:
+ dev_pm_domain_detach(qcom->pd_cx, true);
+ return ret;
+}
+
+static void dwc3_qcom_detach_pd(struct device *dev)
+{
+ struct dwc3_qcom *qcom = dev_get_drvdata(dev);
+
+ if (dev->pm_domain)
+ return;
+
+ device_link_del(qcom->pd_link_usb_gdsc);
+ dev_pm_domain_detach(qcom->pd_usb_gdsc, true);
+ device_link_del(qcom->pd_link_cx);
+ dev_pm_domain_detach(qcom->pd_cx, true);
+}
+
static int dwc3_qcom_clk_init(struct dwc3_qcom *qcom, int count)
{
struct device *dev = qcom->dev;
@@ -837,6 +919,10 @@ static int dwc3_qcom_probe(struct platform_device *pdev)
if (ret)
goto interconnect_exit;
+ ret = dwc3_qcom_attach_pd(dev);
+ if (ret)
+ goto interconnect_exit;
+
device_init_wakeup(&pdev->dev, 1);
qcom->is_suspended = false;
pm_runtime_set_active(dev);
@@ -878,6 +964,7 @@ static int dwc3_qcom_remove(struct platform_device *pdev)
}
qcom->num_clocks = 0;
+ dwc3_qcom_detach_pd(dev);
dwc3_qcom_interconnect_exit(qcom);
reset_control_assert(qcom->resets);
--
2.7.4
Add multi pd support to set performance state for cx domain
to maintain minimum corner voltage for USB clocks.
Signed-off-by: Sandeep Maheswaram <[email protected]>
---
v2:
Changed rpmhd_opp_svs to rmphd_opp_nom for cx domain.
arch/arm64/boot/dts/qcom/sc7280.dtsi | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/qcom/sc7280.dtsi b/arch/arm64/boot/dts/qcom/sc7280.dtsi
index d74a4c8..9e3b6ad 100644
--- a/arch/arm64/boot/dts/qcom/sc7280.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7280.dtsi
@@ -2538,7 +2538,8 @@
interrupt-names = "hs_phy_irq", "dp_hs_phy_irq",
"dm_hs_phy_irq", "ss_phy_irq";
- power-domains = <&gcc GCC_USB30_PRIM_GDSC>;
+ power-domains = <&rpmhpd SC7280_CX>, <&gcc GCC_USB30_PRIM_GDSC>;
+ required-opps = <&rpmhpd_opp_svs>, <>;
resets = <&gcc GCC_USB30_PRIM_BCR>;
--
2.7.4
Quoting Sandeep Maheswaram (2021-10-25 02:07:31)
> Add multi pd support to set performance state for cx domain
> to maintain minimum corner voltage for USB clocks.
>
> Signed-off-by: Sandeep Maheswaram <[email protected]>
> ---
> v2:
> Changed rpmhd_opp_svs to rmphd_opp_nom for cx domain.
>
> arch/arm64/boot/dts/qcom/sc7280.dtsi | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm64/boot/dts/qcom/sc7280.dtsi b/arch/arm64/boot/dts/qcom/sc7280.dtsi
> index d74a4c8..9e3b6ad 100644
> --- a/arch/arm64/boot/dts/qcom/sc7280.dtsi
> +++ b/arch/arm64/boot/dts/qcom/sc7280.dtsi
> @@ -2538,7 +2538,8 @@
> interrupt-names = "hs_phy_irq", "dp_hs_phy_irq",
> "dm_hs_phy_irq", "ss_phy_irq";
>
> - power-domains = <&gcc GCC_USB30_PRIM_GDSC>;
> + power-domains = <&rpmhpd SC7280_CX>, <&gcc GCC_USB30_PRIM_GDSC>;
Order matters and thus the order here can't be flipped.
> + required-opps = <&rpmhpd_opp_svs>, <>;