/*
 * Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr.h>
#include <ztest.h>
#include <devicetree.h>
#include <sys/printk.h>
#include <drivers/flash.h>
#include <random/rand32.h>
#include <soc/soc_memory_layout.h>

/* definitions used in Flash & RAM operations */
#define SPIRAM_ALLOC_SIZE               (24 * 1024)
#define FLASH_PAGE_TESTED               (1023)
#define FLASH_PAGE_OFFSET               (0)
#define FLASH_BYTE_PATTERN              (0x38)
#define FLASH_READBACK_LEN              (1024)
#define FLASH_ITERATIONS                (10)
#define PSRAM_ITERATIONS                (10)

/* common thread definitions */
#define STACKSIZE 1024
#define PRIORITY 7

static const struct device *flash_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_flash_controller));
static struct flash_pages_info page_info;
static int *mem;
uint8_t flash_fill_buff[FLASH_READBACK_LEN];
uint8_t flash_read_buff[FLASH_READBACK_LEN];

static uint8_t flash_val = FLASH_BYTE_PATTERN;
static bool buffer_ready;
static bool needs_fill = true;
static bool unfinished_tasks = true;
static struct k_spinlock lock;

struct coex_test_results {
	bool using_ext_ram;
	int flash_cnt;
	bool psram_ok;
};
static struct coex_test_results coex_result;

static void buffer_fill(void)
{
	while (needs_fill) {
		if (!buffer_ready) {
			k_spinlock_key_t key = k_spin_lock(&lock);

			memset(flash_fill_buff, ++flash_val, sizeof(flash_fill_buff));
			buffer_ready = true;
			k_spin_unlock(&lock, key);
		}
		k_usleep(10);
	}
	while (true) {
		k_usleep(1);
	}
}

static void check_flash(void)
{
	int cnt = 0;

	for (size_t i = 0; i < sizeof(flash_read_buff); ++i) {
		if (flash_read_buff[i] == (FLASH_BYTE_PATTERN + FLASH_ITERATIONS)) {
			++cnt;
		}
	}
	coex_result.flash_cnt = cnt;
	unfinished_tasks = false;
}

static int do_erase(off_t offset, size_t size)
{
	int rc;

	rc = flash_erase(flash_dev, offset, size);
	if (rc) {
		TC_ERROR("flash erase has failed\n");
		return rc;
	}

	return rc;
}

static int page_erase(void)
{
	int rc;

	rc = flash_get_page_info_by_idx(flash_dev, FLASH_PAGE_TESTED, &page_info);
	if (rc) {
		return rc;
	}

	rc = do_erase(page_info.start_offset, page_info.size);
	if (rc) {
		return rc;
	}

	return rc;
}

static int page_read(void)
{
	int rc = flash_get_page_info_by_idx(flash_dev, FLASH_PAGE_TESTED, &page_info);

	if (rc) {
		TC_ERROR("could not read flash info\n");
		return rc;
	}
	rc = flash_read(flash_dev,
			page_info.start_offset + FLASH_PAGE_OFFSET,
			flash_read_buff,
			sizeof(flash_read_buff));
	if (rc) {
		TC_ERROR("flash read back has failed\n");
		return rc;
	}

	return 0;
}

static int page_write(void)
{
	int rc = flash_get_page_info_by_idx(flash_dev, FLASH_PAGE_TESTED, &page_info);

	if (rc) {
		TC_ERROR("could not retrieve flash info\n");
		return rc;
	}

	rc = flash_write(flash_dev,
			page_info.start_offset + FLASH_PAGE_OFFSET,
			flash_fill_buff,
			sizeof(flash_fill_buff));
	if (rc) {
		TC_ERROR("could not write to flash\n");
		return rc;
	}

	return 0;
}

static bool do_flashop(void)
{
	int rc = page_write();

	if (rc) {
		return false;
	}

	return true;
}

static void fill_value(int value)
{
	int i;

	/* fills external RAM with given value */
	for (i = 0; i < (SPIRAM_ALLOC_SIZE / sizeof(int)); ++i) {
		mem[i] = value;
	}
}

static bool check_psram(int value)
{
	int *ptr = mem;

	/* checks if external RAM is filled with the expected value */
	for (size_t i = 0; i < (SPIRAM_ALLOC_SIZE / sizeof(int)); ++i) {
		if (*ptr++ != value) {
			return false;
		}
	}
	return true;
}

void psram_test(void)
{
	uint32_t sleep_ms = 10;
	int rand_val;

	for (size_t i = 0; i < PSRAM_ITERATIONS; ++i) {
		rand_val = (int)sys_rand32_get();
		fill_value(rand_val);
		k_msleep(sleep_ms);
	}
	if (check_psram(rand_val)) {
		coex_result.psram_ok = true;
	} else {
		coex_result.psram_ok = false;
	}
	while (true) {
		k_usleep(1);
	}
}

void psram_init(void)
{
	mem = k_malloc(SPIRAM_ALLOC_SIZE);
	if (!mem) {
		TC_ERROR("SPIRAM allocation has failed\n");
	}

	if (!esp_ptr_external_ram(mem)) {
		coex_result.using_ext_ram = false;
		TC_ERROR("allocation is not within specified bounds\n");
		return;
	}

	coex_result.using_ext_ram = true;
	psram_test();
}

void flash_test(void)
{
	uint32_t sleep_ms = 15;

	for (size_t i = 0; i < FLASH_ITERATIONS; ++i) {
		page_erase();
		if (buffer_ready) {
			k_spinlock_key_t key = k_spin_lock(&lock);

			do_flashop();
			buffer_ready = false;
			k_spin_unlock(&lock, key);
		}
		k_msleep(sleep_ms);
	}
	needs_fill = false;
	page_read();
	check_flash();
	while (true) {
		k_usleep(1);
	}
}

void flash_init(void)
{
	if (!device_is_ready(flash_dev)) {
		TC_ERROR("flash controller not ready\n");
	}
	flash_test();
}

void test_using_spiram(void)
{
	zassert_equal(true, coex_result.using_ext_ram, "external RAM is not being used");
}

void test_flash_integrity(void)
{
	zassert_equal(FLASH_READBACK_LEN, coex_result.flash_cnt, "flash integrity test failed");
}

void test_ram_integrity(void)
{
	zassert_equal(true, coex_result.psram_ok, "SPIRAM integrity test failed");
}

void test_main(void)
{
	while (unfinished_tasks) {
		k_usleep(1);
	}

	ztest_test_suite(cache_coex_test,
			ztest_unit_test(test_using_spiram),
			ztest_unit_test(test_flash_integrity),
			ztest_unit_test(test_ram_integrity)
	);

	ztest_run_test_suite(cache_coex_test);
}

K_THREAD_DEFINE(psram_id, STACKSIZE, psram_init, NULL, NULL, NULL, PRIORITY, 0, 0);
K_THREAD_DEFINE(flash_id, STACKSIZE, flash_init, NULL, NULL, NULL, PRIORITY, 0, 0);
K_THREAD_DEFINE(buffer_id, STACKSIZE, buffer_fill, NULL, NULL, NULL, PRIORITY, 0, 0);
