1
0
mirror of https://github.com/physwizz/a155-U-u1.git synced 2024-11-19 13:27:49 +00:00
a155-U-u1/kernel-5.10/drivers/misc/mediatek/qos/mtk_qos_ipi_v2.c
2024-03-11 06:53:12 +11:00

153 lines
3.3 KiB
C

// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2019 MediaTek Inc.
*/
#include <linux/kthread.h>
#include <linux/mutex.h>
#if defined(CONFIG_MTK_TINYSYS_SSPM_V2)
#include <sspm_ipi_id.h>
#include <sspm_define.h>
#endif
#include "mtk_qos_common.h"
#include "mtk_qos_bound.h"
#include "mtk_qos_ipi.h"
#if defined(CONFIG_MTK_TINYSYS_SSPM_V2)
static DEFINE_MUTEX(qos_ipi_mutex);
static int qos_sspm_ready;
int qos_ipi_ackdata;
struct qos_ipi_data qos_recv_ackdata;
static int qos_ipi_recv_thread(void *arg)
{
struct qos_ipi_data *qos_ipi_d;
int bound_cmd_id = qos_get_ipi_cmd(QOS_IPI_QOS_BOUND);
pr_info("%s start!\n", __func__);
do {
mtk_ipi_recv(&sspm_ipidev, IPIR_I_QOS);
qos_ipi_d = &qos_recv_ackdata;
if (qos_ipi_d->cmd == bound_cmd_id)
qos_notifier_call_chain(
qos_ipi_d->u.qos_bound.state,
get_qos_bound());
else
pr_info("wrong QoS IPI command: %d\n", qos_ipi_d->cmd);
} while (!kthread_should_stop());
return 0;
}
#endif
int qos_ipi_to_sspm_command(void *buffer, int slot)
{
#if defined(CONFIG_MTK_TINYSYS_SSPM_V2)
int ret, ackdata;
struct qos_ipi_data *qos_ipi_d = buffer;
int slot_num = sizeof(struct qos_ipi_data)/SSPM_MBOX_SLOT_SIZE;
mutex_lock(&qos_ipi_mutex);
ret = qos_get_ipi_cmd(qos_ipi_d->cmd);
if (qos_ipi_d->cmd < 0) {
pr_info("qos ipi cmd get error (in= %d, out = %d)\n",
qos_ipi_d->cmd, ret);
goto error;
}
qos_ipi_d->cmd = ret;
if (qos_sspm_ready != 1) {
pr_info("qos ipi not ready, skip cmd=%d\n", qos_ipi_d->cmd);
goto error;
}
pr_info("qos ipi cmd(%d) send\n", qos_ipi_d->cmd);
qos_ipi_ackdata = 0;
if (slot > slot_num) {
pr_info("qos ipi cmd %d req slot error(%d > %d)\n",
qos_ipi_d->cmd, slot, slot_num);
goto error;
}
ret = mtk_ipi_send_compl(&sspm_ipidev, IPIS_C_QOS,
IPI_SEND_POLLING, buffer,
slot_num, 2000);
if (ret) {
pr_info("qos ipi cmd %d send fail,ret=%d\n",
qos_ipi_d->cmd, ret);
goto error;
}
if (!qos_ipi_ackdata) {
pr_info("qos ipi cmd %d ack fail, ackdata=%d\n",
qos_ipi_d->cmd, qos_ipi_ackdata);
goto error;
}
ackdata = qos_ipi_ackdata;
mutex_unlock(&qos_ipi_mutex);
return ackdata;
error:
mutex_unlock(&qos_ipi_mutex);
#endif
return -1;
}
EXPORT_SYMBOL_GPL(qos_ipi_to_sspm_command);
static void qos_sspm_enable(void)
{
struct qos_ipi_data qos_ipi_d;
qos_ipi_d.cmd = QOS_IPI_QOS_ENABLE;
qos_ipi_to_sspm_command(&qos_ipi_d, 1);
}
void qos_ipi_init(struct mtk_qos *qos)
{
#if defined(CONFIG_MTK_TINYSYS_SSPM_V2)
unsigned int ret;
/* for AP to SSPM */
ret = mtk_ipi_register(&sspm_ipidev, IPIS_C_QOS, NULL, NULL,
(void *) &qos_ipi_ackdata);
if (ret) {
pr_info("qos IPIS_C_QOS ipi_register fail, ret %d\n", ret);
qos_sspm_ready = -1;
return;
}
/* for SSPM to AP */
ret = mtk_ipi_register(&sspm_ipidev, IPIR_I_QOS, NULL, NULL,
(void *) &qos_recv_ackdata);
if (ret) {
pr_info("qos IPIR_I_QOS ipi_register fail, ret %d\n", ret);
qos_sspm_ready = -2;
return;
}
qos_sspm_ready = 1;
qos_sspm_enable();
pr_info("%s ready!\n", __func__);
#endif
}
EXPORT_SYMBOL_GPL(qos_ipi_init);
void qos_ipi_recv_init(struct mtk_qos *qos)
{
#if defined(CONFIG_MTK_TINYSYS_SSPM_V2)
if (qos_sspm_ready != 1) {
pr_info("QOS SSPM not ready, recv thread not start!\n");
return;
}
kthread_run(qos_ipi_recv_thread, NULL, "qos_ipi_recv");
#endif
}
EXPORT_SYMBOL_GPL(qos_ipi_recv_init);