/*
 * Copyright (c) 2018 Google LLC.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#define SYS_LOG_DOMAIN "flash"
#include <logging/sys_log.h>

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

/*
 * Zephyr and the SAM0 series use different and conflicting names for
 * the erasable units and programmable units:
 *
 * The erase unit is a row, which is a 'page' in Zephyr terms.
 * The program unit is a page, which is a 'write_block' in Zephyr.
 *
 * This file uses the SAM0 names internally and the Zephyr names in
 * any error messages.
 */

/*
 * Number of lock regions.  The number is fixed and the region size
 * grows with the flash size.
 */
#define LOCK_REGIONS 16
#define LOCK_REGION_SIZE (FLASH_SIZE / LOCK_REGIONS)

#define PAGES_PER_ROW 4
#define ROW_SIZE (FLASH_PAGE_SIZE * PAGES_PER_ROW)

#define FLASH_MEM(_a) ((u32_t *)((u8_t *)((_a) + CONFIG_FLASH_BASE_ADDRESS)))

struct flash_sam0_data {
#if CONFIG_SOC_FLASH_SAM0_EMULATE_BYTE_PAGES
	u8_t buf[ROW_SIZE];
	off_t offset;
#endif

	struct k_sem sem;
};

static const struct flash_pages_layout flash_sam0_pages_layout = {
	.pages_count = CONFIG_FLASH_SIZE * 1024 / ROW_SIZE,
	.pages_size = ROW_SIZE,
};

static inline void flash_sam0_sem_take(struct device *dev)
{
	struct flash_sam0_data *ctx = dev->driver_data;

	k_sem_take(&ctx->sem, K_FOREVER);
}

static inline void flash_sam0_sem_give(struct device *dev)
{
	struct flash_sam0_data *ctx = dev->driver_data;

	k_sem_give(&ctx->sem);
}

static int flash_sam0_valid_range(off_t offset, size_t len)
{
	if (offset < 0) {
		SYS_LOG_WRN("%x: before start of flash", offset);
		return -EINVAL;
	}
	if ((offset + len) > CONFIG_FLASH_SIZE * 1024) {
		SYS_LOG_WRN("%x: ends past the end of flash", offset);
		return -EINVAL;
	}

	return 0;
}

static void flash_sam0_wait_ready(void)
{
	while (NVMCTRL->INTFLAG.bit.READY == 0) {
	}
}

static int flash_sam0_check_status(off_t offset)
{
	NVMCTRL_STATUS_Type status;

	flash_sam0_wait_ready();

	status = NVMCTRL->STATUS;
	/* Clear any flags */
	NVMCTRL->STATUS = status;

	if (status.bit.PROGE) {
		SYS_LOG_ERR("programming error at 0x%x", offset);
		return -EIO;
	} else if (status.bit.LOCKE) {
		SYS_LOG_ERR("lock error at 0x%x", offset);
		return -EROFS;
	} else if (status.bit.NVME) {
		SYS_LOG_ERR("NVM error at 0x%x", offset);
		return -EIO;
	}

	return 0;
}

static int flash_sam0_write_page(struct device *dev, off_t offset,
				 const void *data)
{
	const u32_t *src = data;
	const u32_t *end = src + FLASH_PAGE_SIZE / sizeof(*src);
	u32_t *dst = FLASH_MEM(offset);
	int err;

	NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMD_PBC | NVMCTRL_CTRLA_CMDEX_KEY;
	flash_sam0_wait_ready();

	/* Ensure writes happen 32 bits at a time. */
	for (; src != end; src++, dst++) {
		*dst = *src;
	}

	NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMD_WP | NVMCTRL_CTRLA_CMDEX_KEY;

	err = flash_sam0_check_status(offset);
	if (err != 0) {
		return err;
	}

	if (memcmp(data, FLASH_MEM(offset), FLASH_PAGE_SIZE) != 0) {
		SYS_LOG_ERR("verify error at offset 0x%x", offset);
		return -EIO;
	}

	return 0;
}

static int flash_sam0_erase_row(struct device *dev, off_t offset)
{
	*FLASH_MEM(offset) = 0;
	NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMD_ER | NVMCTRL_CTRLA_CMDEX_KEY;

	return flash_sam0_check_status(offset);
}

#if CONFIG_SOC_FLASH_SAM0_EMULATE_BYTE_PAGES

static int flash_sam0_commit(struct device *dev)
{
	struct flash_sam0_data *ctx = dev->driver_data;
	int err;
	int page;
	off_t offset = ctx->offset;

	ctx->offset = 0;

	if (offset == 0) {
		return 0;
	}

	err = flash_sam0_erase_row(dev, offset);
	if (err != 0) {
		return err;
	}

	for (page = 0; page < PAGES_PER_ROW; page++) {
		err = flash_sam0_write_page(
			dev, offset + page * FLASH_PAGE_SIZE,
			&ctx->buf[page * FLASH_PAGE_SIZE]);
		if (err != 0) {
			return err;
		}
	}

	return 0;
}

static int flash_sam0_write(struct device *dev, off_t offset,
			    const void *data, size_t len)
{
	struct flash_sam0_data *ctx = dev->driver_data;
	const u8_t *pdata = data;
	off_t addr;
	int err;

	SYS_LOG_DBG("%x: len %u", offset, len);

	err = flash_sam0_valid_range(offset, len);
	if (err != 0) {
		return err;
	}

	flash_sam0_sem_take(dev);

	for (addr = offset; addr < offset + len; addr++) {
		off_t base = addr & ~(ROW_SIZE - 1);

		if (base != ctx->offset) {
			/* Started a new row.  Flush any pending ones. */
			flash_sam0_commit(dev);
			memcpy(ctx->buf, (void *)base, sizeof(ctx->buf));
			ctx->offset = base;
		}

		ctx->buf[addr % ROW_SIZE] = *pdata++;
	}

	flash_sam0_commit(dev);
	flash_sam0_sem_give(dev);

	return 0;
}

#else /* CONFIG_SOC_FLASH_SAM0_EMULATE_BYTE_PAGES */

static int flash_sam0_write(struct device *dev, off_t offset,
			    const void *data, size_t len)
{
	const u8_t *pdata = data;
	int err;
	size_t idx;

	err = flash_sam0_valid_range(offset, len);
	if (err != 0) {
		return err;
	}

	if ((offset % FLASH_PAGE_SIZE) != 0) {
		SYS_LOG_WRN("%x: not on a write block boundrary", offset);
		return -EINVAL;
	}

	if ((len % FLASH_PAGE_SIZE) != 0) {
		SYS_LOG_WRN("%x: not a integer number of write blocks", len);
		return -EINVAL;
	}

	flash_sam0_sem_take(dev);

	for (idx = 0; idx < len; idx += FLASH_PAGE_SIZE) {
		err = flash_sam0_write_page(dev, offset + idx, &pdata[idx]);
		if (err != 0) {
			goto done;
		}
	}

done:
	flash_sam0_sem_give(dev);

	return err;
}

#endif

static int flash_sam0_read(struct device *dev, off_t offset, void *data,
			   size_t len)
{
	int err;

	err = flash_sam0_valid_range(offset, len);
	if (err != 0) {
		return err;
	}

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

	return 0;
}

static int flash_sam0_erase(struct device *dev, off_t offset, size_t size)
{
	int err;

	err = flash_sam0_valid_range(offset, ROW_SIZE);
	if (err != 0) {
		return err;
	}

	if ((offset % ROW_SIZE) != 0) {
		SYS_LOG_WRN("%x: not on a page boundrary", offset);
		return -EINVAL;
	}

	if ((size % ROW_SIZE) != 0) {
		SYS_LOG_WRN("%x: not a integer number of pages", size);
		return -EINVAL;
	}

	flash_sam0_sem_take(dev);

	for (size_t addr = offset; addr < offset + size; addr += ROW_SIZE) {
		err = flash_sam0_erase_row(dev, addr);
		if (err != 0) {
			goto done;
		}
	}

done:
	flash_sam0_sem_give(dev);

	return err;
}

static int flash_sam0_write_protection(struct device *dev, bool enable)
{
	off_t offset;
	int err;

	flash_sam0_sem_take(dev);

	for (offset = 0; offset < CONFIG_FLASH_SIZE * 1024;
	     offset += LOCK_REGION_SIZE) {
		*FLASH_MEM(offset) = 0;

		if (enable) {
			NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMD_LR |
					     NVMCTRL_CTRLA_CMDEX_KEY;
		} else {
			NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMD_UR |
					     NVMCTRL_CTRLA_CMDEX_KEY;
		}
		err = flash_sam0_check_status(offset);
		if (err != 0) {
			goto done;
		}
	}

done:
	flash_sam0_sem_give(dev);

	return err;
}

void flash_sam0_page_layout(struct device *dev,
			    const struct flash_pages_layout **layout,
			    size_t *layout_size)
{
	*layout = &flash_sam0_pages_layout;
	*layout_size = 1;
}

static int flash_sam0_init(struct device *dev)
{
	struct flash_sam0_data *ctx = dev->driver_data;

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

	/* Ensure the clock is on. */
	PM->APBBMASK.bit.NVMCTRL_ = 1;
	/* Require an explicit write command */
	NVMCTRL->CTRLB.bit.MANW = 1;

	return flash_sam0_write_protection(dev, false);
}

static const struct flash_driver_api flash_sam0_api = {
	.write_protection = flash_sam0_write_protection,
	.erase = flash_sam0_erase,
	.write = flash_sam0_write,
	.read = flash_sam0_read,
#ifdef CONFIG_FLASH_PAGE_LAYOUT
	.page_layout = flash_sam0_page_layout,
#endif
	.write_block_size = FLASH_PAGE_SIZE,
};

static struct flash_sam0_data flash_sam0_data_0;

DEVICE_AND_API_INIT(flash_sam0, FLASH_DEV_NAME,
		    flash_sam0_init, &flash_sam0_data_0, NULL, POST_KERNEL,
		    CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &flash_sam0_api);
