From ea4ace171f43f4c2a69f6c1de1e9e00a08411f98 Mon Sep 17 00:00:00 2001 From: Meng Wang Date: Tue, 25 Jun 2019 17:28:59 +0800 Subject: [PATCH] soc: lpi: force lpi runtime suspend during adsp ssr During adsp SSR, lpi runtime suspend is not called and hw vote clks are not reset. Force LPI runtime suspend during adsp SSR to avoid kernel panic. Change-Id: I153c5826a282d7beb175a41a55e2d6bf5907eb62 Signed-off-by: Meng Wang --- soc/pinctrl-lpi.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/soc/pinctrl-lpi.c b/soc/pinctrl-lpi.c index ff9e9406c4..c4e9985588 100644 --- a/soc/pinctrl-lpi.c +++ b/soc/pinctrl-lpi.c @@ -111,6 +111,7 @@ struct lpi_gpio_state { struct clk *lpass_core_hw_vote; struct mutex slew_access_lock; bool core_hw_vote_status; + struct mutex core_hw_vote_lock; }; static const char *const lpi_gpio_groups[] = { @@ -134,6 +135,8 @@ static const char *const lpi_gpio_functions[] = { [LPI_GPIO_FUNC_INDEX_FUNC5] = LPI_GPIO_FUNC_FUNC5, }; +int lpi_pinctrl_runtime_suspend(struct device *dev); + static int lpi_gpio_read(struct lpi_gpio_pad *pad, unsigned int addr) { int ret; @@ -464,7 +467,11 @@ static struct notifier_block service_nb = { static void lpi_pinctrl_ssr_disable(struct device *dev, void *data) { + struct lpi_gpio_state *state = dev_get_drvdata(dev); + lpi_dev_up = false; + if (state->core_hw_vote_status) + lpi_pinctrl_runtime_suspend(dev); } static const struct snd_event_ops lpi_pinctrl_ssr_ops = { @@ -664,6 +671,7 @@ static int lpi_pinctrl_probe(struct platform_device *pdev) state->chip.can_sleep = false; mutex_init(&state->slew_access_lock); + mutex_init(&state->core_hw_vote_lock); state->ctrl = devm_pinctrl_register(dev, pctrldesc, state); if (IS_ERR(state->ctrl)) @@ -724,6 +732,7 @@ err_snd_evt: err_range: gpiochip_remove(&state->chip); err_chip: + mutex_destroy(&state->core_hw_vote_lock); mutex_destroy(&state->slew_access_lock); err_io: return ret; @@ -739,6 +748,7 @@ static int lpi_pinctrl_remove(struct platform_device *pdev) snd_event_client_deregister(&pdev->dev); audio_notifier_deregister("lpi_tlmm"); gpiochip_remove(&state->chip); + mutex_destroy(&state->core_hw_vote_lock); mutex_destroy(&state->slew_access_lock); return 0; @@ -761,6 +771,7 @@ int lpi_pinctrl_runtime_resume(struct device *dev) return 0; } + mutex_lock(&state->core_hw_vote_lock); ret = clk_prepare_enable(state->lpass_core_hw_vote); if (ret < 0) dev_err(dev, "%s:lpass core hw island enable failed\n", @@ -769,6 +780,7 @@ int lpi_pinctrl_runtime_resume(struct device *dev) state->core_hw_vote_status = true; pm_runtime_set_autosuspend_delay(dev, LPI_AUTO_SUSPEND_DELAY); + mutex_unlock(&state->core_hw_vote_lock); return 0; } @@ -781,10 +793,12 @@ int lpi_pinctrl_runtime_suspend(struct device *dev) return 0; } + mutex_lock(&state->core_hw_vote_lock); if (state->core_hw_vote_status) { clk_disable_unprepare(state->lpass_core_hw_vote); state->core_hw_vote_status = false; } + mutex_unlock(&state->core_hw_vote_lock); return 0; }