From 285046aa11ad85a4de24891f5458d45f50d1bcc5 Mon Sep 17 00:00:00 2001 From: Gregory Herrero Date: Wed, 29 Apr 2015 22:09:19 +0200 Subject: [PATCH] usb: dwc2: add hibernation core parameter dwc2 may not be able to exit from hibernation if the hardware does not provide a way to detect resume signalling in this state. Thus, add the possibility to disable hibernation feature. Acked-by: John Youn Signed-off-by: Gregory Herrero Signed-off-by: Felipe Balbi --- drivers/usb/dwc2/core.c | 24 ++++++++++++++++++++++++ drivers/usb/dwc2/core.h | 7 +++++++ drivers/usb/dwc2/core_intr.c | 7 ++++--- drivers/usb/dwc2/platform.c | 2 ++ 4 files changed, 37 insertions(+), 3 deletions(-) diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c index 7f461e3bc7a1..e5b546f1152e 100644 --- a/drivers/usb/dwc2/core.c +++ b/drivers/usb/dwc2/core.c @@ -342,6 +342,9 @@ int dwc2_exit_hibernation(struct dwc2_hsotg *hsotg, bool restore) u32 pcgcctl; int ret = 0; + if (!hsotg->core_params->hibernation) + return -ENOTSUPP; + pcgcctl = readl(hsotg->regs + PCGCTL); pcgcctl &= ~PCGCTL_STOPPCLK; writel(pcgcctl, hsotg->regs + PCGCTL); @@ -392,6 +395,9 @@ int dwc2_enter_hibernation(struct dwc2_hsotg *hsotg) u32 pcgcctl; int ret = 0; + if (!hsotg->core_params->hibernation) + return -ENOTSUPP; + /* Backup all registers */ ret = dwc2_backup_global_registers(hsotg); if (ret) { @@ -2998,6 +3004,23 @@ static void dwc2_set_param_external_id_pin_ctl(struct dwc2_hsotg *hsotg, hsotg->core_params->external_id_pin_ctl = val; } +static void dwc2_set_param_hibernation(struct dwc2_hsotg *hsotg, + int val) +{ + if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) { + if (val >= 0) { + dev_err(hsotg->dev, + "'%d' invalid for parameter hibernation\n", + val); + dev_err(hsotg->dev, "hibernation must be 0 or 1\n"); + } + val = 0; + dev_dbg(hsotg->dev, "Setting hibernation to %d\n", val); + } + + hsotg->core_params->hibernation = val; +} + /* * This function is called during module intialization to pass module parameters * for the DWC_otg core. @@ -3043,6 +3066,7 @@ void dwc2_set_parameters(struct dwc2_hsotg *hsotg, dwc2_set_param_otg_ver(hsotg, params->otg_ver); dwc2_set_param_uframe_sched(hsotg, params->uframe_sched); dwc2_set_param_external_id_pin_ctl(hsotg, params->external_id_pin_ctl); + dwc2_set_param_hibernation(hsotg, params->hibernation); } /** diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h index d7fb1f793207..53b8de03f102 100644 --- a/drivers/usb/dwc2/core.h +++ b/drivers/usb/dwc2/core.h @@ -336,6 +336,12 @@ enum dwc2_ep0_state { * case. * 0 - No (default) * 1 - Yes + * @hibernation: Specifies whether the controller support hibernation. + * If hibernation is enabled, the controller will enter + * hibernation in both peripheral and host mode when + * needed. + * 0 - No (default) + * 1 - Yes * * The following parameters may be specified when starting the module. These * parameters define how the DWC_otg controller should be configured. A @@ -374,6 +380,7 @@ struct dwc2_core_params { int ahbcfg; int uframe_sched; int external_id_pin_ctl; + int hibernation; }; /** diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c index 9e510bb612bd..927be1e8b3dc 100644 --- a/drivers/usb/dwc2/core_intr.c +++ b/drivers/usb/dwc2/core_intr.c @@ -347,7 +347,7 @@ static void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg) dctl &= ~DCTL_RMTWKUPSIG; writel(dctl, hsotg->regs + DCTL); ret = dwc2_exit_hibernation(hsotg, true); - if (ret) + if (ret && (ret != -ENOTSUPP)) dev_err(hsotg->dev, "exit hibernation failed\n"); call_gadget(hsotg, resume); @@ -428,8 +428,9 @@ static void dwc2_handle_usb_suspend_intr(struct dwc2_hsotg *hsotg) ret = dwc2_enter_hibernation(hsotg); if (ret) { - dev_err(hsotg->dev, - "enter hibernation failed\n"); + if (ret != -ENOTSUPP) + dev_err(hsotg->dev, + "enter hibernation failed\n"); goto skip_power_saving; } diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c index 2562c9019955..90935304185a 100644 --- a/drivers/usb/dwc2/platform.c +++ b/drivers/usb/dwc2/platform.c @@ -78,6 +78,7 @@ static const struct dwc2_core_params params_bcm2835 = { .ahbcfg = 0x10, .uframe_sched = 0, .external_id_pin_ctl = -1, + .hibernation = -1, }; static const struct dwc2_core_params params_rk3066 = { @@ -107,6 +108,7 @@ static const struct dwc2_core_params params_rk3066 = { .ahbcfg = 0x7, /* INCR16 */ .uframe_sched = -1, .external_id_pin_ctl = -1, + .hibernation = -1, }; /**