This commit is contained in:
2025-12-24 17:21:08 +09:00
parent a96323de19
commit 96dc62d8dc
2302 changed files with 455822 additions and 0 deletions

View File

@@ -0,0 +1,95 @@
/*******************************************************************************
* DISCLAIMER
* This software is supplied by Renesas Electronics Corporation and is only
* intended for use with Renesas products. No other uses are authorized. This
* software is owned by Renesas Electronics Corporation and is protected under
* all applicable laws, including copyright laws.
* THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING
* THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT
* LIMITED TO WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
* AND NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED.
* TO THE MAXIMUM EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS
* ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES SHALL BE LIABLE
* FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR
* ANY REASON RELATED TO THIS SOFTWARE, EVEN IF RENESAS OR ITS AFFILIATES HAVE
* BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
* Renesas reserves the right, without notice, to make changes to this software
* and to discontinue the availability of this software. By using this software,
* you agree to the additional terms and conditions found by accessing the
* following link:
* http://www.renesas.com/disclaimer
* Copyright 2018-2022 Renesas Electronics Corporation All rights reserved.
*******************************************************************************/
/*******************************************************************************
* DESCRIPTION : emmc boot
******************************************************************************/
/******************************************************************************
* @file emmc_boot.c
* - Version : 0.04
* @brief
* .
*****************************************************************************/
/******************************************************************************
* History : DD.MM.YYYY Version Description
* : 02.02.2022 0.01 First Release
* : 18.03.2022 0.02 Removed unnecessary functions
* Removed unnecessary header file inclusions
* : 16.06.2022 0.03 Change log output
* : 31.10.2022 0.04 License notation change.
*****************************************************************************/
#include "emmc_boot.h"
#include "log.h"
#include "emmc_std.h"
#include "emmc_def.h"
/************************************************************************************************/
/* Definitions */
/************************************************************************************************/
/************************************************************************************************/
/* Unions */
/************************************************************************************************/
/************************************************************************************************/
/* Structs */
/************************************************************************************************/
/************************************************************************************************/
/* Globals */
/************************************************************************************************/
/************************************************************************************************/
/* Macros */
/************************************************************************************************/
/************************************************************************************************/
/* Prototypes */
/************************************************************************************************/
void emmc_initialize( void )
{
EMMC_ERROR_CODE result;
/* eMMC driver initialize */
(void)emmc_init(); /* Normal clock mode */
/* Card power on */
(void)emmc_memcard_power(TRUE);
/* Card mount */
result = emmc_mount();
if (result != EMMC_SUCCESS)
{
NOTICE("eMMC initialize error!!\n");
panic;
}
}

View File

@@ -0,0 +1,622 @@
/*******************************************************************************
* DISCLAIMER
* This software is supplied by Renesas Electronics Corporation and is only
* intended for use with Renesas products. No other uses are authorized. This
* software is owned by Renesas Electronics Corporation and is protected under
* all applicable laws, including copyright laws.
* THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING
* THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT
* LIMITED TO WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
* AND NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED.
* TO THE MAXIMUM EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS
* ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES SHALL BE LIABLE
* FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR
* ANY REASON RELATED TO THIS SOFTWARE, EVEN IF RENESAS OR ITS AFFILIATES HAVE
* BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
* Renesas reserves the right, without notice, to make changes to this software
* and to discontinue the availability of this software. By using this software,
* you agree to the additional terms and conditions found by accessing the
* following link:
* http://www.renesas.com/disclaimer
* Copyright 2018-2024 Renesas Electronics Corporation All rights reserved.
*******************************************************************************/
/*******************************************************************************
* DESCRIPTION : emmc command
******************************************************************************/
/******************************************************************************
* @file emmc_cmd.c
* - Version : 0.04
* @brief
* .
*****************************************************************************/
/******************************************************************************
* History : DD.MM.YYYY Version Description
* : 02.02.2022 0.01 First Release
* : 16.06.2022 0.02 Change log output
* : 31.10.2022 0.03 License notation change.
* : 07.06.2024 0.04 Modify the transfer end bit of DMAC channel.
*****************************************************************************/
#include "emmc_config.h"
#include "emmc_hal.h"
#include "emmc_std.h"
#include "emmc_registers.h"
#include "emmc_def.h"
#include "timer.h"
#include "log.h"
/* ***************** MACROS, CONSTANTS, COMPILATION FLAGS ****************** */
/* ********************** STRUCTURES, TYPE DEFINITIONS ********************* */
/* ********************** DECLARATION OF EXTERNAL DATA ********************* */
/* ************************** FUNCTION PROTOTYPES ************************** */
static void emmc_read_response(uint32_t *response);
static void emmc_little_to_big(uint8_t *p, uint32_t value);
static void emmc_data_transfer_dma(void);
static EMMC_ERROR_CODE emmc_response_check(const uint32_t *response, uint32_t error_mask);
static void emmc_softreset(void);
static void emmc_WaitCmd2Cmd_8Cycle(void);
/* ********************************* CODE ********************************** */
/* execute MMC command.
*
* - Pre-conditions:<BR>
* * Clock to memory card IF is enabled.
* - Post-conditions:<BR>
* Requested command is executed successfully
*
* param[in] error_mask Errors to be checked (error values; HAL_MEMCARD_ERRORS)
* param[in,out] *response Response from the card (virtual address)
* return eMMC error code.
*/
EMMC_ERROR_CODE emmc_exec_cmd(uint32_t error_mask, uint32_t *response)
{
EMMC_ERROR_CODE rtn_code = EMMC_ERR;
HAL_MEMCARD_RESPONSE_TYPE response_type;
HAL_MEMCARD_COMMAND_TYPE cmd_type;
EMMC_INT_STATE state;
/* parameter check */
if (response == NULL)
{
ERROR("%s:0x%x\n",__func__,EMMC_ERR_PARAM);
return EMMC_ERR_PARAM;
}
/* state check */
if (mmc_drv_obj.clock_enable != TRUE)
{
ERROR("%s:0x%x\n",__func__,EMMC_ERR_STATE);
return EMMC_ERR_STATE;
}
if (mmc_drv_obj.state_machine_blocking == TRUE)
{
ERROR("%s:0x%x\n",__func__,EMMC_ERR);
return EMMC_ERR;
}
state = ESTATE_BEGIN;
response_type = (HAL_MEMCARD_RESPONSE_TYPE)(uintptr_t)((uint32_t)(mmc_drv_obj.cmd_info.cmd) & (uint32_t)HAL_MEMCARD_RESPONSE_TYPE_MASK);
cmd_type = (HAL_MEMCARD_COMMAND_TYPE)(uintptr_t)((uint32_t)(mmc_drv_obj.cmd_info.cmd) & (uint32_t)HAL_MEMCARD_COMMAND_TYPE_MASK);
/* state machine */
while ((mmc_drv_obj.force_terminate != TRUE) && (state != ESTATE_END))
{
/* The interrupt factor flag is observed. */
(void)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) != 0U)
{
ERROR("%s:0x%x\n",__func__,EMMC_ERR_CARD_BUSY);
return EMMC_ERR_CARD_BUSY;
}
/* clear register */
mem_write32(SD_INFO1, 0x00000000U);
mem_write32(SD_INFO2, SD_INFO2_CLEAR);
mem_write32(SD_INFO1_MASK, SD_INFO1_INFO0);
mem_write32(SD_INFO2_MASK, ( SD_INFO2_ALL_ERR | SD_INFO2_CLEAR ));
/* fallthrough */
case ESTATE_ISSUE_CMD:
/* ARG */
mem_write32(SD_ARG, mmc_drv_obj.cmd_info.arg);
/* issue cmd */
mem_write32(SD_CMD, mmc_drv_obj.cmd_info.hw);
/* Set driver flag */
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 */
mem_write32(SD_INFO1_MASK, 0x00000000U);
mem_write32(SD_INFO2_MASK, SD_INFO2_CLEAR);
/* check interrupt */
if ((mmc_drv_obj.int_event2 & SD_INFO2_ALL_ERR) != 0U)
{
/* error interrupt */
rtn_code = EMMC_ERR_INFO2;
state = ESTATE_ERROR;
} else if ((mmc_drv_obj.int_event1 & SD_INFO1_INFO0) == 0U) {
/* 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 */
mem_write32(SD_INFO1_MASK, 0x00000000U);
mem_write32(SD_INFO2_MASK, SD_INFO2_CLEAR);
/* check interrupt */
if ((mmc_drv_obj.int_event2 & SD_INFO2_ALL_ERR) != 0U)
{
/* error interrupt */
rtn_code = EMMC_ERR_INFO2;
state = ESTATE_ERROR;
break;
} else if ((mmc_drv_obj.int_event1 & SD_INFO1_INFO0) == 0U) {
/* not receive expected interrupt */
rtn_code = EMMC_ERR_RESPONSE;
state = ESTATE_ERROR;
break;
} else {
/* nop */
}
/* 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 */
mem_write32(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) != 0U)
{
/* error interrupt */
rtn_code = EMMC_ERR_INFO2;
state = ESTATE_ERROR;
break;
}
/* DAT0 not Busy */
if ((SD_INFO2_DAT0 & mmc_drv_obj.error_info.info2) != 0U)
{
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)
{
mem_write32(SD_INFO2_MASK, ( SD_INFO2_BWE | SD_INFO2_ALL_ERR | SD_INFO2_CLEAR ));
} else {
mem_write32(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) != 0U)
{
/* error interrupt */
rtn_code = EMMC_ERR_INFO2;
state = ESTATE_TRANSFER_ERROR;
break;
} else {
/* success. nothing to do. */
}
/* 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 {
mem_write32(SD_INFO1_MASK, SD_INFO1_INFO2);
mem_write32(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)
{
mem_write32(CC_EXT_MODE, CC_EXT_MODE_CLEAR); /* W (CC_EXT_MODE, H'0000_1010) SD_BUF DMA transfer disabled */
mem_write32(SD_STOP, 0x00000000U);
mmc_drv_obj.during_dma_transfer = FALSE;
}
mem_write32(SD_INFO1_MASK, 0x00000000U);
mem_write32(SD_INFO2_MASK, SD_INFO2_CLEAR);
mem_write32(SD_INFO1, 0x00000000U);
mem_write32(SD_INFO2, SD_INFO2_CLEAR);
if ((mmc_drv_obj.int_event1 & SD_INFO1_INFO2) != 0U)
{
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)
{
mem_write32(CC_EXT_MODE, CC_EXT_MODE_CLEAR); /* W (CC_EXT_MODE, H'0000_1010) SD_BUF DMA transfer disabled */
mem_write32(SD_STOP, 0x00000000U);
mmc_drv_obj.during_dma_transfer = FALSE;
}
/* fallthrough */
case ESTATE_ERROR:
emmc_softreset();
ERROR("%s:0x%x\n",__func__,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;
}
emmc_softreset();
return EMMC_ERR_FORCE_TERMINATE; /* error information has already been written. */
}
/* success */
mmc_drv_obj.during_transfer = FALSE;
return EMMC_SUCCESS;
}
/** host controller softrest.
*
* - Pre-conditions:<BR>
* .
* - Post-conditions:<BR>
* .
*
* param None.
* return None.
*/
static void emmc_softreset(void)
{
int32_t loop = 10000;
int32_t retry = 1000;
/* flag clear */
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 ((mem_read32(SD_INFO2) & SD_INFO2_CBSY) != 0U)
{
/* wait CMDSEQ = 0 */
while (loop > 0)
{
if ((mem_read32(SD_INFO2) & SD_INFO2_CBSY) == 0U)
{
break; /* ready */
}
loop--;
if ((loop == 0) && (retry > 0))
{
micro_wait(1000U); /* wait 1ms */
loop = 10000;
retry--;
}
}
}
/* reset */
mem_write32(SOFT_RST, ( mem_read32(SOFT_RST) & (~SOFT_RST_SDRST) )); /* Soft reset */
mem_write32(SOFT_RST, ( mem_read32(SOFT_RST) | SOFT_RST_SDRST )); /* Soft reset released */
/* initialize */
mem_write32(SD_INFO1, 0x00000000U);
mem_write32(SD_INFO2, SD_INFO2_CLEAR);
mem_write32(SD_INFO1_MASK, 0x00000000U); /* all interrupt disable */
mem_write32(SD_INFO2_MASK, SD_INFO2_CLEAR); /* all interrupt disable */
}
/** read response
*
* - Pre-conditions:<BR>
* Called from emmc_exec_cmd().
* - Post-conditions:<BR>
* .
*
* param[in,out] *response Response from the card
* return None.
*/
static void emmc_read_response(uint32_t *response)
{
uint8_t *p = NULL;
if (response == NULL)
{
return;
}
/* read response */
if (mmc_drv_obj.response_length == EMMC_MAX_RESPONSE_LENGTH)
{
/* CSD or CID */
p = (uint8_t *)(response);
emmc_little_to_big(p, ((mem_read32(SD_RSP76) << 8U) | (mem_read32(SD_RSP54) >> 24U))); /* [127:96] */
emmc_little_to_big(p + 4U, ((mem_read32(SD_RSP54) << 8U) | (mem_read32(SD_RSP32) >> 24U))); /* [95:64] */
emmc_little_to_big(p + 8U, ((mem_read32(SD_RSP32) << 8U) | (mem_read32(SD_RSP10) >> 24U))); /* [63:32] */
emmc_little_to_big(p + 12U, (mem_read32(SD_RSP10) << 8U)); /* [31:0] */
} else {
*response = mem_read32(SD_RSP10); /* [39:8] */
}
}
/** response check
*
* - Pre-conditions:<BR>
* Called from emmc_exec_cmd().
* - Post-conditions:<BR>
* .
*
* param[in] *response Response from the card
* param[in] error_mask Errors to be checked (for R1/R1b response)
* return error code.
*/
static EMMC_ERROR_CODE emmc_response_check(const uint32_t *response, uint32_t error_mask)
{
HAL_MEMCARD_RESPONSE_TYPE response_type = (HAL_MEMCARD_RESPONSE_TYPE)(uintptr_t)((uint32_t)(mmc_drv_obj.cmd_info.cmd)
& (uint32_t)HAL_MEMCARD_RESPONSE_TYPE_MASK);
if (response == NULL)
{
return EMMC_ERR_PARAM;
}
if (response_type == HAL_MEMCARD_RESPONSE_NONE)
{
return EMMC_SUCCESS;
}
/* response check */
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) != 0U)
{
return EMMC_ERR_CARD_STATUS_BIT;
}
} else if (response_type == HAL_MEMCARD_RESPONSE_R4) {
/* R4 */
if ((*response & EMMC_R4_STATUS) != 0U)
{
return EMMC_ERR_CARD_STATUS_BIT;
}
} else {
; /* nothing to do. other type does not have status bit */
}
return EMMC_SUCCESS;
}
/** brief converts endian from little to big
*
* - Pre-conditions:<BR>
* .
* - Post-conditions:<BR>
* .
*
* param[in,out] p destination buffer address.
* param[in] value convert data.(little)
* return None.
*/
static void emmc_little_to_big(uint8_t *p, uint32_t value)
{
if (p == NULL)
{
return;
}
p[0] = (uint8_t)(value >> 24U);
p[1] = (uint8_t)(value >> 16U);
p[2] = (uint8_t)(value >> 8U);
p[3] = (uint8_t)value;
}
/** data transfer with DMA.
*
* - Pre-conditions:<BR>
* Called from emmc_exec_cmd().
* - Post-conditions:<BR>
* .
*
* return error code.
*/
static void emmc_data_transfer_dma(void)
{
mmc_drv_obj.during_dma_transfer = TRUE;
mmc_drv_obj.dma_error_flag = FALSE;
mem_write32(SD_INFO1_MASK, 0x00000000U);
mem_write32(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 when write to eMMC */
mem_write32(DM_CM_INFO1_MASK, ( DM_CM_INFO_MASK_CLEAR | DM_CM_INFO_CH0_ENABLE ));
/* When writing to eMMC, set only bit 17 to "0". */
mem_write32(DM_CM_INFO2_MASK, ( DM_CM_INFO2_MASK_CLEAR | DM_CM_INFO2_CH0_ENABLE ));
/* BUFF --> FIFO */
mem_write32(DM_CM_DTRAN_MODE, ( DM_CM_DTRAN_MODE_CH0 | DM_CM_DTRAN_MODE_BIT_WIDTH )); /* CH0(downstream), 64-bit width */
} else {
/* transfer complete interrupt enable when read from eMMC */
mem_write32(DM_CM_INFO1_MASK, ( DM_CM_INFO_MASK_CLEAR | DM_CM_INFO_CH1_ENABLE ));
/* When reading from eMMC, set only bit 16 to "0". */
mem_write32(DM_CM_INFO2_MASK, ( DM_CM_INFO2_MASK_CLEAR | DM_CM_INFO2_CH1_ENABLE ));
/* FIFO --> BUFF */
mem_write32(DM_CM_DTRAN_MODE, ( DM_CM_DTRAN_MODE_CH1 | DM_CM_DTRAN_MODE_BIT_WIDTH )); /* CH1(upstream), 64-bit width */
}
mem_write32(DM_DTRAN_ADDR, ( ( (uintptr_t)mmc_drv_obj.buff_address_virtual & DM_DTRAN_ADDR_WRITE_MASK ) )); /* Set address */
mem_write32(DM_CM_DTRAN_CTRL, DM_CM_DTRAN_CTRL_START); /* DMAC Start */
}
/** wait cmd-cmd 8cycle
*
* - Pre-conditions:<BR>
*
* - Post-conditions:<BR>
* .
*
* return None.
*/
static void emmc_WaitCmd2Cmd_8Cycle(void)
{
uint32_t dataL, wait = 0U;
dataL = mem_read32(SD_CLK_CTRL);
dataL &= 0x000000FFU;
switch (dataL)
{
case 0xFFU: /* 1/1 10 us wait ( 1/200MHz)*8= 0.04 us(min) */
wait = 10U;
break;
case 0x00U: /* 1/2 10 us wait ( 2/200MHz)*8= 0.08 us(min) */
wait = 10U;
break;
case 0x01U: /* 1/4 10 us wait ( 4/200MHz)*8= 0.16 us(min) */
wait = 10U;
break;
case 0x02U: /* 1/8 10 us wait ( 8/200MHz)*8= 0.32 us(min) */
wait = 10U;
break;
case 0x04U: /* 1/16 10 us wait ( 16/200MHz)*8= 0.64 us(min) */
wait = 10U;
break;
case 0x08U: /* 1/32 10 us wait ( 32/200MHz)*8= 1.28 us(min) */
wait = 10U;
break;
case 0x10U: /* 1/64 10 us wait ( 64/200MHz)*8= 2.56 us(min) */
wait = 10U;
break;
case 0x20U: /* 1/128 10 us wait (128/200MHz)*8= 5.12 us(min) */
wait = 10U;
break;
case 0x40U: /* 1/256 20 us wait (256/200MHz)*8= 10.24 us(min) */
wait = 20U;
break;
case 0x80U: /* 1/512 30 us wait (512/200MHz)*8= 20.48 us(min) */
wait = 30U;
break;
default:
/* nop */
break;
}
micro_wait(wait);
}
/* ******************************** END ************************************ */

View File

@@ -0,0 +1,399 @@
/*******************************************************************************
* DISCLAIMER
* This software is supplied by Renesas Electronics Corporation and is only
* intended for use with Renesas products. No other uses are authorized. This
* software is owned by Renesas Electronics Corporation and is protected under
* all applicable laws, including copyright laws.
* THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING
* THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT
* LIMITED TO WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
* AND NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED.
* TO THE MAXIMUM EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS
* ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES SHALL BE LIABLE
* FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR
* ANY REASON RELATED TO THIS SOFTWARE, EVEN IF RENESAS OR ITS AFFILIATES HAVE
* BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
* Renesas reserves the right, without notice, to make changes to this software
* and to discontinue the availability of this software. By using this software,
* you agree to the additional terms and conditions found by accessing the
* following link:
* http://www.renesas.com/disclaimer
* Copyright 2018-2022 Renesas Electronics Corporation All rights reserved.
*******************************************************************************/
/*******************************************************************************
* DESCRIPTION : emmc initialize
******************************************************************************/
/******************************************************************************
* @file emmc_init.c
* - Version : 0.04
* @brief
* .
*****************************************************************************/
/******************************************************************************
* History : DD.MM.YYYY Version Description
* : 02.02.2022 0.01 First Release
* : 22.03.2022 0.02 Removed CPG setting
* Added Function End comment
* Added header file inclusion
* : 24.10.2022 0.03 Add CPG setting to support HS200/400
* : 31.10.2022 0.04 License notation change.
*****************************************************************************/
/* ************************ HEADER (INCLUDE) SECTION *********************** */
#include "emmc_config.h"
#include "emmc_hal.h"
#include "emmc_std.h"
#include "emmc_registers.h"
#include "emmc_def.h"
#include "mem_io.h"
/* ***************** MACROS, CONSTANTS, COMPILATION FLAGS ****************** */
#undef DUMP_EMMC_REGISTERS
/* ********************** STRUCTURES, TYPE DEFINITIONS ********************* */
/* ********************** DECLARATION OF EXTERNAL DATA ********************* */
st_mmc_base mmc_drv_obj;
#define CX_IPL_EMMC_DATA (0x41DFF000UL)
#define CX_IPL_CSD_DATA (CX_IPL_EMMC_DATA)
#define CX_IPL_CID_DATA (CX_IPL_CSD_DATA + EMMC_MAX_CSD_LENGTH)
#define CX_IPL_EXT_CSD_DATA (CX_IPL_CID_DATA + EMMC_MAX_CID_LENGTH)
volatile uint8_t *default_csd_data = (volatile uint8_t *)CX_IPL_CSD_DATA;
volatile uint8_t *default_cid_data = (volatile uint8_t *)CX_IPL_CID_DATA;
volatile uint8_t *default_ext_csd_data = (volatile uint8_t *)CX_IPL_EXT_CSD_DATA;
/* ************************** FUNCTION PROTOTYPES ************************** */
static void emmc_drv_init(void);
static EMMC_ERROR_CODE emmc_dev_init(void);
static EMMC_ERROR_CODE emmc_dev_finalize(void);
static void emmc_memset(void *buff, uint8_t data, uint32_t cnt);
static EMMC_ERROR_CODE emmc_reset_controller(void);
static void emmc_driver_config(void);
static void emmc_set_data_timeout(uint32_t data_timeout);
/* ********************************* CODE ********************************** */
#if defined(DUMP_EMMC_REGISTERS) && (LOG_LEVEL >= LOG_NOTICE)
static void dump_buf(const uint8_t *buf, int size)
{
int i;
for (i = 0; i < size; i++)
{
if ((i % 16) == 0)
{
log_printf("\n%x: ", i);
}
log_printf("%b ", (uint8_t)buf[i]);
}
log_printf("\n");
}
#endif
void dump_mmc_drv_obj(void)
{
#if defined(DUMP_EMMC_REGISTERS) && (LOG_LEVEL >= LOG_NOTICE)
NOTICE("[%s:%d] size of mmc_drv_obj %d\n", __func__, __LINE__, sizeof(mmc_drv_obj));
NOTICE("CSD data:");
dump_buf(mmc_drv_obj.csd_data, sizeof(mmc_drv_obj.csd_data));
NOTICE("CID data:");
dump_buf(mmc_drv_obj.cid_data, sizeof(mmc_drv_obj.cid_data));
NOTICE("ext CSD data:");
dump_buf(mmc_drv_obj.ext_csd_data, sizeof(mmc_drv_obj.ext_csd_data));
#endif
}
void import_mmc_drv_obj(void)
{
/* Fill mmc_drv_obj with default values */
emmc_memset((uint8_t *)(&mmc_drv_obj), 0U, sizeof(st_mmc_base));
for(int i=0; i < EMMC_MAX_CID_LENGTH; i++)
{
mmc_drv_obj.cid_data[i] = default_cid_data[i];
}
for(int i=0; i < EMMC_MAX_CSD_LENGTH; i++)
{
mmc_drv_obj.csd_data[i] = default_csd_data[i];
}
for(int i=0; i < EMMC_MAX_EXT_CSD_LENGTH; i++)
{
mmc_drv_obj.ext_csd_data[i] = default_ext_csd_data[i];
}
dump_mmc_drv_obj();
mmc_drv_obj.card_power_enable = TRUE;
mmc_drv_obj.clock_enable = TRUE;
mmc_drv_obj.initialize = TRUE;
mmc_drv_obj.mount = TRUE;
mmc_drv_obj.selected = TRUE;
}
void export_mmc_drv_obj(void)
{
for(int i=0; i < EMMC_MAX_CID_LENGTH; i++)
{
*((volatile uint8_t *)&default_cid_data[i]) = mmc_drv_obj.cid_data[i];
}
for(int i=0; i < EMMC_MAX_CSD_LENGTH; i++)
{
*((volatile uint8_t *)&default_csd_data[i]) = mmc_drv_obj.csd_data[i];
}
for(int i=0; i < EMMC_MAX_EXT_CSD_LENGTH; i++)
{
*((volatile uint8_t *)&default_ext_csd_data[i]) = mmc_drv_obj.ext_csd_data[i];
}
dump_mmc_drv_obj();
}
/** brief eMMC initialize.
*
* - Pre-conditions:<BR>
* .
* - Post-conditions:<BR>
* .
*
* retval EMMC_SUCCESS successful.
* retval EMMC_ERR error from interrupt API.
*/
EMMC_ERROR_CODE emmc_init(void)
{
/* initialize H/W */
(void)emmc_reset_controller();
/* Configuration */
emmc_driver_config();
return EMMC_SUCCESS;
}
/** terminate emmc driver
*
* EMMC H/W and S/W resource is released.
*
* - Pre-conditions:<BR>
* .
* - Post-conditions:<BR>
* .
*
* return None.
*/
EMMC_ERROR_CODE emmc_terminate(void)
{
EMMC_ERROR_CODE result = EMMC_ERR;
/* H/W finalize */
result = emmc_dev_finalize();
/* driver finalize */
emmc_memset((uint8_t *)(&mmc_drv_obj), 0U, sizeof(st_mmc_base)); /* clear global variable */
return result;
}
/** Function executes full reset to MMC host controller without taking power out from the memory card.
*
* - Pre-conditions:<BR>
* .
* - Post-conditions:<BR>
* Reset MMC host controller without taking power out from the memory card.
* Memory card preserves its state.
*
* return None
*/
static EMMC_ERROR_CODE emmc_reset_controller(void)
{
EMMC_ERROR_CODE result = EMMC_ERR;
/* initialize mmc driver */
emmc_drv_init();
mmc_drv_obj.base_address = MMC0_SD_BASE;
/* initialize H/W */
result = emmc_dev_init();
mmc_drv_obj.initialize = TRUE;
return result;
}
/** Configuration eMMC driver
*
* - Pre-conditions:<BR>
* initialized eMMC driver.
* - Post-conditions:<BR>
* .
*
* return None
*/
static void emmc_driver_config(void)
{
/* Read/Write data timeout */
emmc_set_data_timeout(EMMC_RW_DATA_TIMEOUT);
}
/** Sets data timeout
*
* Sets the data timeout value for read and write operations.
*
* - Pre-conditions:<BR>
* initialized eMMC driver.
*
* - Post-conditions:<BR>
* After this function is called, the timeout value is set according to argument.
*
* param[in] time_out The desired timeout value in milliseconds.
* return None
*/
static void emmc_set_data_timeout(uint32_t data_timeout)
{
mmc_drv_obj.data_timeout = data_timeout;
}
/** eMMC driver initialize. (software)
*
* - Pre-conditions:<BR>
* .
* - Post-conditions:<BR>
* .
*
* return None.
*/
static void emmc_drv_init(void)
{
/* initialize */
emmc_memset((uint8_t *)(&mmc_drv_obj), 0U, sizeof(st_mmc_base));
mmc_drv_obj.data_timeout = EMMC_RW_DATA_TIMEOUT;
mmc_drv_obj.bus_width = HAL_MEMCARD_DATA_WIDTH_1_BIT;
}
/** eMMC driver initialize. (H/W)
*
* - Pre-conditions:<BR>
* .
* - Post-conditions:<BR>
* .
*
* return None.
*/
static EMMC_ERROR_CODE emmc_dev_init(void)
{
/* InitSdCkcr */
mem_write32(CPG_CPGWPR, ~(0x00000001U));
mem_write32(CPG_SD0CKCR, 0x00000001U); /* SD0H-Clock=800MHz(Supply), SD0=200MHz(Supply) */
/* MMCIF initialize */
mem_write32(SD_INFO1, 0x00000000U); /* all interrupt clear */
mem_write32(SD_INFO2, SD_INFO2_CLEAR); /* all interrupt clear */
mem_write32(SD_INFO1_MASK, 0x00000000U); /* all interrupt disable */
mem_write32(SD_INFO2_MASK, SD_INFO2_CLEAR); /* all interrupt disable */
mem_write32(HOST_MODE, 0x00000000U); /* SD_BUF access width = 64-bit */
mem_write32(SD_OPTION, 0x0000C0EEU); /* Bus width = 1bit, timeout=MAX */
mem_write32(SD_CLK_CTRL, 0x00000000U); /* Automatic Control=Disable, Clock Output=Disable */
return EMMC_SUCCESS;
}
/** EMMC H/W finalize
*
* EMMC Host and Card hardware resource is released.
*
* - Pre-conditions:<BR>
* .
*
* - Post-conditions:<BR>
* .
* return None.
*/
static EMMC_ERROR_CODE emmc_dev_finalize(void)
{
EMMC_ERROR_CODE result = EMMC_ERR;
/* MMC power off
* the power supply of eMMC device is always turning on.
* RST_n : Hi --> Low level.
*/
result = emmc_memcard_power(FALSE);
mem_write32(SD_INFO1, 0x00000000U);
mem_write32(SD_INFO2, 0x00000800U);
mem_write32(DM_CM_INFO1, 0x00000000U);
mem_write32(DM_CM_INFO2, 0x00000000U);
mem_write32(SD_CLK_CTRL, 0x00000020U);
mem_write32(CC_EXT_MODE, 0x00000000U);
mem_write32(SD_STOP, 0x00000000U);
mem_write32(SD_SECCNT, 0x00000000U);
mem_write32(DM_CM_DTRAN_MODE, 0x00000000U);
mem_write32(DM_DTRAN_ADDR, 0x00000000U);
mem_write32(SD_OPTION, 0x00000000U);
mem_write32(DM_CM_DTRAN_CTRL, 0x00000000U);
return result;
}
/** Set power to memory card IF.
* This function control Vcc and Vccq and RST_n.
*
* attention
* CPU cannot control Vcc&Vccq.
* The power supply of eMMC device is always turning on.
*
* param[in] mode TRUE = power on, FALSE = power off
*
* retval EMMC_SUCCESS powering succeeded
* retval EMMC_ERR_CARD_POWER powering failed
*/
EMMC_ERROR_CODE emmc_memcard_power(uint32_t mode)
{
if (mode == TRUE)
{
/* power on (Vcc&Vccq is always power on) */
mmc_drv_obj.card_power_enable = TRUE;
} else {
/* power off (Vcc&Vccq is always power on) */
mmc_drv_obj.card_power_enable = FALSE;
mmc_drv_obj.mount = FALSE;
mmc_drv_obj.selected = FALSE;
}
return EMMC_SUCCESS;
}
/** memset(). no use C standard library.
*
* - Pre-conditions:<BR>
* .
* - Post-conditions:<BR>
* .
*
* param[in,out] buff pointer to buffer (virtual)
* param[in] data fill data.
* param[in] cnt fill size (number of bytes)
* return None.
*/
static void emmc_memset(void *buff, uint8_t data, uint32_t cnt)
{
uint8_t *tmp = NULL;
tmp = (uint8_t *)buff;
if (buff == NULL)
{
return;
}
while (cnt > 0U)
{
*tmp = data;
tmp++;
cnt--;
}
}
/* ******************************** END ************************************ */

View File

@@ -0,0 +1,239 @@
/*******************************************************************************
* DISCLAIMER
* This software is supplied by Renesas Electronics Corporation and is only
* intended for use with Renesas products. No other uses are authorized. This
* software is owned by Renesas Electronics Corporation and is protected under
* all applicable laws, including copyright laws.
* THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING
* THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT
* LIMITED TO WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
* AND NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED.
* TO THE MAXIMUM EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS
* ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES SHALL BE LIABLE
* FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR
* ANY REASON RELATED TO THIS SOFTWARE, EVEN IF RENESAS OR ITS AFFILIATES HAVE
* BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
* Renesas reserves the right, without notice, to make changes to this software
* and to discontinue the availability of this software. By using this software,
* you agree to the additional terms and conditions found by accessing the
* following link:
* http://www.renesas.com/disclaimer
* Copyright 2018-2024 Renesas Electronics Corporation All rights reserved.
*******************************************************************************/
/*******************************************************************************
* DESCRIPTION : emmc interrupt
******************************************************************************/
/******************************************************************************
* @file emmc_interrupt.c
* - Version : 0.04
* @brief
* .
*****************************************************************************/
/******************************************************************************
* History : DD.MM.YYYY Version Description
* : 02.02.2022 0.01 First Release
* : 16.06.2022 0.02 Change log output
* : 31.10.2022 0.03 License notation change.
* : 07.06.2024 0.04 Modify the transfer end bit of DMAC channel.
*****************************************************************************/
#include "emmc_config.h"
#include "emmc_hal.h"
#include "emmc_std.h"
#include "emmc_registers.h"
#include "emmc_def.h"
#include "log.h"
#include "mem_io.h"
#include <stdint.h>
/* ***************** MACROS, CONSTANTS, COMPILATION FLAGS ****************** */
/* ********************** STRUCTURES, TYPE DEFINITIONS ********************* */
/* ********************** DECLARATION OF EXTERNAL DATA ********************* */
/* ************************** FUNCTION PROTOTYPES ************************** */
static EMMC_ERROR_CODE emmc_trans_sector(uint32_t *buff_address_virtual);
/* ********************************* CODE ********************************** */
/** emmc driver interrupt service routine.
*
* - Pre-conditions:<BR>
* Must be block emmc driver state machine.
* - Post-conditions:<BR>
* unblocking emmc driver state machine.
*
* retval INT_SUCCESS
*/
uint32_t emmc_interrupt(void)
{
EMMC_ERROR_CODE result = EMMC_ERR;
/* SD_INFO */
mmc_drv_obj.error_info.info1 = mem_read32(SD_INFO1);
mmc_drv_obj.error_info.info2 = mem_read32(SD_INFO2);
/* SD_INFO EVENT */
mmc_drv_obj.int_event1 = mmc_drv_obj.error_info.info1 & mem_read32(SD_INFO1_MASK);
mmc_drv_obj.int_event2 = mmc_drv_obj.error_info.info2 & mem_read32(SD_INFO2_MASK);
/* ERR_STS */
mmc_drv_obj.error_info.status1 = mem_read32(SD_ERR_STS1);
mmc_drv_obj.error_info.status2 = mem_read32(SD_ERR_STS2);
/* DM_CM_INFO */
mmc_drv_obj.error_info.dm_info1 = mem_read32(DM_CM_INFO1);
mmc_drv_obj.error_info.dm_info2 = mem_read32(DM_CM_INFO2);
/* DM_CM_INFO EVENT */
mmc_drv_obj.dm_event1 = mmc_drv_obj.error_info.dm_info1 & mem_read32(DM_CM_INFO1_MASK);
mmc_drv_obj.dm_event2 = mmc_drv_obj.error_info.dm_info2 & mem_read32(DM_CM_INFO2_MASK);
/* ERR SD_INFO2 */
if ((SD_INFO2_ALL_ERR & mmc_drv_obj.int_event2) != 0U)
{
mem_write32(SD_INFO1_MASK, 0x00000000U); /* interrupt disable */
mem_write32(SD_INFO2_MASK, SD_INFO2_CLEAR); /* interrupt disable */
mem_write32(SD_INFO1, 0x00000000U); /* interrupt clear */
mem_write32(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) != 0U) {
/* BWE */
if (( SD_INFO2_BWE & mmc_drv_obj.int_event2) != 0U)
{
mem_write32(SD_INFO2, (mem_read32(SD_INFO2) & ~SD_INFO2_BWE)); /* interrupt clear */
}
/* BRE */
else {
mem_write32(SD_INFO2, (mem_read32(SD_INFO2) & ~SD_INFO2_BRE)); /* interrupt clear */
}
result = emmc_trans_sector((uint32_t *)mmc_drv_obj.buff_address_virtual); /* sector R/W */
mmc_drv_obj.buff_address_virtual += EMMC_BLOCK_LENGTH;
mmc_drv_obj.remain_size -= EMMC_BLOCK_LENGTH;
if (result != EMMC_SUCCESS)
{
/* data transfer error */
ERROR("%s:0x%x\n",__func__, result);
/* Panic */
mem_write32(SD_INFO1_MASK, 0x00000000U); /* interrupt disable */
mem_write32(SD_INFO2_MASK, SD_INFO2_CLEAR); /* interrupt disable */
mem_write32(SD_INFO1, 0x00000000U); /* interrupt clear */
mem_write32(SD_INFO2, SD_INFO2_CLEAR); /* interrupt 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 occured */
else if ((DM_CM_INFO_DTRANEND0 & mmc_drv_obj.dm_event1) != 0U) {
mem_write32(DM_CM_INFO1, 0x00000000U);
mem_write32(DM_CM_INFO2, 0x00000000U);
mem_write32(SD_INFO2, (mem_read32(SD_INFO2) & ~SD_INFO2_BWE)); /* interrupt clear */
/* DM_CM_INFO2: DMA-ch0 error occured */
if (( DM_CM_INFO2_DTRANEND0 & mmc_drv_obj.dm_event2) != 0U)
{
mmc_drv_obj.dma_error_flag = TRUE;
} else {
mmc_drv_obj.during_dma_transfer = FALSE;
mmc_drv_obj.during_transfer = FALSE;
}
mmc_drv_obj.state_machine_blocking = FALSE; /* wait next interrupt */
}
/* DM_CM_INFO1: DMA-ch1 transfer complete or error occured */
else if ((DM_CM_INFO_DTRANEND1 & mmc_drv_obj.dm_event1) != 0U) {
mem_write32(DM_CM_INFO1, 0x00000000U);
mem_write32(DM_CM_INFO2, 0x00000000U);
mem_write32(SD_INFO2, (mem_read32(SD_INFO2) & ~SD_INFO2_BRE)); /* interrupt clear */
/* DM_CM_INFO2: DMA-ch1 error occured */
if (( DM_CM_INFO2_DTRANEND1 & mmc_drv_obj.dm_event2) != 0U)
{
mmc_drv_obj.dma_error_flag = TRUE;
} else {
mmc_drv_obj.during_dma_transfer = FALSE;
mmc_drv_obj.during_transfer = FALSE;
}
mmc_drv_obj.state_machine_blocking = FALSE; /* wait next interrupt */
}
/* Response end */
else if ((SD_INFO1_INFO0 & mmc_drv_obj.int_event1) != 0U) {
mem_write32(SD_INFO1, (mem_read32(SD_INFO1) & ~SD_INFO1_INFO0)); /* interrupt clear */
mmc_drv_obj.state_machine_blocking = FALSE;
}
/* Access end */
else if ((SD_INFO1_INFO2 & mmc_drv_obj.int_event1) != 0U) {
mem_write32(SD_INFO1, (mem_read32(SD_INFO1) & ~SD_INFO1_INFO2)); /* interrupt clear */
mmc_drv_obj.state_machine_blocking = FALSE;
} else {
/* nothing to do. */
}
return 0U;
}
/** Data transfer function with PIO (Single sector).
*
* - Pre-conditions:<BR>
* Called from interrupt service.
* - Post-conditions:<BR>
* .
*
* param[in,out] buff_address_virtual Dest/Src buffer address(virtual).
* retval EMMC_SUCCESS successful.
* retval EMMC_ERR_PARAM parameter error.
* retval EMMC_ERR_STATE state error.
*/
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 == 0U))
{
return EMMC_ERR_STATE;
}
bufPtrLL = (uint64_t*)buff_address_virtual;
length = mmc_drv_obj.remain_size;
/* data transefer */
for (i = 0U; i < (length >> 3U); i++)
{
/* Write */
if (mmc_drv_obj.cmd_info.dir == HAL_MEMCARD_WRITE)
{
mem_write64(SD_BUF0, *bufPtrLL); /* buffer --> FIFO */
}
/* Read */
else {
*bufPtrLL = mem_read64(SD_BUF0); /* FIFO --> buffer */
}
bufPtrLL++;
}
return EMMC_SUCCESS;
}
/* ******************************** END ************************************ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,94 @@
/*******************************************************************************
* DISCLAIMER
* This software is supplied by Renesas Electronics Corporation and is only
* intended for use with Renesas products. No other uses are authorized. This
* software is owned by Renesas Electronics Corporation and is protected under
* all applicable laws, including copyright laws.
* THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING
* THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT
* LIMITED TO WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
* AND NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED.
* TO THE MAXIMUM EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS
* ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES SHALL BE LIABLE
* FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR
* ANY REASON RELATED TO THIS SOFTWARE, EVEN IF RENESAS OR ITS AFFILIATES HAVE
* BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
* Renesas reserves the right, without notice, to make changes to this software
* and to discontinue the availability of this software. By using this software,
* you agree to the additional terms and conditions found by accessing the
* following link:
* http://www.renesas.com/disclaimer
* Copyright 2018-2022 Renesas Electronics Corporation All rights reserved.
*******************************************************************************/
/*******************************************************************************
* DESCRIPTION : emmc multi boot
******************************************************************************/
/******************************************************************************
* @file emmc multiboot.c
* - Version : 0.02
* @brief
* .
*****************************************************************************/
/******************************************************************************
* History : DD.MM.YYYY Version Description
* : 02.02.2022 0.01 First Release
* : 31.10.2022 0.02 License notation change.
*****************************************************************************/
/* ************************ HEADER (INCLUDE) SECTION *********************** */
#include "emmc_config.h"
#include "emmc_hal.h"
#include "emmc_std.h"
#include "emmc_def.h"
#include "emmc_multiboot.h"
#include "types.h"
/* ********************** STRUCTURES, TYPE DEFINITIONS ********************* */
/* ********************** DECLARATION OF EXTERNAL DATA ********************* */
/* ************************** FUNCTION PROTOTYPES ************************** */
uint32_t emmc_check_result(uint32_t result);
/* ********************************* CODE ********************************** */
uint32_t emmc_trans_data(uint32_t next_bootPartition, uintptr_t sourceSct, uintptr_t targetAd, uint32_t sectorSize)
{
EMMC_ERROR_CODE result;
uint32_t rtn_val = EMMC_DEV_ERR;
/* Partition select */
result = emmc_select_partition((EMMC_PARTITION_ID)next_bootPartition);
if (result == EMMC_SUCCESS)
{
result = emmc_read_sector((uint32_t *)targetAd, sourceSct, sectorSize, LOADIMAGE_FLAGS_DMA_ENABLE);
}
/* EMMC_ERROR_CODE -> ROM_XX */
rtn_val = emmc_check_result((uint32_t)result);
return rtn_val;
}
uint32_t emmc_check_result(uint32_t result)
{
uint32_t ret = EMMC_DEV_ERR_FAULT_INJECTION;
if (result == EMMC_SUCCESS)
{
ret = EMMC_DEV_OK;
} else if (result == EMMC_ERR) {
ret = EMMC_DEV_ERR;
} else { /* other */
ret = EMMC_DEV_ERR_HW;
}
return ret;
}
/* ******************************** END ************************************ */

View File

@@ -0,0 +1,216 @@
/*******************************************************************************
* DISCLAIMER
* This software is supplied by Renesas Electronics Corporation and is only
* intended for use with Renesas products. No other uses are authorized. This
* software is owned by Renesas Electronics Corporation and is protected under
* all applicable laws, including copyright laws.
* THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING
* THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT
* LIMITED TO WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
* AND NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED.
* TO THE MAXIMUM EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS
* ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES SHALL BE LIABLE
* FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR
* ANY REASON RELATED TO THIS SOFTWARE, EVEN IF RENESAS OR ITS AFFILIATES HAVE
* BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
* Renesas reserves the right, without notice, to make changes to this software
* and to discontinue the availability of this software. By using this software,
* you agree to the additional terms and conditions found by accessing the
* following link:
* http://www.renesas.com/disclaimer
* Copyright 2018-2022 Renesas Electronics Corporation All rights reserved.
*******************************************************************************/
/*******************************************************************************
* DESCRIPTION : emmc read
******************************************************************************/
/******************************************************************************
* @file emmc_read.c
* - Version : 0.04
* @brief
* .
*****************************************************************************/
/******************************************************************************
* History : DD.MM.YYYY Version Description
* : 02.02.2022 0.01 First Release
* : 23.03.2022 0.02 Added header file inclusion
* : 16.06.2022 0.03 Change log output
* : 31.10.2022 0.04 License notation change.
*****************************************************************************/
/* ************************ HEADER (INCLUDE) SECTION *********************** */
#include "emmc_config.h"
#include "emmc_hal.h"
#include "emmc_std.h"
#include "emmc_registers.h"
#include "emmc_def.h"
#include "log.h"
#include "mem_io.h"
/* ***************** MACROS, CONSTANTS, COMPILATION FLAGS ****************** */
#define EMMC_RW_SECTOR_COUNT_MAX 0x0000ffffUL
/* ********************** STRUCTURES, TYPE DEFINITIONS ********************* */
/* ********************** DECLARATION OF EXTERNAL DATA ********************* */
/* ************************** FUNCTION PROTOTYPES ************************** */
static EMMC_ERROR_CODE emmc_multiple_block_read (uint32_t *buff_address_virtual, uint32_t sector_number, uint32_t count, HAL_MEMCARD_DATA_TRANSFER_MODE transfer_mode);
static inline uint32_t get_min_value(uint32_t a, uint32_t b)
{
uint32_t ret = a;
if(b < a)
{
ret = b;
}
return ret;
}
/* ********************************* CODE ********************************** */
/** function of read sector
*
* This function always use block read.
* Single block read is not used.
*
* - Pre-conditions:<BR>
* MMC card is mounted.
*
* - Post-conditions:<BR>
* .
*
* param[in,out] buff_address_virtual virtual address of read data buffer.
* param[in] sector_number data address for MMC device (sector number).
* param[in] count number of sector.
* param[in] transfermode Mode of data transfer, DMA or not DMA.
*/
EMMC_ERROR_CODE emmc_read_sector(uint32_t *buff_address_virtual, uint32_t sector_number, uint32_t count,
uint32_t feature_flags)
{
uint32_t trans_count;
uint32_t remain;
EMMC_ERROR_CODE result = EMMC_ERR;
HAL_MEMCARD_DATA_TRANSFER_MODE transfermode;
/* parameter check */
if (count == 0U)
{
ERROR("%s:0x%x\n",__func__,EMMC_ERR_PARAM);
return EMMC_ERR_PARAM;
}
/* state check */
if (mmc_drv_obj.mount != TRUE)
{
ERROR("%s:0x%x\n",__func__,EMMC_ERR_STATE);
return EMMC_ERR_STATE;
}
/* DMA? */
if ((feature_flags & LOADIMAGE_FLAGS_DMA_ENABLE) != 0U)
{
transfermode = HAL_MEMCARD_DMA;
} else {
transfermode = HAL_MEMCARD_NOT_DMA;
}
remain = count;
while (remain != 0U)
{
trans_count = get_min_value(remain, EMMC_RW_SECTOR_COUNT_MAX);
result = emmc_multiple_block_read(buff_address_virtual, sector_number, trans_count, transfermode);
if (result != EMMC_SUCCESS)
{
return result;
}
buff_address_virtual += (EMMC_BLOCK_LENGTH_DW * trans_count);
sector_number += trans_count;
remain -= trans_count;
}
return EMMC_SUCCESS;
}
/** multiple block read
*
* Multiple block read with pre-defined block count.
*
* - Pre-conditions:<BR>
* MMC card is mounted.
*
* - Post-conditions:<BR>
* .
*
* param[in,out] buff_address_virtual virtual address of read data buffer.
* param[in] sector_number data address for MMC device (sector number).
* param[in] count number of sector. (0x1 - 0xffff)
* param[in] transfer_mode Mode of data transfer, DMA or not DMA.
*/
static EMMC_ERROR_CODE emmc_multiple_block_read(uint32_t *buff_address_virtual, uint32_t sector_number, uint32_t count,
HAL_MEMCARD_DATA_TRANSFER_MODE transfer_mode)
{
EMMC_ERROR_CODE result = EMMC_ERR;
/* parameter check */
if ((count > EMMC_RW_SECTOR_COUNT_MAX) || (count == 0U)
|| ((transfer_mode != HAL_MEMCARD_DMA) && (transfer_mode != HAL_MEMCARD_NOT_DMA)))
{
ERROR("%s:0x%x\n",__func__,EMMC_ERR_PARAM);
return EMMC_ERR_PARAM;
}
/* CMD23 */
emmc_make_nontrans_cmd(CMD23_SET_BLOCK_COUNT, count);
result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response);
if (result != EMMC_SUCCESS)
{
return result;
}
mem_write32(SD_SECCNT, count);
mem_write32(SD_STOP, 0x00000100U);
mem_write32(CC_EXT_MODE, (CC_EXT_MODE_CLEAR | CC_EXT_MODE_DMASDRW_ENABLE)); /* SD_BUF Read/Write DMA Transfer enable */
/* CMD18 */
emmc_make_trans_cmd(CMD18_READ_MULTIPLE_BLOCK, sector_number, buff_address_virtual, count << EMMC_SECTOR_SIZE_SHIFT,
HAL_MEMCARD_READ, transfer_mode);
result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response);
if (result != EMMC_SUCCESS)
{
return result; /* CMD18 error code */
}
/* CMD13 */
emmc_make_nontrans_cmd(CMD13_SEND_STATUS, EMMC_RCA << 16U);
result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response);
if (result != EMMC_SUCCESS)
{
return result;
}
/* ready status check */
if ((mmc_drv_obj.r1_card_status & EMMC_R1_READY) == 0U)
{
ERROR("%s:0x%x\n",__func__,EMMC_ERR_CARD_BUSY);
return EMMC_ERR_CARD_BUSY;
}
/* state check */
if (mmc_drv_obj.current_state != EMMC_R1_STATE_TRAN)
{
ERROR("%s:0x%x\n",__func__,EMMC_ERR_CARD_STATE);
return EMMC_ERR_CARD_STATE;
}
return EMMC_SUCCESS;
}
/* ******************************** END ************************************ */

View File

@@ -0,0 +1,305 @@
/*******************************************************************************
* DISCLAIMER
* This software is supplied by Renesas Electronics Corporation and is only
* intended for use with Renesas products. No other uses are authorized. This
* software is owned by Renesas Electronics Corporation and is protected under
* all applicable laws, including copyright laws.
* THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING
* THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT
* LIMITED TO WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
* AND NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED.
* TO THE MAXIMUM EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS
* ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES SHALL BE LIABLE
* FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR
* ANY REASON RELATED TO THIS SOFTWARE, EVEN IF RENESAS OR ITS AFFILIATES HAVE
* BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
* Renesas reserves the right, without notice, to make changes to this software
* and to discontinue the availability of this software. By using this software,
* you agree to the additional terms and conditions found by accessing the
* following link:
* http://www.renesas.com/disclaimer
* Copyright 2018-2022 Renesas Electronics Corporation All rights reserved.
*******************************************************************************/
/*******************************************************************************
* DESCRIPTION : emmc utility
******************************************************************************/
/******************************************************************************
* @file emmc_utility
* - Version : 0.02
* @brief
* .
*****************************************************************************/
/******************************************************************************
* History : DD.MM.YYYY Version Description
* : 02.02.2022 0.01 First Release
* : 31.10.2022 0.02 License notation change.
*****************************************************************************/
/* ************************ HEADER (INCLUDE) SECTION *********************** */
#include "emmc_config.h"
#include "emmc_hal.h"
#include "emmc_std.h"
#include "emmc_registers.h"
#include "emmc_def.h"
/* ***************** MACROS, CONSTANTS, COMPILATION FLAGS ****************** */
#define BUSY_SIGNAL (1U << 10U)
static const uint32_t cmd_reg_hw[EMMC_CMD_MAX + 1U] =
{
0x00000000U, /* CMD0 */
0x00000701U, /* CMD1 */
0x00000002U, /* CMD2 */
0x00000003U, /* CMD3 */
0x00000004U, /* CMD4 */
0x00000505U, /* CMD5 */
0x00000406U, /* CMD6 */
0x00000007U, /* CMD7 */
0x00001C08U, /* CMD8 */
0x00000009U, /* CMD9 */
0x0000000AU, /* CMD10 */
0x00000000U, /* reserved */
0x0000000CU, /* CMD12 */
0x0000000DU, /* CMD13 */
0x00001C0EU, /* CMD14 */
0x0000000FU, /* CMD15 */
0x00000010U, /* CMD16 */
0x00000011U, /* CMD17 */
0x00007C12U, /* CMD18 */
0x00000C13U, /* CMD19 */
0x00000000U,
0x00001C15U, /* CMD21 */
0x00000000U,
0x00000017U, /* CMD23 */
0x00000018U, /* CMD24 */
0x00006C19U, /* CMD25 */
0x00000C1AU, /* CMD26 */
0x0000001BU, /* CMD27 */
0x0000001CU, /* CMD28 */
0x0000001DU, /* CMD29 */
0x0000001EU, /* CMD30 */
0x00001C1FU, /* CMD31 */
0x00000000U,
0x00000000U,
0x00000000U,
0x00000423U, /* CMD35 */
0x00000424U, /* CMD36 */
0x00000000U,
0x00000026U, /* CMD38 */
0x00000427U, /* CMD39 */
0x00000428U, /* CMD40 : send cmd */
0x00000000U,
0x0000002AU, /* CMD42 */
0x00000000U,
0x00000000U,
0x00000000U,
0x00000000U,
0x00000000U,
0x00000000U,
0x00000C31U,
0x00000000U,
0x00000000U,
0x00000000U,
0x00007C35U,
0x00006C36U,
0x00000037U, /* CMD55 */
0x00000038U, /* CMD56 : Read */
0x00000000U,
0x00000000U,
0x00000000U,
0x00000000U
};
/* ********************** STRUCTURES, TYPE DEFINITIONS ********************* */
/* ********************** DECLARATION OF EXTERNAL DATA ********************* */
/* ************************** FUNCTION PROTOTYPES ************************** */
/* ********************************* CODE ********************************** */
/** make non-transfer command data
*
* Response data buffer is automatically selected.
*
* - Pre-conditions:<BR>
* Clock to memory card IF is enabled.
*
* - Post-conditions:<BR>
* After this function is called, command can be executed.
*
* param[in] cmd command information.
* param[in] arg command argument
* return None.
*/
void emmc_make_nontrans_cmd(HAL_MEMCARD_COMMAND cmd, uint32_t arg)
{
/* command information */
mmc_drv_obj.cmd_info.cmd = cmd;
mmc_drv_obj.cmd_info.arg = arg;
mmc_drv_obj.cmd_info.dir = HAL_MEMCARD_READ;
mmc_drv_obj.cmd_info.hw = cmd_reg_hw[(uint32_t)cmd & HAL_MEMCARD_COMMAND_INDEX_MASK];
/* clear data transfer information */
mmc_drv_obj.trans_size = 0U;
mmc_drv_obj.remain_size = 0U;
mmc_drv_obj.buff_address_virtual = NULL;
mmc_drv_obj.buff_address_physical = NULL;
/* response information */
mmc_drv_obj.response_length = 6U;
switch ((HAL_MEMCARD_RESPONSE_TYPE)((uint32_t)(mmc_drv_obj.cmd_info.cmd) & (uint32_t)HAL_MEMCARD_RESPONSE_TYPE_MASK))
{
case HAL_MEMCARD_RESPONSE_NONE:
mmc_drv_obj.response = (uint32_t *)mmc_drv_obj.response_data;
mmc_drv_obj.response_length = 0U;
break;
case HAL_MEMCARD_RESPONSE_R1:
mmc_drv_obj.response = &mmc_drv_obj.r1_card_status;
break;
case HAL_MEMCARD_RESPONSE_R1b:
mmc_drv_obj.cmd_info.hw |= BUSY_SIGNAL; /* bit10 = R1 busy bit */
mmc_drv_obj.response = &mmc_drv_obj.r1_card_status;
break;
case HAL_MEMCARD_RESPONSE_R2:
mmc_drv_obj.response = (uint32_t *)mmc_drv_obj.response_data;
mmc_drv_obj.response_length = 17U;
break;
case HAL_MEMCARD_RESPONSE_R3:
mmc_drv_obj.response = &mmc_drv_obj.r3_ocr;
break;
case HAL_MEMCARD_RESPONSE_R4:
mmc_drv_obj.response = &mmc_drv_obj.r4_resp;
break;
case HAL_MEMCARD_RESPONSE_R5:
mmc_drv_obj.response = &mmc_drv_obj.r5_resp;
break;
default:
mmc_drv_obj.response = (uint32_t *)mmc_drv_obj.response_data;
break;
}
}
/** Making command information for data transfer command.
*
* - Pre-conditions:<BR>
* None.
*
* - Post-conditions:<BR>
* After this function is called, command can be executed.
*
* param[in] cmd command
* param[in] arg command argument
* param[in] buff_address_virtual Pointer to buffer where data is/will be stored. (virtual address)
* Client is responsible of allocation and deallocation of the buffer.
* param[in] len transfer length in bytes
* param[in] dir direction
* param[in] transfer_mode Mode of data transfer, DMA or not DMA.
* return None.
*/
void emmc_make_trans_cmd(HAL_MEMCARD_COMMAND cmd, uint32_t arg, uint32_t *buff_address_virtual, /* virtual address */
uint32_t len, HAL_MEMCARD_OPERATION dir, HAL_MEMCARD_DATA_TRANSFER_MODE transfer_mode)
{
emmc_make_nontrans_cmd(cmd, arg); /* update common information */
/* for data transfer command */
mmc_drv_obj.cmd_info.dir = dir;
mmc_drv_obj.buff_address_virtual = buff_address_virtual;
mmc_drv_obj.buff_address_physical = buff_address_virtual;
mmc_drv_obj.trans_size = len;
mmc_drv_obj.remain_size = len;
mmc_drv_obj.transfer_mode = transfer_mode;
}
/** Send idle command.
* Function execute CMD0.
*
* - Pre-conditions:<BR>
* Clock to MMC I/F enabled.
*
* - Post-conditions:<BR>
* Card reset to idle or pre-idle state.
*
* param[in] arg CMD0 argument.
* return error code
*/
EMMC_ERROR_CODE emmc_send_idle_cmd(uint32_t arg)
{
EMMC_ERROR_CODE result = EMMC_ERR;
/* initialize state */
mmc_drv_obj.mount = FALSE;
mmc_drv_obj.selected = FALSE;
mmc_drv_obj.during_transfer = FALSE;
mmc_drv_obj.during_dma_transfer = FALSE;
mmc_drv_obj.dma_error_flag = FALSE;
mmc_drv_obj.force_terminate = FALSE;
mmc_drv_obj.state_machine_blocking = FALSE;
mmc_drv_obj.bus_width = HAL_MEMCARD_DATA_WIDTH_1_BIT;
mmc_drv_obj.max_freq = MMC_20MHZ; /* 20MHz */
mmc_drv_obj.current_state = EMMC_R1_STATE_IDLE;
/* CMD0 (MMC clock is current frequency. if Data transfer mode, 20MHz or higher.) */
emmc_make_nontrans_cmd(CMD0_GO_IDLE_STATE, arg); /* CMD0 */
result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response);
if (result != EMMC_SUCCESS)
{
return result;
}
/* change MMC clock(400KHz) */
mmc_drv_obj.set_freq = MMC_400KHZ;
result = emmc_set_request_mmc_clock(&mmc_drv_obj.set_freq);
if (result != EMMC_SUCCESS)
{
return result;
}
return EMMC_SUCCESS;
}
/** get bit field data for 16bytes data(CSD register).
*
* - Pre-conditions:<BR>
* .
* - Post-conditions:<BR>
* .
*
* param[in] data 16bytes data.
* param[in] top bit number(top). 128>top
* param[in] bottom bit number(bottom). (0<=bottom<=top)
* return bit field.
*/
uint32_t emmc_bit_field(const uint8_t *data, uint32_t top, uint32_t bottom)
{
uint32_t value;
uint32_t index_top = (uint32_t)(15U - (top >> 3U));
uint32_t index_bottom = (uint32_t)(15U - (bottom >> 3U));
if (index_top == index_bottom)
{
value = data[index_top];
} else if ((index_top + 1U) == index_bottom) {
value = (uint32_t)(((uint32_t)data[index_top] << 8U) | data[index_bottom]);
} else if ((index_top + 2U) == index_bottom) {
value = (uint32_t)(
((uint32_t)data[index_top] << 16U) | ((uint32_t)data[index_top + 1U] << 8U) | data[index_top + 2U]);
} else {
value = (uint32_t)(
((uint32_t)data[index_top] << 24U) | ((uint32_t)data[index_top + 1U] << 16U)
| ((uint32_t)data[index_top + 2U] << 8U) | data[index_top + 3U]);
}
value = ((value >> (bottom & 0x07U)) & ((1U << ((top - bottom) + 1U)) - 1U));
return value;
}
/* ******************************** END ************************************ */