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; }