/*
 * 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/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 + CONFIG_FLASH_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;
}

/*
 * 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;
}
