/*
 * Copyright (c) 2018 Intel Corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <device.h>
#include <errno.h>
#include <init.h>
#include <string.h>
#include <soc.h>
#include <dma.h>
#include <altera_common.h>
#include "altera_msgdma_csr_regs.h"
#include "altera_msgdma_descriptor_regs.h"
#include "altera_msgdma.h"

#define LOG_LEVEL CONFIG_DMA_LOG_LEVEL
#include <logging/log.h>
LOG_MODULE_REGISTER(dma_nios2);

/* Device configuration parameters */
struct nios2_msgdma_dev_cfg {
	alt_msgdma_dev *msgdma_dev;
	alt_msgdma_standard_descriptor desc;
	u32_t direction;
	struct k_sem sem_lock;
	void *callback_arg;
	void (*dma_callback)(void *arg, u32_t id,
			     int error_code);
};

#define DEV_NAME(dev) ((dev)->config->name)
#define DEV_CFG(dev) \
	((struct nios2_msgdma_dev_cfg *)(dev)->config->config_info)

static void nios2_msgdma_isr(void *arg)
{
	struct device *dev = (struct device *)arg;
	struct nios2_msgdma_dev_cfg *cfg = DEV_CFG(dev);

	/* Call Altera HAL driver ISR */
	alt_handle_irq(cfg->msgdma_dev, MSGDMA_0_CSR_IRQ);
}

static void nios2_msgdma_callback(void *context)
{
	struct nios2_msgdma_dev_cfg *dev_cfg =
				DEV_CFG((struct device *)context);
	int err_code;
	u32_t status;

	status = IORD_ALTERA_MSGDMA_CSR_STATUS(dev_cfg->msgdma_dev->csr_base);

	if (status & ALTERA_MSGDMA_CSR_STOPPED_ON_ERROR_MASK) {
		err_code = -EIO;
	} else if (status & ALTERA_MSGDMA_CSR_BUSY_MASK) {
		err_code = -EBUSY;
	} else {
		err_code = 0;
	}

	LOG_DBG("msgdma csr status Reg: 0x%x", status);

	dev_cfg->dma_callback(dev_cfg->callback_arg, 0, err_code);
}

static int nios2_msgdma_config(struct device *dev, u32_t channel,
			       struct dma_config *cfg)
{
	struct nios2_msgdma_dev_cfg *dev_cfg = DEV_CFG(dev);
	struct dma_block_config *dma_block;
	int status;
	u32_t control;

	/* Nios-II MSGDMA supports only one channel per DMA core */
	if (channel != 0U) {
		LOG_ERR("invalid channel number");
		return -EINVAL;
	}

#if MSGDMA_0_CSR_PREFETCHER_ENABLE
	if (cfg->block_count > 1) {
		LOG_ERR("driver yet add support multiple descriptors");
		return -EINVAL;
	}
#else
	if (cfg->block_count != 1U) {
		LOG_ERR("invalid block count!!");
		return -EINVAL;
	}
#endif

	if (cfg->head_block == NULL) {
		LOG_ERR("head_block ptr NULL!!");
		return -EINVAL;
	}

	if (cfg->head_block->block_size > MSGDMA_0_DESCRIPTOR_SLAVE_MAX_BYTE) {
		LOG_ERR("DMA error: Data size too big: %d",
			    cfg->head_block->block_size);
		return -EINVAL;
	}

	k_sem_take(&dev_cfg->sem_lock, K_FOREVER);
	dev_cfg->dma_callback = cfg->dma_callback;
	dev_cfg->callback_arg = cfg->callback_arg;
	dev_cfg->direction = cfg->channel_direction;
	dma_block = cfg->head_block;
	control =  ALTERA_MSGDMA_DESCRIPTOR_CONTROL_TRANSFER_COMPLETE_IRQ_MASK |
		  ALTERA_MSGDMA_DESCRIPTOR_CONTROL_EARLY_TERMINATION_IRQ_MASK;

	if (dev_cfg->direction == MEMORY_TO_MEMORY) {
		status = alt_msgdma_construct_standard_mm_to_mm_descriptor(
			dev_cfg->msgdma_dev, &dev_cfg->desc,
			(alt_u32 *)dma_block->source_address,
			(alt_u32 *)dma_block->dest_address,
			dma_block->block_size,
			control);
	} else if (dev_cfg->direction == MEMORY_TO_PERIPHERAL) {
		status = alt_msgdma_construct_standard_mm_to_st_descriptor(
			dev_cfg->msgdma_dev, &dev_cfg->desc,
			(alt_u32 *)dma_block->source_address,
			dma_block->block_size,
			control);
	} else if (dev_cfg->direction == PERIPHERAL_TO_MEMORY) {
		status = alt_msgdma_construct_standard_st_to_mm_descriptor(
			dev_cfg->msgdma_dev, &dev_cfg->desc,
			(alt_u32 *)dma_block->dest_address,
			dma_block->block_size,
			control);
	} else {
		LOG_ERR("invalid channel direction");
		status = -EINVAL;
	}

	/* Register msgdma callback */
	alt_msgdma_register_callback(dev_cfg->msgdma_dev,
			nios2_msgdma_callback,
			ALTERA_MSGDMA_CSR_GLOBAL_INTERRUPT_MASK |
			ALTERA_MSGDMA_CSR_STOP_ON_ERROR_MASK |
			ALTERA_MSGDMA_CSR_STOP_ON_EARLY_TERMINATION_MASK,
			dev);

	/* Clear the IRQ status */
	IOWR_ALTERA_MSGDMA_CSR_STATUS(dev_cfg->msgdma_dev->csr_base,
				      ALTERA_MSGDMA_CSR_IRQ_SET_MASK);
	k_sem_give(&dev_cfg->sem_lock);

	return status;
}

static int nios2_msgdma_transfer_start(struct device *dev, u32_t channel)
{
	struct nios2_msgdma_dev_cfg *cfg = DEV_CFG(dev);
	int status;

	/* Nios-II mSGDMA supports only one channel per DMA core */
	if (channel != 0U) {
		LOG_ERR("Invalid channel number");
		return -EINVAL;
	}

	k_sem_take(&cfg->sem_lock, K_FOREVER);
	status = alt_msgdma_standard_descriptor_async_transfer(cfg->msgdma_dev,
								&cfg->desc);
	k_sem_give(&cfg->sem_lock);

	if (status < 0) {
		LOG_ERR("DMA transfer error (%d)", status);
	}

	return status;
}

static int nios2_msgdma_transfer_stop(struct device *dev, u32_t channel)
{
	struct nios2_msgdma_dev_cfg *cfg = DEV_CFG(dev);
	int ret = -EIO;
	u32_t status;

	k_sem_take(&cfg->sem_lock, K_FOREVER);
	/* Stop the DMA Dispatcher */
	IOWR_ALTERA_MSGDMA_CSR_CONTROL(cfg->msgdma_dev->csr_base,
				       ALTERA_MSGDMA_CSR_STOP_MASK);

	status = IORD_ALTERA_MSGDMA_CSR_STATUS(cfg->msgdma_dev->csr_base);
	k_sem_give(&cfg->sem_lock);

	if (status & ALTERA_MSGDMA_CSR_STOP_STATE_MASK) {
		LOG_DBG("DMA Dispatcher stopped");
		ret = 0;
	}

	LOG_DBG("msgdma csr status Reg: 0x%x", status);

	return status;
}

static const struct dma_driver_api nios2_msgdma_driver_api = {
	.config = nios2_msgdma_config,
	.start = nios2_msgdma_transfer_start,
	.stop = nios2_msgdma_transfer_stop,
};

/* DMA0 */
static struct device DEVICE_NAME_GET(dma0_nios2);

static int nios2_msgdma0_initialize(struct device *dev)
{
	struct nios2_msgdma_dev_cfg *dev_cfg = DEV_CFG(dev);

	/* Initialize semaphore */
	k_sem_init(&dev_cfg->sem_lock, 1, 1);

	alt_msgdma_init(dev_cfg->msgdma_dev, 0, MSGDMA_0_CSR_IRQ);

	IRQ_CONNECT(MSGDMA_0_CSR_IRQ, CONFIG_DMA_0_IRQ_PRI,
		    nios2_msgdma_isr, DEVICE_GET(dma0_nios2), 0);

	irq_enable(MSGDMA_0_CSR_IRQ);

	return 0;
}

ALTERA_MSGDMA_CSR_DESCRIPTOR_SLAVE_INSTANCE(MSGDMA_0, MSGDMA_0_CSR,
				MSGDMA_0_DESCRIPTOR_SLAVE, msgdma_dev0)

static struct nios2_msgdma_dev_cfg dma0_nios2_config = {
	.msgdma_dev = &msgdma_dev0,
};

DEVICE_AND_API_INIT(dma0_nios2, CONFIG_DMA_0_NAME, &nios2_msgdma0_initialize,
		    NULL, &dma0_nios2_config, POST_KERNEL,
		    CONFIG_KERNEL_INIT_PRIORITY_DEVICE,
		    &nios2_msgdma_driver_api);
