summaryrefslogtreecommitdiff
path: root/drivers/remoteproc/mtk_scp_ipi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/remoteproc/mtk_scp_ipi.c')
-rw-r--r--drivers/remoteproc/mtk_scp_ipi.c52
1 files changed, 27 insertions, 25 deletions
diff --git a/drivers/remoteproc/mtk_scp_ipi.c b/drivers/remoteproc/mtk_scp_ipi.c
index 3d3d87210ef2..c068227e251e 100644
--- a/drivers/remoteproc/mtk_scp_ipi.c
+++ b/drivers/remoteproc/mtk_scp_ipi.c
@@ -6,13 +6,17 @@
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/io.h>
+#include <linux/iopoll.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
+#include <linux/time64.h>
#include <linux/remoteproc/mtk_scp.h>
#include "mtk_common.h"
+#define SCP_TIMEOUT_US (2000 * USEC_PER_MSEC)
+
/**
* scp_ipi_register() - register an ipi function
*
@@ -23,17 +27,15 @@
*
* Register an ipi function to receive ipi interrupt from SCP.
*
- * Returns 0 if ipi registers successfully, -error on error.
+ * Return: 0 if ipi registers successfully, -error on error.
*/
int scp_ipi_register(struct mtk_scp *scp,
u32 id,
scp_ipi_handler_t handler,
void *priv)
{
- if (!scp) {
- dev_err(scp->dev, "scp device is not ready\n");
+ if (!scp)
return -EPROBE_DEFER;
- }
if (WARN_ON(id >= SCP_IPI_MAX) || WARN_ON(handler == NULL))
return -EINVAL;
@@ -123,7 +125,7 @@ void scp_ipi_lock(struct mtk_scp *scp, u32 id)
EXPORT_SYMBOL_GPL(scp_ipi_lock);
/**
- * scp_ipi_lock() - Unlock after operations of an IPI ID
+ * scp_ipi_unlock() - Unlock after operations of an IPI ID
*
* @scp: mtk_scp structure
* @id: IPI ID
@@ -152,53 +154,54 @@ EXPORT_SYMBOL_GPL(scp_ipi_unlock);
* When the processing completes, IPI handler registered
* by scp_ipi_register will be called in interrupt context.
*
- * Returns 0 if sending data successfully, -error on error.
+ * Return: 0 if sending data successfully, -error on error.
**/
int scp_ipi_send(struct mtk_scp *scp, u32 id, void *buf, unsigned int len,
unsigned int wait)
{
struct mtk_share_obj __iomem *send_obj = scp->send_buf;
- unsigned long timeout;
+ u32 val;
int ret;
+ const struct mtk_scp_sizes_data *scp_sizes;
+
+ scp_sizes = scp->data->scp_sizes;
if (WARN_ON(id <= SCP_IPI_INIT) || WARN_ON(id >= SCP_IPI_MAX) ||
WARN_ON(id == SCP_IPI_NS_SERVICE) ||
- WARN_ON(len > sizeof(send_obj->share_buf)) || WARN_ON(!buf))
+ WARN_ON(len > scp_sizes->ipi_share_buffer_size) || WARN_ON(!buf))
return -EINVAL;
- mutex_lock(&scp->send_lock);
-
ret = clk_prepare_enable(scp->clk);
if (ret) {
dev_err(scp->dev, "failed to enable clock\n");
- goto unlock_mutex;
+ return ret;
}
+ mutex_lock(&scp->send_lock);
+
/* Wait until SCP receives the last command */
- timeout = jiffies + msecs_to_jiffies(2000);
- do {
- if (time_after(jiffies, timeout)) {
- dev_err(scp->dev, "%s: IPI timeout!\n", __func__);
- ret = -ETIMEDOUT;
- goto clock_disable;
- }
- } while (readl(scp->reg_base + MT8183_HOST_TO_SCP));
+ ret = readl_poll_timeout_atomic(scp->cluster->reg_base + scp->data->host_to_scp_reg,
+ val, !val, 0, SCP_TIMEOUT_US);
+ if (ret) {
+ dev_err(scp->dev, "%s: IPI timeout!\n", __func__);
+ goto unlock_mutex;
+ }
- scp_memcpy_aligned(send_obj->share_buf, buf, len);
+ scp_memcpy_aligned(&send_obj->share_buf, buf, len);
writel(len, &send_obj->len);
writel(id, &send_obj->id);
scp->ipi_id_ack[id] = false;
/* send the command to SCP */
- writel(MT8183_HOST_IPC_INT_BIT, scp->reg_base + MT8183_HOST_TO_SCP);
+ writel(scp->data->host_to_scp_int_bit,
+ scp->cluster->reg_base + scp->data->host_to_scp_reg);
if (wait) {
/* wait for SCP's ACK */
- timeout = msecs_to_jiffies(wait);
ret = wait_event_timeout(scp->ack_wq,
scp->ipi_id_ack[id],
- timeout);
+ msecs_to_jiffies(wait));
scp->ipi_id_ack[id] = false;
if (WARN(!ret, "scp ipi %d ack time out !", id))
ret = -EIO;
@@ -206,10 +209,9 @@ int scp_ipi_send(struct mtk_scp *scp, u32 id, void *buf, unsigned int len,
ret = 0;
}
-clock_disable:
- clk_disable_unprepare(scp->clk);
unlock_mutex:
mutex_unlock(&scp->send_lock);
+ clk_disable_unprepare(scp->clk);
return ret;
}