Add bus protection for reset controller. Signed-off-by: Trevor Wu <trevor.wu@xxxxxxxxxxxx> --- sound/soc/mediatek/mt8188/mt8188-afe-pcm.c | 76 ++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/sound/soc/mediatek/mt8188/mt8188-afe-pcm.c b/sound/soc/mediatek/mt8188/mt8188-afe-pcm.c index fecc891f892d..c3fd32764da0 100644 --- a/sound/soc/mediatek/mt8188/mt8188-afe-pcm.c +++ b/sound/soc/mediatek/mt8188/mt8188-afe-pcm.c @@ -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) -- 2.18.0