Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0960969b authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "soc: pinctrl-lpi: Fix core hw vote issue in LPI GPIO access"

parents 8fea9401 9513df13
Loading
Loading
Loading
Loading
+18 −2
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@
#include <linux/platform_device.h>
#include <dt-bindings/clock/qcom,audio-ext-clk.h>
#include <dsp/q6afe-v2.h>
#include <dsp/q6core.h>
#include "audio-ext-clk-up.h"

enum {
@@ -147,14 +148,29 @@ static int lpass_hw_vote_prepare(struct clk_hw *hw)
{
	struct audio_ext_clk_priv *clk_priv = to_audio_clk(hw);
	int ret = 0;
	int32_t avs_state = 0;
	uint32_t *client_handle = &clk_priv->lpass_core_hwvote_client_handle;

	if (clk_priv->clk_src == AUDIO_EXT_CLK_LPASS_CORE_HW_VOTE)  {
		ret = afe_vote_lpass_core_hw(AFE_LPASS_CORE_HW_MACRO_BLOCK,
					     "LPASS_HW_MACRO",
			&clk_priv->lpass_core_hwvote_client_handle);
					     client_handle);
		if (ret < 0) {
			pr_err("%s lpass core hw vote failed %d\n",
				__func__, ret);
			/*
			 * DSP returns -EBUSY when AVS services are not up
			 * Check for AVS state and then retry voting
			 * for core hw clock.
			 */
			if (ret == -EBUSY) {
				q6core_is_avs_up(&avs_state);
				if (avs_state)
					ret = afe_vote_lpass_core_hw(
						AFE_LPASS_CORE_HW_MACRO_BLOCK,
						"LPASS_HW_MACRO",
						client_handle);
			}
			return ret;
		}
	}
+13 −1
Original line number Diff line number Diff line
@@ -8690,6 +8690,12 @@ int afe_vote_lpass_core_hw(uint32_t hw_block_id, char *client_name,
		return -EINVAL;
	}

	ret = afe_q6_interface_prepare();
	if (ret != 0) {
		pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
		return ret;
	}

	mutex_lock(&this_afe.afe_cmd_lock);

	memset(cmd_ptr, 0, sizeof(hw_vote_cfg));
@@ -8752,7 +8758,7 @@ EXPORT_SYMBOL(afe_vote_lpass_core_hw);

/*
 * afe_unvote_lpass_core_hw -
 *        Voting for lpass core hardware
 *        unvoting for lpass core hardware
 *
 * @hw_block_id: ID of hw block to vote for
 * @client_handle: Handle for the client
@@ -8765,6 +8771,12 @@ int afe_unvote_lpass_core_hw(uint32_t hw_block_id, uint32_t client_handle)
						&hw_vote_cfg;
	int ret = 0;

	ret = afe_q6_interface_prepare();
	if (ret != 0) {
		pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
		return ret;
	}

	mutex_lock(&this_afe.afe_cmd_lock);

	memset(cmd_ptr, 0, sizeof(hw_vote_cfg));
+3 −2
Original line number Diff line number Diff line
/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -1433,7 +1433,7 @@ static int q6core_init_cal_data(void)
	return ret;
}

static int q6core_is_avs_up(int32_t *avs_state)
int q6core_is_avs_up(int32_t *avs_state)
{
	unsigned long timeout;
	int32_t adsp_ready = 0;
@@ -1471,6 +1471,7 @@ static int q6core_is_avs_up(int32_t *avs_state)

	return ret;
}
EXPORT_SYMBOL(q6core_is_avs_up);

static int q6core_ssr_enable(struct device *dev, void *data)
{
+2 −1
Original line number Diff line number Diff line
/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -207,6 +207,7 @@ int32_t core_get_license_status(uint32_t module_id);

int32_t q6core_load_unload_topo_modules(uint32_t topology_id,
			bool preload_type);
int q6core_is_avs_up(int32_t *avs_state);

#if IS_ENABLED(CONFIG_USE_Q6_32CH_SUPPORT)
static inline bool q6core_use_Q6_32ch_support(void)
+34 −15
Original line number Diff line number Diff line
@@ -501,6 +501,25 @@ static const struct gpio_chip lpi_gpio_template = {
	.dbg_show		= lpi_gpio_dbg_show,
};

static int lpi_get_lpass_core_hw_clk(struct device *dev,
				     struct lpi_gpio_state *state)
{
	struct clk *lpass_core_hw_vote = NULL;
	int ret = 0;

	if (state->lpass_core_hw_vote == NULL) {
		lpass_core_hw_vote = devm_clk_get(dev, "lpass_core_hw_vote");
		if (IS_ERR(lpass_core_hw_vote) || lpass_core_hw_vote == NULL) {
			ret = PTR_ERR(lpass_core_hw_vote);
			dev_dbg(dev, "%s: clk get %s failed %d\n",
				__func__, "lpass_core_hw_vote", ret);
			return ret;
		}
		state->lpass_core_hw_vote = lpass_core_hw_vote;
	}
	return 0;
}

static int lpi_pinctrl_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
@@ -511,7 +530,6 @@ static int lpi_pinctrl_probe(struct platform_device *pdev)
	int ret, npins, i;
	char __iomem *lpi_base;
	u32 reg;
	struct clk *lpass_core_hw_vote = NULL;

	ret = of_property_read_u32(dev->of_node, "reg", &reg);
	if (ret < 0) {
@@ -622,15 +640,10 @@ static int lpi_pinctrl_probe(struct platform_device *pdev)
	}

	/* Register LPASS core hw vote */
	lpass_core_hw_vote = devm_clk_get(&pdev->dev, "lpass_core_hw_vote");
	if (IS_ERR(lpass_core_hw_vote)) {
		ret = PTR_ERR(lpass_core_hw_vote);
		dev_dbg(&pdev->dev, "%s: clk get %s failed %d\n",
			__func__, "lpass_core_hw_vote", ret);
		lpass_core_hw_vote = NULL;
		ret = 0;
	}
	state->lpass_core_hw_vote = lpass_core_hw_vote;
	ret = lpi_get_lpass_core_hw_clk(dev, state);
	if (ret)
		dev_dbg(dev, "%s: unable to get core clk handle %d\n",
			__func__, ret);

	pm_runtime_set_autosuspend_delay(&pdev->dev, LPI_AUTO_SUSPEND_DELAY);
	pm_runtime_use_autosuspend(&pdev->dev);
@@ -671,14 +684,16 @@ static int lpi_pinctrl_runtime_resume(struct device *dev)
	struct lpi_gpio_state *state = dev_get_drvdata(dev);
	int ret = 0;

	if (state->lpass_core_hw_vote == NULL) {
		dev_dbg(dev, "%s: Invalid core hw node\n", __func__);
	ret = lpi_get_lpass_core_hw_clk(dev, state);
	if (ret) {
		dev_err(dev, "%s: unable to get core clk handle %d\n",
			__func__, ret);
		return 0;
	}

	ret = clk_prepare_enable(state->lpass_core_hw_vote);
	if (ret < 0)
		dev_dbg(dev, "%s:lpass core hw enable failed\n",
		dev_err(dev, "%s: lpass core hw enable failed\n",
			__func__);

	pm_runtime_set_autosuspend_delay(dev, LPI_AUTO_SUSPEND_DELAY);
@@ -688,11 +703,15 @@ static int lpi_pinctrl_runtime_resume(struct device *dev)
static int lpi_pinctrl_runtime_suspend(struct device *dev)
{
	struct lpi_gpio_state *state = dev_get_drvdata(dev);
	int ret = 0;

	if (state->lpass_core_hw_vote == NULL) {
		dev_dbg(dev, "%s: Invalid lpass core hw node\n", __func__);
	ret = lpi_get_lpass_core_hw_clk(dev, state);
	if (ret) {
		dev_err(dev, "%s: unable to get core clk handle %d\n",
			__func__, ret);
		return 0;
	}

	clk_disable_unprepare(state->lpass_core_hw_vote);
	return 0;
}