diff options
| author | Li Jun <b47624@freescale.com> | 2014-06-26 21:52:29 -0400 |
|---|---|---|
| committer | Li Jun <B47624@freescale.com> | 2014-06-30 04:36:15 -0400 |
| commit | 746ae5611a7610a4585c1836f292527ff7a260a1 (patch) | |
| tree | 1909c306b679ca238a160d4b019db4b4cbca393a /drivers/usb | |
| parent | 7cae872ea9776770043f8c34908e16b27f96cccf (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.c | 10 | ||||
| -rw-r--r-- | drivers/usb/chipidea/ci_hdrc_imx.h | 1 | ||||
| -rw-r--r-- | drivers/usb/chipidea/usbmisc_imx.c | 31 |
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 */ |
| 35 | int imx_usbmisc_hsic_set_connect(struct imx_usbmisc_data *); | 35 | int imx_usbmisc_hsic_set_connect(struct imx_usbmisc_data *); |
| 36 | int imx_usbmisc_hsic_set_clk(struct imx_usbmisc_data *, bool); | 36 | int imx_usbmisc_hsic_set_clk(struct imx_usbmisc_data *, bool); |
| 37 | int 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 | ||
| 80 | struct imx_usbmisc { | 82 | struct 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 | ||
| 260 | static 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 | |||
| 258 | static int usbmisc_imx6q_hsic_set_connect(struct imx_usbmisc_data *data) | 278 | static 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 | ||
| 363 | int imx_usbmisc_init(struct imx_usbmisc_data *data) | 384 | int 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 | } |
| 411 | EXPORT_SYMBOL_GPL(imx_usbmisc_hsic_set_clk); | 432 | EXPORT_SYMBOL_GPL(imx_usbmisc_hsic_set_clk); |
| 412 | 433 | ||
| 434 | int 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 | } | ||
| 442 | EXPORT_SYMBOL_GPL(imx_usbmisc_power_lost_check); | ||
| 443 | |||
| 413 | static const struct of_device_id usbmisc_imx_dt_ids[] = { | 444 | static const struct of_device_id usbmisc_imx_dt_ids[] = { |
| 414 | { | 445 | { |
| 415 | .compatible = "fsl,imx25-usbmisc", | 446 | .compatible = "fsl,imx25-usbmisc", |
