mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-18 10:34:19 +00:00

Enforce full include path for includes. Deprecate old paths. The following folders inside include/lib have been left unchanged: - include/lib/cpus/${ARCH} - include/lib/el3_runtime/${ARCH} The reason for this change is that having a global namespace for includes isn't a good idea. It defeats one of the advantages of having folders and it introduces problems that are sometimes subtle (because you may not know the header you are actually including if there are two of them). For example, this patch had to be created because two headers were called the same way:e0ea0928d5
("Fix gpio includes of mt8173 platform to avoid collision."). More recently, this patch has had similar problems:46f9b2c3a2
("drivers: add tzc380 support"). This problem was introduced in commit4ecca33988
("Move include and source files to logical locations"). At that time, there weren't too many headers so it wasn't a real issue. However, time has shown that this creates problems. Platforms that want to preserve the way they include headers may add the removed paths to PLAT_INCLUDES, but this is discouraged. Change-Id: I39dc53ed98f9e297a5966e723d1936d6ccf2fc8f Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
492 lines
12 KiB
C
492 lines
12 KiB
C
/*
|
|
* Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
|
|
#include <common/debug.h>
|
|
|
|
#include "emmc_config.h"
|
|
#include "emmc_hal.h"
|
|
#include "emmc_std.h"
|
|
#include "emmc_registers.h"
|
|
#include "emmc_def.h"
|
|
#include "micro_delay.h"
|
|
|
|
static void emmc_little_to_big(uint8_t *p, uint32_t value)
|
|
{
|
|
if (p == NULL)
|
|
return;
|
|
|
|
p[0] = (uint8_t) (value >> 24);
|
|
p[1] = (uint8_t) (value >> 16);
|
|
p[2] = (uint8_t) (value >> 8);
|
|
p[3] = (uint8_t) value;
|
|
}
|
|
|
|
static void emmc_softreset(void)
|
|
{
|
|
int32_t loop = 10000;
|
|
int32_t retry = 1000;
|
|
|
|
/* flag clear */
|
|
mmc_drv_obj.during_cmd_processing = FALSE;
|
|
mmc_drv_obj.during_transfer = FALSE;
|
|
mmc_drv_obj.during_dma_transfer = FALSE;
|
|
mmc_drv_obj.state_machine_blocking = FALSE;
|
|
mmc_drv_obj.force_terminate = FALSE;
|
|
mmc_drv_obj.dma_error_flag = FALSE;
|
|
|
|
/* during operation ? */
|
|
if ((GETR_32(SD_INFO2) & SD_INFO2_CBSY) == 0)
|
|
goto reset;
|
|
|
|
/* wait CMDSEQ = 0 */
|
|
while (loop > 0) {
|
|
if ((GETR_32(SD_INFO2) & SD_INFO2_CBSY) == 0)
|
|
break; /* ready */
|
|
|
|
loop--;
|
|
if ((loop == 0) && (retry > 0)) {
|
|
rcar_micro_delay(1000U); /* wait 1ms */
|
|
loop = 10000;
|
|
retry--;
|
|
}
|
|
}
|
|
|
|
reset:
|
|
/* reset */
|
|
SETR_32(SOFT_RST, (GETR_32(SOFT_RST) & (~SOFT_RST_SDRST)));
|
|
SETR_32(SOFT_RST, (GETR_32(SOFT_RST) | SOFT_RST_SDRST));
|
|
|
|
/* initialize */
|
|
SETR_32(SD_INFO1, 0x00000000U);
|
|
SETR_32(SD_INFO2, SD_INFO2_CLEAR);
|
|
SETR_32(SD_INFO1_MASK, 0x00000000U); /* all interrupt disable */
|
|
SETR_32(SD_INFO2_MASK, SD_INFO2_CLEAR); /* all interrupt disable */
|
|
|
|
}
|
|
|
|
static void emmc_read_response(uint32_t *response)
|
|
{
|
|
uint8_t *p;
|
|
|
|
if (response == NULL)
|
|
return;
|
|
|
|
/* read response */
|
|
if (mmc_drv_obj.response_length != EMMC_MAX_RESPONSE_LENGTH) {
|
|
*response = GETR_32(SD_RSP10); /* [39:8] */
|
|
return;
|
|
}
|
|
|
|
/* CSD or CID */
|
|
p = (uint8_t *) (response);
|
|
emmc_little_to_big(p, ((GETR_32(SD_RSP76) << 8)
|
|
| (GETR_32(SD_RSP54) >> 24))); /* [127:96] */
|
|
emmc_little_to_big(p + 4, ((GETR_32(SD_RSP54) << 8)
|
|
| (GETR_32(SD_RSP32) >> 24))); /* [95:64] */
|
|
emmc_little_to_big(p + 8, ((GETR_32(SD_RSP32) << 8)
|
|
| (GETR_32(SD_RSP10) >> 24))); /* [63:32] */
|
|
emmc_little_to_big(p + 12, (GETR_32(SD_RSP10) << 8));
|
|
}
|
|
|
|
static EMMC_ERROR_CODE emmc_response_check(uint32_t *response,
|
|
uint32_t error_mask)
|
|
{
|
|
|
|
HAL_MEMCARD_RESPONSE_TYPE response_type =
|
|
(HAL_MEMCARD_RESPONSE_TYPE) (mmc_drv_obj.cmd_info.
|
|
cmd & HAL_MEMCARD_RESPONSE_TYPE_MASK);
|
|
|
|
if (response == NULL)
|
|
return EMMC_ERR_PARAM;
|
|
|
|
if (response_type == HAL_MEMCARD_RESPONSE_NONE)
|
|
return EMMC_SUCCESS;
|
|
|
|
|
|
if (response_type <= HAL_MEMCARD_RESPONSE_R1b) {
|
|
/* R1 or R1b */
|
|
mmc_drv_obj.current_state =
|
|
(EMMC_R1_STATE) ((*response & EMMC_R1_STATE_MASK) >>
|
|
EMMC_R1_STATE_SHIFT);
|
|
if ((*response & error_mask) != 0) {
|
|
if ((0x80 & *response) != 0) {
|
|
ERROR("BL2: emmc SWITCH_ERROR\n");
|
|
}
|
|
return EMMC_ERR_CARD_STATUS_BIT;
|
|
}
|
|
return EMMC_SUCCESS;;
|
|
}
|
|
|
|
if (response_type == HAL_MEMCARD_RESPONSE_R4) {
|
|
if ((*response & EMMC_R4_STATUS) != 0)
|
|
return EMMC_ERR_CARD_STATUS_BIT;
|
|
}
|
|
|
|
return EMMC_SUCCESS;
|
|
}
|
|
|
|
static void emmc_WaitCmd2Cmd_8Cycle(void)
|
|
{
|
|
uint32_t dataL, wait = 0;
|
|
|
|
dataL = GETR_32(SD_CLK_CTRL);
|
|
dataL &= 0x000000FF;
|
|
|
|
switch (dataL) {
|
|
case 0xFF:
|
|
case 0x00:
|
|
case 0x01:
|
|
case 0x02:
|
|
case 0x04:
|
|
case 0x08:
|
|
case 0x10:
|
|
case 0x20:
|
|
wait = 10U;
|
|
break;
|
|
case 0x40:
|
|
wait = 20U;
|
|
break;
|
|
case 0x80:
|
|
wait = 30U;
|
|
break;
|
|
}
|
|
|
|
rcar_micro_delay(wait);
|
|
}
|
|
|
|
static void cmdErrSdInfo2Log(void)
|
|
{
|
|
ERROR("BL2: emmc ERR SD_INFO2 = 0x%x\n", mmc_drv_obj.error_info.info2);
|
|
}
|
|
|
|
static void emmc_data_transfer_dma(void)
|
|
{
|
|
mmc_drv_obj.during_dma_transfer = TRUE;
|
|
mmc_drv_obj.dma_error_flag = FALSE;
|
|
|
|
SETR_32(SD_INFO1_MASK, 0x00000000U);
|
|
SETR_32(SD_INFO2_MASK, (SD_INFO2_ALL_ERR | SD_INFO2_CLEAR));
|
|
|
|
/* DMAC setting */
|
|
if (mmc_drv_obj.cmd_info.dir == HAL_MEMCARD_WRITE) {
|
|
/* transfer complete interrupt enable */
|
|
SETR_32(DM_CM_INFO1_MASK,
|
|
(DM_CM_INFO_MASK_CLEAR | DM_CM_INFO_CH0_ENABLE));
|
|
SETR_32(DM_CM_INFO2_MASK,
|
|
(DM_CM_INFO_MASK_CLEAR | DM_CM_INFO_CH0_ENABLE));
|
|
/* BUFF --> FIFO */
|
|
SETR_32(DM_CM_DTRAN_MODE, (DM_CM_DTRAN_MODE_CH0 |
|
|
DM_CM_DTRAN_MODE_BIT_WIDTH));
|
|
} else {
|
|
/* transfer complete interrupt enable */
|
|
SETR_32(DM_CM_INFO1_MASK,
|
|
(DM_CM_INFO_MASK_CLEAR | DM_CM_INFO_CH1_ENABLE));
|
|
SETR_32(DM_CM_INFO2_MASK,
|
|
(DM_CM_INFO_MASK_CLEAR | DM_CM_INFO_CH1_ENABLE));
|
|
/* FIFO --> BUFF */
|
|
SETR_32(DM_CM_DTRAN_MODE, (DM_CM_DTRAN_MODE_CH1
|
|
| DM_CM_DTRAN_MODE_BIT_WIDTH));
|
|
}
|
|
SETR_32(DM_DTRAN_ADDR, (((uintptr_t) mmc_drv_obj.buff_address_virtual &
|
|
DM_DTRAN_ADDR_WRITE_MASK)));
|
|
|
|
SETR_32(DM_CM_DTRAN_CTRL, DM_CM_DTRAN_CTRL_START);
|
|
}
|
|
|
|
EMMC_ERROR_CODE emmc_exec_cmd(uint32_t error_mask, uint32_t *response)
|
|
{
|
|
EMMC_ERROR_CODE rtn_code = EMMC_SUCCESS;
|
|
HAL_MEMCARD_RESPONSE_TYPE response_type;
|
|
HAL_MEMCARD_COMMAND_TYPE cmd_type;
|
|
EMMC_INT_STATE state;
|
|
uint32_t err_not_care_flag = FALSE;
|
|
|
|
/* parameter check */
|
|
if (response == NULL) {
|
|
emmc_write_error_info(EMMC_FUNCNO_EXEC_CMD, EMMC_ERR_PARAM);
|
|
return EMMC_ERR_PARAM;
|
|
}
|
|
|
|
/* state check */
|
|
if (mmc_drv_obj.clock_enable != TRUE) {
|
|
emmc_write_error_info(EMMC_FUNCNO_EXEC_CMD, EMMC_ERR_STATE);
|
|
return EMMC_ERR_STATE;
|
|
}
|
|
|
|
if (mmc_drv_obj.state_machine_blocking == TRUE) {
|
|
emmc_write_error_info(EMMC_FUNCNO_EXEC_CMD, EMMC_ERR);
|
|
return EMMC_ERR;
|
|
}
|
|
|
|
state = ESTATE_BEGIN;
|
|
response_type =
|
|
(HAL_MEMCARD_RESPONSE_TYPE) (mmc_drv_obj.cmd_info.
|
|
cmd & HAL_MEMCARD_RESPONSE_TYPE_MASK);
|
|
cmd_type =
|
|
(HAL_MEMCARD_COMMAND_TYPE) (mmc_drv_obj.cmd_info.
|
|
cmd & HAL_MEMCARD_COMMAND_TYPE_MASK);
|
|
|
|
/* state machine */
|
|
while ((mmc_drv_obj.force_terminate != TRUE) && (state != ESTATE_END)) {
|
|
/* The interrupt factor flag is observed. */
|
|
emmc_interrupt();
|
|
|
|
/* wait interrupt */
|
|
if (mmc_drv_obj.state_machine_blocking == TRUE)
|
|
continue;
|
|
|
|
switch (state) {
|
|
case ESTATE_BEGIN:
|
|
/* Busy check */
|
|
if ((mmc_drv_obj.error_info.info2 & SD_INFO2_CBSY) != 0) {
|
|
emmc_write_error_info(EMMC_FUNCNO_EXEC_CMD,
|
|
EMMC_ERR_CARD_BUSY);
|
|
return EMMC_ERR_CARD_BUSY;
|
|
}
|
|
|
|
/* clear register */
|
|
SETR_32(SD_INFO1, 0x00000000U);
|
|
SETR_32(SD_INFO2, SD_INFO2_CLEAR);
|
|
SETR_32(SD_INFO1_MASK, SD_INFO1_INFO0);
|
|
SETR_32(SD_INFO2_MASK,
|
|
(SD_INFO2_ALL_ERR | SD_INFO2_CLEAR));
|
|
|
|
state = ESTATE_ISSUE_CMD;
|
|
/* through */
|
|
|
|
case ESTATE_ISSUE_CMD:
|
|
/* ARG */
|
|
SETR_32(SD_ARG, mmc_drv_obj.cmd_info.arg);
|
|
/* issue cmd */
|
|
SETR_32(SD_CMD, mmc_drv_obj.cmd_info.hw);
|
|
/* Set driver flag */
|
|
mmc_drv_obj.during_cmd_processing = TRUE;
|
|
mmc_drv_obj.state_machine_blocking = TRUE;
|
|
|
|
if (response_type == HAL_MEMCARD_RESPONSE_NONE) {
|
|
state = ESTATE_NON_RESP_CMD;
|
|
} else {
|
|
state = ESTATE_RCV_RESP;
|
|
}
|
|
|
|
break;
|
|
|
|
case ESTATE_NON_RESP_CMD:
|
|
/* interrupt disable */
|
|
SETR_32(SD_INFO1_MASK, 0x00000000U);
|
|
SETR_32(SD_INFO2_MASK, SD_INFO2_CLEAR);
|
|
|
|
/* check interrupt */
|
|
if ((mmc_drv_obj.int_event2 & SD_INFO2_ALL_ERR) != 0) {
|
|
/* error interrupt */
|
|
cmdErrSdInfo2Log();
|
|
rtn_code = EMMC_ERR_INFO2;
|
|
state = ESTATE_ERROR;
|
|
} else if ((mmc_drv_obj.int_event1 & SD_INFO1_INFO0) ==
|
|
0) {
|
|
/* not receive expected interrupt */
|
|
rtn_code = EMMC_ERR_RESPONSE;
|
|
state = ESTATE_ERROR;
|
|
} else {
|
|
emmc_WaitCmd2Cmd_8Cycle();
|
|
state = ESTATE_END;
|
|
}
|
|
break;
|
|
|
|
case ESTATE_RCV_RESP:
|
|
/* interrupt disable */
|
|
SETR_32(SD_INFO1_MASK, 0x00000000U);
|
|
SETR_32(SD_INFO2_MASK, SD_INFO2_CLEAR);
|
|
|
|
/* check interrupt */
|
|
if ((mmc_drv_obj.int_event2 & SD_INFO2_ALL_ERR) != 0) {
|
|
if ((mmc_drv_obj.get_partition_access_flag ==
|
|
TRUE)
|
|
&& ((mmc_drv_obj.int_event2 & SD_INFO2_ERR6)
|
|
!= 0U)) {
|
|
err_not_care_flag = TRUE;
|
|
rtn_code = EMMC_ERR_CMD_TIMEOUT;
|
|
} else {
|
|
/* error interrupt */
|
|
cmdErrSdInfo2Log();
|
|
rtn_code = EMMC_ERR_INFO2;
|
|
}
|
|
state = ESTATE_ERROR;
|
|
break;
|
|
} else if ((mmc_drv_obj.int_event1 & SD_INFO1_INFO0) ==
|
|
0) {
|
|
/* not receive expected interrupt */
|
|
rtn_code = EMMC_ERR_RESPONSE;
|
|
state = ESTATE_ERROR;
|
|
break;
|
|
}
|
|
|
|
/* read response */
|
|
emmc_read_response(response);
|
|
|
|
/* check response */
|
|
rtn_code = emmc_response_check(response, error_mask);
|
|
if (rtn_code != EMMC_SUCCESS) {
|
|
state = ESTATE_ERROR;
|
|
break;
|
|
}
|
|
|
|
if (response_type == HAL_MEMCARD_RESPONSE_R1b) {
|
|
/* R1b */
|
|
SETR_32(SD_INFO2_MASK,
|
|
(SD_INFO2_ALL_ERR | SD_INFO2_CLEAR));
|
|
state = ESTATE_RCV_RESPONSE_BUSY;
|
|
} else {
|
|
state = ESTATE_CHECK_RESPONSE_COMPLETE;
|
|
}
|
|
break;
|
|
|
|
case ESTATE_RCV_RESPONSE_BUSY:
|
|
/* check interrupt */
|
|
if ((mmc_drv_obj.int_event2 & SD_INFO2_ALL_ERR) != 0) {
|
|
/* error interrupt */
|
|
cmdErrSdInfo2Log();
|
|
rtn_code = EMMC_ERR_INFO2;
|
|
state = ESTATE_ERROR;
|
|
break;
|
|
}
|
|
/* DAT0 not Busy */
|
|
if ((SD_INFO2_DAT0 & mmc_drv_obj.error_info.info2) != 0) {
|
|
state = ESTATE_CHECK_RESPONSE_COMPLETE;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case ESTATE_CHECK_RESPONSE_COMPLETE:
|
|
if (cmd_type >= HAL_MEMCARD_COMMAND_TYPE_ADTC_WRITE) {
|
|
state = ESTATE_DATA_TRANSFER;
|
|
} else {
|
|
emmc_WaitCmd2Cmd_8Cycle();
|
|
state = ESTATE_END;
|
|
}
|
|
break;
|
|
|
|
case ESTATE_DATA_TRANSFER:
|
|
/* ADTC command */
|
|
mmc_drv_obj.during_transfer = TRUE;
|
|
mmc_drv_obj.state_machine_blocking = TRUE;
|
|
|
|
if (mmc_drv_obj.transfer_mode == HAL_MEMCARD_DMA) {
|
|
/* DMA */
|
|
emmc_data_transfer_dma();
|
|
} else {
|
|
/* PIO */
|
|
/* interrupt enable (FIFO read/write enable) */
|
|
if (mmc_drv_obj.cmd_info.dir ==
|
|
HAL_MEMCARD_WRITE) {
|
|
SETR_32(SD_INFO2_MASK,
|
|
(SD_INFO2_BWE | SD_INFO2_ALL_ERR
|
|
| SD_INFO2_CLEAR));
|
|
} else {
|
|
SETR_32(SD_INFO2_MASK,
|
|
(SD_INFO2_BRE | SD_INFO2_ALL_ERR
|
|
| SD_INFO2_CLEAR));
|
|
}
|
|
}
|
|
state = ESTATE_DATA_TRANSFER_COMPLETE;
|
|
break;
|
|
|
|
case ESTATE_DATA_TRANSFER_COMPLETE:
|
|
/* check interrupt */
|
|
if ((mmc_drv_obj.int_event2 & SD_INFO2_ALL_ERR) != 0) {
|
|
/* error interrupt */
|
|
cmdErrSdInfo2Log();
|
|
rtn_code = EMMC_ERR_INFO2;
|
|
state = ESTATE_TRANSFER_ERROR;
|
|
break;
|
|
}
|
|
|
|
/* DMAC error ? */
|
|
if (mmc_drv_obj.dma_error_flag == TRUE) {
|
|
/* Error occurred in DMAC driver. */
|
|
rtn_code = EMMC_ERR_FROM_DMAC_TRANSFER;
|
|
state = ESTATE_TRANSFER_ERROR;
|
|
} else if (mmc_drv_obj.during_dma_transfer == TRUE) {
|
|
/* DMAC not finished. unknown error */
|
|
rtn_code = EMMC_ERR;
|
|
state = ESTATE_TRANSFER_ERROR;
|
|
} else {
|
|
SETR_32(SD_INFO1_MASK, SD_INFO1_INFO2);
|
|
SETR_32(SD_INFO2_MASK,
|
|
(SD_INFO2_ALL_ERR | SD_INFO2_CLEAR));
|
|
|
|
mmc_drv_obj.state_machine_blocking = TRUE;
|
|
|
|
state = ESTATE_ACCESS_END;
|
|
}
|
|
break;
|
|
|
|
case ESTATE_ACCESS_END:
|
|
|
|
/* clear flag */
|
|
if (HAL_MEMCARD_DMA == mmc_drv_obj.transfer_mode) {
|
|
SETR_32(CC_EXT_MODE, CC_EXT_MODE_CLEAR); /* W (CC_EXT_MODE, H'0000_1010) SD_BUF DMA transfer disabled */
|
|
SETR_32(SD_STOP, 0x00000000U);
|
|
mmc_drv_obj.during_dma_transfer = FALSE;
|
|
}
|
|
|
|
SETR_32(SD_INFO1_MASK, 0x00000000U);
|
|
SETR_32(SD_INFO2_MASK, SD_INFO2_CLEAR);
|
|
SETR_32(SD_INFO1, 0x00000000U);
|
|
SETR_32(SD_INFO2, SD_INFO2_CLEAR);
|
|
|
|
if ((mmc_drv_obj.int_event1 & SD_INFO1_INFO2) != 0) {
|
|
emmc_WaitCmd2Cmd_8Cycle();
|
|
state = ESTATE_END;
|
|
} else {
|
|
state = ESTATE_ERROR;
|
|
}
|
|
break;
|
|
|
|
case ESTATE_TRANSFER_ERROR:
|
|
/* The error occurred in the Data transfer. */
|
|
if (HAL_MEMCARD_DMA == mmc_drv_obj.transfer_mode) {
|
|
SETR_32(CC_EXT_MODE, CC_EXT_MODE_CLEAR); /* W (CC_EXT_MODE, H'0000_1010) SD_BUF DMA transfer disabled */
|
|
SETR_32(SD_STOP, 0x00000000U);
|
|
mmc_drv_obj.during_dma_transfer = FALSE;
|
|
}
|
|
/* through */
|
|
|
|
case ESTATE_ERROR:
|
|
if (err_not_care_flag == TRUE) {
|
|
mmc_drv_obj.during_cmd_processing = FALSE;
|
|
} else {
|
|
emmc_softreset();
|
|
emmc_write_error_info(EMMC_FUNCNO_EXEC_CMD,
|
|
rtn_code);
|
|
}
|
|
return rtn_code;
|
|
|
|
default:
|
|
state = ESTATE_END;
|
|
break;
|
|
} /* switch (state) */
|
|
} /* while ( (mmc_drv_obj.force_terminate != TRUE) && (state != ESTATE_END) ) */
|
|
|
|
/* force terminate */
|
|
if (mmc_drv_obj.force_terminate == TRUE) {
|
|
/* timeout timer is expired. Or, PIO data transfer error. */
|
|
/* Timeout occurred in the DMA transfer. */
|
|
if (mmc_drv_obj.during_dma_transfer == TRUE) {
|
|
mmc_drv_obj.during_dma_transfer = FALSE;
|
|
}
|
|
ERROR("BL2: emmc exec_cmd:EMMC_ERR_FORCE_TERMINATE\n");
|
|
emmc_softreset();
|
|
|
|
return EMMC_ERR_FORCE_TERMINATE; /* error information has already been written. */
|
|
}
|
|
|
|
/* success */
|
|
mmc_drv_obj.during_cmd_processing = FALSE;
|
|
mmc_drv_obj.during_transfer = FALSE;
|
|
|
|
return EMMC_SUCCESS;
|
|
}
|