ASoC: dwc: add optional reset support
authorMaxim Kochetkov <fido_max@inbox.ru>
Thu, 4 May 2023 07:16:17 +0000 (10:16 +0300)
committerMark Brown <broonie@kernel.org>
Sun, 7 May 2023 23:48:42 +0000 (08:48 +0900)
Some SoC may have resets for I2S subsystem. So add optional reset support.

Signed-off-by: Maxim Kochetkov <fido_max@inbox.ru
Link: https://lore.kernel.org/r/20230504071618.52012-1-fido_max@inbox.ru
Signed-off-by: Mark Brown <broonie@kernel.org
sound/soc/dwc/dwc-i2s.c
sound/soc/dwc/local.h

index acdf98b..e2b2ba0 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/io.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
+#include <linux/reset.h>
 #include <linux/slab.h>
 #include <linux/pm_runtime.h>
 #include <sound/designware_i2s.h>
@@ -648,6 +649,14 @@ static int dw_i2s_probe(struct platform_device *pdev)
        if (IS_ERR(dev->i2s_base))
                return PTR_ERR(dev->i2s_base);
 
+       dev->reset = devm_reset_control_array_get_optional_shared(&pdev->dev);
+       if (IS_ERR(dev->reset))
+               return PTR_ERR(dev->reset);
+
+       ret = reset_control_deassert(dev->reset);
+       if (ret)
+               return ret;
+
        dev->dev = &pdev->dev;
 
        irq = platform_get_irq_optional(pdev, 0);
@@ -656,7 +665,7 @@ static int dw_i2s_probe(struct platform_device *pdev)
                                pdev->name, dev);
                if (ret < 0) {
                        dev_err(&pdev->dev, "failed to request irq\n");
-                       return ret;
+                       goto err_assert_reset;
                }
        }
 
@@ -676,24 +685,27 @@ static int dw_i2s_probe(struct platform_device *pdev)
                ret = dw_configure_dai_by_dt(dev, dw_i2s_dai, res);
        }
        if (ret < 0)
-               return ret;
+               goto err_assert_reset;
 
        if (dev->capability & DW_I2S_MASTER) {
                if (pdata) {
                        dev->i2s_clk_cfg = pdata->i2s_clk_cfg;
                        if (!dev->i2s_clk_cfg) {
                                dev_err(&pdev->dev, "no clock configure method\n");
-                               return -ENODEV;
+                               ret = -ENODEV;
+                               goto err_assert_reset;
                        }
                }
                dev->clk = devm_clk_get(&pdev->dev, clk_id);
 
-               if (IS_ERR(dev->clk))
-                       return PTR_ERR(dev->clk);
+               if (IS_ERR(dev->clk)) {
+                       ret = PTR_ERR(dev->clk);
+                       goto err_assert_reset;
+               }
 
                ret = clk_prepare_enable(dev->clk);
                if (ret < 0)
-                       return ret;
+                       goto err_assert_reset;
        }
 
        dev_set_drvdata(&pdev->dev, dev);
@@ -727,6 +739,8 @@ static int dw_i2s_probe(struct platform_device *pdev)
 err_clk_disable:
        if (dev->capability & DW_I2S_MASTER)
                clk_disable_unprepare(dev->clk);
+err_assert_reset:
+       reset_control_assert(dev->reset);
        return ret;
 }
 
@@ -737,6 +751,7 @@ static void dw_i2s_remove(struct platform_device *pdev)
        if (dev->capability & DW_I2S_MASTER)
                clk_disable_unprepare(dev->clk);
 
+       reset_control_assert(dev->reset);
        pm_runtime_disable(&pdev->dev);
 }
 
index 1c361eb..d64bd4f 100644 (file)
@@ -89,6 +89,7 @@ union dw_i2s_snd_dma_data {
 struct dw_i2s_dev {
        void __iomem *i2s_base;
        struct clk *clk;
+       struct reset_control *reset;
        int active;
        unsigned int capability;
        unsigned int quirks;