1
0
mirror of https://github.com/physwizz/a155-U-u1.git synced 2025-09-26 19:04:54 +00:00
Files
physwizz 99537be4e2 first
2024-03-11 06:53:12 +11:00

253 lines
5.3 KiB
C

// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2019 MediaTek Inc.
*/
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/miscdevice.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/completion.h>
#include <linux/mutex.h>
#include <linux/rpmsg.h>
#include <utilities/mdla_debug.h>
#include <utilities/mdla_ipi.h>
#include <platform/mdla_plat_api.h>
/*
* type0: Distinguish pwr_time, timeout, klog, or CX
* type1: prepare to C1~C16
* dir : Distinguish read or write
* data : store data
*/
struct mdla_ipi_data {
u32 type0;
u16 type1;
u16 dir;
u64 data;
};
static struct mdla_ipi_data ipi_tx_recv_buf;
static struct mdla_ipi_data ipi_rx_send_buf;
static struct mutex mdla_ipi_mtx;
struct mdla_rpmsg_device {
struct rpmsg_endpoint *ept;
struct rpmsg_device *rpdev;
struct completion ack;
};
static struct mdla_rpmsg_device mdla_tx_rpm_dev;
static struct mdla_rpmsg_device mdla_rx_rpm_dev;
int mdla_ipi_send(int type_0, int type_1, u64 val)
{
struct mdla_ipi_data ipi_cmd_send;
if (!mdla_tx_rpm_dev.ept)
return 0;
ipi_cmd_send.type0 = type_0;
ipi_cmd_send.type1 = type_1;
ipi_cmd_send.dir = MDLA_IPI_WRITE;
ipi_cmd_send.data = val;
mdla_verbose("send : %d %d, %d, %llu(0x%llx)\n",
ipi_cmd_send.type0,
ipi_cmd_send.type1,
ipi_cmd_send.dir,
ipi_cmd_send.data, ipi_cmd_send.data);
mutex_lock(&mdla_ipi_mtx);
rpmsg_send(mdla_tx_rpm_dev.ept, &ipi_cmd_send, sizeof(ipi_cmd_send));
mutex_unlock(&mdla_ipi_mtx);
return 0;
}
int mdla_ipi_recv(int type_0, int type_1, u64 *val)
{
struct mdla_ipi_data ipi_cmd_send;
ipi_cmd_send.type0 = type_0;
ipi_cmd_send.type1 = type_1;
ipi_cmd_send.dir = MDLA_IPI_READ;
ipi_cmd_send.data = 0;
mutex_lock(&mdla_ipi_mtx);
rpmsg_send(mdla_tx_rpm_dev.ept, &ipi_cmd_send, sizeof(ipi_cmd_send));
if (wait_for_completion_interruptible_timeout(
&mdla_tx_rpm_dev.ack,
msecs_to_jiffies(10)) == 0) {
mutex_unlock(&mdla_ipi_mtx);
mdla_err("%s: timeout\n", __func__);
return -1;
}
*val = (u64)ipi_tx_recv_buf.data;
mutex_unlock(&mdla_ipi_mtx);
return 0;
}
static int mdla_rpmsg_tx_cb(struct rpmsg_device *rpdev, void *data,
int len, void *priv, u32 src)
{
struct mdla_ipi_data *d = (struct mdla_ipi_data *)data;
if (d->dir != MDLA_IPI_READ)
return 0;
if (d->type0 == MDLA_IPI_MICROP_MSG) {
mdla_err("Receive uP message -> use the wrong channel!?\n");
} else {
ipi_tx_recv_buf.type0 = d->type0;
ipi_tx_recv_buf.type1 = d->type1;
ipi_tx_recv_buf.dir = d->dir;
ipi_tx_recv_buf.data = d->data;
complete(&mdla_tx_rpm_dev.ack);
}
mdla_verbose("tx rpmsg cb : %d %d, %d, %llu(0x%llx)\n",
d->type0,
d->type1,
d->dir,
d->data,
d->data);
return 0;
}
static void mdla_ipi_up_msg(u32 type, u64 val)
{
mdla_err("tpye = %d, val = 0x%llx\n", type, val);
if (type == MDLA_IPI_MICROP_MSG_TIMEOUT)
mdla_aee_warn("MDLA", "MDLA timeout");
}
static int mdla_rpmsg_rx_cb(struct rpmsg_device *rpdev, void *data,
int len, void *priv, u32 src)
{
struct mdla_ipi_data *d = (struct mdla_ipi_data *)data;
if (d->type0 == MDLA_IPI_MICROP_MSG) {
ipi_rx_send_buf.type0 = d->type0;
ipi_rx_send_buf.type1 = d->type1;
ipi_rx_send_buf.dir = d->dir;
ipi_rx_send_buf.data = d->data;
rpmsg_send(mdla_rx_rpm_dev.ept, &ipi_rx_send_buf, sizeof(ipi_rx_send_buf));
mdla_ipi_up_msg(d->type1, d->data);
} else {
mdla_err("Receive command ack -> use the wrong channel!?\n");
}
mdla_verbose("rpmsg cb : %d %d, %d, %llu(0x%llx)\n",
d->type0,
d->type1,
d->dir,
d->data,
d->data);
return 0;
}
static int mdla_rpmsg_tx_probe(struct rpmsg_device *rpdev)
{
struct device *dev = &rpdev->dev;
dev_info(dev, "%s: name=%s, src=%d\n",
rpdev->id.name, rpdev->src);
mdla_tx_rpm_dev.ept = rpdev->ept;
mdla_tx_rpm_dev.rpdev = rpdev;
mdla_plat_up_init();
return 0;
}
static int mdla_rpmsg_rx_probe(struct rpmsg_device *rpdev)
{
struct device *dev = &rpdev->dev;
dev_info(dev, "%s: name=%s, src=%d\n",
rpdev->id.name, rpdev->src);
mdla_rx_rpm_dev.ept = rpdev->ept;
mdla_rx_rpm_dev.rpdev = rpdev;
return 0;
}
static void mdla_rpmsg_remove(struct rpmsg_device *rpdev)
{
}
static const struct of_device_id mdla_tx_rpmsg_of_match[] = {
{ .compatible = "mediatek,mdla-tx-rpmsg"},
{},
};
static const struct of_device_id mdla_rx_rpmsg_of_match[] = {
{ .compatible = "mediatek,mdla-rx-rpmsg"},
{},
};
static struct rpmsg_driver mdla_rpmsg_tx_drv = {
.drv = {
.name = "mdla-tx-rpmsg",
.owner = THIS_MODULE,
.of_match_table = mdla_tx_rpmsg_of_match,
},
.probe = mdla_rpmsg_tx_probe,
.callback = mdla_rpmsg_tx_cb,
.remove = mdla_rpmsg_remove,
};
static struct rpmsg_driver mdla_rpmsg_rx_drv = {
.drv = {
.name = "mdla-rx-rpmsg",
.owner = THIS_MODULE,
.of_match_table = mdla_rx_rpmsg_of_match,
},
.probe = mdla_rpmsg_rx_probe,
.callback = mdla_rpmsg_rx_cb,
.remove = mdla_rpmsg_remove,
};
int mdla_ipi_init(void)
{
int ret;
init_completion(&mdla_rx_rpm_dev.ack);
init_completion(&mdla_tx_rpm_dev.ack);
mutex_init(&mdla_ipi_mtx);
ret = register_rpmsg_driver(&mdla_rpmsg_rx_drv);
if (ret)
mdla_err("failed to register mdla rx rpmsg\n");
ret = register_rpmsg_driver(&mdla_rpmsg_tx_drv);
if (ret)
mdla_err("failed to register mdla tx rpmsg\n");
return 0;
}
void mdla_ipi_deinit(void)
{
unregister_rpmsg_driver(&mdla_rpmsg_tx_drv);
unregister_rpmsg_driver(&mdla_rpmsg_rx_drv);
mutex_destroy(&mdla_ipi_mtx);
}