/*
 * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include <errno.h>
#include <mmio.h>
#include <v2m_flash.h>

/*
 * This file supplies a low level interface to the vexpress NOR flash
 * memory of juno and fvp. This memory is organized as an interleaved
 * memory of two chips with a 16 bit word. It means that every 32 bit
 * access is going to access to two different chips. This is very
 * important when we send commands or read status of the chips.
 */

/*
 * DWS ready poll retries. The number of retries in this driver have been
 * obtained empirically from Juno. FVP implements a zero wait state NOR flash
 * model
 */
#define DWS_WORD_PROGRAM_RETRIES	1000
#define DWS_WORD_ERASE_RETRIES		3000000
#define DWS_WORD_LOCK_RETRIES		1000

/* Helper macro to detect end of command */
#define NOR_CMD_END (NOR_DWS | NOR_DWS << 16l)

/* Helper macros to access two flash banks in parallel */
#define NOR_2X16(d)			((d << 16) | (d & 0xffff))

static unsigned int nor_status(uintptr_t base_addr)
{
	unsigned long status;

	nor_send_cmd(base_addr, NOR_CMD_READ_STATUS_REG);
	status = mmio_read_32(base_addr);
	status |= status >> 16; /* merge status from both flash banks */

	return status & 0xFFFF;
}

/*
 * Poll Write State Machine.
 * Return values:
 *    0      = WSM ready
 *    -EBUSY = WSM busy after the number of retries
 */
static int nor_poll_dws(uintptr_t base_addr, unsigned long int retries)
{
	unsigned long status;

	do {
		nor_send_cmd(base_addr, NOR_CMD_READ_STATUS_REG);
		status = mmio_read_32(base_addr);
		if ((status & NOR_CMD_END) == NOR_CMD_END)
			return 0;
	} while (retries-- > 0);

	return -EBUSY;
}

/*
 * Return values:
 *    0      = success
 *    -EPERM = Device protected or Block locked
 *    -EIO   = General I/O error
 */
static int nor_full_status_check(uintptr_t base_addr)
{
	unsigned long status;

	/* Full status check */
	status = nor_status(base_addr);

	if (status & (NOR_PS | NOR_BLS | NOR_ESS | NOR_PSS))
		return -EPERM;
	if (status & (NOR_VPPS | NOR_ES))
		return -EIO;
	return 0;
}

void nor_send_cmd(uintptr_t base_addr, unsigned long cmd)
{
	mmio_write_32(base_addr, NOR_2X16(cmd));
}

/*
 * This function programs a word in the flash. Be aware that it only
 * can reset bits that were previously set. It cannot set bits that
 * were previously reset. The resulting bits = old_bits & new bits.
 * Return values:
 *  0 = success
 *  otherwise it returns a negative value
 */
int nor_word_program(uintptr_t base_addr, unsigned long data)
{
	uint32_t status;
	int ret;

	nor_send_cmd(base_addr, NOR_CMD_CLEAR_STATUS_REG);

	/* Set the device in write word mode */
	nor_send_cmd(base_addr, NOR_CMD_WORD_PROGRAM);
	mmio_write_32(base_addr, data);

	ret = nor_poll_dws(base_addr, DWS_WORD_PROGRAM_RETRIES);
	if (ret == 0) {
		/* Full status check */
		nor_send_cmd(base_addr, NOR_CMD_READ_STATUS_REG);
		status = mmio_read_32(base_addr);

		if (status & (NOR_PS | NOR_BLS)) {
			nor_send_cmd(base_addr, NOR_CMD_CLEAR_STATUS_REG);
			ret = -EPERM;
		}
	}

	if (ret == 0)
		ret = nor_full_status_check(base_addr);
	nor_send_cmd(base_addr, NOR_CMD_READ_ARRAY);

	return ret;
}

/*
 * Erase a full 256K block
 * Return values:
 *  0 = success
 *  otherwise it returns a negative value
 */
int nor_erase(uintptr_t base_addr)
{
	int ret;

	nor_send_cmd(base_addr, NOR_CMD_CLEAR_STATUS_REG);

	nor_send_cmd(base_addr, NOR_CMD_BLOCK_ERASE);
	nor_send_cmd(base_addr, NOR_CMD_BLOCK_ERASE_ACK);

	ret = nor_poll_dws(base_addr, DWS_WORD_ERASE_RETRIES);
	if (ret == 0)
		ret = nor_full_status_check(base_addr);
	nor_send_cmd(base_addr, NOR_CMD_READ_ARRAY);

	return ret;
}

/*
 * Lock a full 256 block
 * Return values:
 *  0 = success
 *  otherwise it returns a negative value
 */
int nor_lock(uintptr_t base_addr)
{
	int ret;

	nor_send_cmd(base_addr, NOR_CMD_CLEAR_STATUS_REG);

	nor_send_cmd(base_addr, NOR_CMD_LOCK_UNLOCK);
	nor_send_cmd(base_addr, NOR_LOCK_BLOCK);

	ret = nor_poll_dws(base_addr, DWS_WORD_LOCK_RETRIES);
	if (ret == 0)
		ret = nor_full_status_check(base_addr);
	nor_send_cmd(base_addr, NOR_CMD_READ_ARRAY);

	return ret;
}

/*
 * unlock a full 256 block
 * Return values:
 *  0 = success
 *  otherwise it returns a negative value
 */
int nor_unlock(uintptr_t base_addr)
{
	int ret;

	nor_send_cmd(base_addr, NOR_CMD_CLEAR_STATUS_REG);

	nor_send_cmd(base_addr, NOR_CMD_LOCK_UNLOCK);
	nor_send_cmd(base_addr, NOR_UNLOCK_BLOCK);

	ret = nor_poll_dws(base_addr, DWS_WORD_LOCK_RETRIES);
	if (ret == 0)
		ret = nor_full_status_check(base_addr);
	nor_send_cmd(base_addr, NOR_CMD_READ_ARRAY);

	return ret;
}
