From be0ba9e3e954931a223ad636050c47a1ded0bed3 Mon Sep 17 00:00:00 2001 From: Dara Ramesh Date: Wed, 24 Sep 2014 18:52:26 +0530 Subject: [PATCH] ASoC: tegra-alt: SLCG: Implement MBIST WAR for i2s I2S MBIST comes up in random state and therefore SLCG needs to be toggled OFF and ON before the I2S controller can be used normally. This patch implements WAR in response to SLCG notifier. - Set I2S controller in master mode. - toggled I2S SLCG OFF and ON. Bug 200035860 Change-Id: I17b727034a33adf12f64eed0673665f26f4267c0 Signed-off-by: Dara Ramesh Reviewed-on: http://git-master/r/538402 Reviewed-by: Sumit Bhattacharya Reviewed-by: Prashant Gaikwad Reviewed-by: Automatic_Commit_Validation_User --- sound/soc/tegra-alt/tegra210_i2s_alt.c | 36 ++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/sound/soc/tegra-alt/tegra210_i2s_alt.c b/sound/soc/tegra-alt/tegra210_i2s_alt.c index 6a8df5a7..1b883094 100644 --- a/sound/soc/tegra-alt/tegra210_i2s_alt.c +++ b/sound/soc/tegra-alt/tegra210_i2s_alt.c @@ -31,7 +31,9 @@ #include #include #include +#include #include +#include #include "tegra210_xbar_alt.h" #include "tegra210_i2s_alt.h" @@ -353,6 +355,35 @@ static int tegra210_i2s_codec_probe(struct snd_soc_codec *codec) return 0; } +static int _tegra210_i2s_slcg_notifier(struct notifier_block *nb, + unsigned long unused0, void *unused1) +{ + struct tegra210_i2s *i2s = container_of(nb, struct tegra210_i2s, + slgc_notifier); + unsigned int mask, val, i2s_ctrl; + + /* Save the I2S CTRL before implement MBIST WAR */ + regmap_read(i2s->regmap, TEGRA210_I2S_CTRL, &i2s_ctrl); + + mask = TEGRA210_I2S_CTRL_MASTER_EN_MASK; + val = TEGRA210_I2S_CTRL_MASTER_EN; + /* Set I2S controller in master mode */ + regmap_update_bits(i2s->regmap, TEGRA210_I2S_CTRL, mask, val); + /* Disable slcg, wait a while and re-enable it */ + regmap_write(i2s->regmap, TEGRA210_I2S_CG, 0); + regmap_read(i2s->regmap, TEGRA210_I2S_CG, &val); + + udelay(1); + + regmap_write(i2s->regmap, TEGRA210_I2S_CG, 1); + + /* Restore the I2S CTRL */ + regmap_write(i2s->regmap, TEGRA210_I2S_CTRL, i2s_ctrl); + + return NOTIFY_OK; +} + + static struct snd_soc_dai_ops tegra210_i2s_dai_ops = { .set_fmt = tegra210_i2s_set_fmt, .hw_params = tegra210_i2s_hw_params, @@ -641,6 +672,11 @@ static int tegra210_i2s_platform_probe(struct platform_device *pdev) ret = PTR_ERR(i2s->regmap); goto err_pll_a_out0_clk_put; } + + i2s->slgc_notifier.notifier_call = _tegra210_i2s_slcg_notifier; + slcg_register_notifier(TEGRA_POWERGATE_APE, + &i2s->slgc_notifier); + regcache_cache_only(i2s->regmap, true); if (of_property_read_u32(np, "nvidia,ahub-i2s-id",