// SPDX-License-Identifier: GPL-2.0+
/*
 * Direct Memory Access U-Class Simulation driver
 *
 * Copyright (C) 2018 Texas Instruments Incorporated <www.ti.com>
 *
 * Author: Grygorii Strashko <grygorii.strashko@ti.com>
 */

#include <common.h>
#include <dm.h>
#include <log.h>
#include <malloc.h>
#include <dm/read.h>
#include <dma-uclass.h>
#include <dt-structs.h>
#include <errno.h>

#define SANDBOX_DMA_CH_CNT 3
#define SANDBOX_DMA_BUF_SIZE 1024

struct sandbox_dma_chan {
	struct sandbox_dma_dev *ud;
	char name[20];
	u32 id;
	enum dma_direction dir;
	bool in_use;
	bool enabled;
};

struct sandbox_dma_dev {
	struct device *dev;
	u32 ch_count;
	struct sandbox_dma_chan channels[SANDBOX_DMA_CH_CNT];
	uchar   buf[SANDBOX_DMA_BUF_SIZE];
	uchar	*buf_rx;
	size_t	data_len;
	u32	meta;
};

static int sandbox_dma_transfer(struct udevice *dev, int direction,
				void *dst, void *src, size_t len)
{
	memcpy(dst, src, len);

	return 0;
}

static int sandbox_dma_of_xlate(struct dma *dma,
				struct ofnode_phandle_args *args)
{
	struct sandbox_dma_dev *ud = dev_get_priv(dma->dev);
	struct sandbox_dma_chan *uc;

	debug("%s(dma id=%u)\n", __func__, args->args[0]);

	if (args->args[0] >= SANDBOX_DMA_CH_CNT)
		return -EINVAL;

	dma->id = args->args[0];

	uc = &ud->channels[dma->id];

	if (dma->id == 1)
		uc->dir = DMA_MEM_TO_DEV;
	else if (dma->id == 2)
		uc->dir = DMA_DEV_TO_MEM;
	else
		uc->dir = DMA_MEM_TO_MEM;
	debug("%s(dma id=%lu dir=%d)\n", __func__, dma->id, uc->dir);

	return 0;
}

static int sandbox_dma_request(struct dma *dma)
{
	struct sandbox_dma_dev *ud = dev_get_priv(dma->dev);
	struct sandbox_dma_chan *uc;

	if (dma->id >= SANDBOX_DMA_CH_CNT)
		return -EINVAL;

	uc = &ud->channels[dma->id];
	if (uc->in_use)
		return -EBUSY;

	uc->in_use = true;
	debug("%s(dma id=%lu in_use=%d)\n", __func__, dma->id, uc->in_use);

	return 0;
}

static int sandbox_dma_rfree(struct dma *dma)
{
	struct sandbox_dma_dev *ud = dev_get_priv(dma->dev);
	struct sandbox_dma_chan *uc;

	if (dma->id >= SANDBOX_DMA_CH_CNT)
		return -EINVAL;

	uc = &ud->channels[dma->id];
	if (!uc->in_use)
		return -EINVAL;

	uc->in_use = false;
	ud->buf_rx = NULL;
	ud->data_len = 0;
	debug("%s(dma id=%lu in_use=%d)\n", __func__, dma->id, uc->in_use);

	return 0;
}

static int sandbox_dma_enable(struct dma *dma)
{
	struct sandbox_dma_dev *ud = dev_get_priv(dma->dev);
	struct sandbox_dma_chan *uc;

	if (dma->id >= SANDBOX_DMA_CH_CNT)
		return -EINVAL;

	uc = &ud->channels[dma->id];
	if (!uc->in_use)
		return -EINVAL;
	if (uc->enabled)
		return -EINVAL;

	uc->enabled = true;
	debug("%s(dma id=%lu enabled=%d)\n", __func__, dma->id, uc->enabled);

	return 0;
}

static int sandbox_dma_disable(struct dma *dma)
{
	struct sandbox_dma_dev *ud = dev_get_priv(dma->dev);
	struct sandbox_dma_chan *uc;

	if (dma->id >= SANDBOX_DMA_CH_CNT)
		return -EINVAL;

	uc = &ud->channels[dma->id];
	if (!uc->in_use)
		return -EINVAL;
	if (!uc->enabled)
		return -EINVAL;

	uc->enabled = false;
	debug("%s(dma id=%lu enabled=%d)\n", __func__, dma->id, uc->enabled);

	return 0;
}

static int sandbox_dma_send(struct dma *dma,
			    void *src, size_t len, void *metadata)
{
	struct sandbox_dma_dev *ud = dev_get_priv(dma->dev);
	struct sandbox_dma_chan *uc;

	if (dma->id >= SANDBOX_DMA_CH_CNT)
		return -EINVAL;
	if (!src || !metadata)
		return -EINVAL;

	debug("%s(dma id=%lu)\n", __func__, dma->id);

	uc = &ud->channels[dma->id];
	if (uc->dir != DMA_MEM_TO_DEV)
		return -EINVAL;
	if (!uc->in_use)
		return -EINVAL;
	if (!uc->enabled)
		return -EINVAL;
	if (len >= SANDBOX_DMA_BUF_SIZE)
		return -EINVAL;

	memcpy(ud->buf, src, len);
	ud->data_len = len;
	ud->meta = *((u32 *)metadata);

	debug("%s(dma id=%lu len=%zu meta=%08x)\n",
	      __func__, dma->id, len, ud->meta);

	return 0;
}

static int sandbox_dma_receive(struct dma *dma, void **dst, void *metadata)
{
	struct sandbox_dma_dev *ud = dev_get_priv(dma->dev);
	struct sandbox_dma_chan *uc;

	if (dma->id >= SANDBOX_DMA_CH_CNT)
		return -EINVAL;
	if (!dst || !metadata)
		return -EINVAL;

	uc = &ud->channels[dma->id];
	if (uc->dir != DMA_DEV_TO_MEM)
		return -EINVAL;
	if (!uc->in_use)
		return -EINVAL;
	if (!uc->enabled)
		return -EINVAL;
	if (!ud->data_len)
		return 0;

	if (ud->buf_rx) {
		memcpy(ud->buf_rx, ud->buf, ud->data_len);
		*dst = ud->buf_rx;
	} else {
		memcpy(*dst, ud->buf, ud->data_len);
	}

	*((u32 *)metadata) = ud->meta;

	debug("%s(dma id=%lu len=%zu meta=%08x %p)\n",
	      __func__, dma->id, ud->data_len, ud->meta, *dst);

	return ud->data_len;
}

static int sandbox_dma_prepare_rcv_buf(struct dma *dma, void *dst, size_t size)
{
	struct sandbox_dma_dev *ud = dev_get_priv(dma->dev);

	ud->buf_rx = dst;

	return 0;
}

static const struct dma_ops sandbox_dma_ops = {
	.transfer	= sandbox_dma_transfer,
	.of_xlate	= sandbox_dma_of_xlate,
	.request	= sandbox_dma_request,
	.rfree		= sandbox_dma_rfree,
	.enable		= sandbox_dma_enable,
	.disable	= sandbox_dma_disable,
	.send		= sandbox_dma_send,
	.receive	= sandbox_dma_receive,
	.prepare_rcv_buf = sandbox_dma_prepare_rcv_buf,
};

static int sandbox_dma_probe(struct udevice *dev)
{
	struct dma_dev_priv *uc_priv = dev_get_uclass_priv(dev);
	struct sandbox_dma_dev *ud = dev_get_priv(dev);
	int i, ret = 0;

	uc_priv->supported = DMA_SUPPORTS_MEM_TO_MEM |
			     DMA_SUPPORTS_MEM_TO_DEV |
			     DMA_SUPPORTS_DEV_TO_MEM;

	ud->ch_count = SANDBOX_DMA_CH_CNT;
	ud->buf_rx = NULL;
	ud->meta = 0;
	ud->data_len = 0;

	pr_err("Number of channels: %u\n", ud->ch_count);

	for (i = 0; i < ud->ch_count; i++) {
		struct sandbox_dma_chan *uc = &ud->channels[i];

		uc->ud = ud;
		uc->id = i;
		sprintf(uc->name, "DMA chan%d\n", i);
		uc->in_use = false;
		uc->enabled = false;
	}

	return ret;
}

static const struct udevice_id sandbox_dma_ids[] = {
	{ .compatible = "sandbox,dma" },
	{ }
};

U_BOOT_DRIVER(sandbox_dma) = {
	.name	= "sandbox-dma",
	.id	= UCLASS_DMA,
	.of_match = sandbox_dma_ids,
	.ops	= &sandbox_dma_ops,
	.probe = sandbox_dma_probe,
	.priv_auto	= sizeof(struct sandbox_dma_dev),
};
