ASoC: mediatek: mt8188: add bus protection
authorTrevor Wu <trevor.wu@mediatek.com>
Wed, 10 May 2023 03:55:23 +0000 (11:55 +0800)
committerMark Brown <broonie@kernel.org>
Mon, 15 May 2023 11:05:10 +0000 (20:05 +0900)
Add bus protection for reset controller.

Signed-off-by: Trevor Wu <trevor.wu@mediatek.com
Link: https://lore.kernel.org/r/20230510035526.18137-7-trevor.wu@mediatek.com
Signed-off-by: Mark Brown <broonie@kernel.org
sound/soc/mediatek/mt8188/mt8188-afe-pcm.c

index fecc891..c3fd327 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/of_address.h>
 #include <linux/of_platform.h>
 #include <linux/pm_runtime.h>
+#include <linux/soc/mediatek/infracfg.h>
 #include <linux/reset.h>
 #include <sound/pcm_params.h>
 #include "mt8188-afe-common.h"
@@ -3133,12 +3134,68 @@ static int mt8188_afe_parse_of(struct mtk_base_afe *afe,
        return 0;
 }
 
+#define MT8188_DELAY_US 10
+#define MT8188_TIMEOUT_US USEC_PER_SEC
+
+static int bus_protect_enable(struct regmap *regmap)
+{
+       int ret;
+       u32 val;
+       u32 mask;
+
+       val = 0;
+       mask = MT8188_TOP_AXI_PROT_EN_2_AUDIO_STEP1;
+       regmap_write(regmap, MT8188_TOP_AXI_PROT_EN_2_SET, mask);
+
+       ret = regmap_read_poll_timeout(regmap, MT8188_TOP_AXI_PROT_EN_2_STA,
+                                      val, (val & mask) == mask,
+                                      MT8188_DELAY_US, MT8188_TIMEOUT_US);
+       if (ret)
+               return ret;
+
+       val = 0;
+       mask = MT8188_TOP_AXI_PROT_EN_2_AUDIO_STEP2;
+       regmap_write(regmap, MT8188_TOP_AXI_PROT_EN_2_SET, mask);
+
+       ret = regmap_read_poll_timeout(regmap, MT8188_TOP_AXI_PROT_EN_2_STA,
+                                      val, (val & mask) == mask,
+                                      MT8188_DELAY_US, MT8188_TIMEOUT_US);
+       return ret;
+}
+
+static int bus_protect_disable(struct regmap *regmap)
+{
+       int ret;
+       u32 val;
+       u32 mask;
+
+       val = 0;
+       mask = MT8188_TOP_AXI_PROT_EN_2_AUDIO_STEP2;
+       regmap_write(regmap, MT8188_TOP_AXI_PROT_EN_2_CLR, mask);
+
+       ret = regmap_read_poll_timeout(regmap, MT8188_TOP_AXI_PROT_EN_2_STA,
+                                      val, !(val & mask),
+                                      MT8188_DELAY_US, MT8188_TIMEOUT_US);
+       if (ret)
+               return ret;
+
+       val = 0;
+       mask = MT8188_TOP_AXI_PROT_EN_2_AUDIO_STEP1;
+       regmap_write(regmap, MT8188_TOP_AXI_PROT_EN_2_CLR, mask);
+
+       ret = regmap_read_poll_timeout(regmap, MT8188_TOP_AXI_PROT_EN_2_STA,
+                                      val, !(val & mask),
+                                      MT8188_DELAY_US, MT8188_TIMEOUT_US);
+       return ret;
+}
+
 static int mt8188_afe_pcm_dev_probe(struct platform_device *pdev)
 {
        struct mtk_base_afe *afe;
        struct mt8188_afe_private *afe_priv;
        struct device *dev;
        struct reset_control *rstc;
+       struct regmap *infra_ao;
        int i, irq_id, ret;
 
        ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(33));
@@ -3163,18 +3220,37 @@ static int mt8188_afe_pcm_dev_probe(struct platform_device *pdev)
                return dev_err_probe(dev, PTR_ERR(afe->base_addr),
                                     "AFE base_addr not found\n");
 
+       infra_ao = syscon_regmap_lookup_by_phandle(dev->of_node,
+                                                  "mediatek,infracfg");
+       if (IS_ERR(infra_ao))
+               return dev_err_probe(dev, PTR_ERR(infra_ao),
+                                    "%s() Cannot find infra_ao controller\n",
+                                    __func__);
+
        /* reset controller to reset audio regs before regmap cache */
        rstc = devm_reset_control_get_exclusive(dev, "audiosys");
        if (IS_ERR(rstc))
                return dev_err_probe(dev, PTR_ERR(rstc),
                                     "could not get audiosys reset\n");
 
+       ret = bus_protect_enable(infra_ao);
+       if (ret) {
+               dev_err(dev, "bus_protect_enable failed\n");
+               return ret;
+       }
+
        ret = reset_control_reset(rstc);
        if (ret) {
                dev_err(dev, "failed to trigger audio reset:%d\n", ret);
                return ret;
        }
 
+       ret = bus_protect_disable(infra_ao);
+       if (ret) {
+               dev_err(dev, "bus_protect_disable failed\n");
+               return ret;
+       }
+
        /* initial audio related clock */
        ret = mt8188_afe_init_clock(afe);
        if (ret)