On 20-12-24, 10:11, Joy Zou wrote: > Introduce runtime suspend and resume support for FSL eDMA. Enable > per-channel power domain management to facilitate runtime suspend and > resume operations. > > Implement runtime suspend and resume functions for the eDMA engine and > individual channels. > > Link per-channel power domain device to eDMA per-channel device instead of > eDMA engine device. So Power Manage framework manage power state of linked > domain device when per-channel device request runtime resume/suspend. > > Trigger the eDMA engine's runtime suspend when all channels are suspended, > disabling all common clocks through the runtime PM framework. > > Signed-off-by: Joy Zou <joy.zou@xxxxxxx> > Signed-off-by: Frank Li <Frank.Li@xxxxxxx> > --- > drivers/dma/fsl-edma-common.c | 15 ++--- > drivers/dma/fsl-edma-main.c | 115 ++++++++++++++++++++++++++++++---- > 2 files changed, 110 insertions(+), 20 deletions(-) > > diff --git a/drivers/dma/fsl-edma-common.c b/drivers/dma/fsl-edma-common.c > index b7f15ab96855..fcdb53b21f38 100644 > --- a/drivers/dma/fsl-edma-common.c > +++ b/drivers/dma/fsl-edma-common.c > @@ -243,9 +243,6 @@ int fsl_edma_terminate_all(struct dma_chan *chan) > spin_unlock_irqrestore(&fsl_chan->vchan.lock, flags); > vchan_dma_desc_free_list(&fsl_chan->vchan, &head); > > - if (fsl_edma_drvflags(fsl_chan) & FSL_EDMA_DRV_HAS_PD) > - pm_runtime_allow(fsl_chan->pd_dev); > - > return 0; > } > > @@ -805,8 +802,12 @@ int fsl_edma_alloc_chan_resources(struct dma_chan *chan) > struct fsl_edma_chan *fsl_chan = to_fsl_edma_chan(chan); > int ret; > > - if (fsl_edma_drvflags(fsl_chan) & FSL_EDMA_DRV_HAS_CHCLK) > - clk_prepare_enable(fsl_chan->clk); > + ret = pm_runtime_get_sync(&fsl_chan->vchan.chan.dev->device); > + if (ret < 0) { > + dev_err(&fsl_chan->vchan.chan.dev->device, "pm_runtime_get_sync() failed\n"); > + pm_runtime_disable(&fsl_chan->vchan.chan.dev->device); > + return ret; > + } > > fsl_chan->tcd_pool = dma_pool_create("tcd_pool", chan->device->dev, > fsl_edma_drvflags(fsl_chan) & FSL_EDMA_DRV_TCD64 ? > @@ -819,6 +820,7 @@ int fsl_edma_alloc_chan_resources(struct dma_chan *chan) > > if (ret) { > dma_pool_destroy(fsl_chan->tcd_pool); > + pm_runtime_put_sync_suspend(&fsl_chan->vchan.chan.dev->device); > return ret; > } > } > @@ -851,8 +853,7 @@ void fsl_edma_free_chan_resources(struct dma_chan *chan) > fsl_chan->is_sw = false; > fsl_chan->srcid = 0; > fsl_chan->is_remote = false; > - if (fsl_edma_drvflags(fsl_chan) & FSL_EDMA_DRV_HAS_CHCLK) > - clk_disable_unprepare(fsl_chan->clk); > + pm_runtime_put_sync_suspend(&fsl_chan->vchan.chan.dev->device); > } > > void fsl_edma_cleanup_vchan(struct dma_device *dmadev) > diff --git a/drivers/dma/fsl-edma-main.c b/drivers/dma/fsl-edma-main.c > index 60de1003193a..75d6c8984c8e 100644 > --- a/drivers/dma/fsl-edma-main.c > +++ b/drivers/dma/fsl-edma-main.c > @@ -420,7 +420,6 @@ MODULE_DEVICE_TABLE(of, fsl_edma_dt_ids); > static int fsl_edma3_attach_pd(struct platform_device *pdev, struct fsl_edma_engine *fsl_edma) > { > struct fsl_edma_chan *fsl_chan; > - struct device_link *link; > struct device *pd_chan; > struct device *dev; > int i; > @@ -439,24 +438,39 @@ static int fsl_edma3_attach_pd(struct platform_device *pdev, struct fsl_edma_eng > return -EINVAL; > } > > - link = device_link_add(dev, pd_chan, DL_FLAG_STATELESS | > - DL_FLAG_PM_RUNTIME | > - DL_FLAG_RPM_ACTIVE); > - if (!link) { > - dev_err(dev, "Failed to add device_link to %d\n", i); > - return -EINVAL; > - } > - > fsl_chan->pd_dev = pd_chan; > - > - pm_runtime_use_autosuspend(fsl_chan->pd_dev); > - pm_runtime_set_autosuspend_delay(fsl_chan->pd_dev, 200); > - pm_runtime_set_active(fsl_chan->pd_dev); > } > > return 0; > } > > +/* Per channel dma power domain */ > +static int fsl_edma_chan_runtime_suspend(struct device *dev) > +{ > + struct fsl_edma_chan *fsl_chan = dev_get_drvdata(dev); > + int ret = 0; > + > + clk_disable_unprepare(fsl_chan->clk); > + > + return ret; Unused ret! drop it > +} > + > +static int fsl_edma_chan_runtime_resume(struct device *dev) > +{ > + struct fsl_edma_chan *fsl_chan = dev_get_drvdata(dev); > + int ret; > + > + ret = clk_prepare_enable(fsl_chan->clk); > + > + return ret; how about return clk_prepare_enable() -- ~Vinod