/*
 * Copyright (c) 2019 Philippe Retornaz <philippe@shapescale.com>
 * Copyright (c) 2017 Linaro Limited
 * Copyright (c) 2017 BayLibre, SAS
 *
 * SPDX-License-Identifier: Apache-2.0
 */

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

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

#include "flash_stm32.h"


/* FLASH_DBANK_SUPPORT is defined in the HAL for all G0Bx and G0C1 SoCs,
 * while only those with 256KiB and 512KiB Flash have two banks.
 */
#if defined(FLASH_DBANK_SUPPORT) && (CONFIG_FLASH_SIZE > (128))
#define STM32G0_DBANK_SUPPORT
#endif

#if defined(STM32G0_DBANK_SUPPORT)
#define STM32G0_BANK_COUNT		2
#define STM32G0_BANK2_START_PAGE_NR	256
#else
#define STM32G0_BANK_COUNT		1
#endif

#define STM32G0_FLASH_SIZE		(FLASH_SIZE)
#define STM32G0_FLASH_PAGE_SIZE		(FLASH_PAGE_SIZE)
#define STM32G0_PAGES_PER_BANK		\
	((STM32G0_FLASH_SIZE / STM32G0_FLASH_PAGE_SIZE) / STM32G0_BANK_COUNT)

static inline void flush_cache(FLASH_TypeDef *regs)
{
	if (regs->ACR & FLASH_ACR_ICEN) {
		regs->ACR &= ~FLASH_ACR_ICEN;
		/* Datasheet: ICRST: Instruction cache reset :
		 * This bit can be written only when the instruction cache
		 * is disabled
		 */
		regs->ACR |= FLASH_ACR_ICRST;
		regs->ACR &= ~FLASH_ACR_ICRST;
		regs->ACR |= FLASH_ACR_ICEN;
	}
}

static int write_dword(const struct device *dev, off_t offset, uint64_t val)
{
	volatile uint32_t *flash = (uint32_t *)(offset + FLASH_STM32_BASE_ADDRESS);
	FLASH_TypeDef *regs = FLASH_STM32_REGS(dev);
	uint32_t tmp;
	int rc;

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

	/* Check that no Flash main memory operation is ongoing */
	rc = flash_stm32_wait_flash_idle(dev);
	if (rc < 0) {
		return rc;
	}

	/* Check if this double word is erased and value isn't 0.
	 *
	 * It is allowed to write only zeros over an already written dword
	 * See 3.3.8 in reference manual.
	 */
	if ((flash[0] != 0xFFFFFFFFUL ||
	     flash[1] != 0xFFFFFFFFUL) && val != 0UL) {
		LOG_ERR("Word at offs %ld not erased", (long)offset);
		return -EIO;
	}

	/* Set the PG bit */
	regs->CR |= FLASH_CR_PG;

	/* Flush the register write */
	tmp = regs->CR;

	/* Perform the data write operation at the desired memory address */
	flash[0] = (uint32_t)val;
	flash[1] = (uint32_t)(val >> 32);

	/* Wait until the BSY bit is cleared */
	rc = flash_stm32_wait_flash_idle(dev);

	/* Clear the PG bit */
	regs->CR &= (~FLASH_CR_PG);

	return rc;
}

static int erase_page(const struct device *dev, unsigned int offset)
{
	FLASH_TypeDef *regs = FLASH_STM32_REGS(dev);
	uint32_t tmp;
	int rc;
	int page;

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

	/* Check that no Flash memory operation is ongoing */
	rc = flash_stm32_wait_flash_idle(dev);
	if (rc < 0) {
		return rc;
	}

	/*
	 * If an erase operation in Flash memory also concerns data
	 * in the instruction cache, the user has to ensure that these data
	 * are rewritten before they are accessed during code execution.
	 */
	flush_cache(regs);

	tmp = regs->CR;
	page = offset / STM32G0_FLASH_PAGE_SIZE;

#if defined(STM32G0_DBANK_SUPPORT)
	bool swap_enabled = (regs->OPTR & FLASH_OPTR_nSWAP_BANK) == 0;

	/* big page-nr w/o swap or small page-nr w/ swap indicate bank2 */
	if ((page >= STM32G0_PAGES_PER_BANK) != swap_enabled) {
		page = (page % STM32G0_PAGES_PER_BANK) + STM32G0_BANK2_START_PAGE_NR;
		tmp |= FLASH_CR_BKER;
		LOG_DBG("Erase page %d on bank 2", page);
	} else {
		page = page % STM32G0_PAGES_PER_BANK;
		tmp &= ~FLASH_CR_BKER;
		LOG_DBG("Erase page %d on bank 1", page);
	}
#endif

	/* Set the PER bit and select the page you wish to erase */
	tmp |= FLASH_CR_PER;
	tmp &= ~FLASH_CR_PNB_Msk;
	tmp |= ((page << FLASH_CR_PNB_Pos) & FLASH_CR_PNB_Msk);

	/* Set the STRT bit and write the reg */
	tmp |= FLASH_CR_STRT;
	regs->CR = tmp;

	/* Wait for the BSY bit */
	rc = flash_stm32_wait_flash_idle(dev);

	regs->CR &= ~FLASH_CR_PER;

	return rc;
}

int flash_stm32_block_erase_loop(const struct device *dev,
				 unsigned int offset,
				 unsigned int len)
{
	unsigned int addr = offset;
	int rc = 0;

	for (; addr <= offset + len - 1 ; addr += STM32G0_FLASH_PAGE_SIZE) {
		rc = erase_page(dev, addr);
		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 += 8, offset += 8) {
		rc = write_dword(dev, offset,
				UNALIGNED_GET((const uint64_t *) data + (i >> 3)));
		if (rc < 0) {
			return rc;
		}
	}

	return rc;
}

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

	if (regs->CR & FLASH_CR_OPTLOCK) {
		return -EIO;
	}

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

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

	regs->OPTR = (regs->OPTR & ~mask) | value;
	regs->CR |= FLASH_CR_OPTSTRT;

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

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

	/* Force the option byte loading */
	regs->CR |= FLASH_CR_OBL_LAUNCH;

	return flash_stm32_wait_flash_idle(dev);
}

uint32_t flash_stm32_option_bytes_read(const struct device *dev)
{
	FLASH_TypeDef *regs = FLASH_STM32_REGS(dev);

	return regs->OPTR;
}

#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->OPTR & FLASH_OPTR_RDP_Msk) >> FLASH_OPTR_RDP_Pos;
}

void flash_stm32_set_rdp_level(const struct device *dev, uint8_t level)
{
	flash_stm32_option_bytes_write(dev, FLASH_OPTR_RDP_Msk,
				       (uint32_t)level << FLASH_OPTR_RDP_Pos);
}
#endif /* CONFIG_FLASH_STM32_READOUT_PROTECTION */

/*
 * The address space is always continuous, even though a subset of G0 SoCs has
 * two flash banks.
 * Only the "physical" flash page-NRs are not continuous on those SoCs.
 * As a result the page numbers used in the zephyr flash api differs
 * from the "physical" flash page number.
 * The first is equal to the address offset divided by the page size, while
 * "physical" pages are numbered starting with 0 on bank1 and 256 on bank2.
 * As a result only a single homogeneous flash page layout needs to be defined.
 */
void flash_stm32_page_layout(const struct device *dev,
			     const struct flash_pages_layout **layout,
			     size_t *layout_size)
{
	static struct flash_pages_layout stm32g0_flash_layout = {
		.pages_count = 0,
		.pages_size = 0,
	};

	ARG_UNUSED(dev);

	if (stm32g0_flash_layout.pages_count == 0) {
		stm32g0_flash_layout.pages_count =
				STM32G0_FLASH_SIZE / STM32G0_FLASH_PAGE_SIZE;
		stm32g0_flash_layout.pages_size = STM32G0_FLASH_PAGE_SIZE;
	}

	*layout = &stm32g0_flash_layout;
	*layout_size = 1;
}

/* Override weak function */
int  flash_stm32_check_configuration(void)
{
#if defined(STM32G0_DBANK_SUPPORT) && (CONFIG_FLASH_SIZE == 256)
	/* Single bank mode not supported on dual bank SoCs with 256kiB flash */
	if ((FLASH->OPTR & FLASH_OPTR_DUAL_BANK) == 0) {
		LOG_ERR("Single bank configuration not supported by the driver");
		return -ENOTSUP;
	}
#endif
	return 0;
}
