add IPL
This commit is contained in:
95
IPL/Customer/Mobis/V4H_Cx_Loader/ip/emmc/emmc_boot.c
Normal file
95
IPL/Customer/Mobis/V4H_Cx_Loader/ip/emmc/emmc_boot.c
Normal 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;
|
||||
}
|
||||
}
|
||||
622
IPL/Customer/Mobis/V4H_Cx_Loader/ip/emmc/emmc_cmd.c
Normal file
622
IPL/Customer/Mobis/V4H_Cx_Loader/ip/emmc/emmc_cmd.c
Normal 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 ************************************ */
|
||||
|
||||
399
IPL/Customer/Mobis/V4H_Cx_Loader/ip/emmc/emmc_init.c
Normal file
399
IPL/Customer/Mobis/V4H_Cx_Loader/ip/emmc/emmc_init.c
Normal 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 ************************************ */
|
||||
239
IPL/Customer/Mobis/V4H_Cx_Loader/ip/emmc/emmc_interrupt.c
Normal file
239
IPL/Customer/Mobis/V4H_Cx_Loader/ip/emmc/emmc_interrupt.c
Normal 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 ************************************ */
|
||||
|
||||
1592
IPL/Customer/Mobis/V4H_Cx_Loader/ip/emmc/emmc_mount.c
Normal file
1592
IPL/Customer/Mobis/V4H_Cx_Loader/ip/emmc/emmc_mount.c
Normal file
File diff suppressed because it is too large
Load Diff
94
IPL/Customer/Mobis/V4H_Cx_Loader/ip/emmc/emmc_multiboot.c
Normal file
94
IPL/Customer/Mobis/V4H_Cx_Loader/ip/emmc/emmc_multiboot.c
Normal 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 ************************************ */
|
||||
|
||||
216
IPL/Customer/Mobis/V4H_Cx_Loader/ip/emmc/emmc_read.c
Normal file
216
IPL/Customer/Mobis/V4H_Cx_Loader/ip/emmc/emmc_read.c
Normal 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 ************************************ */
|
||||
|
||||
305
IPL/Customer/Mobis/V4H_Cx_Loader/ip/emmc/emmc_utility.c
Normal file
305
IPL/Customer/Mobis/V4H_Cx_Loader/ip/emmc/emmc_utility.c
Normal 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 ************************************ */
|
||||
|
||||
Reference in New Issue
Block a user