/*
 * Copyright (c) 2016 Intel Corporation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <errno.h>

#include <nanokernel.h>
#include <device.h>
#include <init.h>

#include <flash.h>

#include "qm_flash.h"
#include "qm_soc_regs.h"

static inline bool is_aligned_32(uint32_t data)
{
	return (data & 0x3) ? false : true;
}

static qm_flash_region_t flash_region(uint32_t addr)
{
	if ((addr >= QM_FLASH_REGION_SYS_0_BASE) && (addr <
	    (QM_FLASH_REGION_SYS_0_BASE + CONFIG_SOC_FLASH_QMSI_SYS_SIZE))) {
		return QM_FLASH_REGION_SYS;
	}

#if defined(CONFIG_SOC_QUARK_D2000)
	if ((addr >= QM_FLASH_REGION_DATA_0_BASE) &&
	    (addr < (QM_FLASH_REGION_DATA_0_BASE +
	    QM_FLASH_REGION_DATA_0_SIZE))) {
		return QM_FLASH_REGION_DATA;
	}
#endif

	/* invalid address */
	return QM_FLASH_REGION_NUM;
}

static uint32_t get_page_num(uint32_t addr)
{
	switch (flash_region(addr)) {
	case QM_FLASH_REGION_SYS:
		return (addr - QM_FLASH_REGION_SYS_0_BASE) >>
		       QM_FLASH_PAGE_SIZE_BITS;
#if defined(CONFIG_SOC_QUARK_D2000)
	case QM_FLASH_REGION_DATA:
		return (addr - QM_FLASH_REGION_DATA_0_BASE) >>
		       QM_FLASH_PAGE_SIZE_BITS;
#endif
	default:
		/* invalid address */
		return 0xffffffff;
	}
}

static int flash_qmsi_read(struct device *dev, off_t addr,
			   void *data, size_t len)
{
	if ((!is_aligned_32(len)) || (!is_aligned_32(addr))) {
		return -EINVAL;
	}

	if (flash_region(addr) == QM_FLASH_REGION_NUM) {
		/* starting address is not within flash */
		return -EIO;
	}

	if (flash_region(addr + len - 4) == QM_FLASH_REGION_NUM) {
		/* data area is not within flash */
		return -EIO;
	}

	for (uint32_t i = 0; i < (len >> 2); i++) {
		UNALIGNED_PUT(sys_read32(addr + (i << 2)),
			      (uint32_t *)data + i);
	}

	return 0;
}

static int flash_qmsi_write(struct device *dev, off_t addr,
			    const void *data, size_t len)
{
	qm_flash_t flash = QM_FLASH_0;
	qm_flash_region_t reg;
	uint32_t data_word = 0, offset = 0, f_addr = 0;

	if ((!is_aligned_32(len)) || (!is_aligned_32(addr))) {
		return -EINVAL;
	}

	reg = flash_region(addr);
	if (reg == QM_FLASH_REGION_NUM) {
		return -EIO;
	}

	if (flash_region(addr + len - 4) == QM_FLASH_REGION_NUM) {
		return -EIO;
	}

	for (uint32_t i = 0; i < (len >> 2); i++) {
		data_word = UNALIGNED_GET((uint32_t *)data + i);
		reg = flash_region(addr + (i << 2));
		f_addr = addr + (i << 2);

		switch (reg) {
		case QM_FLASH_REGION_SYS:
			offset = f_addr - QM_FLASH_REGION_SYS_0_BASE;
			break;
#if defined(CONFIG_SOC_QUARK_D2000)
		case QM_FLASH_REGION_DATA:
			offset = f_addr - QM_FLASH_REGION_DATA_0_BASE;
			break;
#endif
		default:
			return -EIO;
		}

#if defined(CONFIG_SOC_QUARK_SE)
		if (offset >= (CONFIG_SOC_FLASH_QMSI_SYS_SIZE >> 1)) {
			flash = QM_FLASH_1;
			offset -= CONFIG_SOC_FLASH_QMSI_SYS_SIZE >> 1;
		}
#endif

		qm_flash_word_write(flash, reg, offset, data_word);
	}

	return 0;
}

static int flash_qmsi_erase(struct device *dev, off_t addr, size_t size)
{
	qm_flash_t flash = QM_FLASH_0;
	qm_flash_region_t reg;
	uint32_t page = 0;

	/* starting address needs to be a 2KB aligned address */
	if (addr & QM_FLASH_ADDRESS_MASK) {
		return -EINVAL;
	}

	/* size needs to be multiple of 2KB */
	if (size & QM_FLASH_ADDRESS_MASK) {
		return -EINVAL;
	}

	reg = flash_region(addr);
	if (reg == QM_FLASH_REGION_NUM) {
		return -EIO;
	}

	if (flash_region(addr + size - (QM_FLASH_PAGE_SIZE_DWORDS << 2)) ==
	    QM_FLASH_REGION_NUM) {
		return -EIO;
	}

	for (uint32_t i = 0; i < (size >> QM_FLASH_PAGE_SIZE_BITS); i++) {
		page = get_page_num(addr) + i;
#if defined(CONFIG_SOC_QUARK_SE)
		if (page >= (CONFIG_SOC_FLASH_QMSI_SYS_SIZE >>
				 (QM_FLASH_PAGE_SIZE_BITS + 1))) {
			flash = QM_FLASH_1;
			page -= (CONFIG_SOC_FLASH_QMSI_SYS_SIZE >>
				     (QM_FLASH_PAGE_SIZE_BITS + 1));
		}
#endif
		qm_flash_page_erase(flash, reg, page);
	}

	return 0;
}

static int flash_qmsi_write_protection(struct device *dev, bool enable)
{
	qm_flash_config_t qm_cfg;

	qm_cfg.us_count = CONFIG_SOC_FLASH_QMSI_CLK_COUNT_US;
	qm_cfg.wait_states = CONFIG_SOC_FLASH_QMSI_WAIT_STATES;

	if (enable) {
		qm_cfg.write_disable = QM_FLASH_WRITE_DISABLE;
	} else {
		qm_cfg.write_disable = QM_FLASH_WRITE_ENABLE;
	}

	qm_flash_set_config(QM_FLASH_0, &qm_cfg);

#if defined(CONFIG_SOC_QUARK_SE)
	qm_flash_set_config(QM_FLASH_1, &qm_cfg);
#endif

	return 0;
}

static struct flash_driver_api flash_qmsi_api = {
	.read = flash_qmsi_read,
	.write = flash_qmsi_write,
	.erase = flash_qmsi_erase,
	.write_protection = flash_qmsi_write_protection,
};

static int quark_flash_init(struct device *dev)
{
	qm_flash_config_t qm_cfg;

	dev->driver_api = &flash_qmsi_api;

	qm_cfg.us_count = CONFIG_SOC_FLASH_QMSI_CLK_COUNT_US;
	qm_cfg.wait_states = CONFIG_SOC_FLASH_QMSI_WAIT_STATES;
	qm_cfg.write_disable = QM_FLASH_WRITE_ENABLE;

	qm_flash_set_config(QM_FLASH_0, &qm_cfg);

#if defined(CONFIG_SOC_QUARK_SE)
	qm_flash_set_config(QM_FLASH_1, &qm_cfg);
#endif

	return 0;
}

DEVICE_INIT(quark_flash, CONFIG_SOC_FLASH_QMSI_DEV_NAME,
	    quark_flash_init, NULL, NULL, SECONDARY,
	    CONFIG_KERNEL_INIT_PRIORITY_DEVICE);
