Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 //
0003 // Copyright (c) 2019 MediaTek Inc.
0004 
0005 #include <asm/barrier.h>
0006 #include <linux/clk.h>
0007 #include <linux/err.h>
0008 #include <linux/io.h>
0009 #include <linux/kernel.h>
0010 #include <linux/module.h>
0011 #include <linux/platform_device.h>
0012 #include <linux/remoteproc/mtk_scp.h>
0013 
0014 #include "mtk_common.h"
0015 
0016 /**
0017  * scp_ipi_register() - register an ipi function
0018  *
0019  * @scp:    mtk_scp structure
0020  * @id:     IPI ID
0021  * @handler:    IPI handler
0022  * @priv:   private data for IPI handler
0023  *
0024  * Register an ipi function to receive ipi interrupt from SCP.
0025  *
0026  * Return: 0 if ipi registers successfully, -error on error.
0027  */
0028 int scp_ipi_register(struct mtk_scp *scp,
0029              u32 id,
0030              scp_ipi_handler_t handler,
0031              void *priv)
0032 {
0033     if (!scp)
0034         return -EPROBE_DEFER;
0035 
0036     if (WARN_ON(id >= SCP_IPI_MAX) || WARN_ON(handler == NULL))
0037         return -EINVAL;
0038 
0039     scp_ipi_lock(scp, id);
0040     scp->ipi_desc[id].handler = handler;
0041     scp->ipi_desc[id].priv = priv;
0042     scp_ipi_unlock(scp, id);
0043 
0044     return 0;
0045 }
0046 EXPORT_SYMBOL_GPL(scp_ipi_register);
0047 
0048 /**
0049  * scp_ipi_unregister() - unregister an ipi function
0050  *
0051  * @scp:    mtk_scp structure
0052  * @id:     IPI ID
0053  *
0054  * Unregister an ipi function to receive ipi interrupt from SCP.
0055  */
0056 void scp_ipi_unregister(struct mtk_scp *scp, u32 id)
0057 {
0058     if (!scp)
0059         return;
0060 
0061     if (WARN_ON(id >= SCP_IPI_MAX))
0062         return;
0063 
0064     scp_ipi_lock(scp, id);
0065     scp->ipi_desc[id].handler = NULL;
0066     scp->ipi_desc[id].priv = NULL;
0067     scp_ipi_unlock(scp, id);
0068 }
0069 EXPORT_SYMBOL_GPL(scp_ipi_unregister);
0070 
0071 /*
0072  * scp_memcpy_aligned() - Copy src to dst, where dst is in SCP SRAM region.
0073  *
0074  * @dst:    Pointer to the destination buffer, should be in SCP SRAM region.
0075  * @src:    Pointer to the source buffer.
0076  * @len:    Length of the source buffer to be copied.
0077  *
0078  * Since AP access of SCP SRAM don't support byte write, this always write a
0079  * full word at a time, and may cause some extra bytes to be written at the
0080  * beginning & ending of dst.
0081  */
0082 void scp_memcpy_aligned(void __iomem *dst, const void *src, unsigned int len)
0083 {
0084     void __iomem *ptr;
0085     u32 val;
0086     unsigned int i = 0, remain;
0087 
0088     if (!IS_ALIGNED((unsigned long)dst, 4)) {
0089         ptr = (void __iomem *)ALIGN_DOWN((unsigned long)dst, 4);
0090         i = 4 - (dst - ptr);
0091         val = readl_relaxed(ptr);
0092         memcpy((u8 *)&val + (4 - i), src, i);
0093         writel_relaxed(val, ptr);
0094     }
0095 
0096     __iowrite32_copy(dst + i, src + i, (len - i) / 4);
0097     remain = (len - i) % 4;
0098 
0099     if (remain > 0) {
0100         val = readl_relaxed(dst + len - remain);
0101         memcpy(&val, src + len - remain, remain);
0102         writel_relaxed(val, dst + len - remain);
0103     }
0104 }
0105 EXPORT_SYMBOL_GPL(scp_memcpy_aligned);
0106 
0107 /**
0108  * scp_ipi_lock() - Lock before operations of an IPI ID
0109  *
0110  * @scp:    mtk_scp structure
0111  * @id:     IPI ID
0112  *
0113  * Note: This should not be used by drivers other than mtk_scp.
0114  */
0115 void scp_ipi_lock(struct mtk_scp *scp, u32 id)
0116 {
0117     if (WARN_ON(id >= SCP_IPI_MAX))
0118         return;
0119     mutex_lock(&scp->ipi_desc[id].lock);
0120 }
0121 EXPORT_SYMBOL_GPL(scp_ipi_lock);
0122 
0123 /**
0124  * scp_ipi_lock() - Unlock after operations of an IPI ID
0125  *
0126  * @scp:    mtk_scp structure
0127  * @id:     IPI ID
0128  *
0129  * Note: This should not be used by drivers other than mtk_scp.
0130  */
0131 void scp_ipi_unlock(struct mtk_scp *scp, u32 id)
0132 {
0133     if (WARN_ON(id >= SCP_IPI_MAX))
0134         return;
0135     mutex_unlock(&scp->ipi_desc[id].lock);
0136 }
0137 EXPORT_SYMBOL_GPL(scp_ipi_unlock);
0138 
0139 /**
0140  * scp_ipi_send() - send data from AP to scp.
0141  *
0142  * @scp:    mtk_scp structure
0143  * @id:     IPI ID
0144  * @buf:    the data buffer
0145  * @len:    the data buffer length
0146  * @wait:   number of msecs to wait for ack. 0 to skip waiting.
0147  *
0148  * This function is thread-safe. When this function returns,
0149  * SCP has received the data and starts the processing.
0150  * When the processing completes, IPI handler registered
0151  * by scp_ipi_register will be called in interrupt context.
0152  *
0153  * Return: 0 if sending data successfully, -error on error.
0154  **/
0155 int scp_ipi_send(struct mtk_scp *scp, u32 id, void *buf, unsigned int len,
0156          unsigned int wait)
0157 {
0158     struct mtk_share_obj __iomem *send_obj = scp->send_buf;
0159     unsigned long timeout;
0160     int ret;
0161 
0162     if (WARN_ON(id <= SCP_IPI_INIT) || WARN_ON(id >= SCP_IPI_MAX) ||
0163         WARN_ON(id == SCP_IPI_NS_SERVICE) ||
0164         WARN_ON(len > sizeof(send_obj->share_buf)) || WARN_ON(!buf))
0165         return -EINVAL;
0166 
0167     mutex_lock(&scp->send_lock);
0168 
0169     ret = clk_prepare_enable(scp->clk);
0170     if (ret) {
0171         dev_err(scp->dev, "failed to enable clock\n");
0172         goto unlock_mutex;
0173     }
0174 
0175      /* Wait until SCP receives the last command */
0176     timeout = jiffies + msecs_to_jiffies(2000);
0177     do {
0178         if (time_after(jiffies, timeout)) {
0179             dev_err(scp->dev, "%s: IPI timeout!\n", __func__);
0180             ret = -ETIMEDOUT;
0181             goto clock_disable;
0182         }
0183     } while (readl(scp->reg_base + scp->data->host_to_scp_reg));
0184 
0185     scp_memcpy_aligned(send_obj->share_buf, buf, len);
0186 
0187     writel(len, &send_obj->len);
0188     writel(id, &send_obj->id);
0189 
0190     scp->ipi_id_ack[id] = false;
0191     /* send the command to SCP */
0192     writel(scp->data->host_to_scp_int_bit,
0193            scp->reg_base + scp->data->host_to_scp_reg);
0194 
0195     if (wait) {
0196         /* wait for SCP's ACK */
0197         timeout = msecs_to_jiffies(wait);
0198         ret = wait_event_timeout(scp->ack_wq,
0199                      scp->ipi_id_ack[id],
0200                      timeout);
0201         scp->ipi_id_ack[id] = false;
0202         if (WARN(!ret, "scp ipi %d ack time out !", id))
0203             ret = -EIO;
0204         else
0205             ret = 0;
0206     }
0207 
0208 clock_disable:
0209     clk_disable_unprepare(scp->clk);
0210 unlock_mutex:
0211     mutex_unlock(&scp->send_lock);
0212 
0213     return ret;
0214 }
0215 EXPORT_SYMBOL_GPL(scp_ipi_send);
0216 
0217 MODULE_LICENSE("GPL v2");
0218 MODULE_DESCRIPTION("MediaTek scp IPI interface");