/*
 * Copyright (c) 2017 Linaro Limited
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <kernel.h>
#include <device.h>
#include <string.h>
#include <flash.h>
#include <init.h>
#include <soc.h>

#include <flash_registers.h>
#include <flash_map.h>

struct flash_priv {
	struct stm32f4x_flash *regs;
	struct k_sem sem;
};

static bool valid_range(off_t offset, uint32_t len)
{
	return offset >= 0 && (offset + len - 1 <= STM32F4X_FLASH_END);
}

static int check_status(struct stm32f4x_flash *regs)
{
	uint32_t const error =
		FLASH_FLAG_WRPERR |
		FLASH_FLAG_PGAERR |
		FLASH_FLAG_RDERR  |
		FLASH_FLAG_PGPERR |
		FLASH_FLAG_PGSERR |
		FLASH_FLAG_OPERR;

	if (regs->status & error) {
		return -EIO;
	}

	return 0;
}

static int wait_flash_idle(struct stm32f4x_flash *regs)
{
	uint32_t timeout = STM32F4X_FLASH_TIMEOUT;
	int rc;

	rc = check_status(regs);
	if (rc < 0) {
		return -EIO;
	}

	while ((regs->status & FLASH_FLAG_BSY) && timeout) {
		timeout--;
	}

	if (!timeout) {
		return -EIO;
	}

	return 0;
}

static int write_byte(off_t offset, uint8_t val, struct stm32f4x_flash *regs)
{
	uint32_t tmp;
	int rc;

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

	rc = wait_flash_idle(regs);
	if (rc < 0) {
		return rc;
	}

	regs->ctrl &= CR_PSIZE_MASK;
	regs->ctrl |= FLASH_PSIZE_BYTE;
	regs->ctrl |= FLASH_CR_PG;

	/* flush the register write */
	tmp = regs->ctrl;

	*((uint8_t *) offset + CONFIG_FLASH_BASE_ADDRESS) = val;

	rc = wait_flash_idle(regs);
	regs->ctrl &= (~FLASH_CR_PG);

	return rc;
}

static int erase_sector(uint16_t sector, struct stm32f4x_flash *regs)
{
	uint32_t tmp;
	int rc;

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

	rc = wait_flash_idle(regs);
	if (rc < 0) {
		return rc;
	}

	regs->ctrl &= STM32F4X_SECTOR_MASK;
	regs->ctrl |= FLASH_CR_SER | (sector << 3);
	regs->ctrl |= FLASH_CR_STRT;

	/* flush the register write */
	tmp = regs->ctrl;

	rc = wait_flash_idle(regs);
	regs->ctrl &= (FLASH_CR_SER | FLASH_CR_SNB);

	return rc;
}

static void flush_caches(struct stm32f4x_flash *regs)
{
	if (regs->acr.val & FLASH_ACR_ICEN) {
		regs->acr.val &= ~FLASH_ACR_ICEN;
		regs->acr.val |= FLASH_ACR_ICRST;
		regs->acr.val &= ~FLASH_ACR_ICRST;
		regs->acr.val |= FLASH_ACR_ICEN;
	}

	if (regs->acr.val & FLASH_ACR_DCEN) {
		regs->acr.val &= ~FLASH_ACR_DCEN;
		regs->acr.val |= FLASH_ACR_DCRST;
		regs->acr.val &= ~FLASH_ACR_DCRST;
		regs->acr.val |= FLASH_ACR_DCEN;
	}
}

static int flash_stm32f4x_erase(struct device *dev, off_t offset, size_t len)
{
	struct flash_priv *p = dev->driver_data;
	int i, rc = 0;

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

	if (!len) {
		return 0;
	}

	k_sem_take(&p->sem, K_FOREVER);

	i = stm32f4x_get_sector(offset);
	for (; i <= stm32f4x_get_sector(offset + len - 1); i++) {
		rc = erase_sector(i, p->regs);
		if (rc < 0) {
			break;
		}
	}
	flush_caches(p->regs);

	k_sem_give(&p->sem);

	return rc;
}

static int flash_stm32f4x_read(struct device *dev, off_t offset, void *data,
	size_t len)
{
	if (!valid_range(offset, len)) {
		return -EINVAL;
	}

	if (!len) {
		return 0;
	}

	memcpy(data, (void *) CONFIG_FLASH_BASE_ADDRESS + offset, len);

	return 0;
}

static int flash_stm32f4x_write(struct device *dev, off_t offset,
	const void *data, size_t len)
{
	struct flash_priv *p = dev->driver_data;
	int rc, i;

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

	if (!len) {
		return 0;
	}

	k_sem_take(&p->sem, K_FOREVER);

	for (i = 0; i < len; i++, offset++) {
		rc = write_byte(offset, ((const uint8_t *) data)[i], p->regs);
		if (rc < 0) {
			k_sem_give(&p->sem);
			return rc;
		}
	}

	k_sem_give(&p->sem);

	return 0;
}

static int flash_stm32f4x_write_protection(struct device *dev, bool enable)
{
	struct flash_priv *p = dev->driver_data;
	struct stm32f4x_flash *regs = p->regs;
	int rc = 0;

	k_sem_take(&p->sem, K_FOREVER);

	if (enable) {
		rc = wait_flash_idle(regs);
		if (rc) {
			k_sem_give(&p->sem);
			return rc;
		}
		regs->ctrl |= FLASH_CR_LOCK;
	} else {
		if (regs->ctrl & FLASH_CR_LOCK) {
			regs->key = FLASH_KEY1;
			regs->key = FLASH_KEY2;
		}
	}

	k_sem_give(&p->sem);

	return rc;
}

static struct flash_priv flash_data = {
	.regs = (struct stm32f4x_flash *) FLASH_R_BASE,
};

static const struct flash_driver_api flash_stm32f4x_api = {
	.write_protection = flash_stm32f4x_write_protection,
	.erase = flash_stm32f4x_erase,
	.write = flash_stm32f4x_write,
	.read = flash_stm32f4x_read,
};

static int stm32f4x_flash_init(struct device *dev)
{
	struct flash_priv *p = dev->driver_data;

	k_sem_init(&p->sem, 1, 1);

	return flash_stm32f4x_write_protection(dev, false);
}

DEVICE_AND_API_INIT(stm32f4x_flash,
	CONFIG_SOC_FLASH_STM32_DEV_NAME,
	stm32f4x_flash_init,
	&flash_data,
	NULL,
	POST_KERNEL,
	CONFIG_KERNEL_INIT_PRIORITY_DEVICE,
	&flash_stm32f4x_api);

