aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorLi Jun <b47624@freescale.com>2014-06-26 21:52:29 -0400
committerLi Jun <B47624@freescale.com>2014-06-30 04:36:15 -0400
commit746ae5611a7610a4585c1836f292527ff7a260a1 (patch)
tree1909c306b679ca238a160d4b019db4b4cbca393a /drivers/usb
parent7cae872ea9776770043f8c34908e16b27f96cccf (diff)
ENGR00320439-1 usb: chipidea: imx: usb resume from power lost during system sleep
i.MX6SX mega off can shutdown domain power supply if none of peripheral in this domain is registered as wakeup source, this patch adds usb controller imx specific re-init after resume from such power lost during system sleep. Acked-by: Peter Chen <peter.chen@freescale.com> Signed-off-by: Li Jun <b47624@freescale.com>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/chipidea/ci_hdrc_imx.c10
-rw-r--r--drivers/usb/chipidea/ci_hdrc_imx.h1
-rw-r--r--drivers/usb/chipidea/usbmisc_imx.c31
3 files changed, 42 insertions, 0 deletions
diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c
index 9a53efd1ad44..c0f6f902aaad 100644
--- a/drivers/usb/chipidea/ci_hdrc_imx.c
+++ b/drivers/usb/chipidea/ci_hdrc_imx.c
@@ -512,6 +512,16 @@ static int imx_controller_resume(struct device *dev)
512 data->in_lpm = false; 512 data->in_lpm = false;
513 513
514 if (data->usbmisc_data) { 514 if (data->usbmisc_data) {
515 ret = imx_usbmisc_power_lost_check(data->usbmisc_data);
516 /* re-init if resume from power lost */
517 if (ret > 0) {
518 ret = imx_usbmisc_init(data->usbmisc_data);
519 if (ret) {
520 dev_err(dev, "usbmisc init failed, ret=%d\n",
521 ret);
522 goto clk_disable;
523 }
524 }
515 ret = imx_usbmisc_set_wakeup(data->usbmisc_data, false); 525 ret = imx_usbmisc_set_wakeup(data->usbmisc_data, false);
516 if (ret) { 526 if (ret) {
517 dev_err(dev, 527 dev_err(dev,
diff --git a/drivers/usb/chipidea/ci_hdrc_imx.h b/drivers/usb/chipidea/ci_hdrc_imx.h
index 3376c88c1ae6..a195a8961a0f 100644
--- a/drivers/usb/chipidea/ci_hdrc_imx.h
+++ b/drivers/usb/chipidea/ci_hdrc_imx.h
@@ -34,5 +34,6 @@ int imx_usbmisc_set_wakeup(struct imx_usbmisc_data *, bool);
34/* Call it before setting portsc.suspendM */ 34/* Call it before setting portsc.suspendM */
35int imx_usbmisc_hsic_set_connect(struct imx_usbmisc_data *); 35int imx_usbmisc_hsic_set_connect(struct imx_usbmisc_data *);
36int imx_usbmisc_hsic_set_clk(struct imx_usbmisc_data *, bool); 36int imx_usbmisc_hsic_set_clk(struct imx_usbmisc_data *, bool);
37int imx_usbmisc_power_lost_check(struct imx_usbmisc_data *);
37 38
38#endif /* __DRIVER_USB_CHIPIDEA_CI_HDRC_IMX_H */ 39#endif /* __DRIVER_USB_CHIPIDEA_CI_HDRC_IMX_H */
diff --git a/drivers/usb/chipidea/usbmisc_imx.c b/drivers/usb/chipidea/usbmisc_imx.c
index d263ae438d17..acda7a93a612 100644
--- a/drivers/usb/chipidea/usbmisc_imx.c
+++ b/drivers/usb/chipidea/usbmisc_imx.c
@@ -75,6 +75,8 @@ struct usbmisc_ops {
75 int (*hsic_set_connect)(struct imx_usbmisc_data *data); 75 int (*hsic_set_connect)(struct imx_usbmisc_data *data);
76 /* It's called during suspend/resume */ 76 /* It's called during suspend/resume */
77 int (*hsic_set_clk)(struct imx_usbmisc_data *data, bool enabled); 77 int (*hsic_set_clk)(struct imx_usbmisc_data *data, bool enabled);
78 /* It's called when system resume from usb power lost */
79 int (*power_lost_check)(struct imx_usbmisc_data *data);
78}; 80};
79 81
80struct imx_usbmisc { 82struct imx_usbmisc {
@@ -255,6 +257,24 @@ static int usbmisc_imx6sx_init(struct imx_usbmisc_data *data)
255 return 0; 257 return 0;
256} 258}
257 259
260static int usbmisc_imx6sx_power_lost_check(struct imx_usbmisc_data *data)
261{
262 unsigned long flags;
263 u32 val;
264
265 spin_lock_irqsave(&usbmisc->lock, flags);
266 val = readl(usbmisc->base + data->index * 4);
267 spin_unlock_irqrestore(&usbmisc->lock, flags);
268 /*
269 * Here use a power on reset value to judge
270 * if the controller experienced a power lost
271 */
272 if (val == 0x30001000)
273 return 1;
274 else
275 return 0;
276}
277
258static int usbmisc_imx6q_hsic_set_connect(struct imx_usbmisc_data *data) 278static int usbmisc_imx6q_hsic_set_connect(struct imx_usbmisc_data *data)
259{ 279{
260 unsigned long flags; 280 unsigned long flags;
@@ -358,6 +378,7 @@ static const struct usbmisc_ops imx6sx_usbmisc_ops = {
358 .set_wakeup = usbmisc_imx6q_set_wakeup, 378 .set_wakeup = usbmisc_imx6q_set_wakeup,
359 .hsic_set_connect = usbmisc_imx6q_hsic_set_connect, 379 .hsic_set_connect = usbmisc_imx6q_hsic_set_connect,
360 .hsic_set_clk = usbmisc_imx6q_hsic_set_clk, 380 .hsic_set_clk = usbmisc_imx6q_hsic_set_clk,
381 .power_lost_check = usbmisc_imx6sx_power_lost_check,
361}; 382};
362 383
363int imx_usbmisc_init(struct imx_usbmisc_data *data) 384int imx_usbmisc_init(struct imx_usbmisc_data *data)
@@ -410,6 +431,16 @@ int imx_usbmisc_hsic_set_clk(struct imx_usbmisc_data *data, bool on)
410} 431}
411EXPORT_SYMBOL_GPL(imx_usbmisc_hsic_set_clk); 432EXPORT_SYMBOL_GPL(imx_usbmisc_hsic_set_clk);
412 433
434int imx_usbmisc_power_lost_check(struct imx_usbmisc_data *data)
435{
436 if (!usbmisc)
437 return -ENODEV;
438 if (!usbmisc->ops->power_lost_check)
439 return 0;
440 return usbmisc->ops->power_lost_check(data);
441}
442EXPORT_SYMBOL_GPL(imx_usbmisc_power_lost_check);
443
413static const struct of_device_id usbmisc_imx_dt_ids[] = { 444static const struct of_device_id usbmisc_imx_dt_ids[] = {
414 { 445 {
415 .compatible = "fsl,imx25-usbmisc", 446 .compatible = "fsl,imx25-usbmisc",