Merge "soc: swr-mstr: synchronize swr clock requests"
diff --git a/soc/swr-mstr-ctrl.c b/soc/swr-mstr-ctrl.c
index c7fe7d2..d727b46 100644
--- a/soc/swr-mstr-ctrl.c
+++ b/soc/swr-mstr-ctrl.c
@@ -231,21 +231,37 @@
static int swrm_clk_request(struct swr_mstr_ctrl *swrm, bool enable)
{
+ int ret = 0;
+
if (!swrm->clk || !swrm->handle)
return -EINVAL;
+ mutex_lock(&swrm->clklock);
if (enable) {
+ if (!swrm->dev_up)
+ goto exit;
swrm->clk_ref_count++;
if (swrm->clk_ref_count == 1) {
- swrm->clk(swrm->handle, true);
+ ret = swrm->clk(swrm->handle, true);
+ if (ret) {
+ dev_err(swrm->dev,
+ "%s: clock enable req failed",
+ __func__);
+ --swrm->clk_ref_count;
+ }
}
} else if (--swrm->clk_ref_count == 0) {
swrm->clk(swrm->handle, false);
- } else if (swrm->clk_ref_count < 0) {
+ complete(&swrm->clk_off_complete);
+ }
+ if (swrm->clk_ref_count < 0) {
pr_err("%s: swrm clk count mismatch\n", __func__);
swrm->clk_ref_count = 0;
}
- return 0;
+
+exit:
+ mutex_unlock(&swrm->clklock);
+ return ret;
}
static int swrm_ahb_write(struct swr_mstr_ctrl *swrm,
@@ -1723,10 +1739,12 @@
swrm->state = SWR_MSTR_UP;
init_completion(&swrm->reset);
init_completion(&swrm->broadcast);
+ init_completion(&swrm->clk_off_complete);
mutex_init(&swrm->mlock);
mutex_init(&swrm->reslock);
mutex_init(&swrm->force_down_lock);
mutex_init(&swrm->iolock);
+ mutex_init(&swrm->clklock);
mutex_init(&swrm->devlock);
for (i = 0 ; i < SWR_MSTR_PORT_LEN; i++)
@@ -1845,6 +1863,7 @@
mutex_destroy(&swrm->reslock);
mutex_destroy(&swrm->force_down_lock);
mutex_destroy(&swrm->iolock);
+ mutex_destroy(&swrm->clklock);
err_pdata_fail:
err_memory_fail:
return ret;
@@ -1865,6 +1884,8 @@
msm_aud_evt_unregister_client(&swrm->event_notifier);
mutex_destroy(&swrm->mlock);
mutex_destroy(&swrm->reslock);
+ mutex_destroy(&swrm->iolock);
+ mutex_destroy(&swrm->clklock);
mutex_destroy(&swrm->force_down_lock);
devm_kfree(&pdev->dev, swrm);
return 0;
@@ -2063,6 +2084,13 @@
mutex_unlock(&swrm->reslock);
break;
case SWR_DEVICE_SSR_UP:
+ /* wait for clk voting to be zero */
+ if (swrm->clk_ref_count &&
+ !wait_for_completion_timeout(&swrm->clk_off_complete,
+ (1 * HZ/100)))
+ dev_err(swrm->dev, "%s: clock voting not zero\n",
+ __func__);
+
mutex_lock(&swrm->devlock);
swrm->dev_up = true;
mutex_unlock(&swrm->devlock);
diff --git a/soc/swr-mstr-ctrl.h b/soc/swr-mstr-ctrl.h
index f9faed5..4a40fa3 100644
--- a/soc/swr-mstr-ctrl.h
+++ b/soc/swr-mstr-ctrl.h
@@ -110,8 +110,10 @@
struct resource *supplies;
struct clk *mclk;
int clk_ref_count;
+ struct completion clk_off_complete;
struct completion reset;
struct completion broadcast;
+ struct mutex clklock;
struct mutex iolock;
struct mutex devlock;
struct mutex mlock;