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

/* Define a simple and generic interface to access eMMC and SD-card devices. */

#include <arch_helpers.h>
#include <assert.h>
#include <debug.h>
#include <errno.h>
#include <mmc.h>
#include <stdbool.h>
#include <string.h>
#include <utils.h>

#define MMC_DEFAULT_MAX_RETRIES		5
#define SEND_OP_COND_MAX_RETRIES	100

#define MULT_BY_512K_SHIFT		19

static const struct mmc_ops *ops;
static unsigned int mmc_ocr_value;
static struct mmc_csd_emmc mmc_csd;
static unsigned char mmc_ext_csd[512] __aligned(4);
static unsigned int mmc_flags;
static struct mmc_device_info *mmc_dev_info;
static unsigned int rca;

static const unsigned char tran_speed_base[16] = {
	0, 10, 12, 13, 15, 20, 26, 30, 35, 40, 45, 52, 55, 60, 70, 80
};

static const unsigned char sd_tran_speed_base[16] = {
	0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80
};

static bool is_cmd23_enabled(void)
{
	return ((mmc_flags & MMC_FLAG_CMD23) != 0U);
}

static int mmc_send_cmd(unsigned int idx, unsigned int arg,
			unsigned int r_type, unsigned int *r_data)
{
	struct mmc_cmd cmd;
	int ret;

	zeromem(&cmd, sizeof(struct mmc_cmd));

	cmd.cmd_idx = idx;
	cmd.cmd_arg = arg;
	cmd.resp_type = r_type;

	ret = ops->send_cmd(&cmd);

	if ((ret == 0) && (r_data != NULL)) {
		int i;

		for (i = 0; i < 4; i++) {
			*r_data = cmd.resp_data[i];
			r_data++;
		}
	}

	if (ret != 0) {
		VERBOSE("Send command %u error: %d\n", idx, ret);
	}

	return ret;
}

static int mmc_device_state(void)
{
	int retries = MMC_DEFAULT_MAX_RETRIES;
	unsigned int resp_data[4];

	do {
		int ret;

		if (retries == 0) {
			ERROR("CMD13 failed after %d retries\n",
			      MMC_DEFAULT_MAX_RETRIES);
			return -EIO;
		}

		ret = mmc_send_cmd(MMC_CMD(13), rca << RCA_SHIFT_OFFSET,
				   MMC_RESPONSE_R(1), &resp_data[0]);
		if (ret != 0) {
			return ret;
		}

		if ((resp_data[0] & STATUS_SWITCH_ERROR) != 0U) {
			return -EIO;
		}

		retries--;
	} while ((resp_data[0] & STATUS_READY_FOR_DATA) == 0U);

	return MMC_GET_STATE(resp_data[0]);
}

static int mmc_set_ext_csd(unsigned int ext_cmd, unsigned int value)
{
	int ret;

	ret = mmc_send_cmd(MMC_CMD(6),
			   EXTCSD_WRITE_BYTES | EXTCSD_CMD(ext_cmd) |
			   EXTCSD_VALUE(value) | EXTCSD_CMD_SET_NORMAL,
			   0, NULL);
	if (ret != 0) {
		return ret;
	}

	do {
		ret = mmc_device_state();
		if (ret < 0) {
			return ret;
		}
	} while (ret == MMC_STATE_PRG);

	return 0;
}

static int mmc_sd_switch(unsigned int bus_width)
{
	int ret;
	int retries = MMC_DEFAULT_MAX_RETRIES;
	unsigned int scr[2] = { 0 };
	unsigned int bus_width_arg = 0;

	ret = ops->prepare(0, (uintptr_t)&scr, sizeof(scr));
	if (ret != 0) {
		return ret;
	}

	/* CMD55: Application Specific Command */
	ret = mmc_send_cmd(MMC_CMD(55), rca << RCA_SHIFT_OFFSET,
			   MMC_RESPONSE_R(1), NULL);
	if (ret != 0) {
		return ret;
	}

	/* ACMD51: SEND_SCR */
	do {
		ret = mmc_send_cmd(MMC_ACMD(51), 0, MMC_RESPONSE_R(1), NULL);
		if ((ret != 0) && (retries == 0)) {
			ERROR("ACMD51 failed after %d retries (ret=%d)\n",
			      MMC_DEFAULT_MAX_RETRIES, ret);
			return ret;
		}

		retries--;
	} while (ret != 0);

	ret = ops->read(0, (uintptr_t)&scr, sizeof(scr));
	if (ret != 0) {
		return ret;
	}

	if (((scr[0] & SD_SCR_BUS_WIDTH_4) != 0U) &&
	    (bus_width == MMC_BUS_WIDTH_4)) {
		bus_width_arg = 2;
	}

	/* CMD55: Application Specific Command */
	ret = mmc_send_cmd(MMC_CMD(55), rca << RCA_SHIFT_OFFSET,
			   MMC_RESPONSE_R(1), NULL);
	if (ret != 0) {
		return ret;
	}

	/* ACMD6: SET_BUS_WIDTH */
	ret = mmc_send_cmd(MMC_ACMD(6), bus_width_arg, MMC_RESPONSE_R(1), NULL);
	if (ret != 0) {
		return ret;
	}

	do {
		ret = mmc_device_state();
		if (ret < 0) {
			return ret;
		}
	} while (ret == MMC_STATE_PRG);

	return 0;
}

static int mmc_set_ios(unsigned int clk, unsigned int bus_width)
{
	int ret;
	unsigned int width = bus_width;

	if (mmc_dev_info->mmc_dev_type != MMC_IS_EMMC) {
		if (width == MMC_BUS_WIDTH_8) {
			WARN("Wrong bus config for SD-card, force to 4\n");
			width = MMC_BUS_WIDTH_4;
		}
		ret = mmc_sd_switch(width);
		if (ret != 0) {
			return ret;
		}
	} else if (mmc_csd.spec_vers == 4U) {
		ret = mmc_set_ext_csd(CMD_EXTCSD_BUS_WIDTH,
				      (unsigned int)width);
		if (ret != 0) {
			return ret;
		}
	} else {
		VERBOSE("Wrong MMC type or spec version\n");
	}

	return ops->set_ios(clk, width);
}

static int mmc_fill_device_info(void)
{
	unsigned long long c_size;
	unsigned int speed_idx;
	unsigned int nb_blocks;
	unsigned int freq_unit;
	int ret;
	struct mmc_csd_sd_v2 *csd_sd_v2;

	switch (mmc_dev_info->mmc_dev_type) {
	case MMC_IS_EMMC:
		mmc_dev_info->block_size = MMC_BLOCK_SIZE;

		ret = ops->prepare(0, (uintptr_t)&mmc_ext_csd,
				   sizeof(mmc_ext_csd));
		if (ret != 0) {
			return ret;
		}

		/* MMC CMD8: SEND_EXT_CSD */
		ret = mmc_send_cmd(MMC_CMD(8), 0, MMC_RESPONSE_R(1), NULL);
		if (ret != 0) {
			return ret;
		}

		ret = ops->read(0, (uintptr_t)&mmc_ext_csd,
				sizeof(mmc_ext_csd));
		if (ret != 0) {
			return ret;
		}

		nb_blocks = (mmc_ext_csd[CMD_EXTCSD_SEC_CNT] << 0) |
			    (mmc_ext_csd[CMD_EXTCSD_SEC_CNT + 1] << 8) |
			    (mmc_ext_csd[CMD_EXTCSD_SEC_CNT + 2] << 16) |
			    (mmc_ext_csd[CMD_EXTCSD_SEC_CNT + 3] << 24);

		mmc_dev_info->device_size = (unsigned long long)nb_blocks *
			mmc_dev_info->block_size;

		break;

	case MMC_IS_SD:
		/*
		 * Use the same mmc_csd struct, as required fields here
		 * (READ_BL_LEN, C_SIZE, CSIZE_MULT) are common with eMMC.
		 */
		mmc_dev_info->block_size = BIT_32(mmc_csd.read_bl_len);

		c_size = ((unsigned long long)mmc_csd.c_size_high << 2U) |
			 (unsigned long long)mmc_csd.c_size_low;
		assert(c_size != 0xFFFU);

		mmc_dev_info->device_size = (c_size + 1U) *
					    BIT_64(mmc_csd.c_size_mult + 2U) *
					    mmc_dev_info->block_size;

		break;

	case MMC_IS_SD_HC:
		assert(mmc_csd.csd_structure == 1U);

		mmc_dev_info->block_size = MMC_BLOCK_SIZE;

		/* Need to use mmc_csd_sd_v2 struct */
		csd_sd_v2 = (struct mmc_csd_sd_v2 *)&mmc_csd;
		c_size = ((unsigned long long)csd_sd_v2->c_size_high << 16) |
			 (unsigned long long)csd_sd_v2->c_size_low;

		mmc_dev_info->device_size = (c_size + 1U) << MULT_BY_512K_SHIFT;

		break;

	default:
		ret = -EINVAL;
		break;
	}

	if (ret != 0) {
		return ret;
	}

	speed_idx = (mmc_csd.tran_speed & CSD_TRAN_SPEED_MULT_MASK) >>
			 CSD_TRAN_SPEED_MULT_SHIFT;

	assert(speed_idx > 0U);

	if (mmc_dev_info->mmc_dev_type == MMC_IS_EMMC) {
		mmc_dev_info->max_bus_freq = tran_speed_base[speed_idx];
	} else {
		mmc_dev_info->max_bus_freq = sd_tran_speed_base[speed_idx];
	}

	freq_unit = mmc_csd.tran_speed & CSD_TRAN_SPEED_UNIT_MASK;
	while (freq_unit != 0U) {
		mmc_dev_info->max_bus_freq *= 10U;
		--freq_unit;
	}

	mmc_dev_info->max_bus_freq *= 10000U;

	return 0;
}

static int sd_send_op_cond(void)
{
	int retries = SEND_OP_COND_MAX_RETRIES;
	unsigned int resp_data[4];

	do {
		int ret;

		if (retries == 0) {
			ERROR("ACMD41 failed after %d retries\n",
			      SEND_OP_COND_MAX_RETRIES);
			return -EIO;
		}

		/* CMD55: Application Specific Command */
		ret = mmc_send_cmd(MMC_CMD(55), 0, MMC_RESPONSE_R(1), NULL);
		if (ret != 0) {
			return ret;
		}

		/* ACMD41: SD_SEND_OP_COND */
		ret = mmc_send_cmd(MMC_ACMD(41), OCR_HCS, MMC_RESPONSE_R(3),
				   &resp_data[0]);
		if (ret != 0) {
			return ret;
		}

		retries--;
	} while ((resp_data[0] & OCR_POWERUP) == 0U);

	mmc_ocr_value = resp_data[0];

	if ((mmc_ocr_value & OCR_HCS) != 0U) {
		mmc_dev_info->mmc_dev_type = MMC_IS_SD_HC;
	} else {
		mmc_dev_info->mmc_dev_type = MMC_IS_SD;
	}

	return 0;
}

static int mmc_send_op_cond(void)
{
	int ret;
	int retries = SEND_OP_COND_MAX_RETRIES;
	unsigned int resp_data[4];

	/* CMD0: reset to IDLE */
	ret = mmc_send_cmd(MMC_CMD(0), 0, 0, NULL);
	if (ret != 0) {
		return ret;
	}

	do {
		if (retries == 0) {
			ERROR("CMD1 failed after %d retries\n",
			      SEND_OP_COND_MAX_RETRIES);
			return -EIO;
		}

		/* CMD1: get OCR register (SEND_OP_COND) */
		ret = mmc_send_cmd(MMC_CMD(1), OCR_SECTOR_MODE |
				   OCR_VDD_MIN_2V7 | OCR_VDD_MIN_1V7,
				   MMC_RESPONSE_R(3), &resp_data[0]);
		if (ret != 0) {
			return ret;
		}

		retries--;
	} while ((resp_data[0] & OCR_POWERUP) == 0U);

	mmc_ocr_value = resp_data[0];

	return 0;
}

static int mmc_enumerate(unsigned int clk, unsigned int bus_width)
{
	int ret;
	unsigned int resp_data[4];

	ops->init();

	/* CMD0: reset to IDLE */
	ret = mmc_send_cmd(MMC_CMD(0), 0, 0, NULL);
	if (ret != 0) {
		return ret;
	}

	/* CMD8: Send Interface Condition Command */
	ret = mmc_send_cmd(MMC_CMD(8), VHS_2_7_3_6_V | CMD8_CHECK_PATTERN,
			   MMC_RESPONSE_R(7), &resp_data[0]);

	if ((ret == 0) && ((resp_data[0] & 0xffU) == CMD8_CHECK_PATTERN)) {
		ret = sd_send_op_cond();
	} else {
		ret = mmc_send_op_cond();
	}
	if (ret != 0) {
		return ret;
	}

	/* CMD2: Card Identification */
	ret = mmc_send_cmd(MMC_CMD(2), 0, MMC_RESPONSE_R(2), NULL);
	if (ret != 0) {
		return ret;
	}

	/* CMD3: Set Relative Address */
	if (mmc_dev_info->mmc_dev_type == MMC_IS_EMMC) {
		rca = MMC_FIX_RCA;
		ret = mmc_send_cmd(MMC_CMD(3), rca << RCA_SHIFT_OFFSET,
				   MMC_RESPONSE_R(1), NULL);
		if (ret != 0) {
			return ret;
		}
	} else {
		ret = mmc_send_cmd(MMC_CMD(3), 0,
				   MMC_RESPONSE_R(6), &resp_data[0]);
		if (ret != 0) {
			return ret;
		}

		rca = (resp_data[0] & 0xFFFF0000U) >> 16;
	}

	/* CMD9: CSD Register */
	ret = mmc_send_cmd(MMC_CMD(9), rca << RCA_SHIFT_OFFSET,
			   MMC_RESPONSE_R(2), &resp_data[0]);
	if (ret != 0) {
		return ret;
	}

	memcpy(&mmc_csd, &resp_data, sizeof(resp_data));

	/* CMD7: Select Card */
	ret = mmc_send_cmd(MMC_CMD(7), rca << RCA_SHIFT_OFFSET,
			   MMC_RESPONSE_R(1), NULL);
	if (ret != 0) {
		return ret;
	}

	do {
		ret = mmc_device_state();
		if (ret < 0) {
			return ret;
		}
	} while (ret != MMC_STATE_TRAN);

	ret = mmc_fill_device_info();
	if (ret != 0) {
		return ret;
	}

	return mmc_set_ios(clk, bus_width);
}

size_t mmc_read_blocks(unsigned int lba, uintptr_t buf, size_t size)
{
	int ret;
	unsigned int cmd_idx, cmd_arg;

	assert((ops != NULL) &&
	       (ops->read != NULL) &&
	       (size != 0U) &&
	       ((size & MMC_BLOCK_MASK) == 0U));

	ret = ops->prepare(lba, buf, size);
	if (ret != 0) {
		return 0;
	}

	if (is_cmd23_enabled()) {
		/* Set block count */
		ret = mmc_send_cmd(MMC_CMD(23), size / MMC_BLOCK_SIZE,
				   MMC_RESPONSE_R(1), NULL);
		if (ret != 0) {
			return 0;
		}

		cmd_idx = MMC_CMD(18);
	} else {
		if (size > MMC_BLOCK_SIZE) {
			cmd_idx = MMC_CMD(18);
		} else {
			cmd_idx = MMC_CMD(17);
		}
	}

	if (((mmc_ocr_value & OCR_ACCESS_MODE_MASK) == OCR_BYTE_MODE) &&
	    (mmc_dev_info->mmc_dev_type != MMC_IS_SD_HC)) {
		cmd_arg = lba * MMC_BLOCK_SIZE;
	} else {
		cmd_arg = lba;
	}

	ret = mmc_send_cmd(cmd_idx, cmd_arg, MMC_RESPONSE_R(1), NULL);
	if (ret != 0) {
		return 0;
	}

	ret = ops->read(lba, buf, size);
	if (ret != 0) {
		return 0;
	}

	/* Wait buffer empty */
	do {
		ret = mmc_device_state();
		if (ret < 0) {
			return 0;
		}
	} while ((ret != MMC_STATE_TRAN) && (ret != MMC_STATE_DATA));

	if (!is_cmd23_enabled() && (size > MMC_BLOCK_SIZE)) {
		ret = mmc_send_cmd(MMC_CMD(12), 0, 0, NULL);
		if (ret != 0) {
			return 0;
		}
	}

	return size;
}

size_t mmc_write_blocks(unsigned int lba, const uintptr_t buf, size_t size)
{
	int ret;
	unsigned int cmd_idx, cmd_arg;

	assert((ops != NULL) &&
	       (ops->write != NULL) &&
	       (size != 0U) &&
	       ((buf & MMC_BLOCK_MASK) == 0U) &&
	       ((size & MMC_BLOCK_MASK) == 0U));

	ret = ops->prepare(lba, buf, size);
	if (ret != 0) {
		return 0;
	}

	if (is_cmd23_enabled()) {
		/* Set block count */
		ret = mmc_send_cmd(MMC_CMD(23), size / MMC_BLOCK_SIZE,
				   MMC_RESPONSE_R(1), NULL);
		if (ret != 0) {
			return 0;
		}

		cmd_idx = MMC_CMD(25);
	} else {
		if (size > MMC_BLOCK_SIZE) {
			cmd_idx = MMC_CMD(25);
		} else {
			cmd_idx = MMC_CMD(24);
		}
	}

	if ((mmc_ocr_value & OCR_ACCESS_MODE_MASK) == OCR_BYTE_MODE) {
		cmd_arg = lba * MMC_BLOCK_SIZE;
	} else {
		cmd_arg = lba;
	}

	ret = mmc_send_cmd(cmd_idx, cmd_arg, MMC_RESPONSE_R(1), NULL);
	if (ret != 0) {
		return 0;
	}

	ret = ops->write(lba, buf, size);
	if (ret != 0) {
		return 0;
	}

	/* Wait buffer empty */
	do {
		ret = mmc_device_state();
		if (ret < 0) {
			return 0;
		}
	} while ((ret != MMC_STATE_TRAN) && (ret != MMC_STATE_RCV));

	if (!is_cmd23_enabled() && (size > MMC_BLOCK_SIZE)) {
		ret = mmc_send_cmd(MMC_CMD(12), 0, 0, NULL);
		if (ret != 0) {
			return 0;
		}
	}

	return size;
}

size_t mmc_erase_blocks(unsigned int lba, size_t size)
{
	int ret;

	assert(ops != NULL);
	assert((size != 0U) && ((size & MMC_BLOCK_MASK) == 0U));

	ret = mmc_send_cmd(MMC_CMD(35), lba, MMC_RESPONSE_R(1), NULL);
	if (ret != 0) {
		return 0;
	}

	ret = mmc_send_cmd(MMC_CMD(36), lba + (size / MMC_BLOCK_SIZE) - 1U,
			   MMC_RESPONSE_R(1), NULL);
	if (ret != 0) {
		return 0;
	}

	ret = mmc_send_cmd(MMC_CMD(38), lba, MMC_RESPONSE_R(0x1B), NULL);
	if (ret != 0) {
		return 0;
	}

	do {
		ret = mmc_device_state();
		if (ret < 0) {
			return 0;
		}
	} while (ret != MMC_STATE_TRAN);

	return size;
}

static inline void mmc_rpmb_enable(void)
{
	mmc_set_ext_csd(CMD_EXTCSD_PARTITION_CONFIG,
			PART_CFG_BOOT_PARTITION1_ENABLE |
			PART_CFG_PARTITION1_ACCESS);
}

static inline void mmc_rpmb_disable(void)
{
	mmc_set_ext_csd(CMD_EXTCSD_PARTITION_CONFIG,
			PART_CFG_BOOT_PARTITION1_ENABLE);
}

size_t mmc_rpmb_read_blocks(unsigned int lba, uintptr_t buf, size_t size)
{
	size_t size_read;

	mmc_rpmb_enable();
	size_read = mmc_read_blocks(lba, buf, size);
	mmc_rpmb_disable();

	return size_read;
}

size_t mmc_rpmb_write_blocks(unsigned int lba, const uintptr_t buf, size_t size)
{
	size_t size_written;

	mmc_rpmb_enable();
	size_written = mmc_write_blocks(lba, buf, size);
	mmc_rpmb_disable();

	return size_written;
}

size_t mmc_rpmb_erase_blocks(unsigned int lba, size_t size)
{
	size_t size_erased;

	mmc_rpmb_enable();
	size_erased = mmc_erase_blocks(lba, size);
	mmc_rpmb_disable();

	return size_erased;
}

int mmc_init(const struct mmc_ops *ops_ptr, unsigned int clk,
	     unsigned int width, unsigned int flags,
	     struct mmc_device_info *device_info)
{
	assert((ops_ptr != NULL) &&
	       (ops_ptr->init != NULL) &&
	       (ops_ptr->send_cmd != NULL) &&
	       (ops_ptr->set_ios != NULL) &&
	       (ops_ptr->prepare != NULL) &&
	       (ops_ptr->read != NULL) &&
	       (ops_ptr->write != NULL) &&
	       (device_info != NULL) &&
	       (clk != 0) &&
	       ((width == MMC_BUS_WIDTH_1) ||
		(width == MMC_BUS_WIDTH_4) ||
		(width == MMC_BUS_WIDTH_8) ||
		(width == MMC_BUS_WIDTH_DDR_4) ||
		(width == MMC_BUS_WIDTH_DDR_8)));

	ops = ops_ptr;
	mmc_flags = flags;
	mmc_dev_info = device_info;

	return mmc_enumerate(clk, width);
}
