rcar_gen3: drivers: emmc

Signed-off-by: ldts <jramirez@baylibre.com>
diff --git a/drivers/renesas/rcar/emmc/emmc_interrupt.c b/drivers/renesas/rcar/emmc/emmc_interrupt.c
new file mode 100644
index 0000000..3077db4
--- /dev/null
+++ b/drivers/renesas/rcar/emmc/emmc_interrupt.c
@@ -0,0 +1,217 @@
+/*
+ * 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;
+}