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

/*
 * This driver is written based on the Altera's
 * Nios-II QSPI Controller HAL driver.
 */

#define DT_DRV_COMPAT altr_nios2_qspi_nor

#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <string.h>
#include <zephyr/drivers/flash.h>
#include <errno.h>
#include <zephyr/init.h>
#include <soc.h>
#include <zephyr/sys/util.h>
#include "flash_priv.h"
#include "altera_generic_quad_spi_controller2_regs.h"
#include "altera_generic_quad_spi_controller2.h"

#define LOG_LEVEL CONFIG_FLASH_LOG_LEVEL
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(flash_nios2_qspi);

/*
 * Remove the following macros once the Altera HAL
 * supports the QSPI Controller v2 IP.
 */
#define ALTERA_QSPI_CONTROLLER2_FLAG_STATUS_REG		0x0000001C
#define FLAG_STATUS_PROTECTION_ERROR			(1 << 1)
#define FLAG_STATUS_PROGRAM_SUSPENDED			(1 << 2)
#define FLAG_STATUS_PROGRAM_ERROR			(1 << 4)
#define FLAG_STATUS_ERASE_ERROR				(1 << 5)
#define FLAG_STATUS_ERASE_SUSPENDED			(1 << 6)
#define FLAG_STATUS_CONTROLLER_READY			(1 << 7)

/* ALTERA_QSPI_CONTROLLER2_STATUS_REG bits */
#define STATUS_PROTECTION_POS				2
#define STATUS_PROTECTION_MASK				0x1F
#define STATUS_PROTECTION_EN_VAL			0x17
#define STATUS_PROTECTION_DIS_VAL			0x0

/* ALTERA_QSPI_CONTROLLER2_MEM_OP_REG bits */
#define MEM_OP_ERASE_CMD				0x00000002
#define MEM_OP_WRITE_EN_CMD				0x00000004
#define MEM_OP_SECTOR_OFFSET_BIT_POS			8
#define MEM_OP_UNLOCK_ALL_SECTORS			0x00000003
#define MEM_OP_LOCK_ALL_SECTORS				0x00000F03

#define NIOS2_QSPI_BLANK_WORD				0xFFFFFFFF

#define NIOS2_WRITE_BLOCK_SIZE				4

#define USEC_TO_MSEC(x)					(x / 1000)

struct flash_nios2_qspi_config {
	alt_qspi_controller2_dev qspi_dev;
	struct k_sem sem_lock;
};

static const struct flash_parameters flash_nios2_qspi_parameters = {
	.write_block_size = NIOS2_WRITE_BLOCK_SIZE,
	.erase_value = 0xff,
};

static int flash_nios2_qspi_write_protection(const struct device *dev,
					     bool enable);

static int flash_nios2_qspi_erase(const struct device *dev, off_t offset,
				  size_t len)
{
	struct flash_nios2_qspi_config *flash_cfg = dev->data;
	alt_qspi_controller2_dev *qspi_dev = &flash_cfg->qspi_dev;
	uint32_t block_offset, offset_in_block, length_to_erase;
	uint32_t erase_offset = offset; /* address of next byte to erase */
	uint32_t remaining_length = len; /* length of data left to be erased */
	uint32_t flag_status;
	int32_t rc = 0, i, timeout, rc2;

	k_sem_take(&flash_cfg->sem_lock, K_FOREVER);

	rc = flash_nios2_qspi_write_protection(dev, false);
	if (rc) {
		goto qspi_erase_err;
	}
	/*
	 * check if offset is word aligned and
	 * length is with in the range
	 */
	if (((offset + len) > qspi_dev->data_end) ||
			(0 != (erase_offset &
			       (NIOS2_WRITE_BLOCK_SIZE - 1)))) {
		LOG_ERR("erase failed at offset 0x%lx", (long)offset);
		rc = -EINVAL;
		goto qspi_erase_err;
	}

	for (i = offset/qspi_dev->sector_size;
			i < qspi_dev->number_of_sectors; i++) {

		if ((remaining_length <= 0U) ||
				erase_offset >= (offset + len)) {
			break;
		}

		block_offset = 0U; /* block offset in byte addressing */
		offset_in_block = 0U; /* offset into current sector to erase */
		length_to_erase = 0U; /* length to erase in current sector */

		/* calculate current sector/block offset in byte addressing */
		block_offset = erase_offset & ~(qspi_dev->sector_size - 1);

		/* calculate offset into sector/block if there is one */
		if (block_offset != erase_offset) {
			offset_in_block = erase_offset - block_offset;
		}

		/* calculate the byte size of data to be written in a sector */
		length_to_erase = MIN(qspi_dev->sector_size - offset_in_block,
							remaining_length);

		/* Erase sector */
		IOWR_32DIRECT(qspi_dev->csr_base,
				ALTERA_QSPI_CONTROLLER2_MEM_OP_REG,
				MEM_OP_WRITE_EN_CMD);
		IOWR_32DIRECT(qspi_dev->csr_base,
				ALTERA_QSPI_CONTROLLER2_MEM_OP_REG,
				(i << MEM_OP_SECTOR_OFFSET_BIT_POS)
				| MEM_OP_ERASE_CMD);

		/*
		 * poll the status register to know the
		 * completion of the erase operation.
		 */
		timeout = ALTERA_QSPI_CONTROLLER2_1US_TIMEOUT_VALUE;
		while (timeout > 0) {
			/* wait for 1 usec */
			k_busy_wait(1);

			flag_status = IORD_32DIRECT(qspi_dev->csr_base,
				ALTERA_QSPI_CONTROLLER2_FLAG_STATUS_REG);

			if (flag_status & FLAG_STATUS_CONTROLLER_READY) {
				break;
			}

			timeout--;
		}

		if ((flag_status & FLAG_STATUS_ERASE_ERROR) ||
				(flag_status & FLAG_STATUS_PROTECTION_ERROR)) {
			LOG_ERR("erase failed, Flag Status Reg:0x%x",
								flag_status);
			rc = -EIO;
			goto qspi_erase_err;
		}

		/* update remaining length and erase_offset */
		remaining_length -= length_to_erase;
		erase_offset += length_to_erase;
	}

qspi_erase_err:
	rc2 = flash_nios2_qspi_write_protection(dev, true);

	if (!rc) {
		rc = rc2;
	}

	k_sem_give(&flash_cfg->sem_lock);
	return rc;

}

static int flash_nios2_qspi_write_block(const struct device *dev,
					int block_offset,
					int mem_offset, const void *data,
					size_t len)
{
	struct flash_nios2_qspi_config *flash_cfg = dev->data;
	alt_qspi_controller2_dev *qspi_dev = &flash_cfg->qspi_dev;
	uint32_t buffer_offset = 0U; /* offset into data buffer to get write data */
	int32_t remaining_length = len; /* length left to write */
	uint32_t write_offset = mem_offset; /* offset into flash to write too */
	uint32_t word_to_write, padding, bytes_to_copy;
	uint32_t flag_status;
	int32_t rc = 0;

	while (remaining_length > 0) {
		/* initialize word to write to blank word */
		word_to_write = NIOS2_QSPI_BLANK_WORD;

		/* bytes to pad the next word that is written */
		padding = 0U;

		/* number of bytes from source to copy */
		bytes_to_copy = NIOS2_WRITE_BLOCK_SIZE;

		/*
		 * we need to make sure the write is word aligned
		 * this should only be true at most 1 time
		 */
		if (0 != (write_offset & (NIOS2_WRITE_BLOCK_SIZE - 1))) {
			/*
			 * data is not word aligned calculate padding bytes
			 * need to add before start of a data offset
			 */
			padding = write_offset & (NIOS2_WRITE_BLOCK_SIZE - 1);

			/*
			 * update variables to account
			 * for padding being added
			 */
			bytes_to_copy -= padding;

			if (bytes_to_copy > remaining_length) {
				bytes_to_copy = remaining_length;
			}

			write_offset = write_offset - padding;

			if (0 != (write_offset &
					(NIOS2_WRITE_BLOCK_SIZE - 1))) {
				rc = -EINVAL;
				goto qspi_write_block_err;
			}
		} else {
			if (bytes_to_copy > remaining_length) {
				bytes_to_copy = remaining_length;
			}
		}

		/* Check memcpy length is within NIOS2_WRITE_BLOCK_SIZE */
		if (padding + bytes_to_copy > NIOS2_WRITE_BLOCK_SIZE) {
			rc = -EINVAL;
			goto qspi_write_block_err;
		}

		/* prepare the word to be written */
		memcpy((uint8_t *)&word_to_write + padding,
				(const uint8_t *)data + buffer_offset,
				bytes_to_copy);

		/* enable write */
		IOWR_32DIRECT(qspi_dev->csr_base,
				ALTERA_QSPI_CONTROLLER2_MEM_OP_REG,
				MEM_OP_WRITE_EN_CMD);

		/* write to flash 32 bits at a time */
		IOWR_32DIRECT(qspi_dev->data_base, write_offset, word_to_write);

		/* check whether write operation is successful */
		flag_status = IORD_32DIRECT(qspi_dev->csr_base,
				ALTERA_QSPI_CONTROLLER2_FLAG_STATUS_REG);

		if ((flag_status & FLAG_STATUS_PROGRAM_ERROR) ||
			(flag_status & FLAG_STATUS_PROTECTION_ERROR)) {
			LOG_ERR("write failed, Flag Status Reg:0x%x",
								flag_status);
			rc = -EIO; /* sector might be protected */
			goto qspi_write_block_err;
		}

		/* update offset and length variables */
		buffer_offset += bytes_to_copy;
		remaining_length -= bytes_to_copy;
		write_offset = write_offset + NIOS2_WRITE_BLOCK_SIZE;
	}

qspi_write_block_err:
	return rc;
}

static int flash_nios2_qspi_write(const struct device *dev, off_t offset,
				  const void *data, size_t len)
{
	struct flash_nios2_qspi_config *flash_cfg = dev->data;
	alt_qspi_controller2_dev *qspi_dev = &flash_cfg->qspi_dev;
	uint32_t block_offset, offset_in_block, length_to_write;
	uint32_t write_offset = offset; /* address of next byte to write */
	uint32_t buffer_offset = 0U; /* offset into source buffer */
	uint32_t remaining_length = len; /* length of data left to be written */
	int32_t rc = 0, i, rc2;

	k_sem_take(&flash_cfg->sem_lock, K_FOREVER);

	rc = flash_nios2_qspi_write_protection(dev, false);
	if (rc) {
		goto qspi_write_err;
	}
	/*
	 * check if offset is word aligned and
	 * length is with in the range
	 */
	if ((data == NULL) || ((offset + len) > qspi_dev->data_end) ||
			(0 != (write_offset &
			       (NIOS2_WRITE_BLOCK_SIZE - 1)))) {
		LOG_ERR("write failed at offset 0x%lx", (long)offset);
		rc = -EINVAL;
		goto qspi_write_err;
	}

	for (i = offset/qspi_dev->sector_size;
			i < qspi_dev->number_of_sectors; i++) {

		if (remaining_length <= 0U) {
			break;
		}

		block_offset = 0U; /* block offset in byte addressing */
		offset_in_block = 0U; /* offset into current sector to write */
		length_to_write = 0U; /* length to write to current sector */

		/* calculate current sector/block offset in byte addressing */
		block_offset = write_offset & ~(qspi_dev->sector_size - 1);

		/* calculate offset into sector/block if there is one */
		if (block_offset != write_offset) {
			offset_in_block = write_offset - block_offset;
		}

		/* calculate the byte size of data to be written in a sector */
		length_to_write = MIN(qspi_dev->sector_size - offset_in_block,
							remaining_length);

		rc = flash_nios2_qspi_write_block(dev,
				block_offset, write_offset,
				(const uint8_t *)data + buffer_offset,
				length_to_write);
		if (rc < 0) {
			goto qspi_write_err;
		}

		/* update remaining length and buffer_offset */
		remaining_length -= length_to_write;
		buffer_offset += length_to_write;
		write_offset += length_to_write;
	}

qspi_write_err:
	rc2 = flash_nios2_qspi_write_protection(dev, true);

	if (!rc) {
		rc = rc2;
	}

	k_sem_give(&flash_cfg->sem_lock);
	return rc;
}

static int flash_nios2_qspi_read(const struct device *dev, off_t offset,
				 void *data, size_t len)
{
	struct flash_nios2_qspi_config *flash_cfg = dev->data;
	alt_qspi_controller2_dev *qspi_dev = &flash_cfg->qspi_dev;
	uint32_t buffer_offset = 0U; /* offset into data buffer to get read data */
	uint32_t remaining_length = len; /* length left to read */
	uint32_t read_offset = offset; /* offset into flash to read from */
	uint32_t word_to_read, bytes_to_copy;
	int32_t rc = 0;

	/*
	 * check if offset and length are within the range
	 */
	if ((data == NULL) || (offset < qspi_dev->data_base) ||
	    ((offset + len) > qspi_dev->data_end)) {
		LOG_ERR("read failed at offset 0x%lx", (long)offset);
		return -EINVAL;
	}

	if (!len) {
		return 0;
	}

	k_sem_take(&flash_cfg->sem_lock, K_FOREVER);

	/* first unaligned start */
	read_offset &= ~(NIOS2_WRITE_BLOCK_SIZE - 1U);
	if (offset > read_offset) {
		/* number of bytes from source to copy */
		bytes_to_copy = NIOS2_WRITE_BLOCK_SIZE - (offset - read_offset);
		if (bytes_to_copy > remaining_length) {
			bytes_to_copy = remaining_length;
		}
		/* read from flash 32 bits at a time */
		word_to_read = IORD_32DIRECT(qspi_dev->data_base, read_offset);
		memcpy((uint8_t *)data, (uint8_t *)&word_to_read + offset -
		       read_offset, bytes_to_copy);
		/* update offset and length variables */
		read_offset += NIOS2_WRITE_BLOCK_SIZE;
		buffer_offset += bytes_to_copy;
		remaining_length -= bytes_to_copy;
	}

	/* aligned part, including unaligned end */
	while (remaining_length > 0) {
		/* number of bytes from source to copy */
		bytes_to_copy = NIOS2_WRITE_BLOCK_SIZE;

		if (bytes_to_copy > remaining_length) {
			bytes_to_copy = remaining_length;
		}

		/* read from flash 32 bits at a time */
		word_to_read = IORD_32DIRECT(qspi_dev->data_base, read_offset);
		memcpy((uint8_t *)data + buffer_offset, &word_to_read,
		       bytes_to_copy);
		/* update offset and length variables */
		read_offset += bytes_to_copy;
		buffer_offset += bytes_to_copy;
		remaining_length -= bytes_to_copy;
	}

	k_sem_give(&flash_cfg->sem_lock);
	return rc;
}

static int flash_nios2_qspi_write_protection(const struct device *dev,
					     bool enable)
{
	struct flash_nios2_qspi_config *flash_cfg = dev->data;
	alt_qspi_controller2_dev *qspi_dev = &flash_cfg->qspi_dev;
	uint32_t status, lock_val;
	int32_t rc = 0, timeout;

	/* set write enable */
	IOWR_32DIRECT(qspi_dev->csr_base,
			ALTERA_QSPI_CONTROLLER2_MEM_OP_REG,
			MEM_OP_WRITE_EN_CMD);
	if (enable) {
		IOWR_32DIRECT(qspi_dev->csr_base,
				ALTERA_QSPI_CONTROLLER2_MEM_OP_REG,
				MEM_OP_LOCK_ALL_SECTORS);
		lock_val = STATUS_PROTECTION_EN_VAL;
	} else {
		IOWR_32DIRECT(qspi_dev->csr_base,
				ALTERA_QSPI_CONTROLLER2_MEM_OP_REG,
				MEM_OP_UNLOCK_ALL_SECTORS);
		lock_val = STATUS_PROTECTION_DIS_VAL;
	}

	/*
	 * poll the status register to know the
	 * completion of the erase operation.
	 */
	timeout = ALTERA_QSPI_CONTROLLER2_1US_TIMEOUT_VALUE;
	while (timeout > 0) {
		/* wait for 1 usec */
		k_busy_wait(1);

		/*
		 * read flash flag status register before
		 * checking the QSPI status
		 */
		IORD_32DIRECT(qspi_dev->csr_base,
				ALTERA_QSPI_CONTROLLER2_FLAG_STATUS_REG);

		/* read QPSI status register */
		status = IORD_32DIRECT(qspi_dev->csr_base,
				ALTERA_QSPI_CONTROLLER2_STATUS_REG);
		if (((status >> STATUS_PROTECTION_POS) &
			STATUS_PROTECTION_MASK) == lock_val) {
			break;
		}

		timeout--;
	}

	if (timeout <= 0) {
		LOG_ERR("locking failed, status-reg 0x%x", status);
		rc = -EIO;
	}

	/* clear flag status register */
	IOWR_32DIRECT(qspi_dev->csr_base,
			ALTERA_QSPI_CONTROLLER2_FLAG_STATUS_REG, 0x0);
	return rc;
}

static const struct flash_parameters *
flash_nios2_qspi_get_parameters(const struct device *dev)
{
	ARG_UNUSED(dev);

	return &flash_nios2_qspi_parameters;
}

static const struct flash_driver_api flash_nios2_qspi_api = {
	.erase = flash_nios2_qspi_erase,
	.write = flash_nios2_qspi_write,
	.read = flash_nios2_qspi_read,
	.get_parameters = flash_nios2_qspi_get_parameters,
#if defined(CONFIG_FLASH_PAGE_LAYOUT)
	.page_layout = (flash_api_pages_layout)
		       flash_page_layout_not_implemented,
#endif
};

static int flash_nios2_qspi_init(const struct device *dev)
{
	struct flash_nios2_qspi_config *flash_cfg = dev->data;

	k_sem_init(&flash_cfg->sem_lock, 1, 1);
	return 0;
}

struct flash_nios2_qspi_config flash_cfg = {
	.qspi_dev = {
		.data_base = EXT_FLASH_AVL_MEM_BASE,
		.data_end = EXT_FLASH_AVL_MEM_BASE + EXT_FLASH_AVL_MEM_SPAN,
		.csr_base = EXT_FLASH_AVL_CSR_BASE,
		.size_in_bytes = EXT_FLASH_AVL_MEM_SPAN,
		.is_epcs = EXT_FLASH_AVL_MEM_IS_EPCS,
		.number_of_sectors = EXT_FLASH_AVL_MEM_NUMBER_OF_SECTORS,
		.sector_size = EXT_FLASH_AVL_MEM_SECTOR_SIZE,
		.page_size = EXT_FLASH_AVL_MEM_PAGE_SIZE,
	}
};

BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 1,
	"only one 'altr,nios2-qspi-nor' compatible node may be present");

DEVICE_DT_INST_DEFINE(0,
		flash_nios2_qspi_init, NULL, &flash_cfg, NULL,
		POST_KERNEL, CONFIG_FLASH_INIT_PRIORITY,
		&flash_nios2_qspi_api);
