diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h index 3ff41d87125a..86020473b1be 100644 --- a/drivers/usb/dwc2/core.h +++ b/drivers/usb/dwc2/core.h @@ -68,6 +68,9 @@ /* Maximum number of Endpoints/HostChannels */ #define MAX_EPS_CHANNELS 16 +/* Maximum number of dwc2 clocks */ +#define DWC2_MAX_CLKS 3 + /* dwc2-hsotg declarations */ static const char * const dwc2_hsotg_supply_names[] = { "vusb_d", /* digital USB supply, 1.2V */ @@ -1031,7 +1034,7 @@ struct dwc2_hsotg { spinlock_t lock; void *priv; int irq; - struct clk *clk; + struct clk *clks[DWC2_MAX_CLKS]; struct reset_control *reset; struct reset_control *reset_ecc; diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c index 748763bdcc98..97838c7aec03 100644 --- a/drivers/usb/dwc2/platform.c +++ b/drivers/usb/dwc2/platform.c @@ -124,17 +124,20 @@ static int dwc2_get_dr_mode(struct dwc2_hsotg *hsotg) static int __dwc2_lowlevel_hw_enable(struct dwc2_hsotg *hsotg) { struct platform_device *pdev = to_platform_device(hsotg->dev); - int ret; + int clk, ret; ret = regulator_bulk_enable(ARRAY_SIZE(hsotg->supplies), hsotg->supplies); if (ret) return ret; - if (hsotg->clk) { - ret = clk_prepare_enable(hsotg->clk); - if (ret) + for (clk = 0; clk < DWC2_MAX_CLKS && hsotg->clks[clk]; clk++) { + ret = clk_prepare_enable(hsotg->clks[clk]); + if (ret) { + while (--clk >= 0) + clk_disable_unprepare(hsotg->clks[clk]); return ret; + } } if (hsotg->uphy) { @@ -169,7 +172,7 @@ int dwc2_lowlevel_hw_enable(struct dwc2_hsotg *hsotg) static int __dwc2_lowlevel_hw_disable(struct dwc2_hsotg *hsotg) { struct platform_device *pdev = to_platform_device(hsotg->dev); - int ret = 0; + int clk, ret = 0; if (hsotg->uphy) { usb_phy_shutdown(hsotg->uphy); @@ -183,8 +186,9 @@ static int __dwc2_lowlevel_hw_disable(struct dwc2_hsotg *hsotg) if (ret) return ret; - if (hsotg->clk) - clk_disable_unprepare(hsotg->clk); + for (clk = DWC2_MAX_CLKS - 1; clk >= 0; clk--) + if (hsotg->clks[clk]) + clk_disable_unprepare(hsotg->clks[clk]); ret = regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies), hsotg->supplies); @@ -218,7 +222,7 @@ static void dwc2_reset_phy_work(struct work_struct *data) static int dwc2_lowlevel_hw_init(struct dwc2_hsotg *hsotg) { - int i, ret; + int i, clk, ret; hsotg->reset = devm_reset_control_get_optional(hsotg->dev, "dwc2"); if (IS_ERR(hsotg->reset)) { @@ -292,11 +296,19 @@ static int dwc2_lowlevel_hw_init(struct dwc2_hsotg *hsotg) hsotg->phyif = GUSBCFG_PHYIF8; } - /* Clock */ - hsotg->clk = devm_clk_get(hsotg->dev, "otg"); - if (IS_ERR(hsotg->clk)) { - hsotg->clk = NULL; - dev_dbg(hsotg->dev, "cannot get otg clock\n"); + for (clk = 0; clk < DWC2_MAX_CLKS; clk++) { + hsotg->clks[clk] = of_clk_get(hsotg->dev->of_node, clk); + if (IS_ERR(hsotg->clks[clk])) { + ret = PTR_ERR(hsotg->clks[clk]); + if (ret == -EPROBE_DEFER) { + while (--clk >= 0) + clk_put(hsotg->clks[clk]); + return ret; + } + + hsotg->clks[clk] = NULL; + break; + } } /* Regulators */