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

Commit 40bc50d7 authored by Ramprasad Katkam's avatar Ramprasad Katkam
Browse files

mfd: wcd9xxx-core: Synchronize codec down and reset calls from slimbus.



Sometimes after receiving the codec down callback from slimbus, the
context is back-scheduled and before it is complete, codec reset
callback is called and completed.The codec down context is complete
after this. This change of sequence causes codec reset pin to be
low after SSR. Ensure the sequence of codec down and codec reset
callbacks by waiting for codec down to complete in reset and using common
mutex for synchronization.

Change-Id: I2b9e119ce93a17017076738ab96d1fe4a1557982
Signed-off-by: default avatarRamprasad Katkam <katkam@codeaurora.org>
parent 4d9a308b
Loading
Loading
Loading
Loading
+33 −16
Original line number Diff line number Diff line
@@ -228,7 +228,7 @@ static int wcd9xxx_slim_read_device(struct wcd9xxx *wcd9xxx, unsigned short reg,

	if (!wcd9xxx->dev_up) {
		dev_dbg_ratelimited(
			wcd9xxx->dev, "%s: No read allowed. dev_up = %d\n",
			wcd9xxx->dev, "%s: No read allowed. dev_up = %lu\n",
			__func__, wcd9xxx->dev_up);
		return 0;
	}
@@ -268,7 +268,7 @@ static int wcd9xxx_slim_write_device(struct wcd9xxx *wcd9xxx,

	if (!wcd9xxx->dev_up) {
		dev_dbg_ratelimited(
			wcd9xxx->dev, "%s: No write allowed. dev_up = %d\n",
			wcd9xxx->dev, "%s: No write allowed. dev_up = %lu\n",
			__func__, wcd9xxx->dev_up);
		return 0;
	}
@@ -345,7 +345,7 @@ int wcd9xxx_slim_write_repeat(struct wcd9xxx *wcd9xxx, unsigned short reg,

	if (!wcd9xxx->dev_up) {
		dev_dbg_ratelimited(
			wcd9xxx->dev, "%s: No write allowed. dev_up = %d\n",
			wcd9xxx->dev, "%s: No write allowed. dev_up = %lu\n",
			__func__, wcd9xxx->dev_up);
		ret = 0;
		goto done;
@@ -426,7 +426,7 @@ int wcd9xxx_slim_bulk_write(struct wcd9xxx *wcd9xxx,

	if (!wcd9xxx->dev_up) {
		dev_dbg_ratelimited(
			wcd9xxx->dev, "%s: No write allowed. dev_up = %d\n",
			wcd9xxx->dev, "%s: No write allowed. dev_up = %lu\n",
			__func__, wcd9xxx->dev_up);
		return 0;
	}
@@ -1479,12 +1479,27 @@ static int wcd9xxx_slim_device_reset(struct slim_device *sldev)
		return -EINVAL;
	}

	dev_info(wcd9xxx->dev, "%s: device reset, dev_up = %d\n",
	/*
	 * Wait for 500 ms for device down to complete. Observed delay
	 *  of ~200ms for device down to complete after being called,
	 * due to context switch issue.
	 */
	ret = wait_on_bit_timeout(&wcd9xxx->dev_up, 0,
				  TASK_INTERRUPTIBLE,
				  msecs_to_jiffies(500));
	if (ret)
		pr_err("%s: slim device down not complete in 500 msec\n",
				__func__);

	mutex_lock(&wcd9xxx->reset_lock);

	dev_info(wcd9xxx->dev, "%s: device reset, dev_up = %lu\n",
			__func__, wcd9xxx->dev_up);
	if (wcd9xxx->dev_up)
	if (wcd9xxx->dev_up) {
		mutex_unlock(&wcd9xxx->reset_lock);
		return 0;
	}

	mutex_lock(&wcd9xxx->reset_lock);
	ret = wcd9xxx_reset(wcd9xxx->dev);
	if (ret)
		dev_err(wcd9xxx->dev, "%s: Resetting Codec failed\n", __func__);
@@ -1502,7 +1517,7 @@ static int wcd9xxx_slim_device_up(struct slim_device *sldev)
		pr_err("%s: wcd9xxx is NULL\n", __func__);
		return -EINVAL;
	}
	dev_info(wcd9xxx->dev, "%s: slim device up, dev_up = %d\n",
	dev_info(wcd9xxx->dev, "%s: slim device up, dev_up = %lu\n",
			__func__, wcd9xxx->dev_up);
	if (wcd9xxx->dev_up)
		return 0;
@@ -1525,18 +1540,20 @@ static int wcd9xxx_slim_device_down(struct slim_device *sldev)
		return -EINVAL;
	}

	dev_info(wcd9xxx->dev, "%s: device down, dev_up = %d\n",
	mutex_lock(&wcd9xxx->reset_lock);

	dev_info(wcd9xxx->dev, "%s: device down, dev_up = %lu\n",
			__func__, wcd9xxx->dev_up);
	if (!wcd9xxx->dev_up)
	if (!wcd9xxx->dev_up) {
		mutex_unlock(&wcd9xxx->reset_lock);
		return 0;
	}

	wcd9xxx->dev_up = false;

	mutex_lock(&wcd9xxx->reset_lock);
	if (wcd9xxx->dev_down)
		wcd9xxx->dev_down(wcd9xxx);
	wcd9xxx_irq_exit(&wcd9xxx->core_res);
	wcd9xxx_reset_low(wcd9xxx->dev);
	wcd9xxx->dev_up = false;
	mutex_unlock(&wcd9xxx->reset_lock);

	return 0;
+1 −1
Original line number Diff line number Diff line
@@ -350,7 +350,7 @@ struct wcd9xxx {
	int (*post_reset)(struct wcd9xxx *wcd9xxx);

	void *ssr_priv;
	bool dev_up;
	unsigned long dev_up;

	u32 num_of_supplies;
	struct regulator_bulk_data *supplies;