diff --git a/drivers/platform/msm/avtimer.c b/drivers/platform/msm/avtimer.c index 74c81f7c6a7..bb9b2bfc75b 100644 --- a/drivers/platform/msm/avtimer.c +++ b/drivers/platform/msm/avtimer.c @@ -31,6 +31,9 @@ #define TIMEOUT_MS 1000 #define CORE_CLIENT 1 #define TEMP_PORT ((CORE_CLIENT << 8) | 0x0001) +#define SSR_WAKETIME 1000 +#define Q6_READY_RETRY 250 +#define Q6_READY_MAX_RETRIES 40 #define AVCS_CMD_REMOTE_AVTIMER_VOTE_REQUEST 0x00012914 #define AVCS_CMD_RSP_REMOTE_AVTIMER_VOTE_REQUEST 0x00012915 @@ -54,6 +57,7 @@ struct avtimer_t { struct mutex avtimer_lock; int avtimer_open_cnt; struct dev_avtimer_data avtimer_pdata; + struct delayed_work ssr_dwork; wait_queue_head_t adsp_resp_wait; int enable_timer_resp_recieved; int timer_handle; @@ -61,6 +65,7 @@ struct avtimer_t { void __iomem *p_avtimer_lsw; uint32_t clk_div; atomic_t adsp_ready; + int num_retries; }; static struct avtimer_t avtimer; @@ -105,7 +110,10 @@ static int32_t aprv2_core_fn_q(struct apr_client_data *data, void *priv) pr_debug("%s: Reset event received in AV timer\n", __func__); apr_reset(avtimer.core_handle_q); avtimer.core_handle_q = NULL; + avtimer.avtimer_open_cnt = 0; atomic_set(&avtimer.adsp_ready, 0); + schedule_delayed_work(&avtimer.ssr_dwork, + msecs_to_jiffies(SSR_WAKETIME)); break; } @@ -263,21 +271,33 @@ done: } EXPORT_SYMBOL(avcs_core_disable_power_collapse); +static void reset_work(struct work_struct *work) +{ + if (q6core_is_adsp_ready()) { + avcs_core_disable_power_collapse(1); + avtimer.num_retries = Q6_READY_MAX_RETRIES; + return; + } + pr_debug("%s:Q6 not ready-retry after sometime\n", __func__); + if (--avtimer.num_retries > 0) { + schedule_delayed_work(&avtimer.ssr_dwork, + msecs_to_jiffies(Q6_READY_RETRY)); + } else { + pr_err("%s: Q6 failed responding after multiple retries\n", + __func__); + avtimer.num_retries = Q6_READY_MAX_RETRIES; + } +} + int avcs_core_query_timer(uint64_t *avtimer_tick) { - int ret = 0; uint32_t avtimer_msw = 0, avtimer_lsw = 0; uint32_t res = 0; uint64_t avtimer_tick_temp; if (!atomic_read(&avtimer.adsp_ready)) { - if (q6core_is_adsp_ready()) { - ret = avcs_core_disable_power_collapse(1); - if (ret) - return ret; - } else { - return -ENETRESET; - } + pr_debug("%s:In SSR, return\n", __func__); + return -ENETRESET; } avtimer_lsw = ioread32(avtimer.p_avtimer_lsw); avtimer_msw = ioread32(avtimer.p_avtimer_msw); @@ -374,6 +394,8 @@ static int dev_avtimer_probe(struct platform_device *pdev) "avtimer_msb_addr", __func__); return -EINVAL; } + INIT_DELAYED_WORK(&avtimer.ssr_dwork, reset_work); + avtimer.p_avtimer_lsw = devm_ioremap_nocache(&pdev->dev, reg_lsb->start, resource_size(reg_lsb)); if (!avtimer.p_avtimer_lsw) { @@ -389,6 +411,7 @@ static int dev_avtimer_probe(struct platform_device *pdev) __func__); goto unmap; } + avtimer.num_retries = Q6_READY_MAX_RETRIES; /* get the device number */ if (major) result = register_chrdev_region(dev, 1, DEVICE_NAME);