From: Artem Shimko <a.shimko.dev@gmail.com>
To: Vinod Koul <vkoul@kernel.org>,
Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>,
Philipp Zabel <p.zabel@pengutronix.de>
Cc: dan.carpenter@linaro.org, a.shimko.dev@gmail.com,
linux-kernel@vger.kernel.org, dmaengine@vger.kernel.org
Subject: [PATCH v5 2/3] dmaengine: dw-axi-dmac: add reset control support
Date: Thu, 23 Oct 2025 23:21:32 +0300 [thread overview]
Message-ID: <20251023202134.1291034-3-a.shimko.dev@gmail.com> (raw)
In-Reply-To: <20251023202134.1291034-1-a.shimko.dev@gmail.com>
Add proper reset control handling to the AXI DMA driver to ensure
reliable initialization and power management. The driver now manages
resets during probe, remove, and system suspend/resume operations.
The implementation stores reset control in the chip structure and adds
reset assert/deassert calls at the appropriate points: resets are
deasserted during probe after clock acquisition, asserted during remove
and error cleanup, and properly managed during suspend/resume cycles.
Additionally, proper error handling is implemented for reset control
operations to ensure robust behavior.
This ensures the controller is properly reset during power transitions
and prevents potential issues with incomplete initialization.
Signed-off-by: Artem Shimko <a.shimko.dev@gmail.com>
---
.../dma/dw-axi-dmac/dw-axi-dmac-platform.c | 59 +++++++++++++------
drivers/dma/dw-axi-dmac/dw-axi-dmac.h | 1 +
2 files changed, 43 insertions(+), 17 deletions(-)
diff --git a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
index 8b7cf3baf5d3..1496c52f47a6 100644
--- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
+++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
@@ -1316,11 +1316,16 @@ static int dma_chan_resume(struct dma_chan *dchan)
static int axi_dma_suspend(struct device *dev)
{
+ int ret;
struct axi_dma_chip *chip = dev_get_drvdata(dev);
axi_dma_irq_disable(chip);
axi_dma_disable(chip);
+ ret = reset_control_assert(chip->resets);
+ if (ret)
+ dev_warn(dev, "Failed to assert resets, but continuing suspend\n");
+
clk_disable_unprepare(chip->core_clk);
clk_disable_unprepare(chip->cfgr_clk);
@@ -1338,12 +1343,23 @@ static int axi_dma_resume(struct device *dev)
ret = clk_prepare_enable(chip->core_clk);
if (ret < 0)
- return ret;
+ goto cfgr_clk_disable;
+
+ ret = reset_control_deassert(chip->resets);
+ if (ret)
+ goto core_clk_disable;
axi_dma_enable(chip);
axi_dma_irq_enable(chip);
return 0;
+
+core_clk_disable:
+ clk_disable_unprepare(chip->core_clk);
+cfgr_clk_disable:
+ clk_disable_unprepare(chip->cfgr_clk);
+
+ return ret;
}
static struct dma_chan *dw_axi_dma_of_xlate(struct of_phandle_args *dma_spec,
@@ -1455,7 +1471,6 @@ static int dw_probe(struct platform_device *pdev)
struct axi_dma_chip *chip;
struct dw_axi_dma *dw;
struct dw_axi_dma_hcfg *hdata;
- struct reset_control *resets;
unsigned int flags;
u32 i;
int ret;
@@ -1487,16 +1502,6 @@ static int dw_probe(struct platform_device *pdev)
return PTR_ERR(chip->apb_regs);
}
- if (flags & AXI_DMA_FLAG_HAS_RESETS) {
- resets = devm_reset_control_array_get_exclusive(&pdev->dev);
- if (IS_ERR(resets))
- return PTR_ERR(resets);
-
- ret = reset_control_deassert(resets);
- if (ret)
- return ret;
- }
-
chip->dw->hdata->use_cfg2 = !!(flags & AXI_DMA_FLAG_USE_CFG2);
chip->core_clk = devm_clk_get(chip->dev, "core-clk");
@@ -1507,18 +1512,28 @@ static int dw_probe(struct platform_device *pdev)
if (IS_ERR(chip->cfgr_clk))
return PTR_ERR(chip->cfgr_clk);
+ chip->resets = devm_reset_control_array_get_optional_exclusive(&pdev->dev);
+ if (IS_ERR(chip->resets))
+ return PTR_ERR(chip->resets);
+
+ ret = reset_control_deassert(chip->resets);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret, "Failed to deassert resets\n");
+
ret = parse_device_properties(chip);
if (ret)
- return ret;
+ goto err_exit;
dw->chan = devm_kcalloc(chip->dev, hdata->nr_channels,
sizeof(*dw->chan), GFP_KERNEL);
- if (!dw->chan)
- return -ENOMEM;
+ if (!dw->chan) {
+ ret = -ENOMEM;
+ goto err_exit;
+ }
ret = axi_req_irqs(pdev, chip);
if (ret)
- return ret;
+ goto err_exit;
INIT_LIST_HEAD(&dw->dma.channels);
for (i = 0; i < hdata->nr_channels; i++) {
@@ -1605,20 +1620,30 @@ static int dw_probe(struct platform_device *pdev)
err_pm_disable:
pm_runtime_disable(chip->dev);
+err_exit:
+ reset_control_assert(chip->resets);
return ret;
}
static void dw_remove(struct platform_device *pdev)
{
+ int ret;
struct axi_dma_chip *chip = platform_get_drvdata(pdev);
struct dw_axi_dma *dw = chip->dw;
struct axi_dma_chan *chan, *_chan;
u32 i;
- /* Enable clk before accessing to registers */
+ /*
+ * The peripheral must be clocked and out of reset
+ * before its registers can be accessed.
+ */
clk_prepare_enable(chip->cfgr_clk);
clk_prepare_enable(chip->core_clk);
+ ret = reset_control_deassert(chip->resets);
+ if (ret)
+ dev_err(&pdev->dev, "Failed to deassert resets\n");
+
axi_dma_irq_disable(chip);
for (i = 0; i < dw->hdata->nr_channels; i++) {
axi_chan_disable(&chip->dw->chan[i]);
diff --git a/drivers/dma/dw-axi-dmac/dw-axi-dmac.h b/drivers/dma/dw-axi-dmac/dw-axi-dmac.h
index b842e6a8d90d..c74affb9f344 100644
--- a/drivers/dma/dw-axi-dmac/dw-axi-dmac.h
+++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac.h
@@ -71,6 +71,7 @@ struct axi_dma_chip {
struct clk *core_clk;
struct clk *cfgr_clk;
struct dw_axi_dma *dw;
+ struct reset_control *resets;
};
/* LLI == Linked List Item */
--
2.43.0
next prev parent reply other threads:[~2025-10-23 20:21 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-10-23 20:21 [PATCH v5 0/3] dmaengine: dw-axi-dmac: PM cleanup and reset control support Artem Shimko
2025-10-23 20:21 ` [PATCH v5 1/3] dmaengine: dw-axi-dmac: simplify PM functions and use modern macros Artem Shimko
2025-10-23 20:21 ` Artem Shimko [this message]
2025-10-23 20:21 ` [PATCH v5 3/3] dmaengine: dw-axi-dmac: fix inconsistent indentation in pause/resume functions Artem Shimko
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20251023202134.1291034-3-a.shimko.dev@gmail.com \
--to=a.shimko.dev@gmail.com \
--cc=Eugeniy.Paltsev@synopsys.com \
--cc=dan.carpenter@linaro.org \
--cc=dmaengine@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=p.zabel@pengutronix.de \
--cc=vkoul@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).