/*
 * Copyright (c) 2015-2018, Renesas Electronics Corporation. All rights
 * reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include <stddef.h>

#include <lib/mmio.h>

#include "emmc_config.h"
#include "emmc_def.h"
#include "emmc_hal.h"
#include "emmc_registers.h"
#include "emmc_std.h"
#include "rcar_def.h"

static EMMC_ERROR_CODE emmc_trans_sector(uint32_t *buff_address_virtual);

uint32_t emmc_interrupt(void)
{
	EMMC_ERROR_CODE result;
	uint32_t prr_data;
	uint32_t cut_ver;
	uint32_t end_bit;

	prr_data = mmio_read_32((uintptr_t) RCAR_PRR);
	cut_ver = prr_data & RCAR_CUT_MASK;
	if ((prr_data & RCAR_PRODUCT_MASK) == RCAR_PRODUCT_H3) {
		if (cut_ver == RCAR_CUT_VER10) {
			end_bit = BIT17;
		} else if (cut_ver == RCAR_CUT_VER11) {
			end_bit = BIT17;
		} else {
			end_bit = BIT20;
		}
	} else if ((prr_data & RCAR_PRODUCT_MASK) == RCAR_PRODUCT_M3) {
		if (cut_ver == RCAR_CUT_VER10) {
			end_bit = BIT17;
		} else {
			end_bit = BIT20;
		}
	} else {
		end_bit = BIT20;
	}

	/* SD_INFO */
	mmc_drv_obj.error_info.info1 = GETR_32(SD_INFO1);
	mmc_drv_obj.error_info.info2 = GETR_32(SD_INFO2);

	/* SD_INFO EVENT */
	mmc_drv_obj.int_event1 =
	    mmc_drv_obj.error_info.info1 & GETR_32(SD_INFO1_MASK);
	mmc_drv_obj.int_event2 =
	    mmc_drv_obj.error_info.info2 & GETR_32(SD_INFO2_MASK);

	/* ERR_STS */
	mmc_drv_obj.error_info.status1 = GETR_32(SD_ERR_STS1);
	mmc_drv_obj.error_info.status2 = GETR_32(SD_ERR_STS2);

	/* DM_CM_INFO */
	mmc_drv_obj.error_info.dm_info1 = GETR_32(DM_CM_INFO1);
	mmc_drv_obj.error_info.dm_info2 = GETR_32(DM_CM_INFO2);

	/* DM_CM_INFO EVENT */
	mmc_drv_obj.dm_event1 =
	    mmc_drv_obj.error_info.dm_info1 & GETR_32(DM_CM_INFO1_MASK);
	mmc_drv_obj.dm_event2 =
	    mmc_drv_obj.error_info.dm_info2 & GETR_32(DM_CM_INFO2_MASK);

	/* ERR SD_INFO2 */
	if ((SD_INFO2_ALL_ERR & mmc_drv_obj.int_event2) != 0) {
		SETR_32(SD_INFO1_MASK, 0x00000000U);	/* interrupt disable */
		SETR_32(SD_INFO2_MASK, SD_INFO2_CLEAR);	/* interrupt disable */
		SETR_32(SD_INFO1, 0x00000000U);	/* interrupt clear */
		SETR_32(SD_INFO2, SD_INFO2_CLEAR);	/* interrupt clear */
		mmc_drv_obj.state_machine_blocking = FALSE;
	}

	/* PIO Transfer */
	/* BWE/BRE */
	else if (((SD_INFO2_BWE | SD_INFO2_BRE) & mmc_drv_obj.int_event2)) {
		/* BWE */
		if (SD_INFO2_BWE & mmc_drv_obj.int_event2) {
			SETR_32(SD_INFO2, (GETR_32(SD_INFO2) & ~SD_INFO2_BWE));
		}
		/* BRE */
		else {
			SETR_32(SD_INFO2, (GETR_32(SD_INFO2) & ~SD_INFO2_BRE));
		}

		result = emmc_trans_sector(mmc_drv_obj.buff_address_virtual);
		mmc_drv_obj.buff_address_virtual += EMMC_BLOCK_LENGTH;
		mmc_drv_obj.remain_size -= EMMC_BLOCK_LENGTH;

		if (result != EMMC_SUCCESS) {
			/* data transfer error */
			emmc_write_error_info(EMMC_FUNCNO_NONE, result);

			/* Panic */
			SETR_32(SD_INFO1_MASK, 0x00000000U);
			SETR_32(SD_INFO2_MASK, SD_INFO2_CLEAR);
			SETR_32(SD_INFO1, 0x00000000U);
			/* interrupt clear */
			SETR_32(SD_INFO2, SD_INFO2_CLEAR);
			mmc_drv_obj.force_terminate = TRUE;
		} else {
			mmc_drv_obj.during_transfer = FALSE;
		}
		mmc_drv_obj.state_machine_blocking = FALSE;
	}

	/* DMA_TRANSFER */
	/* DM_CM_INFO1: DMA-ch0 transfer complete or error occurred */
	else if ((BIT16 & mmc_drv_obj.dm_event1) != 0) {
		SETR_32(DM_CM_INFO1, 0x00000000U);
		SETR_32(DM_CM_INFO2, 0x00000000U);
		/* interrupt clear */
		SETR_32(SD_INFO2, (GETR_32(SD_INFO2) & ~SD_INFO2_BWE));
		/* DM_CM_INFO2:  DMA-ch0 error occured */
		if ((BIT16 & mmc_drv_obj.dm_event2) != 0) {
			mmc_drv_obj.dma_error_flag = TRUE;
		} else {
			mmc_drv_obj.during_dma_transfer = FALSE;
			mmc_drv_obj.during_transfer = FALSE;
		}
		/* wait next interrupt */
		mmc_drv_obj.state_machine_blocking = FALSE;
	}
	/* DM_CM_INFO1: DMA-ch1 transfer complete or error occured */
	else if ((end_bit & mmc_drv_obj.dm_event1) != 0U) {
		SETR_32(DM_CM_INFO1, 0x00000000U);
		SETR_32(DM_CM_INFO2, 0x00000000U);
		/* interrupt clear */
		SETR_32(SD_INFO2, (GETR_32(SD_INFO2) & ~SD_INFO2_BRE));
		/* DM_CM_INFO2: DMA-ch1 error occured */
		if ((BIT17 & mmc_drv_obj.dm_event2) != 0) {
			mmc_drv_obj.dma_error_flag = TRUE;
		} else {
			mmc_drv_obj.during_dma_transfer = FALSE;
			mmc_drv_obj.during_transfer = FALSE;
		}
		/* wait next interrupt */
		mmc_drv_obj.state_machine_blocking = FALSE;
	}

	/* Response end  */
	else if ((SD_INFO1_INFO0 & mmc_drv_obj.int_event1) != 0) {
		/* interrupt clear */
		SETR_32(SD_INFO1, (GETR_32(SD_INFO1) & ~SD_INFO1_INFO0));
		mmc_drv_obj.state_machine_blocking = FALSE;
	}
	/* Access end  */
	else if ((SD_INFO1_INFO2 & mmc_drv_obj.int_event1) != 0) {
		/* interrupt clear */
		SETR_32(SD_INFO1, (GETR_32(SD_INFO1) & ~SD_INFO1_INFO2));
		mmc_drv_obj.state_machine_blocking = FALSE;
	} else {
		/* nothing to do. */
	}

	return (uint32_t) 0;
}

static EMMC_ERROR_CODE emmc_trans_sector(uint32_t *buff_address_virtual)
{
	uint32_t length, i;
	uint64_t *bufPtrLL;

	if (buff_address_virtual == NULL) {
		return EMMC_ERR_PARAM;
	}

	if ((mmc_drv_obj.during_transfer != TRUE)
	    || (mmc_drv_obj.remain_size == 0)) {
		return EMMC_ERR_STATE;
	}

	bufPtrLL = (uint64_t *) buff_address_virtual;
	length = mmc_drv_obj.remain_size;

	/* data transefer */
	for (i = 0; i < (length >> 3); i++) {
		/* Write */
		if (mmc_drv_obj.cmd_info.dir == HAL_MEMCARD_WRITE) {
			SETR_64(SD_BUF0, *bufPtrLL);	/* buffer --> FIFO */
		}
		/* Read */
		else {
			/* Checks when the read data reaches SD_SIZE. */
			/* The BRE bit is cleared at emmc_interrupt function. */
			if (((i %
			      (uint32_t) (EMMC_BLOCK_LENGTH >>
					  EMMC_BUF_SIZE_SHIFT)) == 0U)
			    && (i != 0U)) {
				/* BRE check */
				while (((GETR_32(SD_INFO2)) & SD_INFO2_BRE) ==
				       0U) {
					/* ERROR check */
					if (((GETR_32(SD_INFO2)) &
					     SD_INFO2_ALL_ERR) != 0U) {
						return EMMC_ERR_TRANSFER;
					}
				}
				/* BRE clear */
				SETR_32(SD_INFO2,
					(uint32_t) (GETR_32(SD_INFO2) &
						    ~SD_INFO2_BRE));
			}
			*bufPtrLL = GETR_64(SD_BUF0);	/* FIFO --> buffer */
		}
		bufPtrLL++;
	}

	return EMMC_SUCCESS;
}
