/*
 * Copyright (C) 2014       Panasonic Corporation
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */

#include <common.h>
#include <asm/io.h>
#include <asm/unaligned.h>
#include <linux/mtd/nand.h>
#include "denali.h"

#define SPARE_ACCESS		0x41
#define MAIN_ACCESS		0x42
#define PIPELINE_ACCESS		0x2000

#define BANK(x) ((x) << 24)

static void __iomem *denali_flash_mem =
			(void __iomem *)CONFIG_SYS_NAND_DATA_BASE;
static void __iomem *denali_flash_reg =
			(void __iomem *)CONFIG_SYS_NAND_REGS_BASE;

static const int flash_bank;
static uint8_t page_buffer[NAND_MAX_PAGESIZE];
static int page_size, oob_size, pages_per_block;

static void index_addr(uint32_t address, uint32_t data)
{
	writel(address, denali_flash_mem + INDEX_CTRL_REG);
	writel(data, denali_flash_mem + INDEX_DATA_REG);
}

static int wait_for_irq(uint32_t irq_mask)
{
	unsigned long timeout = 1000000;
	uint32_t intr_status;

	do {
		intr_status = readl(denali_flash_reg + INTR_STATUS(flash_bank));

		if (intr_status & INTR_STATUS__ECC_UNCOR_ERR) {
			debug("Uncorrected ECC detected\n");
			return -EIO;
		}

		if (intr_status & irq_mask)
			break;

		udelay(1);
		timeout--;
	} while (timeout);

	if (!timeout) {
		debug("Timeout with interrupt status %08x\n", intr_status);
		return -EIO;
	}

	return 0;
}

static void read_data_from_flash_mem(uint8_t *buf, int len)
{
	int i;
	uint32_t *buf32;

	/* transfer the data from the flash */
	buf32 = (uint32_t *)buf;

	/*
	 * Let's take care of unaligned access although it rarely happens.
	 * Avoid put_unaligned() for the normal use cases since it leads to
	 * a bit performance regression.
	 */
	if ((unsigned long)buf32 % 4) {
		for (i = 0; i < len / 4; i++)
			put_unaligned(readl(denali_flash_mem + INDEX_DATA_REG),
				      buf32++);
	} else {
		for (i = 0; i < len / 4; i++)
			*buf32++ = readl(denali_flash_mem + INDEX_DATA_REG);
	}

	if (len % 4) {
		u32 tmp;

		tmp = cpu_to_le32(readl(denali_flash_mem + INDEX_DATA_REG));
		buf = (uint8_t *)buf32;
		for (i = 0; i < len % 4; i++) {
			*buf++ = tmp;
			tmp >>= 8;
		}
	}
}

int denali_send_pipeline_cmd(int page, int ecc_en, int access_type)
{
	uint32_t addr, cmd;
	static uint32_t page_count = 1;

	writel(ecc_en, denali_flash_reg + ECC_ENABLE);

	/* clear all bits of intr_status. */
	writel(0xffff, denali_flash_reg + INTR_STATUS(flash_bank));

	addr = BANK(flash_bank) | page;

	/* setup the acccess type */
	cmd = MODE_10 | addr;
	index_addr(cmd, access_type);

	/* setup the pipeline command */
	index_addr(cmd, PIPELINE_ACCESS | page_count);

	cmd = MODE_01 | addr;
	writel(cmd, denali_flash_mem + INDEX_CTRL_REG);

	return wait_for_irq(INTR_STATUS__LOAD_COMP);
}

static int nand_read_oob(void *buf, int page)
{
	int ret;

	ret = denali_send_pipeline_cmd(page, 0, SPARE_ACCESS);
	if (ret < 0)
		return ret;

	read_data_from_flash_mem(buf, oob_size);

	return 0;
}

static int nand_read_page(void *buf, int page)
{
	int ret;

	ret = denali_send_pipeline_cmd(page, 1, MAIN_ACCESS);
	if (ret < 0)
		return ret;

	read_data_from_flash_mem(buf, page_size);

	return 0;
}

static int nand_block_isbad(int block)
{
	int ret;

	ret = nand_read_oob(page_buffer, block * pages_per_block);
	if (ret < 0)
		return ret;

	return page_buffer[CONFIG_SYS_NAND_BAD_BLOCK_POS] != 0xff;
}

/* nand_init() - initialize data to make nand usable by SPL */
void nand_init(void)
{
	/* access to main area */
	writel(0, denali_flash_reg + TRANSFER_SPARE_REG);

	/*
	 * These registers are expected to be already set by the hardware
	 * or earlier boot code.  So we read these values out.
	 */
	page_size = readl(denali_flash_reg + DEVICE_MAIN_AREA_SIZE);
	oob_size = readl(denali_flash_reg + DEVICE_SPARE_AREA_SIZE);
	pages_per_block = readl(denali_flash_reg + PAGES_PER_BLOCK);
}

int nand_spl_load_image(uint32_t offs, unsigned int size, void *dst)
{
	int block, page, column, readlen;
	int ret;
	int force_bad_block_check = 1;

	page = offs / page_size;
	column = offs % page_size;

	block = page / pages_per_block;
	page = page % pages_per_block;

	while (size) {
		if (force_bad_block_check || page == 0) {
			ret = nand_block_isbad(block);
			if (ret < 0)
				return ret;

			if (ret) {
				block++;
				continue;
			}
		}

		force_bad_block_check = 0;

		if (unlikely(column || size < page_size)) {
			/* Partial page read */
			ret = nand_read_page(page_buffer,
					     block * pages_per_block + page);
			if (ret < 0)
				return ret;

			readlen = min(page_size - column, (int)size);
			memcpy(dst, page_buffer, readlen);

			column = 0;
		} else {
			ret = nand_read_page(dst,
					     block * pages_per_block + page);
			if (ret < 0)
				return ret;

			readlen = page_size;
		}

		size -= readlen;
		dst += readlen;
		page++;
		if (page == pages_per_block) {
			block++;
			page = 0;
		}
	}

	return 0;
}

void nand_deselect(void) {}
