/*
 * Copyright (c) 2018 Aurelien Jarno
 * Copyright (c) 2018 Yong Jin
 *
 * SPDX-License-Identifier: Apache-2.0
 */

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

#include "flash_stm32.h"

bool flash_stm32_valid_range(const struct device *dev, off_t offset,
			     uint32_t len,
			     bool write)
{
	ARG_UNUSED(write);

	return flash_stm32_range_exists(dev, offset, len);
}

static inline void flush_cache(FLASH_TypeDef *regs)
{
	if (regs->ACR & FLASH_ACR_ARTEN) {
		regs->ACR &= ~FLASH_ACR_ARTEN;
		/* Reference manual:
		 * The ART cache can be flushed only if the ART accelerator
		 * is disabled (ARTEN = 0).
		 */
		regs->ACR |= FLASH_ACR_ARTRST;
		regs->ACR &= ~FLASH_ACR_ARTRST;
		regs->ACR |= FLASH_ACR_ARTEN;
	}
}

static int write_byte(const struct device *dev, off_t offset, uint8_t val)
{
	FLASH_TypeDef *regs = FLASH_STM32_REGS(dev);
	int rc;

	/* if the control register is locked, do not fail silently */
	if (regs->CR & FLASH_CR_LOCK) {
		return -EIO;
	}

	rc = flash_stm32_wait_flash_idle(dev);
	if (rc < 0) {
		return rc;
	}

	/* prepare to write a single byte */
	regs->CR = (regs->CR & CR_PSIZE_MASK) |
		   FLASH_PSIZE_BYTE | FLASH_CR_PG;
	/* flush the register write */
	barrier_dsync_fence_full();

	/* write the data */
	*((uint8_t *) offset + FLASH_STM32_BASE_ADDRESS) = val;
	/* flush the register write */
	barrier_dsync_fence_full();

	rc = flash_stm32_wait_flash_idle(dev);
	regs->CR &= (~FLASH_CR_PG);

	return rc;
}

static int erase_sector(const struct device *dev, uint32_t sector)
{
	FLASH_TypeDef *regs = FLASH_STM32_REGS(dev);
	int rc;

	/* if the control register is locked, do not fail silently */
	if (regs->CR & FLASH_CR_LOCK) {
		return -EIO;
	}

	rc = flash_stm32_wait_flash_idle(dev);
	if (rc < 0) {
		return rc;
	}

	/* Dual bank mode, SNB MSB selects the bank2,
	 * others select sector, so we remap sector number.
	 */
#if defined(FLASH_OPTCR_nDBANK) && FLASH_SECTOR_TOTAL == 24
#if CONFIG_FLASH_SIZE == 2048
	if (sector > 11) {
		sector += 4U;
	}
#elif CONFIG_FLASH_SIZE == 1024
	if (sector > 7) {
		sector += 8U;
	}
#endif /* CONFIG_FLASH_SIZE */
#endif /* defined(FLASH_OPTCR_nDBANK) && FLASH_SECTOR_TOTAL == 24 */

	regs->CR = (regs->CR & ~(FLASH_CR_PSIZE | FLASH_CR_SNB)) |
		   FLASH_PSIZE_BYTE |
		   FLASH_CR_SER |
		   (sector << FLASH_CR_SNB_Pos) |
		   FLASH_CR_STRT;
	/* flush the register write */
	barrier_dsync_fence_full();

	rc = flash_stm32_wait_flash_idle(dev);
	regs->CR &= ~(FLASH_CR_SER | FLASH_CR_SNB);

	return rc;
}

int flash_stm32_block_erase_loop(const struct device *dev,
				 unsigned int offset,
				 unsigned int len)
{
	struct flash_pages_info info;
	uint32_t start_sector, end_sector;
	uint32_t i;
	int rc = 0;

	rc = flash_get_page_info_by_offs(dev, offset, &info);
	if (rc) {
		return rc;
	}
	start_sector = info.index;
	rc = flash_get_page_info_by_offs(dev, offset + len - 1, &info);
	if (rc) {
		return rc;
	}
	end_sector = info.index;

	for (i = start_sector; i <= end_sector; i++) {
		rc = erase_sector(dev, i);
		if (rc < 0) {
			break;
		}
	}

	return rc;
}

int flash_stm32_write_range(const struct device *dev, unsigned int offset,
			    const void *data, unsigned int len)
{
	int i, rc = 0;

	for (i = 0; i < len; i++, offset++) {
		rc = write_byte(dev, offset, ((const uint8_t *) data)[i]);
		if (rc < 0) {
			return rc;
		}
	}

	return rc;
}

static __unused int write_optb(const struct device *dev, uint32_t mask,
			       uint32_t value)
{
	FLASH_TypeDef *regs = FLASH_STM32_REGS(dev);
	int rc;

	if (regs->OPTCR & FLASH_OPTCR_OPTLOCK) {
		return -EIO;
	}

	if ((regs->OPTCR & mask) == value) {
		return 0;
	}

	rc = flash_stm32_wait_flash_idle(dev);
	if (rc < 0) {
		return rc;
	}

	regs->OPTCR = (regs->OPTCR & ~mask) | value;
	regs->OPTCR |= FLASH_OPTCR_OPTSTRT;

	/* Make sure previous write is completed. */
	barrier_dsync_fence_full();

	return flash_stm32_wait_flash_idle(dev);
}

#if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION)
uint8_t flash_stm32_get_rdp_level(const struct device *dev)
{
	FLASH_TypeDef *regs = FLASH_STM32_REGS(dev);

	return (regs->OPTCR & FLASH_OPTCR_RDP_Msk) >> FLASH_OPTCR_RDP_Pos;
}

void flash_stm32_set_rdp_level(const struct device *dev, uint8_t level)
{
	write_optb(dev, FLASH_OPTCR_RDP_Msk,
		(uint32_t)level << FLASH_OPTCR_RDP_Pos);
}
#endif /* CONFIG_FLASH_STM32_READOUT_PROTECTION */

/* Some SoC can run in single or dual bank mode, others can't.
 * Different SoC flash layouts are specified in various reference
 * manuals, but the flash layout for a given number of sectors is
 * consistent across these manuals. The number of sectors is given
 * by the HAL as FLASH_SECTOR_TOTAL. And some SoC that with same
 * FLASH_SECTOR_TOTAL have different flash size.
 *
 * In case of 8 sectors and 24 sectors we need to differentiate
 * between two cases by using the memory size.
 * In case of 24 sectors we need to check if the SoC is running
 * in single or dual bank mode.
 */
#ifndef FLASH_SECTOR_TOTAL
#error "Unknown flash layout"
#elif FLASH_SECTOR_TOTAL == 2
static const struct flash_pages_layout stm32f7_flash_layout[] = {
	/* RM0385, table 4: STM32F750xx */
	{.pages_count = 2, .pages_size = KB(32)},
};
#elif FLASH_SECTOR_TOTAL == 4
static const struct flash_pages_layout stm32f7_flash_layout[] = {
	/* RM0431, table 4: STM32F730xx */
	{.pages_count = 4, .pages_size = KB(16)},
};
#elif FLASH_SECTOR_TOTAL == 8
#if CONFIG_FLASH_SIZE == 512
static const struct flash_pages_layout stm32f7_flash_layout[] = {
	/* RM0431, table 3: STM32F72xxx and STM32F732xx/F733xx */
	{.pages_count = 4, .pages_size = KB(16)},
	{.pages_count = 1, .pages_size = KB(64)},
	{.pages_count = 3, .pages_size = KB(128)},
};
#elif CONFIG_FLASH_SIZE == 1024
static const struct flash_pages_layout stm32f7_flash_layout[] = {
	/* RM0385, table 3: STM32F756xx and STM32F74xxx */
	{.pages_count = 4, .pages_size = KB(32)},
	{.pages_count = 1, .pages_size = KB(128)},
	{.pages_count = 3, .pages_size = KB(256)},
};
#endif /* CONFIG_FLASH_SIZE */
#elif FLASH_SECTOR_TOTAL == 24
static const struct flash_pages_layout stm32f7_flash_layout_single_bank[] = {
	/* RM0410, table 3: STM32F76xxx and STM32F77xxx in single bank */
	{.pages_count = 4, .pages_size = KB(32)},
	{.pages_count = 1, .pages_size = KB(128)},
	{.pages_count = 7, .pages_size = KB(256)},
};
static const struct flash_pages_layout stm32f7_flash_layout_dual_bank[] = {
	/* RM0410, table 4: STM32F76xxx and STM32F77xxx in dual bank */
	{.pages_count = 4, .pages_size = KB(16)},
	{.pages_count = 1, .pages_size = KB(64)},
	{.pages_count = 7, .pages_size = KB(128)},
	{.pages_count = 4, .pages_size = KB(16)},
	{.pages_count = 1, .pages_size = KB(64)},
	{.pages_count = 7, .pages_size = KB(128)},
};
#else
#error "Unknown flash layout"
#endif/* !defined(FLASH_SECTOR_TOTAL) */

void flash_stm32_page_layout(const struct device *dev,
			     const struct flash_pages_layout **layout,
			     size_t *layout_size)
{
#if FLASH_OPTCR_nDBANK
	if (FLASH_STM32_REGS(dev)->OPTCR & FLASH_OPTCR_nDBANK) {
		*layout = stm32f7_flash_layout_single_bank;
		*layout_size = ARRAY_SIZE(stm32f7_flash_layout_single_bank);
	} else {
		*layout = stm32f7_flash_layout_dual_bank;
		*layout_size = ARRAY_SIZE(stm32f7_flash_layout_dual_bank);
	}
#else
	ARG_UNUSED(dev);
	*layout = stm32f7_flash_layout;
	*layout_size = ARRAY_SIZE(stm32f7_flash_layout);
#endif
}
