Message ID | 20230414084137.1050487-4-fabrice.gasnier@foss.st.com |
---|---|
State | Accepted |
Commit | 02329adeae1f92b0133cfc1a2b06645f4c496c1b |
Headers | show |
Series | usb: dwc2: add optional clock used on stm32mp15 | expand |
On 4/14/23 12:41, Fabrice Gasnier wrote: > Add support for the utmi clock. It's needed on STM32MP15, when using > the integrated full-speed PHY. This clock is an output of USBPHYC, but > HS USBPHYC is not attached as PHY in this case: Full-Speed PHY is directly > managed in dwc2 glue, through GGPIO register. Typical DT when using FS PHY > &usbotg_hs { > compatible = "st,stm32mp15-fsotg", "snps,dwc2"; > pinctrl-names = "default"; > pinctrl-0 = <&usbotg_hs_pins_a &usbotg_fs_dp_dm_pins_a>; > vbus-supply = <&vbus_otg>; > status = "okay"; > }; > > In this configuration, USBPHYC clock output must be defined, so it can > be properly enabled as a clock provider: > clocks = <&rcc USBO_K>, <&usbphyc>; > clock-names = "otg", "utmi"; > > Signed-off-by: Fabrice Gasnier <fabrice.gasnier@foss.st.com> Acked-by: Minas Harutyunyan <hminas@synopsys.com> > --- > Changes in v2: > - "utmi_clk" renamed "utmi" as per Krzysztof comment on dt-bindings > --- > drivers/usb/dwc2/core.h | 2 ++ > drivers/usb/dwc2/platform.c | 20 +++++++++++++++++++- > 2 files changed, 21 insertions(+), 1 deletion(-) > > diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h > index 40cf2880d7e5..0bb4c0c845bf 100644 > --- a/drivers/usb/dwc2/core.h > +++ b/drivers/usb/dwc2/core.h > @@ -1003,6 +1003,7 @@ struct dwc2_hregs_backup { > * @ctrl_out_desc: EP0 OUT data phase desc chain pointer > * @irq: Interrupt request line number > * @clk: Pointer to otg clock > + * @utmi_clk: Pointer to utmi_clk clock > * @reset: Pointer to dwc2 reset controller > * @reset_ecc: Pointer to dwc2 optional reset controller in Stratix10. > * @regset: A pointer to a struct debugfs_regset32, which contains > @@ -1065,6 +1066,7 @@ struct dwc2_hsotg { > void *priv; > int irq; > struct clk *clk; > + struct clk *utmi_clk; > struct reset_control *reset; > struct reset_control *reset_ecc; > > diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c > index c431ce6c119f..5aee284018c0 100644 > --- a/drivers/usb/dwc2/platform.c > +++ b/drivers/usb/dwc2/platform.c > @@ -101,10 +101,16 @@ static int __dwc2_lowlevel_hw_enable(struct dwc2_hsotg *hsotg) > if (ret) > return ret; > > + if (hsotg->utmi_clk) { > + ret = clk_prepare_enable(hsotg->utmi_clk); > + if (ret) > + goto err_dis_reg; > + } > + > if (hsotg->clk) { > ret = clk_prepare_enable(hsotg->clk); > if (ret) > - goto err_dis_reg; > + goto err_dis_utmi_clk; > } > > if (hsotg->uphy) { > @@ -129,6 +135,10 @@ static int __dwc2_lowlevel_hw_enable(struct dwc2_hsotg *hsotg) > if (hsotg->clk) > clk_disable_unprepare(hsotg->clk); > > +err_dis_utmi_clk: > + if (hsotg->utmi_clk) > + clk_disable_unprepare(hsotg->utmi_clk); > + > err_dis_reg: > regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies), hsotg->supplies); > > @@ -171,6 +181,9 @@ static int __dwc2_lowlevel_hw_disable(struct dwc2_hsotg *hsotg) > if (hsotg->clk) > clk_disable_unprepare(hsotg->clk); > > + if (hsotg->utmi_clk) > + clk_disable_unprepare(hsotg->utmi_clk); > + > return regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies), hsotg->supplies); > } > > @@ -247,6 +260,11 @@ static int dwc2_lowlevel_hw_init(struct dwc2_hsotg *hsotg) > if (IS_ERR(hsotg->clk)) > return dev_err_probe(hsotg->dev, PTR_ERR(hsotg->clk), "cannot get otg clock\n"); > > + hsotg->utmi_clk = devm_clk_get_optional(hsotg->dev, "utmi"); > + if (IS_ERR(hsotg->utmi_clk)) > + return dev_err_probe(hsotg->dev, PTR_ERR(hsotg->utmi_clk), > + "cannot get utmi clock\n"); > + > /* Regulators */ > for (i = 0; i < ARRAY_SIZE(hsotg->supplies); i++) > hsotg->supplies[i].supply = dwc2_hsotg_supply_names[i];
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h index 40cf2880d7e5..0bb4c0c845bf 100644 --- a/drivers/usb/dwc2/core.h +++ b/drivers/usb/dwc2/core.h @@ -1003,6 +1003,7 @@ struct dwc2_hregs_backup { * @ctrl_out_desc: EP0 OUT data phase desc chain pointer * @irq: Interrupt request line number * @clk: Pointer to otg clock + * @utmi_clk: Pointer to utmi_clk clock * @reset: Pointer to dwc2 reset controller * @reset_ecc: Pointer to dwc2 optional reset controller in Stratix10. * @regset: A pointer to a struct debugfs_regset32, which contains @@ -1065,6 +1066,7 @@ struct dwc2_hsotg { void *priv; int irq; struct clk *clk; + struct clk *utmi_clk; struct reset_control *reset; struct reset_control *reset_ecc; diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c index c431ce6c119f..5aee284018c0 100644 --- a/drivers/usb/dwc2/platform.c +++ b/drivers/usb/dwc2/platform.c @@ -101,10 +101,16 @@ static int __dwc2_lowlevel_hw_enable(struct dwc2_hsotg *hsotg) if (ret) return ret; + if (hsotg->utmi_clk) { + ret = clk_prepare_enable(hsotg->utmi_clk); + if (ret) + goto err_dis_reg; + } + if (hsotg->clk) { ret = clk_prepare_enable(hsotg->clk); if (ret) - goto err_dis_reg; + goto err_dis_utmi_clk; } if (hsotg->uphy) { @@ -129,6 +135,10 @@ static int __dwc2_lowlevel_hw_enable(struct dwc2_hsotg *hsotg) if (hsotg->clk) clk_disable_unprepare(hsotg->clk); +err_dis_utmi_clk: + if (hsotg->utmi_clk) + clk_disable_unprepare(hsotg->utmi_clk); + err_dis_reg: regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies), hsotg->supplies); @@ -171,6 +181,9 @@ static int __dwc2_lowlevel_hw_disable(struct dwc2_hsotg *hsotg) if (hsotg->clk) clk_disable_unprepare(hsotg->clk); + if (hsotg->utmi_clk) + clk_disable_unprepare(hsotg->utmi_clk); + return regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies), hsotg->supplies); } @@ -247,6 +260,11 @@ static int dwc2_lowlevel_hw_init(struct dwc2_hsotg *hsotg) if (IS_ERR(hsotg->clk)) return dev_err_probe(hsotg->dev, PTR_ERR(hsotg->clk), "cannot get otg clock\n"); + hsotg->utmi_clk = devm_clk_get_optional(hsotg->dev, "utmi"); + if (IS_ERR(hsotg->utmi_clk)) + return dev_err_probe(hsotg->dev, PTR_ERR(hsotg->utmi_clk), + "cannot get utmi clock\n"); + /* Regulators */ for (i = 0; i < ARRAY_SIZE(hsotg->supplies); i++) hsotg->supplies[i].supply = dwc2_hsotg_supply_names[i];
Add support for the utmi clock. It's needed on STM32MP15, when using the integrated full-speed PHY. This clock is an output of USBPHYC, but HS USBPHYC is not attached as PHY in this case: Full-Speed PHY is directly managed in dwc2 glue, through GGPIO register. Typical DT when using FS PHY &usbotg_hs { compatible = "st,stm32mp15-fsotg", "snps,dwc2"; pinctrl-names = "default"; pinctrl-0 = <&usbotg_hs_pins_a &usbotg_fs_dp_dm_pins_a>; vbus-supply = <&vbus_otg>; status = "okay"; }; In this configuration, USBPHYC clock output must be defined, so it can be properly enabled as a clock provider: clocks = <&rcc USBO_K>, <&usbphyc>; clock-names = "otg", "utmi"; Signed-off-by: Fabrice Gasnier <fabrice.gasnier@foss.st.com> --- Changes in v2: - "utmi_clk" renamed "utmi" as per Krzysztof comment on dt-bindings --- drivers/usb/dwc2/core.h | 2 ++ drivers/usb/dwc2/platform.c | 20 +++++++++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-)