/*
 * Copyright (c) 2016 - 2020, Broadcom
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include <string.h>

#include <emmc_api.h>
#include <cmn_plat_util.h>

#define MAX_CMD_RETRY      10

#if EMMC_USE_DMA
#define USE_DMA 1
#else
#define USE_DMA 0
#endif

struct emmc_global_buffer emmc_global_buf;
struct emmc_global_buffer *emmc_global_buf_ptr = &emmc_global_buf;

struct emmc_global_vars emmc_global_vars;
struct emmc_global_vars *emmc_global_vars_ptr = &emmc_global_vars;

static struct sd_handle *sdio_gethandle(void);
static uint32_t sdio_idle(struct sd_handle *p_sdhandle);

static uint32_t sdio_read(struct sd_handle *p_sdhandle,
			  uintptr_t mem_addr,
			  uintptr_t storage_addr,
			  size_t storage_size,
			  size_t bytes_to_read);

#ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE
static uint32_t sdio_write(struct sd_handle *p_sdhandle,
			   uintptr_t mem_addr,
			   uintptr_t data_addr,
			   size_t bytes_to_write);
#endif

static struct sd_handle *sdio_init(void);
static int32_t bcm_emmc_card_ready_state(struct sd_handle *p_sdhandle);

static void init_globals(void)
{
	memset((void *)emmc_global_buf_ptr, 0, sizeof(*emmc_global_buf_ptr));
	memset((void *)emmc_global_vars_ptr, 0, sizeof(*emmc_global_vars_ptr));
}

/*
 * This function is used to change partition
 */
uint32_t emmc_partition_select(uint32_t partition)
{
	int rc;
	struct sd_handle *sd_handle = sdio_gethandle();

	if (sd_handle->device == 0) {
		EMMC_TRACE("eMMC init is not done");
		return 0;
	}

	switch (partition) {
	case EMMC_BOOT_PARTITION1:
		rc = set_boot_config(sd_handle,
				     SDIO_HW_EMMC_EXT_CSD_BOOT_ACC_BOOT1);
		EMMC_TRACE(
		     "Change to Boot Partition 1 result:%d  (0 means SD_OK)\n",
		     rc);
		break;

	case EMMC_BOOT_PARTITION2:
		rc = set_boot_config(sd_handle,
				     SDIO_HW_EMMC_EXT_CSD_BOOT_ACC_BOOT2);
		EMMC_TRACE(
		     "Change to Boot Partition 2 result:%d  (0 means SD_OK)\n",
		     rc);
		break;

	case EMMC_USE_CURRENT_PARTITION:
		rc = SD_OK;
		EMMC_TRACE("Stay on current partition");
		break;

	case EMMC_USER_AREA:
	default:
		rc = set_boot_config(sd_handle,
				     SDIO_HW_EMMC_EXT_CSD_BOOT_ACC_USER);
		EMMC_TRACE("Change to User area result:%d  (0 means SD_OK)\n",
			   rc);
		break;

	}
	return (rc == SD_OK);
}

/*
 * Initialize emmc controller for eMMC
 * Returns 0 on fail condition
 */
uint32_t bcm_emmc_init(bool card_rdy_only)
{
	struct sd_handle *p_sdhandle;
	uint32_t result = 0;

	EMMC_TRACE("Enter emmc_controller_init()\n");

	/* If eMMC is already initialized, skip init */
	if (emmc_global_vars_ptr->init_done)
		return 1;

	init_globals();

	p_sdhandle = sdio_init();

	if (p_sdhandle == NULL) {
		ERROR("eMMC init failed");
		return result;
	}

	if (card_rdy_only) {
		/* Put the card in Ready state, Not complete init */
		result = bcm_emmc_card_ready_state(p_sdhandle);
		return !result;
	}

	if (sdio_idle(p_sdhandle) == EMMC_BOOT_OK) {
		set_config(p_sdhandle, SD_NORMAL_SPEED, MAX_CMD_RETRY, USE_DMA,
			   SD_DMA_BOUNDARY_256K, EMMC_BLOCK_SIZE,
			   EMMC_WFE_RETRY);

		if (!select_blk_sz(p_sdhandle,
				   p_sdhandle->device->cfg.blockSize)) {
			emmc_global_vars_ptr->init_done = 1;
			result = 1;
		} else {
			ERROR("Select Block Size failed\n");
		}
	} else {
		ERROR("eMMC init failed");
	}

	/* Initialization is failed, so deinit HW setting */
	if (result == 0)
		emmc_deinit();

	return result;
}

/*
 * Function to de-init SDIO controller for eMMC
 */
void emmc_deinit(void)
{
	emmc_global_vars_ptr->init_done = 0;
	emmc_global_vars_ptr->sdHandle.card = 0;
	emmc_global_vars_ptr->sdHandle.device = 0;
}

/*
 * Read eMMC memory
 * Returns read_size
 */
uint32_t emmc_read(uintptr_t mem_addr, uintptr_t storage_addr,
		   size_t storage_size, size_t bytes_to_read)
{
	struct sd_handle *sd_handle = sdio_gethandle();

	if (sd_handle->device == 0) {
		EMMC_TRACE("eMMC init is not done");
		return 0;
	}

	return sdio_read(sdio_gethandle(), mem_addr, storage_addr,
			 storage_size, bytes_to_read);
}

#ifdef INCLUDE_EMMC_DRIVER_ERASE_CODE
#define EXT_CSD_ERASE_GRP_SIZE 224

static int emmc_block_erase(uintptr_t mem_addr, size_t blocks)
{
	struct sd_handle *sd_handle = sdio_gethandle();

	if (sd_handle->device == 0) {
		ERROR("eMMC init is not done");
		return -1;
	}

	return erase_card(sdio_gethandle(), mem_addr, blocks);
}

int emmc_erase(uintptr_t mem_addr, size_t num_of_blocks, uint32_t partition)
{
	int err = 0;
	size_t block_count = 0, blocks = 0;
	size_t erase_group = 0;

	erase_group =
	emmc_global_buf_ptr->u.Ext_CSD_storage[EXT_CSD_ERASE_GRP_SIZE]*1024;

	INFO("eMMC Erase Group Size=0x%lx\n", erase_group);

	emmc_partition_select(partition);

	while (block_count < num_of_blocks) {
		blocks = ((num_of_blocks - block_count) > erase_group) ?
				  erase_group : (num_of_blocks - block_count);
			err = emmc_block_erase(mem_addr + block_count, blocks);
		if (err)
			break;

		block_count += blocks;
	}

	if (err == 0)
		INFO("eMMC Erase of partition %d successful\n", partition);
	else
		ERROR("eMMC Erase of partition %d Failed(%i)\n", partition, err);

	return err;
}
#endif

#ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE
/*
 * Write to eMMC memory
 * Returns written_size
 */
uint32_t emmc_write(uintptr_t mem_addr, uintptr_t data_addr,
		    size_t bytes_to_write)
{
	struct sd_handle *sd_handle = sdio_gethandle();

	if (sd_handle->device == 0) {
		EMMC_TRACE("eMMC init is not done");
		return 0;
	}

	return sdio_write(sd_handle, mem_addr, data_addr, bytes_to_write);
}
#endif

/*
 * Send SDIO Cmd
 * Return 0 for pass condition
 */
uint32_t send_sdio_cmd(uint32_t cmdIndex, uint32_t argument,
		       uint32_t options, struct sd_resp *resp)
{
	struct sd_handle *sd_handle = sdio_gethandle();

	if (sd_handle->device == 0) {
		EMMC_TRACE("eMMC init is not done");
		return 1;
	}

	return send_cmd(sd_handle, cmdIndex, argument, options, resp);
}


/*
 * This function return SDIO handle
 */
struct sd_handle *sdio_gethandle(void)
{
	return &emmc_global_vars_ptr->sdHandle;
}

/*
 * Initialize SDIO controller
 */
struct sd_handle *sdio_init(void)
{
	uint32_t SDIO_base;
	struct sd_handle *p_sdhandle = &emmc_global_vars_ptr->sdHandle;

	SDIO_base = EMMC_CTRL_REGS_BASE_ADDR;

	if (SDIO_base == SDIO0_EMMCSDXC_SYSADDR) {
		EMMC_TRACE(" ---> for SDIO 0 Controller\n\n");
	}

	memset(p_sdhandle, 0, sizeof(struct sd_handle));

	p_sdhandle->device = &emmc_global_vars_ptr->sdDevice;
	p_sdhandle->card = &emmc_global_vars_ptr->sdCard;

	memset(p_sdhandle->device, 0, sizeof(struct sd_dev));
	memset(p_sdhandle->card, 0, sizeof(struct sd_card_info));

	if (chal_sd_start((CHAL_HANDLE *) p_sdhandle->device,
			  SD_PIO_MODE, SDIO_base, SDIO_base) != SD_OK) {
		return NULL;
	}

	set_config(p_sdhandle, SD_NORMAL_SPEED, MAX_CMD_RETRY, SD_DMA_OFF,
		   SD_DMA_BOUNDARY_4K, EMMC_BLOCK_SIZE, EMMC_WFE_RETRY);

	return &emmc_global_vars_ptr->sdHandle;
}

uint32_t sdio_idle(struct sd_handle *p_sdhandle)
{
	reset_card(p_sdhandle);

	SD_US_DELAY(1000);

	if (init_card(p_sdhandle, SD_CARD_DETECT_MMC) != SD_OK) {
		reset_card(p_sdhandle);
		reset_host_ctrl(p_sdhandle);
		return EMMC_BOOT_NO_CARD;
	}

	return EMMC_BOOT_OK;
}

/*
 * This function read eMMC
 */
uint32_t sdio_read(struct sd_handle *p_sdhandle,
		   uintptr_t mem_addr,
		   uintptr_t storage_addr,
		   size_t storage_size, size_t bytes_to_read)
{
	uint32_t offset = 0, blockAddr, readLen = 0, rdCount;
	uint32_t remSize, manual_copy_size;
	uint8_t *outputBuf = (uint8_t *) storage_addr;
	const size_t blockSize = p_sdhandle->device->cfg.blockSize;

	VERBOSE("EMMC READ: dst=0x%lx, src=0x%lx, size=0x%lx\n",
			storage_addr, mem_addr, bytes_to_read);

	if (storage_size < bytes_to_read) {
		/* Don't have sufficient storage to complete the operation */
		return 0;
	}

	/* Range check non high capacity memory */
	if ((p_sdhandle->device->ctrl.ocr & SD_CARD_HIGH_CAPACITY) == 0) {
		if (mem_addr > 0x80000000) {
			return 0;
		}
	}

	/* High capacity card use block address mode */
	if (p_sdhandle->device->ctrl.ocr & SD_CARD_HIGH_CAPACITY) {
		blockAddr = (uint32_t) (mem_addr / blockSize);
		offset = (uint32_t) (mem_addr - (blockAddr * blockSize));
	} else {
		blockAddr = (uint32_t) (mem_addr / blockSize) * blockSize;
		offset = (uint32_t) (mem_addr - blockAddr);
	}

	remSize = bytes_to_read;

	rdCount = 0;

	/* Process first unaligned block of MAX_READ_LENGTH */
	if (offset > 0) {
		if (!read_block(p_sdhandle, emmc_global_buf_ptr->u.tempbuf,
				blockAddr, SD_MAX_READ_LENGTH)) {

			if (remSize < (blockSize - offset)) {
				rdCount += remSize;
				manual_copy_size = remSize;
				remSize = 0;	/* read is done */
			} else {
				remSize -= (blockSize - offset);
				rdCount += (blockSize - offset);
				manual_copy_size = blockSize - offset;
			}

			/* Check for overflow */
			if (manual_copy_size > storage_size ||
			    (((uintptr_t)outputBuf + manual_copy_size) >
			     (storage_addr + storage_size))) {
				ERROR("EMMC READ: Overflow 1\n");
				return 0;
			}

			memcpy(outputBuf,
			       (void *)((uintptr_t)
				(emmc_global_buf_ptr->u.tempbuf + offset)),
			       manual_copy_size);

			/* Update Physical address */
			outputBuf += manual_copy_size;

			if (p_sdhandle->device->ctrl.ocr & SD_CARD_HIGH_CAPACITY) {
				blockAddr++;
			} else {
				blockAddr += blockSize;
			}
		} else {
			return 0;
		}
	}

	while (remSize >= blockSize) {

		if (remSize >= SD_MAX_BLK_TRANSFER_LENGTH) {
			readLen = SD_MAX_BLK_TRANSFER_LENGTH;
		} else {
			readLen = (remSize / blockSize) * blockSize;
		}

		/* Check for overflow */
		if ((rdCount + readLen) > storage_size ||
		    (((uintptr_t) outputBuf + readLen) >
		     (storage_addr + storage_size))) {
			ERROR("EMMC READ: Overflow\n");
			return 0;
		}

		if (!read_block(p_sdhandle, outputBuf, blockAddr, readLen)) {
			if (p_sdhandle->device->ctrl.ocr & SD_CARD_HIGH_CAPACITY) {
				blockAddr += (readLen / blockSize);
			} else {
				blockAddr += readLen;
			}

			remSize -= readLen;
			rdCount += readLen;

			/* Update Physical address */
			outputBuf += readLen;
		} else {
			return 0;
		}
	}

	/* process the last unaligned block reading */
	if (remSize > 0) {
		if (!read_block(p_sdhandle, emmc_global_buf_ptr->u.tempbuf,
				blockAddr, SD_MAX_READ_LENGTH)) {

			rdCount += remSize;
			/* Check for overflow */
			if (rdCount > storage_size ||
			    (((uintptr_t) outputBuf + remSize) >
			     (storage_addr + storage_size))) {
				ERROR("EMMC READ: Overflow\n");
				return 0;
			}

			memcpy(outputBuf,
				emmc_global_buf_ptr->u.tempbuf, remSize);

			/* Update Physical address */
			outputBuf += remSize;
		} else {
			rdCount = 0;
		}
	}

	return rdCount;
}

#ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE
static uint32_t sdio_write(struct sd_handle *p_sdhandle, uintptr_t mem_addr,
			   uintptr_t data_addr, size_t bytes_to_write)
{

	uint32_t offset, blockAddr, writeLen, wtCount = 0;
	uint32_t remSize, manual_copy_size = 0;

	uint8_t *inputBuf = (uint8_t *)data_addr;

	/* range check non high capacity memory */
	if ((p_sdhandle->device->ctrl.ocr & SD_CARD_HIGH_CAPACITY) == 0) {
		if (mem_addr > 0x80000000) {
			return 0;
		}
	}

	/* the high capacity card use block address mode */
	if (p_sdhandle->device->ctrl.ocr & SD_CARD_HIGH_CAPACITY) {
		blockAddr =
		    (uint32_t)(mem_addr / p_sdhandle->device->cfg.blockSize);
		offset =
		    (uint32_t)(mem_addr -
			       blockAddr * p_sdhandle->device->cfg.blockSize);
	} else {
		blockAddr =
		    ((uint32_t)mem_addr / p_sdhandle->device->cfg.blockSize) *
		    p_sdhandle->device->cfg.blockSize;
		offset = (uint32_t) mem_addr - blockAddr;
	}

	remSize = bytes_to_write;

	wtCount = 0;

	/* process first unaligned block */
	if (offset > 0) {
		if (!read_block(p_sdhandle, emmc_global_buf_ptr->u.tempbuf,
				blockAddr, p_sdhandle->device->cfg.blockSize)) {

			if (remSize <
			    (p_sdhandle->device->cfg.blockSize - offset)) {
				manual_copy_size = remSize;
			} else {
				manual_copy_size =
				    p_sdhandle->device->cfg.blockSize - offset;
			}

			memcpy((void *)((uintptr_t)
				(emmc_global_buf_ptr->u.tempbuf + offset)),
			       inputBuf,
			       manual_copy_size);

			/* Update Physical address */

			if (!write_block(p_sdhandle,
					 emmc_global_buf_ptr->u.tempbuf,
					 blockAddr,
					 p_sdhandle->device->cfg.blockSize)) {

				if (remSize <
				    (p_sdhandle->device->cfg.blockSize -
				     offset)) {
					wtCount += remSize;
					manual_copy_size = remSize;
					remSize = 0;	/* read is done */
				} else {
					remSize -=
					    (p_sdhandle->device->cfg.blockSize -
					     offset);
					wtCount +=
					    (p_sdhandle->device->cfg.blockSize -
					     offset);
					manual_copy_size =
					    p_sdhandle->device->cfg.blockSize -
					    offset;
				}

				inputBuf += manual_copy_size;

				if (p_sdhandle->device->ctrl.ocr &
				    SD_CARD_HIGH_CAPACITY) {
					blockAddr++;
				} else {
					blockAddr +=
					    p_sdhandle->device->cfg.blockSize;
				}
			} else
				return 0;
		} else {
			return 0;
		}
	}

	/* process block writing */
	while (remSize >= p_sdhandle->device->cfg.blockSize) {
		if (remSize >= SD_MAX_READ_LENGTH) {
			writeLen = SD_MAX_READ_LENGTH;
		} else {
			writeLen =
			    (remSize / p_sdhandle->device->cfg.blockSize) *
			     p_sdhandle->device->cfg.blockSize;
		}

		if (!write_block(p_sdhandle, inputBuf, blockAddr, writeLen)) {
			if (p_sdhandle->device->ctrl.ocr & SD_CARD_HIGH_CAPACITY)
				blockAddr +=
				    (writeLen /
				     p_sdhandle->device->cfg.blockSize);
			else
				blockAddr += writeLen;

			remSize -= writeLen;
			wtCount += writeLen;
			inputBuf += writeLen;
		} else {
			return 0;
		}
	}

	/* process the last unaligned block reading */
	if (remSize > 0) {
		if (!read_block(p_sdhandle,
				emmc_global_buf_ptr->u.tempbuf,
				blockAddr, p_sdhandle->device->cfg.blockSize)) {

			memcpy(emmc_global_buf_ptr->u.tempbuf,
			       inputBuf, remSize);

			/* Update Physical address */

			if (!write_block(p_sdhandle,
					 emmc_global_buf_ptr->u.tempbuf,
					 blockAddr,
					 p_sdhandle->device->cfg.blockSize)) {
				wtCount += remSize;
				inputBuf += remSize;
			} else {
				return 0;
			}
		} else {
			wtCount = 0;
		}
	}

	return wtCount;
}
#endif

/*
 * Function to put the card in Ready state by sending CMD0 and CMD1
 */
static int32_t bcm_emmc_card_ready_state(struct sd_handle *p_sdhandle)
{
	int32_t result = 0;
	uint32_t argument = MMC_CMD_IDLE_RESET_ARG; /* Exit from Boot mode */

	if (p_sdhandle) {
		send_sdio_cmd(SD_CMD_GO_IDLE_STATE, argument, 0, NULL);

		result = reset_card(p_sdhandle);
		if (result != SD_OK) {
			EMMC_TRACE("eMMC Reset error\n");
			return SD_RESET_ERROR;
		}
		SD_US_DELAY(2000);
		result = mmc_cmd1(p_sdhandle);
	}

	return result;
}
