162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright 2020-2021 NXP
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci#include <linux/init.h>
762306a36Sopenharmony_ci#include <linux/interconnect.h>
862306a36Sopenharmony_ci#include <linux/ioctl.h>
962306a36Sopenharmony_ci#include <linux/list.h>
1062306a36Sopenharmony_ci#include <linux/kernel.h>
1162306a36Sopenharmony_ci#include <linux/module.h>
1262306a36Sopenharmony_ci#include <linux/platform_device.h>
1362306a36Sopenharmony_ci#include "vpu.h"
1462306a36Sopenharmony_ci#include "vpu_mbox.h"
1562306a36Sopenharmony_ci#include "vpu_msgs.h"
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_cistatic void vpu_mbox_rx_callback(struct mbox_client *cl, void *msg)
1862306a36Sopenharmony_ci{
1962306a36Sopenharmony_ci	struct vpu_mbox *rx = container_of(cl, struct vpu_mbox, cl);
2062306a36Sopenharmony_ci	struct vpu_core *core = container_of(rx, struct vpu_core, rx);
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci	vpu_isr(core, *(u32 *)msg);
2362306a36Sopenharmony_ci}
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_cistatic int vpu_mbox_request_channel(struct device *dev, struct vpu_mbox *mbox)
2662306a36Sopenharmony_ci{
2762306a36Sopenharmony_ci	struct mbox_chan *ch;
2862306a36Sopenharmony_ci	struct mbox_client *cl;
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci	if (!dev || !mbox)
3162306a36Sopenharmony_ci		return -EINVAL;
3262306a36Sopenharmony_ci	if (mbox->ch)
3362306a36Sopenharmony_ci		return 0;
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci	cl = &mbox->cl;
3662306a36Sopenharmony_ci	cl->dev = dev;
3762306a36Sopenharmony_ci	if (mbox->block) {
3862306a36Sopenharmony_ci		cl->tx_block = true;
3962306a36Sopenharmony_ci		cl->tx_tout = 1000;
4062306a36Sopenharmony_ci	} else {
4162306a36Sopenharmony_ci		cl->tx_block = false;
4262306a36Sopenharmony_ci	}
4362306a36Sopenharmony_ci	cl->knows_txdone = false;
4462306a36Sopenharmony_ci	cl->rx_callback = vpu_mbox_rx_callback;
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci	ch = mbox_request_channel_byname(cl, mbox->name);
4762306a36Sopenharmony_ci	if (IS_ERR(ch))
4862306a36Sopenharmony_ci		return dev_err_probe(dev, PTR_ERR(ch),
4962306a36Sopenharmony_ci				     "Failed to request mbox chan %s\n",
5062306a36Sopenharmony_ci				     mbox->name);
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci	mbox->ch = ch;
5362306a36Sopenharmony_ci	return 0;
5462306a36Sopenharmony_ci}
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ciint vpu_mbox_init(struct vpu_core *core)
5762306a36Sopenharmony_ci{
5862306a36Sopenharmony_ci	scnprintf(core->tx_type.name, sizeof(core->tx_type.name) - 1, "tx0");
5962306a36Sopenharmony_ci	core->tx_type.block = true;
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci	scnprintf(core->tx_data.name, sizeof(core->tx_data.name) - 1, "tx1");
6262306a36Sopenharmony_ci	core->tx_data.block = false;
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci	scnprintf(core->rx.name, sizeof(core->rx.name) - 1, "rx");
6562306a36Sopenharmony_ci	core->rx.block = true;
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci	return 0;
6862306a36Sopenharmony_ci}
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ciint vpu_mbox_request(struct vpu_core *core)
7162306a36Sopenharmony_ci{
7262306a36Sopenharmony_ci	int ret;
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci	ret = vpu_mbox_request_channel(core->dev, &core->tx_type);
7562306a36Sopenharmony_ci	if (ret)
7662306a36Sopenharmony_ci		goto error;
7762306a36Sopenharmony_ci	ret = vpu_mbox_request_channel(core->dev, &core->tx_data);
7862306a36Sopenharmony_ci	if (ret)
7962306a36Sopenharmony_ci		goto error;
8062306a36Sopenharmony_ci	ret = vpu_mbox_request_channel(core->dev, &core->rx);
8162306a36Sopenharmony_ci	if (ret)
8262306a36Sopenharmony_ci		goto error;
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ci	dev_dbg(core->dev, "%s request mbox\n", vpu_core_type_desc(core->type));
8562306a36Sopenharmony_ci	return 0;
8662306a36Sopenharmony_cierror:
8762306a36Sopenharmony_ci	vpu_mbox_free(core);
8862306a36Sopenharmony_ci	return ret;
8962306a36Sopenharmony_ci}
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_civoid vpu_mbox_free(struct vpu_core *core)
9262306a36Sopenharmony_ci{
9362306a36Sopenharmony_ci	mbox_free_channel(core->tx_type.ch);
9462306a36Sopenharmony_ci	mbox_free_channel(core->tx_data.ch);
9562306a36Sopenharmony_ci	mbox_free_channel(core->rx.ch);
9662306a36Sopenharmony_ci	core->tx_type.ch = NULL;
9762306a36Sopenharmony_ci	core->tx_data.ch = NULL;
9862306a36Sopenharmony_ci	core->rx.ch = NULL;
9962306a36Sopenharmony_ci	dev_dbg(core->dev, "%s free mbox\n", vpu_core_type_desc(core->type));
10062306a36Sopenharmony_ci}
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_civoid vpu_mbox_send_type(struct vpu_core *core, u32 type)
10362306a36Sopenharmony_ci{
10462306a36Sopenharmony_ci	mbox_send_message(core->tx_type.ch, &type);
10562306a36Sopenharmony_ci}
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_civoid vpu_mbox_send_msg(struct vpu_core *core, u32 type, u32 data)
10862306a36Sopenharmony_ci{
10962306a36Sopenharmony_ci	mbox_send_message(core->tx_data.ch, &data);
11062306a36Sopenharmony_ci	mbox_send_message(core->tx_type.ch, &type);
11162306a36Sopenharmony_ci}
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_civoid vpu_mbox_enable_rx(struct vpu_dev *dev)
11462306a36Sopenharmony_ci{
11562306a36Sopenharmony_ci}
116