/* * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ #include #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; }