diff options
author | Geert Uytterhoeven <geert+renesas@glider.be> | 2015-02-26 05:26:34 -0500 |
---|---|---|
committer | Vinod Koul <vinod.koul@intel.com> | 2015-03-02 11:40:44 -0500 |
commit | b6d1778bc5485c55c6f5194b8b2ea84c0ce5adad (patch) | |
tree | 38f42da0239e056a37ea2864f047476545874473 /drivers/dma | |
parent | 3a314f143d82603bd697d7eb6c76518afc3595bc (diff) |
dmaengine: shdma: Move DMA stop to (runtime) suspend callbacks
During system reboot, the sh-dma-engine device may be runtime-suspended,
causing a crash:
Unhandled fault: imprecise external abort (0x1406) at 0x0002c02c
Internal error: : 1406 [#1] SMP ARM
...
PC is at sh_dmae_ctl_stop+0x28/0x64
LR is at sh_dmae_ctl_stop+0x24/0x64
If the sh-dma-engine is runtime-suspended, its module clock is turned
off, and its registers cannot be accessed.
To fix this, move the call to sh_dmae_ctl_stop(), which touches the
DMAOR register, to the sh_dmae_suspend() and sh_dmae_runtime_suspend()
callbacks. This makes PM operations more symmetric, as both
sh_dmae_resume() and sh_dmae_runtime_resume() already call sh_dmae_rst()
to re-initialize the DMAOR register.
Remove sh_dmae_shutdown(), as it became empty.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
Diffstat (limited to 'drivers/dma')
-rw-r--r-- | drivers/dma/sh/shdmac.c | 15 |
1 files changed, 7 insertions, 8 deletions
diff --git a/drivers/dma/sh/shdmac.c b/drivers/dma/sh/shdmac.c index b2431aa30033..9f1d4c7dbab8 100644 --- a/drivers/dma/sh/shdmac.c +++ b/drivers/dma/sh/shdmac.c | |||
@@ -582,15 +582,12 @@ static void sh_dmae_chan_remove(struct sh_dmae_device *shdev) | |||
582 | } | 582 | } |
583 | } | 583 | } |
584 | 584 | ||
585 | static void sh_dmae_shutdown(struct platform_device *pdev) | ||
586 | { | ||
587 | struct sh_dmae_device *shdev = platform_get_drvdata(pdev); | ||
588 | sh_dmae_ctl_stop(shdev); | ||
589 | } | ||
590 | |||
591 | #ifdef CONFIG_PM | 585 | #ifdef CONFIG_PM |
592 | static int sh_dmae_runtime_suspend(struct device *dev) | 586 | static int sh_dmae_runtime_suspend(struct device *dev) |
593 | { | 587 | { |
588 | struct sh_dmae_device *shdev = dev_get_drvdata(dev); | ||
589 | |||
590 | sh_dmae_ctl_stop(shdev); | ||
594 | return 0; | 591 | return 0; |
595 | } | 592 | } |
596 | 593 | ||
@@ -605,6 +602,9 @@ static int sh_dmae_runtime_resume(struct device *dev) | |||
605 | #ifdef CONFIG_PM_SLEEP | 602 | #ifdef CONFIG_PM_SLEEP |
606 | static int sh_dmae_suspend(struct device *dev) | 603 | static int sh_dmae_suspend(struct device *dev) |
607 | { | 604 | { |
605 | struct sh_dmae_device *shdev = dev_get_drvdata(dev); | ||
606 | |||
607 | sh_dmae_ctl_stop(shdev); | ||
608 | return 0; | 608 | return 0; |
609 | } | 609 | } |
610 | 610 | ||
@@ -929,13 +929,12 @@ static int sh_dmae_remove(struct platform_device *pdev) | |||
929 | } | 929 | } |
930 | 930 | ||
931 | static struct platform_driver sh_dmae_driver = { | 931 | static struct platform_driver sh_dmae_driver = { |
932 | .driver = { | 932 | .driver = { |
933 | .pm = &sh_dmae_pm, | 933 | .pm = &sh_dmae_pm, |
934 | .name = SH_DMAE_DRV_NAME, | 934 | .name = SH_DMAE_DRV_NAME, |
935 | .of_match_table = sh_dmae_of_match, | 935 | .of_match_table = sh_dmae_of_match, |
936 | }, | 936 | }, |
937 | .remove = sh_dmae_remove, | 937 | .remove = sh_dmae_remove, |
938 | .shutdown = sh_dmae_shutdown, | ||
939 | }; | 938 | }; |
940 | 939 | ||
941 | static int __init sh_dmae_init(void) | 940 | static int __init sh_dmae_init(void) |