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

/**
 * @file
 *
 * @brief Sample app to illustrate dma transfer on Intel S1000 CRB.
 *
 * Intel S1000 CRB - Xtensa
 * --------------------
 *
 * The dma_cavs driver is being used.
 *
 * In this sample app, multi-block dma is tested in the following manner
 *   - Define 2 strings which will serve as 2 blocks of source data.
 *   - Define 2 empty buffers to receive the data from the DMA operation.
 *   - Set dma channel configuration including source/dest addr, burstlen etc.
 *   - Set direction memory-to-memory
 *   - Start transfer
 *
 * Expected Results
 *   - Data is transferred correctly from src to dest. The DMAed string should
 *     be printed on to the console. No error should be seen.
 */

#include <zephyr/zephyr.h>
#include <zephyr/sys/printk.h>

#include <zephyr/device.h>
#include <zephyr/drivers/dma.h>

#include <string.h>
#include <xtensa/hal.h>

/* size of stack area used by each thread */
#define STACKSIZE               1024

/* scheduling priority used by each thread */
#define PRIORITY                7

/* delay between greetings (in ms) */
#define SLEEPTIME               K_MSEC(500)

/* max time to be waited for dma to complete (in ms) */
#define WAITTIME                K_MSEC(1000)

#define MAX_TRANSFERS		4

/* This semaphore is used as a signal from the dma isr to the app
 * to let it know the DMA is complete. The app should wait till
 * this event comes indicating the completion of DMA.
 */
K_SEM_DEFINE(dma_sem, 0, 1);

extern struct k_sem thread_sem;

#define RX_BUFF_SIZE		(48)

struct transfers {
	const char *source;
	char *destination;
	size_t size;
};

static const char tx_data[] = "It is harder to be kind than to be wise";
static const char tx_data2[] = "India have a good cricket team";
static const char tx_data3[] = "Virat: the best ever?";
static const char tx_data4[] = "Phenomenon";
static char rx_data[RX_BUFF_SIZE] = { 0 };
static char rx_data2[RX_BUFF_SIZE] = { 0 };
static char rx_data3[RX_BUFF_SIZE] = { 0 };
static char rx_data4[RX_BUFF_SIZE] = { 0 };

static struct transfers transfer_blocks[MAX_TRANSFERS] = {
	{
		.source = tx_data,
		.destination = rx_data,
		.size = sizeof(tx_data),
	},
	{
		.source = tx_data2,
		.destination = rx_data2,
		.size = sizeof(tx_data2),
	},
	{
		.source = tx_data3,
		.destination = rx_data3,
		.size = sizeof(tx_data3),
	},
	{
		.source = tx_data4,
		.destination = rx_data4,
		.size = sizeof(tx_data4),
	},
};
static const struct device *dma_device;
static uint32_t current_block_count, total_block_count;

static void test_done(const struct device *dma_dev, void *arg,
		      uint32_t channel, int error_code)
{
	uint32_t src, dst;
	size_t size;

	current_block_count++;

	if (error_code != 0) {
		printk("DMA transfer met an error = 0x%x\n", error_code);
		k_sem_give(&dma_sem);
	} else if (current_block_count < total_block_count) {
		src = (uint32_t)transfer_blocks[current_block_count].source;
		dst = (uint32_t)transfer_blocks[current_block_count].destination;
		size = transfer_blocks[current_block_count].size;
		dma_reload(dma_dev, channel, src, dst, size);
		dma_start(dma_dev, channel);
	} else {
		printk("DMA transfer done\n");
		k_sem_give(&dma_sem);
	}
}

static int test_task(uint32_t chan_id, uint32_t blen, uint32_t block_count)
{
	struct dma_config dma_cfg = {0};

	struct dma_block_config dma_block_cfg = {
		.block_size = sizeof(tx_data),
		.source_address = (uint32_t)tx_data,
		.dest_address = (uint32_t)rx_data,
	};

	if (block_count > ARRAY_SIZE(transfer_blocks)) {
		printk("block_count %u is greater than %zu\n", block_count,
			ARRAY_SIZE(transfer_blocks));
		return -1;
	}

	dma_device = DEVICE_DT_GET(DT_NODELABEL(dma0));

	if (!device_is_ready(dma_device)) {
		printk("dma controller is not ready\n");
		return -1;
	}

	dma_cfg.channel_direction = MEMORY_TO_MEMORY;
	dma_cfg.source_data_size = 1U;
	dma_cfg.dest_data_size = 1U;
	dma_cfg.source_burst_length = blen;
	dma_cfg.dest_burst_length = blen;
	dma_cfg.dma_callback = test_done;
	dma_cfg.complete_callback_en = 0U;
	dma_cfg.error_callback_en = 1U;
	dma_cfg.block_count = 1U;
	dma_cfg.head_block = &dma_block_cfg;

	printk("Preparing DMA Controller: Chan_ID=%u, BURST_LEN=%u\n",
			chan_id, blen);

	(void)memset(rx_data, 0, sizeof(rx_data));
	(void)memset(rx_data2, 0, sizeof(rx_data2));
	(void)memset(rx_data3, 0, sizeof(rx_data3));
	(void)memset(rx_data4, 0, sizeof(rx_data4));

	/*
	 * dma_block_cfg4 is assigned to 0 by default. Hence if user_data is
	 * not assigned, it will be NULL implying there are no more blocks to
	 * transfer
	 */

	if (dma_config(dma_device, chan_id, &dma_cfg)) {
		printk("ERROR: configuring\n");
		return -1;
	}

	printk("Starting the transfer\n");

	current_block_count = 0U;
	total_block_count = block_count;

	if (dma_start(dma_device, chan_id)) {
		printk("ERROR: transfer\n");
		return -1;
	}

	/* Wait a while for the dma to complete */
	if (k_sem_take(&dma_sem, WAITTIME)) {
		printk("*** timed out waiting for dma to complete ***\n");
	}

	z_xtensa_cache_inv(rx_data, RX_BUFF_SIZE);
	z_xtensa_cache_inv(rx_data2, RX_BUFF_SIZE);
	z_xtensa_cache_inv(rx_data3, RX_BUFF_SIZE);
	z_xtensa_cache_inv(rx_data4, RX_BUFF_SIZE);

	/* Intentionally break has been omitted (fall-through) */
	switch (block_count) {
	case 4:
		if (strcmp(tx_data4, rx_data4) != 0) {
			return -1;
		}
		printk("%s\n", rx_data4);

	case 3:
		if (strcmp(tx_data3, rx_data3) != 0) {
			return -1;
		}
		printk("%s\n", rx_data3);

	case 2:
		if (strcmp(tx_data2, rx_data2) != 0) {
			return -1;
		}
		printk("%s\n", rx_data2);

	case 1:
		if (strcmp(tx_data, rx_data) != 0) {
			return -1;
		}
		printk("%s\n", rx_data);
		break;

	default:
		printk("Invalid block count %d\n", block_count);
		return -1;
	}

	return 0;
}

/* export test cases */
void dma_thread(void)
{
	while (1) {
		k_sem_take(&thread_sem, K_FOREVER);
		if (test_task(0, 8, 2) == 0) {
			printk("DMA Passed\n");
		} else {
			printk("DMA Failed\n");
		}
		k_sem_give(&thread_sem);
		k_sleep(SLEEPTIME);

		k_sem_take(&thread_sem, K_FOREVER);
		if (test_task(1, 8, 3) == 0) {
			printk("DMA Passed\n");
		} else {
			printk("DMA Failed\n");
		}
		k_sem_give(&thread_sem);
		k_sleep(SLEEPTIME);

		k_sem_take(&thread_sem, K_FOREVER);
		if (test_task(0, 16, 4) == 0) {
			printk("DMA Passed\n");
		} else {
			printk("DMA Failed\n");
		}
		k_sem_give(&thread_sem);
		k_sleep(SLEEPTIME);

		k_sem_take(&thread_sem, K_FOREVER);
		if (test_task(1, 16, 1) == 0) {
			printk("DMA Passed\n");
		} else {
			printk("DMA Failed\n");
		}
		k_sem_give(&thread_sem);
		k_sleep(SLEEPTIME);
	}
}

K_THREAD_DEFINE(dma_thread_id, STACKSIZE, dma_thread, NULL, NULL, NULL,
		PRIORITY, 0, 0);
