From: Dmitry Osipenko Date: Wed, 20 Jan 2021 00:31:54 +0000 (+0300) Subject: ASoC: tegra: ahub: Reset hardware properly X-Git-Tag: accepted/tizen/unified/20230118.172025~7091^2~1^2~197^2~70 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=ed9ce1ed2239909c23d48c723c6549417c476246;p=platform%2Fkernel%2Flinux-rpi.git ASoC: tegra: ahub: Reset hardware properly Assert hardware resets before clocks are enabled and then de-assert them after clocks are enabled. This brings hardware into a predictable state. Tested-by: Peter Geis # Ouya T30 audio works Tested-by: Matt Merhar # Ouya T30 boot-tested Tested-by: Dmitry Osipenko # Nexus7 T30 audio works Tested-by: Nicolas Chauvet # TK1 boot-tested Signed-off-by: Dmitry Osipenko Link: https://lore.kernel.org/r/20210120003154.26749-7-digetx@gmail.com Signed-off-by: Mark Brown --- diff --git a/sound/soc/tegra/tegra30_ahub.c b/sound/soc/tegra/tegra30_ahub.c index 12ca8e3..9ef05ca 100644 --- a/sound/soc/tegra/tegra30_ahub.c +++ b/sound/soc/tegra/tegra30_ahub.c @@ -65,14 +65,39 @@ static int tegra30_ahub_runtime_resume(struct device *dev) { int ret; + ret = reset_control_assert(ahub->reset); + if (ret) + return ret; + ret = clk_bulk_prepare_enable(ahub->nclocks, ahub->clocks); if (ret) return ret; + usleep_range(10, 100); + + ret = reset_control_deassert(ahub->reset); + if (ret) + goto disable_clocks; + regcache_cache_only(ahub->regmap_apbif, false); regcache_cache_only(ahub->regmap_ahub, false); + regcache_mark_dirty(ahub->regmap_apbif); + regcache_mark_dirty(ahub->regmap_ahub); + + ret = regcache_sync(ahub->regmap_apbif); + if (ret) + goto disable_clocks; + + ret = regcache_sync(ahub->regmap_ahub); + if (ret) + goto disable_clocks; return 0; + +disable_clocks: + clk_bulk_disable_unprepare(ahub->nclocks, ahub->clocks); + + return ret; } int tegra30_ahub_allocate_rx_fifo(enum tegra30_ahub_rxcif *rxcif, @@ -519,7 +544,6 @@ static int tegra30_ahub_probe(struct platform_device *pdev) /* * The AHUB hosts a register bus: the "configlink". For this to * operate correctly, all devices on this bus must be out of reset. - * Ensure that here. */ for (i = 0; i < ARRAY_SIZE(configlink_mods); i++) { if (!(configlink_mods[i].mod_list_mask & @@ -535,10 +559,8 @@ static int tegra30_ahub_probe(struct platform_device *pdev) return ret; } - ret = reset_control_deassert(rst); + /* just check presence of the reset control in DT */ reset_control_put(rst); - if (ret) - return ret; } ahub = devm_kzalloc(&pdev->dev, sizeof(struct tegra30_ahub), @@ -557,6 +579,12 @@ static int tegra30_ahub_probe(struct platform_device *pdev) if (ret) return ret; + ahub->reset = devm_reset_control_array_get_exclusive(&pdev->dev); + if (IS_ERR(ahub->reset)) { + dev_err(&pdev->dev, "Can't get resets: %pe\n", ahub->reset); + return PTR_ERR(ahub->reset); + } + res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0); regs_apbif = devm_ioremap_resource(&pdev->dev, res0); if (IS_ERR(regs_apbif)) diff --git a/sound/soc/tegra/tegra30_ahub.h b/sound/soc/tegra/tegra30_ahub.h index 01480d7..3b85244 100644 --- a/sound/soc/tegra/tegra30_ahub.h +++ b/sound/soc/tegra/tegra30_ahub.h @@ -511,6 +511,7 @@ struct tegra30_ahub_soc_data { struct tegra30_ahub { const struct tegra30_ahub_soc_data *soc_data; struct device *dev; + struct reset_control *reset; struct clk_bulk_data clocks[2]; unsigned int nclocks; resource_size_t apbif_addr;