On Mon, Oct 02, 2017 at 10:44:39AM +0100, Ed Blake wrote: > Add suspend / resume handling using suspend_late and resume_early, and > check that all channels are idle before suspending. > > DMA drivers should use suspend_late / resume_early to ensure that all > DMA client devices are suspended before the DMA device itself, and that > client devices are resumed after the DMA device. This avoids suspending > the DMA device while transactions are still active. > > It is the responsibility of client drivers to terminate all DMA > transactions in their suspend handlers, so there should be no active > transactions by the time suspend_late is called. > > There's no need to save and restore registers for MDC during suspend / > resume, as all transactions will be terminated as a result of the > suspend, and all required registers are programmed anyway at the start > of any new transactions following resume. > > Signed-off-by: Ed Blake <ed.blake@xxxxxxxxxxx> > --- > drivers/dma/img-mdc-dma.c | 36 ++++++++++++++++++++++++++++++++++++ > 1 file changed, 36 insertions(+) > > diff --git a/drivers/dma/img-mdc-dma.c b/drivers/dma/img-mdc-dma.c > index 54db141..ca382c9 100644 > --- a/drivers/dma/img-mdc-dma.c > +++ b/drivers/dma/img-mdc-dma.c > @@ -1009,9 +1009,45 @@ static int mdc_dma_remove(struct platform_device *pdev) > return 0; > } > > +#ifdef CONFIG_PM_SLEEP > +static int img_mdc_suspend_late(struct device *dev) > +{ > + struct mdc_dma *mdma = dev_get_drvdata(dev); > + int i; > + > + /* Check that all channels are idle */ > + for (i = 0; i < mdma->nr_channels; i++) { > + struct mdc_chan *mchan = &mdma->channels[i]; > + > + if (unlikely(mchan->desc)) > + return -EBUSY; > + } > + > + clk_disable_unprepare(mdma->clk); > + > + return 0; > +} > + > +static int img_mdc_resume_early(struct device *dev) > +{ > + struct mdc_dma *mdma = dev_get_drvdata(dev); > + int ret = 0; > + > + ret = clk_prepare_enable(mdma->clk); this can be return clk_prepare_enable() > + > + return ret; > +} > +#endif /* CONFIG_PM_SLEEP */ > + > +static const struct dev_pm_ops img_mdc_pm_ops = { > + SET_LATE_SYSTEM_SLEEP_PM_OPS(img_mdc_suspend_late, > + img_mdc_resume_early) any reason for late ops? > +}; > + > static struct platform_driver mdc_dma_driver = { > .driver = { > .name = "img-mdc-dma", > + .pm = &img_mdc_pm_ops, > .of_match_table = of_match_ptr(mdc_dma_of_match), > }, > .probe = mdc_dma_probe, > -- > 1.9.1 > > -- > To unsubscribe from this list: send the line "unsubscribe dmaengine" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html -- ~Vinod -- To unsubscribe from this list: send the line "unsubscribe dmaengine" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html