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


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

#include <mmio.h>
#include <stddef.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;
}
