/*
 * Copyright (c) 2018 Aurelien Jarno
 * Copyright (c) 2023 Bjarki Arge Andreasen
 *
 * SPDX-License-Identifier: Apache-2.0
 */

/*
 * This driver defines a page as the erase_block_size.
 * This driver defines a write page as defined by the flash controller
 * This driver defines a section as a contiguous array of bytes
 * This driver defines an area as the entire flash area
 * This driver defines the write block size as the minimum write block size
 */

#define DT_DRV_COMPAT atmel_sam_flash_controller

#include <zephyr/kernel.h>
#include <zephyr/devicetree.h>
#include <zephyr/drivers/flash.h>
#include <zephyr/sys/barrier.h>
#include <string.h>
#include <soc.h>

#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(flash_sam, CONFIG_FLASH_LOG_LEVEL);

#define SAM_FLASH_WRITE_PAGE_SIZE (512)

typedef void (*sam_flash_irq_init_fn_ptr)(void);

struct sam_flash_config {
	Efc *regs;
	sam_flash_irq_init_fn_ptr irq_init;
	off_t area_address;
	off_t area_size;
	struct flash_parameters parameters;
	struct flash_pages_layout *pages_layouts;
	size_t pages_layouts_size;
};

struct sam_flash_erase_data {
	off_t section_start;
	size_t section_end;
	bool succeeded;
};

struct sam_flash_data {
	const struct device *dev;
	struct k_spinlock lock;
	struct sam_flash_erase_data erase_data;
	struct k_sem ready_sem;
};

static bool sam_flash_validate_offset_len(off_t offset, size_t len)
{
	if (offset < 0) {
		return false;
	}

	if ((offset + len) < len) {
		return false;
	}

	return true;
}

static bool sam_flash_aligned(size_t value, size_t alignment)
{
	return (value & (alignment - 1)) == 0;
}

static bool sam_flash_offset_is_on_write_page_boundary(off_t offset)
{
	return sam_flash_aligned(offset, SAM_FLASH_WRITE_PAGE_SIZE);
}

static inline void sam_flash_mask_ready_interrupt(const struct sam_flash_config *config)
{
	Efc *regs = config->regs;

	regs->EEFC_FMR &= ~EEFC_FMR_FRDY;
}

static inline void sam_flash_unmask_ready_interrupt(const struct sam_flash_config *config)
{
	Efc *regs = config->regs;

	regs->EEFC_FMR |= EEFC_FMR_FRDY;
}

static void sam_flash_isr(const struct device *dev)
{
	struct sam_flash_data *data = dev->data;
	const struct sam_flash_config *config = dev->config;

	sam_flash_mask_ready_interrupt(config);
	k_sem_give(&data->ready_sem);
}

static int sam_flash_section_wait_until_ready(const struct device *dev)
{
	struct sam_flash_data *data = dev->data;
	const struct sam_flash_config *config = dev->config;
	Efc *regs = config->regs;
	uint32_t eefc_fsr;

	k_sem_reset(&data->ready_sem);
	sam_flash_unmask_ready_interrupt(config);

	if (k_sem_take(&data->ready_sem, K_MSEC(500)) < 0) {
		LOG_ERR("Command did not execute in time");
		return -EFAULT;
	}

	/* FSR register is cleared on read */
	eefc_fsr = regs->EEFC_FSR;

	if (eefc_fsr & EEFC_FSR_FCMDE) {
		LOG_ERR("Invalid command requested");
		return -EPERM;
	}

	if (eefc_fsr & EEFC_FSR_FLOCKE) {
		LOG_ERR("Tried to modify locked region");
		return -EPERM;
	}

	if (eefc_fsr & EEFC_FSR_FLERR) {
		LOG_ERR("Programming failed");
		return -EPERM;
	}

	return 0;
}

static bool sam_flash_section_is_within_area(const struct device *dev, off_t offset, size_t len)
{
	const struct sam_flash_config *config = dev->config;

	if ((offset + ((off_t)len)) < offset) {
		return false;
	}

	if ((offset >= 0) && ((offset + len) <= config->area_size)) {
		return true;
	}

	LOG_WRN("Section from 0x%x to 0x%x is not within flash area (0x0 to %x)",
		(size_t)offset, (size_t)(offset + len), (size_t)config->area_size);

	return false;
}

static bool sam_flash_section_is_aligned_with_write_block_size(const struct device *dev,
							       off_t offset, size_t len)
{
	const struct sam_flash_config *config = dev->config;

	if (sam_flash_aligned(offset, config->parameters.write_block_size) &&
	    sam_flash_aligned(len, config->parameters.write_block_size)) {
		return true;
	}

	LOG_WRN("Section from 0x%x to 0x%x is not aligned with write block size (%u)",
		(size_t)offset, (size_t)(offset + len), config->parameters.write_block_size);

	return false;
}

static bool sam_flash_section_is_aligned_with_pages(const struct device *dev, off_t offset,
						    size_t len)
{
	const struct sam_flash_config *config = dev->config;
	struct flash_pages_info pages_info;

	/* Get the page offset points to */
	if (flash_get_page_info_by_offs(dev, offset, &pages_info) < 0) {
		return false;
	}

	/* Validate offset points to start of page */
	if (offset != pages_info.start_offset) {
		return false;
	}

	/* Check if end of section is aligned with end of area */
	if ((offset + len) == (config->area_size)) {
		return true;
	}

	/* Get the page pointed to by end of section */
	if (flash_get_page_info_by_offs(dev, offset + len, &pages_info) < 0) {
		return false;
	}

	/* Validate offset points to start of page */
	if ((offset + len) != pages_info.start_offset) {
		return false;
	}

	return true;
}

static int sam_flash_read(const struct device *dev, off_t offset, void *data, size_t len)
{
	struct sam_flash_data *sam_data = dev->data;
	const struct sam_flash_config *sam_config = dev->config;
	k_spinlock_key_t key;

	if (len == 0) {
		return 0;
	}

	if (!sam_flash_validate_offset_len(offset, len)) {
		return -EINVAL;
	}

	if (!sam_flash_section_is_within_area(dev, offset, len)) {
		return -EINVAL;
	}

	key = k_spin_lock(&sam_data->lock);
	memcpy(data, (uint8_t *)(sam_config->area_address + offset), len);
	k_spin_unlock(&sam_data->lock, key);
	return 0;
}

static int sam_flash_write_latch_buffer_to_page(const struct device *dev, off_t offset)
{
	const struct sam_flash_config *sam_config = dev->config;
	Efc *regs = sam_config->regs;
	uint32_t page = offset / SAM_FLASH_WRITE_PAGE_SIZE;

	regs->EEFC_FCR = EEFC_FCR_FCMD_WP | EEFC_FCR_FARG(page) | EEFC_FCR_FKEY_PASSWD;
	sam_flash_section_wait_until_ready(dev);
	return 0;
}

static int sam_flash_write_latch_buffer_to_previous_page(const struct device *dev, off_t offset)
{
	return sam_flash_write_latch_buffer_to_page(dev, offset - SAM_FLASH_WRITE_PAGE_SIZE);
}

static void sam_flash_write_dword_to_latch_buffer(off_t offset, uint32_t dword)
{
	*((uint32_t *)offset) = dword;
	barrier_dsync_fence_full();
}

static int sam_flash_write_dwords_to_flash(const struct device *dev, off_t offset,
					   const uint32_t *dwords, size_t size)
{
	for (size_t i = 0; i < size; i++) {
		sam_flash_write_dword_to_latch_buffer(offset, dwords[i]);
		offset += sizeof(uint32_t);
		if (sam_flash_offset_is_on_write_page_boundary(offset)) {
			sam_flash_write_latch_buffer_to_previous_page(dev, offset);
		}
	}

	if (!sam_flash_offset_is_on_write_page_boundary(offset)) {
		sam_flash_write_latch_buffer_to_page(dev, offset);
	}

	return 0;
}

static int sam_flash_write(const struct device *dev, off_t offset, const void *data, size_t len)
{
	struct sam_flash_data *sam_data = dev->data;
	k_spinlock_key_t key;

	if (len == 0) {
		return 0;
	}

	if (!sam_flash_validate_offset_len(offset, len)) {
		return -EINVAL;
	}

	if (!sam_flash_section_is_aligned_with_write_block_size(dev, offset, len)) {
		return -EINVAL;
	}

	LOG_DBG("Writing sector from 0x%x to 0x%x", (size_t)offset, (size_t)(offset + len));

	key = k_spin_lock(&sam_data->lock);
	if (sam_flash_write_dwords_to_flash(dev, offset, data, len / sizeof(uint32_t)) < 0) {
		k_spin_unlock(&sam_data->lock, key);
		return -EAGAIN;
	}

	k_spin_unlock(&sam_data->lock, key);
	return 0;
}

static int sam_flash_unlock_write_page(const struct device *dev, uint16_t page_index)
{
	const struct sam_flash_config *sam_config = dev->config;
	Efc *regs = sam_config->regs;

	/* Perform unlock command of write page */
	regs->EEFC_FCR = EEFC_FCR_FCMD_CLB
		       | EEFC_FCR_FARG(page_index)
		       | EEFC_FCR_FKEY_PASSWD;

	return sam_flash_section_wait_until_ready(dev);
}

static int sam_flash_unlock_page(const struct device *dev, const struct flash_pages_info *info)
{
	uint16_t page_index_start;
	uint16_t page_index_end;
	int ret;

	/* Convert from page offset and size to write page index and count */
	page_index_start = info->start_offset / SAM_FLASH_WRITE_PAGE_SIZE;
	page_index_end = page_index_start + (info->size / SAM_FLASH_WRITE_PAGE_SIZE);

	for (uint16_t i = page_index_start; i < page_index_end; i++) {
		ret = sam_flash_unlock_write_page(dev, i);
		if (ret < 0) {
			return ret;
		}
	}

	return 0;
}

static int sam_flash_erase_page(const struct device *dev, const struct flash_pages_info *info)
{
	const struct sam_flash_config *sam_config = dev->config;
	Efc *regs = sam_config->regs;
	uint32_t page_index;
	int ret;

	/* Convert from page offset to write page index */
	page_index = info->start_offset / SAM_FLASH_WRITE_PAGE_SIZE;

	LOG_DBG("Erasing page at 0x%x of size 0x%x", (size_t)info->start_offset, info->size);

	/* Perform erase command of page */
	switch (info->size) {
	case 0x800:
		regs->EEFC_FCR = EEFC_FCR_FCMD_EPA
			       | EEFC_FCR_FARG(page_index)
			       | EEFC_FCR_FKEY_PASSWD;
		break;

	case 0x1000:
		regs->EEFC_FCR = EEFC_FCR_FCMD_EPA
			       | EEFC_FCR_FARG(page_index | 1)
			       | EEFC_FCR_FKEY_PASSWD;
		break;

	case 0x2000:
		regs->EEFC_FCR = EEFC_FCR_FCMD_EPA
			       | EEFC_FCR_FARG(page_index | 2)
			       | EEFC_FCR_FKEY_PASSWD;
		break;

	case 0x4000:
		regs->EEFC_FCR = EEFC_FCR_FCMD_EPA
			       | EEFC_FCR_FARG(page_index | 3)
			       | EEFC_FCR_FKEY_PASSWD;
		break;

	default:
		return -EINVAL;
	}

	ret = sam_flash_section_wait_until_ready(dev);
	if (ret == 0) {
		return ret;
	}

	LOG_ERR("Failed to erase page at 0x%x of size 0x%x", (size_t)info->start_offset,
		info->size);

	return ret;
}

static bool sam_flash_erase_foreach_page(const struct flash_pages_info *info, void *data)
{
	struct sam_flash_data *sam_data = data;
	const struct device *dev = sam_data->dev;
	struct sam_flash_erase_data *erase_data = &sam_data->erase_data;

	/* Validate we reached first page to erase */
	if (info->start_offset < erase_data->section_start) {
		/* Next page */
		return true;
	}

	/* Check if we've reached the end of pages to erase */
	if (info->start_offset >= erase_data->section_end) {
		/* Succeeded, stop iterating */
		erase_data->succeeded = true;
		return false;
	}

	if (sam_flash_unlock_page(dev, info) < 0) {
		/* Failed to unlock page, stop iterating */
		return false;
	}

	if (sam_flash_erase_page(dev, info) < 0) {
		/* Failed to erase page, stop iterating */
		return false;
	}

	/* Next page */
	return true;
}

static int sam_flash_erase(const struct device *dev, off_t offset, size_t size)
{
	struct sam_flash_data *sam_data = dev->data;
	k_spinlock_key_t key;

	if (size == 0) {
		return 0;
	}

	if (!sam_flash_validate_offset_len(offset, size)) {
		return -EINVAL;
	}

	if (!sam_flash_section_is_aligned_with_pages(dev, offset, size)) {
		return -EINVAL;
	}

	LOG_DBG("Erasing sector from 0x%x to 0x%x", (size_t)offset, (size_t)(offset + size));

	key = k_spin_lock(&sam_data->lock);
	sam_data->erase_data.section_start = offset;
	sam_data->erase_data.section_end = offset + size;
	sam_data->erase_data.succeeded = false;
	flash_page_foreach(dev, sam_flash_erase_foreach_page, sam_data);
	if (!sam_data->erase_data.succeeded) {
		k_spin_unlock(&sam_data->lock, key);
		return -EFAULT;
	}

	k_spin_unlock(&sam_data->lock, key);
	return 0;
}

static const struct flash_parameters *sam_flash_get_parameters(const struct device *dev)
{
	const struct sam_flash_config *config = dev->config;

	return &config->parameters;
}

static void sam_flash_api_pages_layout(const struct device *dev,
				       const struct flash_pages_layout **layout,
				       size_t *layout_size)
{
	const struct sam_flash_config *config = dev->config;

	*layout = config->pages_layouts;
	*layout_size = config->pages_layouts_size;
}

static struct flash_driver_api sam_flash_api = {
	.read = sam_flash_read,
	.write = sam_flash_write,
	.erase = sam_flash_erase,
	.get_parameters = sam_flash_get_parameters,
	.page_layout = sam_flash_api_pages_layout,
};

static int sam_flash_init(const struct device *dev)
{
	struct sam_flash_data *sam_data = dev->data;
	const struct sam_flash_config *sam_config = dev->config;

	sam_data->dev = dev;
	k_sem_init(&sam_data->ready_sem, 0, 1);
	sam_flash_mask_ready_interrupt(sam_config);
	sam_config->irq_init();
	return 0;
}

#define SAM_FLASH_DEVICE DT_INST(0, atmel_sam_flash)

#define SAM_FLASH_PAGES_LAYOUT(node_id, prop, idx)						\
	{											\
		.pages_count = DT_PHA_BY_IDX(node_id, prop, idx, pages_count),			\
		.pages_size = DT_PHA_BY_IDX(node_id, prop, idx, pages_size),			\
	}

#define SAM_FLASH_PAGES_LAYOUTS									\
	DT_FOREACH_PROP_ELEM_SEP(SAM_FLASH_DEVICE, erase_blocks, SAM_FLASH_PAGES_LAYOUT, (,))

#define SAM_FLASH_CONTROLLER(inst)								\
	struct flash_pages_layout sam_flash_pages_layouts##inst[] = {				\
		SAM_FLASH_PAGES_LAYOUTS								\
	};											\
												\
	static void sam_flash_irq_init_##inst(void)						\
	{											\
		IRQ_CONNECT(DT_INST_IRQN(inst), DT_INST_IRQ(inst, priority),			\
			    sam_flash_isr, DEVICE_DT_INST_GET(inst), 0);			\
		irq_enable(DT_INST_IRQN(inst));							\
												\
	}											\
												\
	static const struct sam_flash_config sam_flash_config##inst = {				\
		.regs = (Efc *)DT_INST_REG_ADDR(inst),						\
		.irq_init = sam_flash_irq_init_##inst,						\
		.area_address = DT_REG_ADDR(SAM_FLASH_DEVICE),					\
		.area_size = DT_REG_SIZE(SAM_FLASH_DEVICE),					\
		.parameters = {									\
			.write_block_size = DT_PROP(SAM_FLASH_DEVICE, write_block_size),	\
			.erase_value = 0xFF,							\
		},										\
		.pages_layouts = sam_flash_pages_layouts##inst,					\
		.pages_layouts_size = ARRAY_SIZE(sam_flash_pages_layouts##inst),		\
	};											\
												\
	static struct sam_flash_data sam_flash_data##inst;					\
												\
	DEVICE_DT_INST_DEFINE(inst, sam_flash_init, NULL, &sam_flash_data##inst,		\
			      &sam_flash_config##inst, POST_KERNEL, CONFIG_FLASH_INIT_PRIORITY,	\
			      &sam_flash_api);

SAM_FLASH_CONTROLLER(0)
