/*
 * Copyright (c) 2020 NXP
 *
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * @file
 * @brief Verify zephyr dma link transfer
 * @details
 * - Test Steps
 *   -# Set dma channel configuration including source/dest addr, burstlen
 *   -# Set direction memory-to-memory
 *   -# Start transfer tx -> rx
 *   -# after a major/minor loop trigger another channel to transfer, rx -> rx2
 * - Expected Results
 *   -# Data is transferred correctly from src to dest
 */

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

#define DMA_DEVICE_NAME CONFIG_DMA_LINK_TRANSFER_DRV_NAME
#define TEST_DMA_CHANNEL_0 (0)
#define TEST_DMA_CHANNEL_1 (1)
#define RX_BUFF_SIZE (48)

#ifdef CONFIG_NOCACHE_MEMORY
static __aligned(32) char tx_data[RX_BUFF_SIZE] __used
	__attribute__((__section__(".nocache")));
static const char TX_DATA[] = "It is harder to be kind than to be wise........";
static __aligned(32) char rx_data[RX_BUFF_SIZE] __used
	__attribute__((__section__(".nocache.dma")));
static __aligned(32) char rx_data2[RX_BUFF_SIZE] __used
	__attribute__((__section__(".nocache.dma")));
#else
static const char tx_data[] = "It is harder to be kind than to be wise........";
static char rx_data[RX_BUFF_SIZE] = { 0 };
static char rx_data2[RX_BUFF_SIZE] = { 0 };
#endif

static void test_done(const struct device *dma_dev, void *arg, uint32_t id,
		      int error_code)
{
	if (error_code == 0) {
		TC_PRINT("DMA transfer done ch %d\n", id);
	} else {
		TC_PRINT("DMA transfer met an error\n");
	}
}

static int test_task(int minor, int major)
{
	struct dma_config dma_cfg = { 0 };
	struct dma_block_config dma_block_cfg = { 0 };
	const struct device *dma = device_get_binding(DMA_DEVICE_NAME);

	if (!dma) {
		TC_PRINT("Cannot get dma controller\n");
		return TC_FAIL;
	}

#ifdef CONFIG_NOCACHE_MEMORY
	memcpy(tx_data, TX_DATA, sizeof(TX_DATA));
#endif

	dma_cfg.channel_direction = MEMORY_TO_MEMORY;
	dma_cfg.source_data_size = 1U;
	dma_cfg.dest_data_size = 1U;
	dma_cfg.source_burst_length = 16;
	dma_cfg.dest_burst_length = 16;
	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;
#ifdef CONFIG_DMA_MCUX_TEST_SLOT_START
	dma_cfg.dma_slot = CONFIG_DMA_MCUX_TEST_SLOT_START;
#endif

	TC_PRINT("Preparing DMA Controller: Chan_ID=%u, BURST_LEN=%u\n",
		 TEST_DMA_CHANNEL_1, 8 >> 3);

	TC_PRINT("Starting the transfer\n");
	(void)memset(rx_data, 0, sizeof(rx_data));
	(void)memset(rx_data2, 0, sizeof(rx_data2));

	dma_block_cfg.block_size = sizeof(tx_data);
	dma_block_cfg.source_address = (uint32_t)tx_data;
	dma_block_cfg.dest_address = (uint32_t)rx_data2;

	if (dma_config(dma, TEST_DMA_CHANNEL_1, &dma_cfg)) {
		TC_PRINT("ERROR: transfer\n");
		return TC_FAIL;
	}

#ifdef CONFIG_DMA_MCUX_TEST_SLOT_START
	dma_cfg.dma_slot = CONFIG_DMA_MCUX_TEST_SLOT_START + 1;
#endif

	dma_cfg.source_chaining_en = minor;
	dma_cfg.dest_chaining_en = major;
	dma_cfg.linked_channel = TEST_DMA_CHANNEL_1;

	dma_block_cfg.block_size = sizeof(tx_data);
	dma_block_cfg.source_address = (uint32_t)tx_data;
	dma_block_cfg.dest_address = (uint32_t)rx_data;

	if (dma_config(dma, TEST_DMA_CHANNEL_0, &dma_cfg)) {
		TC_PRINT("ERROR: transfer\n");
		return TC_FAIL;
	}

	if (dma_start(dma, TEST_DMA_CHANNEL_0)) {
		TC_PRINT("ERROR: transfer\n");
		return TC_FAIL;
	}
	k_sleep(K_MSEC(2000));
	TC_PRINT("%s\n", rx_data);
	TC_PRINT("%s\n", rx_data2);
	if (minor == 0 && major == 1) {
		/* major link only trigger lined channel minor loop once */
		if (strncmp(tx_data, rx_data2,
				dma_cfg.source_burst_length) != 0)
			return TC_FAIL;
	} else if (minor == 1 && major == 0) {
		/* minor link trigger linked channel except the last one*/
		if (strncmp(tx_data, rx_data2,
				dma_block_cfg.block_size - dma_cfg.source_burst_length) != 0)
			return TC_FAIL;
	} else if (minor == 1 && major == 1) {
		if (strcmp(tx_data, rx_data2) != 0)
			return TC_FAIL;
	}

	return TC_PASS;
}

/* export test cases */
void test_dma_m2m_chan0_1_major_link(void)
{
	zassert_true((test_task(0, 1) == TC_PASS), NULL);
}

void test_dma_m2m_chan0_1_minor_link(void)
{
	zassert_true((test_task(1, 0) == TC_PASS), NULL);
}

void test_dma_m2m_chan0_1_minor_major_link(void)
{
	zassert_true((test_task(1, 1) == TC_PASS), NULL);
}
