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

/**
 * @file
 * @brief Verify zephyr dma memory to memory transfer loops with scatter gather
 * @details
 * - Test Steps
 *   -# Set dma configuration for scatter gather enable
 *   -# Set direction memory-to-memory with two block transfers
 *   -# Start transfer tx -> rx
 * - Expected Results
 *   -# Data is transferred correctly from src buffers to dest buffers without
 *      software intervention.
 */

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

#define XFERS 2
#define XFER_SIZE 64

#if CONFIG_NOCACHE_MEMORY
static __aligned(32) const char TX_DATA[] = "The quick brown fox jumps over the lazy dog";
static __aligned(32) char tx_data[XFER_SIZE] __used
	__attribute__((__section__(".nocache")));
static __aligned(32) char rx_data[XFERS][XFER_SIZE] __used
	__attribute__((__section__(".nocache.dma")));
#else
/* this src memory shall be in RAM to support usingas a DMA source pointer.*/
static __aligned(32) const char tx_data[] = "The quick brown fox jumps over the lazy dog";
static __aligned(32) char rx_data[XFERS][XFER_SIZE] = { { 0 } };
#endif

K_SEM_DEFINE(xfer_sem, 0, 1);

static struct dma_config dma_cfg = {0};
static struct dma_block_config dma_block_cfgs[XFERS];

static void dma_sg_callback(const struct device *dma_dev, void *user_data,
			    uint32_t channel, int status)
{
	if (status < 0) {
		TC_PRINT("callback status %d\n", status);
	} else {
		TC_PRINT("giving xfer_sem\n");
		k_sem_give(&xfer_sem);
	}
}

static int test_sg(void)
{
	const struct device *dma;
	static int chan_id;

	TC_PRINT("DMA memory to memory transfer started\n");
	TC_PRINT("Preparing DMA Controller\n");

#if CONFIG_NOCACHE_MEMORY
	memset(tx_data, 0, sizeof(tx_data));
	memcpy(tx_data, TX_DATA, sizeof(TX_DATA));
#endif
	memset(rx_data, 0, sizeof(rx_data));

	dma = DEVICE_DT_GET(DT_ALIAS(dma0));
	if (!device_is_ready(dma)) {
		TC_PRINT("dma controller device is not ready\n");
		return TC_FAIL;
	}

	dma_cfg.channel_direction = MEMORY_TO_MEMORY;
	dma_cfg.source_data_size = 4U;
	dma_cfg.dest_data_size = 4U;
	dma_cfg.source_burst_length = 4U;
	dma_cfg.dest_burst_length = 4U;
#ifdef CONFIG_DMAMUX_STM32
	dma_cfg.user_data = (struct device *)dma;
#else
	dma_cfg.user_data = NULL;
#endif /* CONFIG_DMAMUX_STM32 */
	dma_cfg.dma_callback = dma_sg_callback;
	dma_cfg.block_count = XFERS;
	dma_cfg.head_block = dma_block_cfgs;
	dma_cfg.complete_callback_en = false; /* per block completion */

#ifdef CONFIG_DMA_MCUX_TEST_SLOT_START
	dma_cfg.dma_slot = CONFIG_DMA_MCUX_TEST_SLOT_START;
#endif

	chan_id = dma_request_channel(dma, NULL);
	if (chan_id < 0) {
		TC_PRINT("Platform does not support dma request channel,"
			 " using Kconfig DMA_SG_CHANNEL_NR\n");
		chan_id = CONFIG_DMA_SG_CHANNEL_NR;
	}

	memset(dma_block_cfgs, 0, sizeof(dma_block_cfgs));
	for (int i = 0; i < XFERS; i++) {
		dma_block_cfgs[i].source_gather_en = 1U;
		dma_block_cfgs[i].block_size = XFER_SIZE;
#ifdef CONFIG_DMA_64BIT
		dma_block_cfgs[i].source_address = (uint64_t)(tx_data);
		dma_block_cfgs[i].dest_address = (uint64_t)(rx_data[i]);
		TC_PRINT("dma block %d block_size %d, source addr %" PRIx64 ", dest addr %"
		     PRIx64 "\n", i, XFER_SIZE, dma_block_cfgs[i].source_address,
			 dma_block_cfgs[i].dest_address);
#else
		dma_block_cfgs[i].source_address = (uint32_t)(tx_data);
		dma_block_cfgs[i].dest_address = (uint32_t)(rx_data[i]);
		TC_PRINT("dma block %d block_size %d, source addr %x, dest addr %x\n",
			 i, XFER_SIZE, dma_block_cfgs[i].source_address,
			 dma_block_cfgs[i].dest_address);
#endif
		if (i < XFERS - 1) {
			dma_block_cfgs[i].next_block = &dma_block_cfgs[i+1];
			TC_PRINT("set next block pointer to %p\n", dma_block_cfgs[i].next_block);
		}
	}

	TC_PRINT("Configuring the scatter-gather transfer on channel %d\n", chan_id);

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

	TC_PRINT("Starting the transfer on channel %d and waiting completion\n", chan_id);

	if (dma_start(dma, chan_id)) {
		TC_PRINT("ERROR: transfer start (%d)\n", chan_id);
		return TC_FAIL;
	}

	if (k_sem_take(&xfer_sem, K_MSEC(1000)) != 0) {
		TC_PRINT("timed out waiting for xfers\n");
		return TC_FAIL;
	}

	TC_PRINT("Verify RX buffer should contain the full TX buffer string.\n");

	for (int i = 0; i < XFERS; i++) {
		TC_PRINT("rx_data[%d] %s\n", i, rx_data[i]);
		if (strncmp(tx_data, rx_data[i], sizeof(rx_data[i])) != 0) {
			return TC_FAIL;
		}
	}

	TC_PRINT("Finished: DMA Scatter-Gather\n");
	return TC_PASS;
}

/* export test cases */
ZTEST(dma_m2m_sg, test_dma_m2m_sg)
{
	zassert_true((test_sg() == TC_PASS));
}
