/*
 * Copyright 2008, Freescale Semiconductor, Inc
 * Andy Fleming
 *
 * Based vaguely on the Linux code
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */

#include <config.h>
#include <common.h>
#include <part.h>
#include "mmc_private.h"
#include <malloc.h>

extern bool emmckey_is_access_range_legal(struct mmc *mmc,
		ulong start, lbaint_t blkcnt);

static ulong mmc_erase_t(struct mmc *mmc, ulong start, lbaint_t blkcnt)
{
	struct mmc_cmd cmd;
	ulong end;
	int err, start_cmd, end_cmd;

	if (mmc->high_capacity) {
		end = start + blkcnt - 1;
	} else {
		end = (start + blkcnt - 1) * mmc->write_bl_len;
		start *= mmc->write_bl_len;
	}
	printf("start = 0x%lx,end = 0x%lx\n",start,end);
	if (IS_SD(mmc)) {
		start_cmd = SD_CMD_ERASE_WR_BLK_START;
		end_cmd = SD_CMD_ERASE_WR_BLK_END;
	} else {
		start_cmd = MMC_CMD_ERASE_GROUP_START;
		end_cmd = MMC_CMD_ERASE_GROUP_END;
	}

	cmd.cmdidx = start_cmd;
	cmd.cmdarg = start;
	cmd.resp_type = MMC_RSP_R1;

	err = mmc_send_cmd(mmc, &cmd, NULL);
	if (err)
		goto err_out;

	cmd.cmdidx = end_cmd;
	cmd.cmdarg = end;

	err = mmc_send_cmd(mmc, &cmd, NULL);
	if (err)
		goto err_out;

	cmd.cmdidx = MMC_CMD_ERASE;
	cmd.cmdarg = NORMAL_ERASE;
	cmd.resp_type = MMC_RSP_R1b;

	err = mmc_send_cmd(mmc, &cmd, NULL);
	if (err)
		goto err_out;

	return 0;

err_out:
	puts("mmc erase failed\n");
	return err;
}

unsigned long mmc_berase_becalled(int dev_num, lbaint_t start, lbaint_t blkcnt)
{
	int err = 0;
	struct mmc *mmc = find_mmc_device(dev_num);
	int timeout = 1000;

	if (!mmc)
		return -1;

	err = mmc_erase_t(mmc, start, blkcnt);
	if (err)
		return 1;

	/* Waiting for the ready status */
	if (mmc_send_status(mmc, timeout))
		return 1;

	return 0;
}

/*
 * Function: Zero out blk_len blocks at the blk_addr by writing zeros. The
 *           function can be used when we want to erase the blocks not
 *           aligned with the mmc erase group.
 * Arg     : Block address & length
 * Return  : Returns 0
 * Flow    : Erase the card from specified addr
 */

static uint32_t mmc_zero_out(int dev_num, uint32_t blk_addr, uint32_t num_blks)
{
	uint32_t erase_size = (512 * num_blks);
	uint32_t *out = malloc(erase_size);

	if (out == NULL) {
		printf("mmc zero out: malloc fail\n");
		return 1;
	}
	memset((void *)out, 0, erase_size);

	/* Flush the data to memory before writing to storage */

	if (mmc_bwrite(dev_num, blk_addr, num_blks, out) != num_blks)
	{
		printf("failed to erase the block: %x\n", blk_addr);
		free(out);
		return 1;
	}
	free(out);
	return 0;
}

/*
 * Function: mmc erase
 * Arg     : Block address & length
 * Return  : Returns 0
 * Flow    : Erase the card from specified addr
 */
unsigned long mmc_berase(int dev_num, lbaint_t start, lbaint_t blkcnt)
{
	struct mmc *mmc;
	uint32_t unaligned_blks;
	uint32_t head_unit;
	uint32_t tail_unit;
	uint32_t erase_unit_sz;
	uint64_t blks_to_erase;


	mmc = find_mmc_device(dev_num);
	if (!mmc)
		return 0;

	if (!emmckey_is_access_range_legal(mmc, start, blkcnt))
		return blkcnt;

	if (blkcnt == 0) {

		blkcnt = mmc->capacity/512 - (mmc->capacity/512)% mmc->erase_grp_size; // erase whole
		printf("blkcnt = %lu\n",blkcnt);

		if (mmc_berase_becalled(dev_num, start, blkcnt))
			return 1;
	}

	erase_unit_sz = mmc->erase_grp_size;
	head_unit = start / erase_unit_sz;
	tail_unit = (start + blkcnt - 1) / erase_unit_sz;

	if (tail_unit - head_unit <= 1)
	{
		return mmc_zero_out(dev_num, start, blkcnt);
	}

	unaligned_blks = erase_unit_sz - (start % erase_unit_sz);

	if (unaligned_blks < erase_unit_sz)
	{
		if (mmc_zero_out(dev_num, start, unaligned_blks))
			return 1;

		start += unaligned_blks;
		blkcnt -= unaligned_blks;

		head_unit = start / erase_unit_sz;
		tail_unit = (start + blkcnt - 1) / erase_unit_sz;

		if (tail_unit - head_unit <= 1)
		{
			return mmc_zero_out(dev_num, start, blkcnt);
		}
	}

	unaligned_blks = blkcnt % erase_unit_sz;
	blks_to_erase = blkcnt - unaligned_blks;

	if (mmc_berase_becalled(dev_num, start, blks_to_erase))
	{
		printf("MMC erase failed\n");
		return 1;
	}

	start += blks_to_erase;

	if (unaligned_blks)
	{
		if (mmc_zero_out(dev_num, start, unaligned_blks))
			return 1;
	}


	return 0;
}

static ulong mmc_write_blocks(struct mmc *mmc, lbaint_t start,
		lbaint_t blkcnt, const void *src)
{
	struct mmc_cmd cmd;
	struct mmc_data data;
	int timeout = 1000;
	int ret;

	if ((start + blkcnt) > mmc->block_dev.lba) {
		printf("MMC: block number 0x" LBAF " exceeds max(0x" LBAF ")\n",
		       start + blkcnt, mmc->block_dev.lba);
		return 0;
	}

#ifdef MMC_CMD23
	if (blkcnt > 1) {
		cmd.cmdidx = MMC_CMD_SET_BLOCK_COUNT;
		cmd.cmdarg = blkcnt & 0xFFFF;
		cmd.cmdarg |= 1 << 31;
		cmd.resp_type = MMC_RSP_R1;
		ret = mmc_send_cmd(mmc, &cmd, NULL);
		if (ret) {
			printf("mmc set blkcnt failed\n");
			return 0;
		}
	}
#endif

	if (blkcnt == 0)
		return 0;
	else if (blkcnt == 1)
		cmd.cmdidx = MMC_CMD_WRITE_SINGLE_BLOCK;
	else
		cmd.cmdidx = MMC_CMD_WRITE_MULTIPLE_BLOCK;

	if (mmc->high_capacity)
		cmd.cmdarg = start;
	else
		cmd.cmdarg = start * mmc->write_bl_len;

	cmd.resp_type = MMC_RSP_R1;

	data.src = src;
	data.blocks = blkcnt;
	data.blocksize = mmc->write_bl_len;
	data.flags = MMC_DATA_WRITE;

	ret = mmc_send_cmd(mmc, &cmd, &data);
	if (ret)
		printf("mmc write failed\n");
#ifndef MMC_CMD23
	/* SPI multiblock writes terminate using a special
	 * token, not a STOP_TRANSMISSION request
	 */
	if (!mmc_host_is_spi(mmc) && blkcnt > 1) {
		cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION;
		cmd.cmdarg = 0;
		cmd.resp_type = MMC_RSP_R1b;
		if (mmc_send_cmd(mmc, &cmd, NULL)) {
			printf("mmc fail to send stop cmd\n");
			return 0;
		}
	}
#endif
	if (ret)
		return 0;

	/* Waiting for the ready status */
	if (mmc_send_status(mmc, timeout))
		return 0;

	return blkcnt;
}

ulong mmc_bwrite(int dev_num, lbaint_t start, lbaint_t blkcnt, const void *src)
{
	lbaint_t cur, blocks_todo = blkcnt;

	struct mmc *mmc = find_mmc_device(dev_num);
	if (!mmc)
		return 0;

	if (!emmckey_is_access_range_legal(mmc, start, blkcnt))
		return 0;
#ifndef MMC_HS400_MODE
	if (mmc_set_blocklen(mmc, mmc->write_bl_len))
		return 0;
#endif
	do {
		cur = (blocks_todo > mmc->cfg->b_max) ?
			mmc->cfg->b_max : blocks_todo;
		if (mmc_write_blocks(mmc, start, cur, src) != cur)
			return 0;
		blocks_todo -= cur;
		start += cur;
		src += cur * mmc->write_bl_len;
	} while (blocks_todo > 0);

	return blkcnt;
}

extern int aml_sd_send_cmd_ffu(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data);
ulong mmc_ffu_write(int dev_num, lbaint_t start, lbaint_t blkcnt, const void *src)
{
	struct mmc_cmd cmd;
	struct mmc_data data;
	int ret, timeout = 1000;
	struct mmc *mmc = find_mmc_device(dev_num);
	if (!mmc || !blkcnt)
		return 0;

	printf("mmc ffu start = %lx, cnt = %lx, addr = %p\n", start, blkcnt, src);

	cmd.cmdidx = MMC_CMD_SET_BLOCK_COUNT;
	cmd.cmdarg = blkcnt & 0xFFFF;
	cmd.resp_type = MMC_RSP_R1;
	ret = mmc_send_cmd(mmc, &cmd, NULL);
	if (ret) {
		printf("mmc set blkcnt failed\n");
		return 0;
	}

	cmd.cmdidx = MMC_CMD_WRITE_MULTIPLE_BLOCK;
	cmd.cmdarg = start;
	cmd.resp_type = MMC_RSP_R1b;

	data.src = src;
	data.blocks = blkcnt;
	data.blocksize = mmc->write_bl_len;
	data.flags = MMC_DATA_WRITE;

	ret = aml_sd_send_cmd_ffu(mmc, &cmd, &data);
	if (ret) {
		printf("mmc write failed\n");
		return 0;
	}

	/* Waiting for the ready status */
	if (mmc_send_status(mmc, timeout))
		return 0;

	return blkcnt;
}
