Enable runtime power management in the rz-dmac driver by adding suspend and
resume callbacks. This ensures the driver can correctly assert and deassert
the reset control and manage power state transitions during suspend and
resume. Adding runtime PM support allows the DMA controller to reduce power
consumption when idle and maintain correct operation across system sleep
states, addressing the previous lack of dynamic power management in the
driver.
Signed-off-by: Tommaso Merciai <tommaso.merciai.xr@bp.renesas.com>
---
v1->v2:
- No chanes
drivers/dma/sh/rz-dmac.c | 57 +++++++++++++++++++++++++++++++++++-----
1 file changed, 50 insertions(+), 7 deletions(-)
diff --git a/drivers/dma/sh/rz-dmac.c b/drivers/dma/sh/rz-dmac.c
index 1f687b08d6b86..2f06bdb7ce3be 100644
--- a/drivers/dma/sh/rz-dmac.c
+++ b/drivers/dma/sh/rz-dmac.c
@@ -437,6 +437,17 @@ static int rz_dmac_xfer_desc(struct rz_dmac_chan *chan)
* DMA engine operations
*/
+static void rz_dmac_chan_init_all(struct rz_dmac *dmac)
+{
+ unsigned int i;
+
+ rz_dmac_writel(dmac, DCTRL_DEFAULT, CHANNEL_0_7_COMMON_BASE + DCTRL);
+ rz_dmac_writel(dmac, DCTRL_DEFAULT, CHANNEL_8_15_COMMON_BASE + DCTRL);
+
+ for (i = 0; i < dmac->n_channels; i++)
+ rz_dmac_ch_writel(&dmac->channels[i], CHCTRL_DEFAULT, CHCTRL, 1);
+}
+
static int rz_dmac_alloc_chan_resources(struct dma_chan *chan)
{
struct rz_dmac_chan *channel = to_rz_dmac_chan(chan);
@@ -970,10 +981,6 @@ static int rz_dmac_probe(struct platform_device *pdev)
goto err_pm_disable;
}
- ret = reset_control_deassert(dmac->rstc);
- if (ret)
- goto err_pm_runtime_put;
-
for (i = 0; i < dmac->n_channels; i++) {
ret = rz_dmac_chan_probe(dmac, &dmac->channels[i], i);
if (ret < 0)
@@ -1028,8 +1035,6 @@ static int rz_dmac_probe(struct platform_device *pdev)
channel->lmdesc.base_dma);
}
- reset_control_assert(dmac->rstc);
-err_pm_runtime_put:
pm_runtime_put(&pdev->dev);
err_pm_disable:
pm_runtime_disable(&pdev->dev);
@@ -1052,13 +1057,50 @@ static void rz_dmac_remove(struct platform_device *pdev)
channel->lmdesc.base,
channel->lmdesc.base_dma);
}
- reset_control_assert(dmac->rstc);
pm_runtime_put(&pdev->dev);
pm_runtime_disable(&pdev->dev);
platform_device_put(dmac->icu.pdev);
}
+static int rz_dmac_runtime_suspend(struct device *dev)
+{
+ struct rz_dmac *dmac = dev_get_drvdata(dev);
+
+ return reset_control_assert(dmac->rstc);
+}
+
+static int rz_dmac_runtime_resume(struct device *dev)
+{
+ struct rz_dmac *dmac = dev_get_drvdata(dev);
+
+ return reset_control_deassert(dmac->rstc);
+}
+
+static int rz_dmac_resume(struct device *dev)
+{
+ struct rz_dmac *dmac = dev_get_drvdata(dev);
+ int ret;
+
+ ret = pm_runtime_force_resume(dev);
+ if (ret)
+ return ret;
+
+ rz_dmac_chan_init_all(dmac);
+
+ return 0;
+}
+
+static const struct dev_pm_ops rz_dmac_pm_ops = {
+ /*
+ * TODO for system sleep/resume:
+ * - Wait for the current transfer to complete and stop the device,
+ * - Resume transfers, if any.
+ */
+ NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, rz_dmac_resume)
+ RUNTIME_PM_OPS(rz_dmac_runtime_suspend, rz_dmac_runtime_resume, NULL)
+};
+
static const struct of_device_id of_rz_dmac_match[] = {
{ .compatible = "renesas,r9a09g057-dmac", },
{ .compatible = "renesas,rz-dmac", },
@@ -1068,6 +1110,7 @@ MODULE_DEVICE_TABLE(of, of_rz_dmac_match);
static struct platform_driver rz_dmac_driver = {
.driver = {
+ .pm = pm_ptr(&rz_dmac_pm_ops),
.name = "rz-dmac",
.of_match_table = of_rz_dmac_match,
},
--
2.43.0
Hi Tommaso, Thanks for your patch! I don't understand why you included this patch in a series with clock patches. AFAIUC, there is no dependency. Am I missing something? On Wed, 3 Sept 2025 at 10:28, Tommaso Merciai <tommaso.merciai.xr@bp.renesas.com> wrote: > Enable runtime power management in the rz-dmac driver by adding suspend and > resume callbacks. This ensures the driver can correctly assert and deassert This is not really what this patch does: the Runtime PM-related changes just hide^Wmove reset handling into the runtime callbacks. > the reset control and manage power state transitions during suspend and > resume. Adding runtime PM support allows the DMA controller to reduce power (I assume) This patch does fix resuming from _system_ suspend. > consumption when idle and maintain correct operation across system sleep > states, addressing the previous lack of dynamic power management in the > driver. The driver still does not do dynamic power management: you still call pm_runtime_resume_and_get() from the driver's probe() .callback, and call pm_runtime_put() only from the .remove() callback, so the device is powered all the time. To implement dynamic power management, you have to change that, and call pm_runtime_resume_and_get() and pm_runtime_put() from the .device_alloc_chan_resources() resp. .device_free_chan_resources() callbacks (see e.g. drivers/dma/sh/rcar-dmac.c). > Signed-off-by: Tommaso Merciai <tommaso.merciai.xr@bp.renesas.com> > --- a/drivers/dma/sh/rz-dmac.c > +++ b/drivers/dma/sh/rz-dmac.c > @@ -437,6 +437,17 @@ static int rz_dmac_xfer_desc(struct rz_dmac_chan *chan) > * DMA engine operations > */ > > +static void rz_dmac_chan_init_all(struct rz_dmac *dmac) > +{ > + unsigned int i; > + > + rz_dmac_writel(dmac, DCTRL_DEFAULT, CHANNEL_0_7_COMMON_BASE + DCTRL); > + rz_dmac_writel(dmac, DCTRL_DEFAULT, CHANNEL_8_15_COMMON_BASE + DCTRL); > + > + for (i = 0; i < dmac->n_channels; i++) > + rz_dmac_ch_writel(&dmac->channels[i], CHCTRL_DEFAULT, CHCTRL, 1); > +} > + > static int rz_dmac_alloc_chan_resources(struct dma_chan *chan) > { > struct rz_dmac_chan *channel = to_rz_dmac_chan(chan); > @@ -970,10 +981,6 @@ static int rz_dmac_probe(struct platform_device *pdev) > goto err_pm_disable; > } > > - ret = reset_control_deassert(dmac->rstc); > - if (ret) > - goto err_pm_runtime_put; > - > for (i = 0; i < dmac->n_channels; i++) { > ret = rz_dmac_chan_probe(dmac, &dmac->channels[i], i); > if (ret < 0) > @@ -1028,8 +1035,6 @@ static int rz_dmac_probe(struct platform_device *pdev) > channel->lmdesc.base_dma); > } > > - reset_control_assert(dmac->rstc); > -err_pm_runtime_put: > pm_runtime_put(&pdev->dev); > err_pm_disable: > pm_runtime_disable(&pdev->dev); > @@ -1052,13 +1057,50 @@ static void rz_dmac_remove(struct platform_device *pdev) > channel->lmdesc.base, > channel->lmdesc.base_dma); > } > - reset_control_assert(dmac->rstc); > pm_runtime_put(&pdev->dev); > pm_runtime_disable(&pdev->dev); > > platform_device_put(dmac->icu.pdev); > } > > +static int rz_dmac_runtime_suspend(struct device *dev) > +{ > + struct rz_dmac *dmac = dev_get_drvdata(dev); > + > + return reset_control_assert(dmac->rstc); Do you really want to reset the device (and thus loose register state) each and every time the device is runtime-suspended? For now it doesn't matter much, but once you implement real dynamic power management, it does. I think the reset handling should be moved to the system suspend/resume callbacks. > +} > + > +static int rz_dmac_runtime_resume(struct device *dev) > +{ > + struct rz_dmac *dmac = dev_get_drvdata(dev); > + > + return reset_control_deassert(dmac->rstc); Shouldn't this reinitialize some registers? For now that indeed doesn't matter, as reset is only deasserted from .probe(), before any register initialization. > +} > + > +static int rz_dmac_resume(struct device *dev) > +{ > + struct rz_dmac *dmac = dev_get_drvdata(dev); > + int ret; > + > + ret = pm_runtime_force_resume(dev); > + if (ret) > + return ret; > + > + rz_dmac_chan_init_all(dmac); > + > + return 0; > +} > + > +static const struct dev_pm_ops rz_dmac_pm_ops = { > + /* > + * TODO for system sleep/resume: > + * - Wait for the current transfer to complete and stop the device, > + * - Resume transfers, if any. > + */ > + NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, rz_dmac_resume) > + RUNTIME_PM_OPS(rz_dmac_runtime_suspend, rz_dmac_runtime_resume, NULL) > +}; > + > static const struct of_device_id of_rz_dmac_match[] = { > { .compatible = "renesas,r9a09g057-dmac", }, > { .compatible = "renesas,rz-dmac", }, > @@ -1068,6 +1110,7 @@ MODULE_DEVICE_TABLE(of, of_rz_dmac_match); > > static struct platform_driver rz_dmac_driver = { > .driver = { > + .pm = pm_ptr(&rz_dmac_pm_ops), > .name = "rz-dmac", > .of_match_table = of_rz_dmac_match, > }, Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds
Hi Geert, Thanks for your comments! (And sorry for the delay :) ) On Wed, Sep 03, 2025 at 02:17:53PM +0200, Geert Uytterhoeven wrote: > Hi Tommaso, > > Thanks for your patch! > > I don't understand why you included this patch in a series with clock > patches. AFAIUC, there is no dependency. Am I missing something? I was working on pm support for RZ DMAC when I wrote previous clk patches, sorry. For that I've included also this one. :'( > > On Wed, 3 Sept 2025 at 10:28, Tommaso Merciai > <tommaso.merciai.xr@bp.renesas.com> wrote: > > Enable runtime power management in the rz-dmac driver by adding suspend and > > resume callbacks. This ensures the driver can correctly assert and deassert > > This is not really what this patch does: the Runtime PM-related changes > just hide^Wmove reset handling into the runtime callbacks. Agreed. > > > the reset control and manage power state transitions during suspend and > > resume. Adding runtime PM support allows the DMA controller to reduce power > > (I assume) This patch does fix resuming from _system_ suspend. > > > consumption when idle and maintain correct operation across system sleep > > states, addressing the previous lack of dynamic power management in the > > driver. > > The driver still does not do dynamic power management: you still call > pm_runtime_resume_and_get() from the driver's probe() .callback, and > call pm_runtime_put() only from the .remove() callback, so the device > is powered all the time. > To implement dynamic power management, you have to change that, > and call pm_runtime_resume_and_get() and pm_runtime_put() from the > .device_alloc_chan_resources() resp. .device_free_chan_resources() > callbacks (see e.g. drivers/dma/sh/rcar-dmac.c). Thanks for the hints! So following your hints we need to: - call pm_runtime_get_sync() from rz_dmac_alloc_chan_resources() - call pm_runtime_put() from rz_dmac_free_chan_resources() With that then we can remove pm_runtime_put() from the remove function and add this at the end of the probe function. > > > Signed-off-by: Tommaso Merciai <tommaso.merciai.xr@bp.renesas.com> > > > --- a/drivers/dma/sh/rz-dmac.c > > +++ b/drivers/dma/sh/rz-dmac.c > > @@ -437,6 +437,17 @@ static int rz_dmac_xfer_desc(struct rz_dmac_chan *chan) > > * DMA engine operations > > */ > > > > +static void rz_dmac_chan_init_all(struct rz_dmac *dmac) > > +{ > > + unsigned int i; > > + > > + rz_dmac_writel(dmac, DCTRL_DEFAULT, CHANNEL_0_7_COMMON_BASE + DCTRL); > > + rz_dmac_writel(dmac, DCTRL_DEFAULT, CHANNEL_8_15_COMMON_BASE + DCTRL); > > + > > + for (i = 0; i < dmac->n_channels; i++) > > + rz_dmac_ch_writel(&dmac->channels[i], CHCTRL_DEFAULT, CHCTRL, 1); > > +} > > + > > static int rz_dmac_alloc_chan_resources(struct dma_chan *chan) > > { > > struct rz_dmac_chan *channel = to_rz_dmac_chan(chan); > > @@ -970,10 +981,6 @@ static int rz_dmac_probe(struct platform_device *pdev) > > goto err_pm_disable; > > } > > > > - ret = reset_control_deassert(dmac->rstc); > > - if (ret) > > - goto err_pm_runtime_put; > > - > > for (i = 0; i < dmac->n_channels; i++) { > > ret = rz_dmac_chan_probe(dmac, &dmac->channels[i], i); > > if (ret < 0) > > @@ -1028,8 +1035,6 @@ static int rz_dmac_probe(struct platform_device *pdev) > > channel->lmdesc.base_dma); > > } > > > > - reset_control_assert(dmac->rstc); > > -err_pm_runtime_put: > > pm_runtime_put(&pdev->dev); > > err_pm_disable: > > pm_runtime_disable(&pdev->dev); > > @@ -1052,13 +1057,50 @@ static void rz_dmac_remove(struct platform_device *pdev) > > channel->lmdesc.base, > > channel->lmdesc.base_dma); > > } > > - reset_control_assert(dmac->rstc); > > pm_runtime_put(&pdev->dev); > > pm_runtime_disable(&pdev->dev); > > > > platform_device_put(dmac->icu.pdev); > > } > > > > +static int rz_dmac_runtime_suspend(struct device *dev) > > +{ > > + struct rz_dmac *dmac = dev_get_drvdata(dev); > > + > > + return reset_control_assert(dmac->rstc); > > Do you really want to reset the device (and thus loose register state) > each and every time the device is runtime-suspended? For now it doesn't > matter much, but once you implement real dynamic power management, > it does. > I think the reset handling should be moved to the system suspend/resume > callbacks. Agreed. With above changes maybe we can move all into NOIRQ_SYSTEM_SLEEP_PM_OPS(rz_dmac_suspend, rz_dmac_resume) With your suggested changes I'm not sure if pm_runtime_ops are really needed. Thanks & Regards, Tommaso > > > +} > > + > > +static int rz_dmac_runtime_resume(struct device *dev) > > +{ > > + struct rz_dmac *dmac = dev_get_drvdata(dev); > > + > > + return reset_control_deassert(dmac->rstc); > > Shouldn't this reinitialize some registers? > For now that indeed doesn't matter, as reset is only deasserted > from .probe(), before any register initialization. > > > +} > > + > > +static int rz_dmac_resume(struct device *dev) > > +{ > > + struct rz_dmac *dmac = dev_get_drvdata(dev); > > + int ret; > > + > > + ret = pm_runtime_force_resume(dev); > > + if (ret) > > + return ret; > > + > > + rz_dmac_chan_init_all(dmac); > > + > > + return 0; > > +} > > + > > +static const struct dev_pm_ops rz_dmac_pm_ops = { > > + /* > > + * TODO for system sleep/resume: > > + * - Wait for the current transfer to complete and stop the device, > > + * - Resume transfers, if any. > > + */ > > + NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, rz_dmac_resume) > > + RUNTIME_PM_OPS(rz_dmac_runtime_suspend, rz_dmac_runtime_resume, NULL) > > +}; > > + > > static const struct of_device_id of_rz_dmac_match[] = { > > { .compatible = "renesas,r9a09g057-dmac", }, > > { .compatible = "renesas,rz-dmac", }, > > @@ -1068,6 +1110,7 @@ MODULE_DEVICE_TABLE(of, of_rz_dmac_match); > > > > static struct platform_driver rz_dmac_driver = { > > .driver = { > > + .pm = pm_ptr(&rz_dmac_pm_ops), > > .name = "rz-dmac", > > .of_match_table = of_rz_dmac_match, > > }, > > Gr{oetje,eeting}s, > > Geert > > -- > Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org > > In personal conversations with technical people, I call myself a hacker. But > when I'm talking to journalists I just say "programmer" or something like that. > -- Linus Torvalds
Hi Tommaso, On Thu, 4 Sept 2025 at 17:02, Tommaso Merciai <tommaso.merciai.xr@bp.renesas.com> wrote: > On Wed, Sep 03, 2025 at 02:17:53PM +0200, Geert Uytterhoeven wrote: > > On Wed, 3 Sept 2025 at 10:28, Tommaso Merciai > > <tommaso.merciai.xr@bp.renesas.com> wrote: > > > Enable runtime power management in the rz-dmac driver by adding suspend and > > > resume callbacks. This ensures the driver can correctly assert and deassert > > > > This is not really what this patch does: the Runtime PM-related changes > > just hide^Wmove reset handling into the runtime callbacks. > > Agreed. > > > > the reset control and manage power state transitions during suspend and > > > resume. Adding runtime PM support allows the DMA controller to reduce power > > > > (I assume) This patch does fix resuming from _system_ suspend. > > > > > consumption when idle and maintain correct operation across system sleep > > > states, addressing the previous lack of dynamic power management in the > > > driver. > > > > The driver still does not do dynamic power management: you still call > > pm_runtime_resume_and_get() from the driver's probe() .callback, and > > call pm_runtime_put() only from the .remove() callback, so the device > > is powered all the time. > > To implement dynamic power management, you have to change that, > > and call pm_runtime_resume_and_get() and pm_runtime_put() from the > > .device_alloc_chan_resources() resp. .device_free_chan_resources() > > callbacks (see e.g. drivers/dma/sh/rcar-dmac.c). > > Thanks for the hints! > So following your hints we need to: > > - call pm_runtime_get_sync() from rz_dmac_alloc_chan_resources() > - call pm_runtime_put() from rz_dmac_free_chan_resources() > > With that then we can remove pm_runtime_put() from the remove function > and add this at the end of the probe function. > > > > Signed-off-by: Tommaso Merciai <tommaso.merciai.xr@bp.renesas.com> > > > > > --- a/drivers/dma/sh/rz-dmac.c > > > +++ b/drivers/dma/sh/rz-dmac.c > > > @@ -437,6 +437,17 @@ static int rz_dmac_xfer_desc(struct rz_dmac_chan *chan) > > > * DMA engine operations > > > */ > > > > > > +static void rz_dmac_chan_init_all(struct rz_dmac *dmac) > > > +{ > > > + unsigned int i; > > > + > > > + rz_dmac_writel(dmac, DCTRL_DEFAULT, CHANNEL_0_7_COMMON_BASE + DCTRL); > > > + rz_dmac_writel(dmac, DCTRL_DEFAULT, CHANNEL_8_15_COMMON_BASE + DCTRL); > > > + > > > + for (i = 0; i < dmac->n_channels; i++) > > > + rz_dmac_ch_writel(&dmac->channels[i], CHCTRL_DEFAULT, CHCTRL, 1); > > > +} > > > + > > > static int rz_dmac_alloc_chan_resources(struct dma_chan *chan) > > > { > > > struct rz_dmac_chan *channel = to_rz_dmac_chan(chan); > > > @@ -970,10 +981,6 @@ static int rz_dmac_probe(struct platform_device *pdev) > > > goto err_pm_disable; > > > } > > > > > > - ret = reset_control_deassert(dmac->rstc); > > > - if (ret) > > > - goto err_pm_runtime_put; > > > - > > > for (i = 0; i < dmac->n_channels; i++) { > > > ret = rz_dmac_chan_probe(dmac, &dmac->channels[i], i); > > > if (ret < 0) > > > @@ -1028,8 +1035,6 @@ static int rz_dmac_probe(struct platform_device *pdev) > > > channel->lmdesc.base_dma); > > > } > > > > > > - reset_control_assert(dmac->rstc); > > > -err_pm_runtime_put: > > > pm_runtime_put(&pdev->dev); > > > err_pm_disable: > > > pm_runtime_disable(&pdev->dev); > > > @@ -1052,13 +1057,50 @@ static void rz_dmac_remove(struct platform_device *pdev) > > > channel->lmdesc.base, > > > channel->lmdesc.base_dma); > > > } > > > - reset_control_assert(dmac->rstc); > > > pm_runtime_put(&pdev->dev); > > > pm_runtime_disable(&pdev->dev); > > > > > > platform_device_put(dmac->icu.pdev); > > > } > > > > > > +static int rz_dmac_runtime_suspend(struct device *dev) > > > +{ > > > + struct rz_dmac *dmac = dev_get_drvdata(dev); > > > + > > > + return reset_control_assert(dmac->rstc); > > > > Do you really want to reset the device (and thus loose register state) > > each and every time the device is runtime-suspended? For now it doesn't > > matter much, but once you implement real dynamic power management, > > it does. > > I think the reset handling should be moved to the system suspend/resume > > callbacks. > > Agreed. With above changes maybe we can move all into > NOIRQ_SYSTEM_SLEEP_PM_OPS(rz_dmac_suspend, rz_dmac_resume) > With your suggested changes I'm not sure if pm_runtime_ops are really needed. After these changes, you indeed no longer need any pm_runtime_ops. Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds
Hi Geert, On Thu, Sep 04, 2025 at 05:10:41PM +0200, Geert Uytterhoeven wrote: > Hi Tommaso, > > On Thu, 4 Sept 2025 at 17:02, Tommaso Merciai > <tommaso.merciai.xr@bp.renesas.com> wrote: > > On Wed, Sep 03, 2025 at 02:17:53PM +0200, Geert Uytterhoeven wrote: > > > On Wed, 3 Sept 2025 at 10:28, Tommaso Merciai > > > <tommaso.merciai.xr@bp.renesas.com> wrote: > > > > Enable runtime power management in the rz-dmac driver by adding suspend and > > > > resume callbacks. This ensures the driver can correctly assert and deassert > > > > > > This is not really what this patch does: the Runtime PM-related changes > > > just hide^Wmove reset handling into the runtime callbacks. > > > > Agreed. > > > > > > the reset control and manage power state transitions during suspend and > > > > resume. Adding runtime PM support allows the DMA controller to reduce power > > > > > > (I assume) This patch does fix resuming from _system_ suspend. > > > > > > > consumption when idle and maintain correct operation across system sleep > > > > states, addressing the previous lack of dynamic power management in the > > > > driver. > > > > > > The driver still does not do dynamic power management: you still call > > > pm_runtime_resume_and_get() from the driver's probe() .callback, and > > > call pm_runtime_put() only from the .remove() callback, so the device > > > is powered all the time. > > > To implement dynamic power management, you have to change that, > > > and call pm_runtime_resume_and_get() and pm_runtime_put() from the > > > .device_alloc_chan_resources() resp. .device_free_chan_resources() > > > callbacks (see e.g. drivers/dma/sh/rcar-dmac.c). > > > > Thanks for the hints! > > So following your hints we need to: > > > > - call pm_runtime_get_sync() from rz_dmac_alloc_chan_resources() > > - call pm_runtime_put() from rz_dmac_free_chan_resources() > > > > With that then we can remove pm_runtime_put() from the remove function > > and add this at the end of the probe function. > > > > > > Signed-off-by: Tommaso Merciai <tommaso.merciai.xr@bp.renesas.com> > > > > > > > --- a/drivers/dma/sh/rz-dmac.c > > > > +++ b/drivers/dma/sh/rz-dmac.c > > > > @@ -437,6 +437,17 @@ static int rz_dmac_xfer_desc(struct rz_dmac_chan *chan) > > > > * DMA engine operations > > > > */ > > > > > > > > +static void rz_dmac_chan_init_all(struct rz_dmac *dmac) > > > > +{ > > > > + unsigned int i; > > > > + > > > > + rz_dmac_writel(dmac, DCTRL_DEFAULT, CHANNEL_0_7_COMMON_BASE + DCTRL); > > > > + rz_dmac_writel(dmac, DCTRL_DEFAULT, CHANNEL_8_15_COMMON_BASE + DCTRL); > > > > + > > > > + for (i = 0; i < dmac->n_channels; i++) > > > > + rz_dmac_ch_writel(&dmac->channels[i], CHCTRL_DEFAULT, CHCTRL, 1); > > > > +} > > > > + > > > > static int rz_dmac_alloc_chan_resources(struct dma_chan *chan) > > > > { > > > > struct rz_dmac_chan *channel = to_rz_dmac_chan(chan); > > > > @@ -970,10 +981,6 @@ static int rz_dmac_probe(struct platform_device *pdev) > > > > goto err_pm_disable; > > > > } > > > > > > > > - ret = reset_control_deassert(dmac->rstc); > > > > - if (ret) > > > > - goto err_pm_runtime_put; > > > > - > > > > for (i = 0; i < dmac->n_channels; i++) { > > > > ret = rz_dmac_chan_probe(dmac, &dmac->channels[i], i); > > > > if (ret < 0) > > > > @@ -1028,8 +1035,6 @@ static int rz_dmac_probe(struct platform_device *pdev) > > > > channel->lmdesc.base_dma); > > > > } > > > > > > > > - reset_control_assert(dmac->rstc); > > > > -err_pm_runtime_put: > > > > pm_runtime_put(&pdev->dev); > > > > err_pm_disable: > > > > pm_runtime_disable(&pdev->dev); > > > > @@ -1052,13 +1057,50 @@ static void rz_dmac_remove(struct platform_device *pdev) > > > > channel->lmdesc.base, > > > > channel->lmdesc.base_dma); > > > > } > > > > - reset_control_assert(dmac->rstc); > > > > pm_runtime_put(&pdev->dev); > > > > pm_runtime_disable(&pdev->dev); > > > > > > > > platform_device_put(dmac->icu.pdev); > > > > } > > > > > > > > +static int rz_dmac_runtime_suspend(struct device *dev) > > > > +{ > > > > + struct rz_dmac *dmac = dev_get_drvdata(dev); > > > > + > > > > + return reset_control_assert(dmac->rstc); > > > > > > Do you really want to reset the device (and thus loose register state) > > > each and every time the device is runtime-suspended? For now it doesn't > > > matter much, but once you implement real dynamic power management, > > > it does. > > > I think the reset handling should be moved to the system suspend/resume > > > callbacks. > > > > Agreed. With above changes maybe we can move all into > > NOIRQ_SYSTEM_SLEEP_PM_OPS(rz_dmac_suspend, rz_dmac_resume) > > With your suggested changes I'm not sure if pm_runtime_ops are really needed. > > After these changes, you indeed no longer need any pm_runtime_ops. Thank you for the quick feedback! Kind Regards, Tommaso > > Gr{oetje,eeting}s, > > Geert > > -- > Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org > > In personal conversations with technical people, I call myself a hacker. But > when I'm talking to journalists I just say "programmer" or something like that. > -- Linus Torvalds
© 2016 - 2025 Red Hat, Inc.