add IPL
This commit is contained in:
249
IPL/Customer/Mobis/Gen4_ICUMX_Loader/ip/emmc/emmc_boot.c
Normal file
249
IPL/Customer/Mobis/Gen4_ICUMX_Loader/ip/emmc/emmc_boot.c
Normal file
@@ -0,0 +1,249 @@
|
||||
/*******************************************************************************
|
||||
* 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 2021-2024 Renesas Electronics Corporation All rights reserved.
|
||||
*******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* DESCRIPTION : eMMC boot
|
||||
******************************************************************************/
|
||||
/******************************************************************************
|
||||
* @file emmc_boot.c
|
||||
* - Version : 0.07
|
||||
* @brief eMMC initialze interface.
|
||||
* .
|
||||
*****************************************************************************/
|
||||
/******************************************************************************
|
||||
* History : DD.MM.YYYY Version Description
|
||||
* : 30.09.2021 0.01 First Release
|
||||
* : 22.10.2021 0.02 Remove unnecessary code
|
||||
* : 22.12.2021 0.03 Support static analysis
|
||||
* : 06.01.2022 0.04 Add WWDT timer reset function
|
||||
* : 06.04.2022 0.05 Fix Set SDCLK to 200MHz
|
||||
* : 23.05.2022 0.06 Integration of S4 and V4H
|
||||
* : 24.06.2024 0.07 Add process that set SDHI_D1.8/3.3V to 1.8V.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "emmc_boot.h"
|
||||
#include "mem_io.h"
|
||||
#include "log.h"
|
||||
#include "rom_api.h"
|
||||
#include "image_load_emmc.h"
|
||||
#include "emmc_hal.h"
|
||||
#include "emmc_std.h"
|
||||
#include "emmc_multiboot.h"
|
||||
#include "emmc_def.h"
|
||||
#include "emmc_config.h"
|
||||
#if (RCAR_LSI == RCAR_V4M) /* Gray Hawk */
|
||||
#include "i2c.h"
|
||||
#include "remap.h"
|
||||
#endif /* (RCAR_LSI == RCAR_V4M) */
|
||||
|
||||
/************************************************************************************************/
|
||||
/* Definitions */
|
||||
/************************************************************************************************/
|
||||
|
||||
|
||||
/************************************************************************************************/
|
||||
/* Unions */
|
||||
/************************************************************************************************/
|
||||
|
||||
|
||||
/************************************************************************************************/
|
||||
/* Structs */
|
||||
/************************************************************************************************/
|
||||
|
||||
|
||||
/************************************************************************************************/
|
||||
/* Globals */
|
||||
/************************************************************************************************/
|
||||
|
||||
/************************************************************************************************/
|
||||
/* Macros */
|
||||
/************************************************************************************************/
|
||||
|
||||
/************************************************************************************************/
|
||||
/* Prototypes */
|
||||
/************************************************************************************************/
|
||||
static void power_on_mmc(void);
|
||||
static void set_sd_clock(void);
|
||||
static void init_mmc_pin_function(void);
|
||||
#if (RCAR_LSI == RCAR_V4M) /* Gray Hawk */
|
||||
static void sdhi_random_address_read_pmic(uint32_t sl_add, uint32_t access_add, uint32_t *rd_buf);
|
||||
static void sdhi_page_write_pmic(uint32_t sl_add, uint32_t access_add, uint32_t *wr_buf);
|
||||
static void pmic_set_sdhi_vdd18(void);
|
||||
#endif /* (RCAR_LSI == RCAR_V4M) */
|
||||
|
||||
void emmc_initialize( void )
|
||||
{
|
||||
#if (RCAR_LSI == RCAR_V4M) /* Gray Hawk */
|
||||
/* Register I2C base address(physical:0xE6600000) to SIC REMAP14 for V4M. */
|
||||
set_sicremap_fcpr();
|
||||
pmic_set_sdhi_vdd18();
|
||||
#endif /* (RCAR_LSI == RCAR_V4M) */
|
||||
|
||||
/*****************************************************************
|
||||
PFC setting
|
||||
*****************************************************************/
|
||||
init_mmc_pin_function();
|
||||
|
||||
/*****************************************************************
|
||||
CPG setting
|
||||
*****************************************************************/
|
||||
power_on_mmc();
|
||||
set_sd_clock();
|
||||
|
||||
#if (RCAR_SA9_TYPE == EMMC_BOOT)
|
||||
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;
|
||||
}
|
||||
#endif /* (RCAR_SA9_TYPE == EMMC_BOOT) */
|
||||
} /* End of function emmc_initialize( void ) */
|
||||
|
||||
/************************************************************************************************/
|
||||
/* Func power_on_mmc */
|
||||
/************************************************************************************************/
|
||||
static void power_on_mmc(void)
|
||||
{
|
||||
uint32_t reg;
|
||||
uint32_t tmp_val;
|
||||
|
||||
tmp_val = CPG_MSTPCR_SDHI;
|
||||
|
||||
reg = mem_read32(CPG_MSTPCR7D0);
|
||||
if ((reg & tmp_val) != 0x0U)
|
||||
{
|
||||
reg &= ~(tmp_val);
|
||||
cpg_reg_write(CPG_MSTPCR7D0, CPG_MSTPSR7D0, reg);
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
reg = mem_read32(CPG_MSTPCR7D0);
|
||||
}
|
||||
while ((reg & tmp_val) != 0x0U); /* wait tmp_val=0 */
|
||||
} /* End of function power_on_mmc(void) */
|
||||
|
||||
/************************************************************************************************/
|
||||
/* Func set_sd_clock */
|
||||
/************************************************************************************************/
|
||||
static void set_sd_clock(void)
|
||||
{
|
||||
uint32_t reg;
|
||||
|
||||
reg = mem_read32(CPG_SD0CKCR0);
|
||||
reg &= (~(CPG_SD0CKCR0_STP0HCK | CPG_SD0CKCR0_SDSRCFC_MASK | CPG_SD0CKCR0_SD0FC_MASK));
|
||||
reg |= CPG_SD0CKCR0_200MHZ;
|
||||
cpg_reg_write(CPG_SD0CKCR0, CPG_SD0CKCR0, reg); /* Stop SDnH clock & SDn=200MHz */
|
||||
} /* End of function set_sd_clock(void) */
|
||||
|
||||
/************************************************************************************************/
|
||||
/* Func init_mmc_pin_function */
|
||||
/************************************************************************************************/
|
||||
static void init_mmc_pin_function(void)
|
||||
{
|
||||
uint32_t reg;
|
||||
|
||||
reg = mem_read32(PFC_POC_MMC_RW);
|
||||
reg &= (~(PFC_POC_MMC_MASK));
|
||||
reg |= PFC_POC_MMC_VAL;
|
||||
pfc_reg_write(PFC_POC_MMC_RW, reg);
|
||||
} /* End of function init_mmc_pin_function(void) */
|
||||
|
||||
#if (RCAR_LSI == RCAR_V4M) /* Gray Hawk */
|
||||
static void sdhi_random_address_read_pmic(uint32_t sl_add, uint32_t access_add, uint32_t *rd_buf)
|
||||
{
|
||||
uint32_t data;
|
||||
|
||||
/* for PMIC_RAA271005 */
|
||||
data = (access_add & 0x300U) >> 8U;
|
||||
i2c3_write(sl_add, 0x00U, data); /* Bank Set */
|
||||
|
||||
i2c3_read(sl_add, (access_add & 0x0FFU), rd_buf);
|
||||
}
|
||||
/* End of function sdhi_random_address_read_pmic(uint32_t sl_add, uint32_t access_add, uint32_t *rd_buf) */
|
||||
|
||||
static void sdhi_page_write_pmic(uint32_t sl_add, uint32_t access_add, uint32_t *wr_buf)
|
||||
{
|
||||
uint32_t data;
|
||||
|
||||
/* for PMIC_RAA271005 */
|
||||
data = (access_add & 0x300U) >> 8U;
|
||||
i2c3_write(sl_add, 0x00U, data); /* Bank Set */
|
||||
|
||||
i2c3_read(sl_add, (access_add & 0x0FFU), wr_buf);
|
||||
}
|
||||
/* End of function sdhi_page_write_pmic(uint32_t sl_add, uint32_t access_add, uint32_t *wr_buf) */
|
||||
|
||||
static void pmic_set_sdhi_vdd18(void)
|
||||
{
|
||||
/* In case of Gray Hawk board, change SDHI_18/33 voltage. */
|
||||
uint32_t slv_addr = 0xA8U; /* for PMIC-RAA271005: "reg 0xA8 0xA9 prot 0xAA 0xAB" */
|
||||
uint32_t data;
|
||||
|
||||
/* Init I2C */
|
||||
i2c3_init();
|
||||
|
||||
/* Setting 1.8V to SDHI_D1.8/3.3V(VDDQ18_33_SDHI) on PMIC-RAA271005 */
|
||||
data = 0x1U;
|
||||
i2c3_write(slv_addr, 0x00U, data); /* Write IO_PAGE. Chenge BANK1 */
|
||||
|
||||
i2c3_read(slv_addr, 0x3BU, &data);
|
||||
if ((data & 0x0CU) != 0x0U)
|
||||
{
|
||||
data &= ~(0x0CU);
|
||||
i2c3_write(slv_addr, 0x3BU, data);
|
||||
}
|
||||
|
||||
sdhi_random_address_read_pmic(slv_addr, 0x02U, &data);
|
||||
if ((data & 0xF0U) == 0xB0U)
|
||||
{
|
||||
// RAA271005 rev.B only
|
||||
data = 0x1U;
|
||||
sdhi_page_write_pmic(slv_addr, 0x00U, &data); /* Write IO_PAGE. Chenge BANK1 */
|
||||
|
||||
sdhi_random_address_read_pmic(slv_addr, 0x3BU, &data); /* Read FLT_CTRL1 */
|
||||
|
||||
data &= 0xF3U; /* LDO1 Fault remove */
|
||||
sdhi_page_write_pmic(slv_addr, 0x3BU, &data); /* Write FLT_CTRL1 */
|
||||
|
||||
data = 0x0U;
|
||||
sdhi_page_write_pmic(slv_addr, 0x00U, &data); /* Write IO_PAGE. Chenge BANK0 */
|
||||
}
|
||||
|
||||
data = 0x75U; /* LDO voltage 1.8V Value */
|
||||
i2c3_write(slv_addr, 0xBAU, data);
|
||||
sdhi_random_address_read_pmic(slv_addr, 0xBAU, &data);
|
||||
}
|
||||
/* End of function pmic_set_sdhi_vdd18(void) */
|
||||
#endif /* (RCAR_LSI == RCAR_V4M) */
|
||||
|
||||
580
IPL/Customer/Mobis/Gen4_ICUMX_Loader/ip/emmc/emmc_cmd.c
Normal file
580
IPL/Customer/Mobis/Gen4_ICUMX_Loader/ip/emmc/emmc_cmd.c
Normal file
@@ -0,0 +1,580 @@
|
||||
/*******************************************************************************
|
||||
* 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 2021-2022 Renesas Electronics Corporation All rights reserved.
|
||||
*******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* DESCRIPTION : eMMC CMD driver
|
||||
******************************************************************************/
|
||||
/******************************************************************************
|
||||
* @file emmc_cmd.c
|
||||
* - Version : 0.04
|
||||
* @brief control of CMD in SDHI.
|
||||
* .
|
||||
*****************************************************************************/
|
||||
/******************************************************************************
|
||||
* History : DD.MM.YYYY Version Description
|
||||
* : 22.02.2022 0.01 First Release
|
||||
* : 22.10.2021 0.02 Remove unnecessary code
|
||||
* : 22.12.2021 0.03 Support static analysis
|
||||
* : 06.01.2022 0.04 Modify SDHI access from DMA to PIO.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "emmc_config.h"
|
||||
#include "emmc_hal.h"
|
||||
#include "emmc_std.h"
|
||||
#include "emmc_registers.h"
|
||||
#include "emmc_def.h"
|
||||
#include "micro_wait.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%08x\n",__func__,EMMC_ERR_PARAM);
|
||||
return EMMC_ERR_PARAM;
|
||||
}
|
||||
|
||||
/* state check */
|
||||
if (mmc_drv_obj.clock_enable != TRUE) {
|
||||
ERROR("%s:0x%08x\n",__func__,EMMC_ERR_STATE);
|
||||
return EMMC_ERR_STATE;
|
||||
}
|
||||
|
||||
if (mmc_drv_obj.state_machine_blocking == TRUE) {
|
||||
ERROR("%s:0x%08x\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%08x\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%08x\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 */
|
||||
mem_write32(DM_CM_INFO1_MASK, ( DM_CM_INFO_MASK_CLEAR | DM_CM_INFO_CH0_ENABLE ));
|
||||
mem_write32(DM_CM_INFO2_MASK, ( DM_CM_INFO_MASK_CLEAR | DM_CM_INFO_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 */
|
||||
mem_write32(DM_CM_INFO1_MASK, ( DM_CM_INFO_MASK_CLEAR | DM_CM_INFO_CH1_ENABLE ));
|
||||
mem_write32(DM_CM_INFO2_MASK, ( DM_CM_INFO_MASK_CLEAR | DM_CM_INFO_CH1_ENABLE ));
|
||||
/* FIFO --> BUFF */
|
||||
mem_write32(DM_CM_DTRAN_MODE, ( DM_CM_DTRAN_MODE_CH1 | DM_CM_DTRAN_MODE_BIT_WIDTH )); /* CH0(downstream), 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 ************************************ */
|
||||
|
||||
311
IPL/Customer/Mobis/Gen4_ICUMX_Loader/ip/emmc/emmc_init.c
Normal file
311
IPL/Customer/Mobis/Gen4_ICUMX_Loader/ip/emmc/emmc_init.c
Normal file
@@ -0,0 +1,311 @@
|
||||
/*******************************************************************************
|
||||
* 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 2021-2022 Renesas Electronics Corporation All rights reserved.
|
||||
*******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* DESCRIPTION : eMMC initialze
|
||||
******************************************************************************/
|
||||
/******************************************************************************
|
||||
* @file emmc_init.c
|
||||
* - Version : 0.05
|
||||
* @brief initialize of SDHI driver.
|
||||
* .
|
||||
*****************************************************************************/
|
||||
/******************************************************************************
|
||||
* History : DD.MM.YYYY Version Description
|
||||
* : 22.02.2022 0.01 First Release
|
||||
* : 22.10.2021 0.02 Remove unnecessary code
|
||||
* : 22.12.2021 0.03 Support static analysis
|
||||
* : 06.01.2022 0.04 Modify SDHI access from DMA to PIO.
|
||||
* : 06.04/2022 0.05 Del SDnH clock & SDn=200MHz(Duplicate settings)
|
||||
*****************************************************************************/
|
||||
|
||||
/* ************************ 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 ****************** */
|
||||
|
||||
/* ********************** STRUCTURES, TYPE DEFINITIONS ********************* */
|
||||
|
||||
/* ********************** DECLARATION OF EXTERNAL DATA ********************* */
|
||||
st_mmc_base mmc_drv_obj;
|
||||
|
||||
/* ************************** 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 ********************************** */
|
||||
|
||||
/** 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)
|
||||
{
|
||||
|
||||
/* 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 ************************************ */
|
||||
|
||||
227
IPL/Customer/Mobis/Gen4_ICUMX_Loader/ip/emmc/emmc_interrupt.c
Normal file
227
IPL/Customer/Mobis/Gen4_ICUMX_Loader/ip/emmc/emmc_interrupt.c
Normal file
@@ -0,0 +1,227 @@
|
||||
/*******************************************************************************
|
||||
* 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 2021-2022 Renesas Electronics Corporation All rights reserved.
|
||||
*******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* DESCRIPTION : eMMC interrupt
|
||||
******************************************************************************/
|
||||
/******************************************************************************
|
||||
* @file emmc_interrupt.c
|
||||
* - Version : 0.04
|
||||
* @brief state check of SDHI.
|
||||
* .
|
||||
*****************************************************************************/
|
||||
/******************************************************************************
|
||||
* History : DD.MM.YYYY Version Description
|
||||
* : 22.02.2022 0.01 First Release
|
||||
* : 22.10.2021 0.02 Remove unnecessary code
|
||||
* : 22.12.2021 0.03 Support static analysis
|
||||
* : 06.01.2022 0.04 Modify SDHI access from DMA to PIO.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "emmc_config.h"
|
||||
#include "emmc_hal.h"
|
||||
#include "emmc_std.h"
|
||||
#include "emmc_registers.h"
|
||||
#include "emmc_def.h"
|
||||
#include "log.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%08x\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_INFO_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_INFO_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 ************************************ */
|
||||
|
||||
767
IPL/Customer/Mobis/Gen4_ICUMX_Loader/ip/emmc/emmc_mount.c
Normal file
767
IPL/Customer/Mobis/Gen4_ICUMX_Loader/ip/emmc/emmc_mount.c
Normal file
@@ -0,0 +1,767 @@
|
||||
/*******************************************************************************
|
||||
* 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 2021-2022 Renesas Electronics Corporation All rights reserved.
|
||||
*******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* DESCRIPTION : eMMC Mount
|
||||
******************************************************************************/
|
||||
/******************************************************************************
|
||||
* @file emmc_mount.c
|
||||
* - Version : 0.04
|
||||
* @brief initialize of condition.
|
||||
* .
|
||||
*****************************************************************************/
|
||||
/******************************************************************************
|
||||
* History : DD.MM.YYYY Version Description
|
||||
* : 22.02.2022 0.01 First Release
|
||||
* : 22.10.2021 0.02 Remove unnecessary code
|
||||
* : 22.12.2021 0.03 Support static analysis
|
||||
* : 06.01.2022 0.04 Modify SDHI access from DMA to PIO.
|
||||
*****************************************************************************/
|
||||
|
||||
/* ************************ HEADER (INCLUDE) SECTION *********************** */
|
||||
#include "emmc_config.h"
|
||||
#include "emmc_hal.h"
|
||||
#include "emmc_std.h"
|
||||
#include "emmc_registers.h"
|
||||
#include "emmc_def.h"
|
||||
#include <stdint.h>
|
||||
#include "micro_wait.h"
|
||||
#include "remap.h"
|
||||
#include "log.h"
|
||||
|
||||
/* ***************** MACROS, CONSTANTS, COMPILATION FLAGS ****************** */
|
||||
|
||||
/* ********************** STRUCTURES, TYPE DEFINITIONS ********************* */
|
||||
|
||||
/* ********************** DECLARATION OF EXTERNAL DATA ********************* */
|
||||
|
||||
/* ************************** FUNCTION PROTOTYPES ************************** */
|
||||
static EMMC_ERROR_CODE emmc_clock_ctrl(uint32_t mode);
|
||||
static EMMC_ERROR_CODE emmc_card_init(void);
|
||||
static EMMC_ERROR_CODE emmc_high_speed(void);
|
||||
static EMMC_ERROR_CODE emmc_bus_width(uint32_t width);
|
||||
static uint32_t emmc_set_timeout_register_value(uint32_t freq);
|
||||
static void set_sd_clk(uint32_t clkDiv);
|
||||
static uint32_t emmc_calc_tran_speed(uint32_t* freq);
|
||||
|
||||
/* ********************************* CODE ********************************** */
|
||||
|
||||
/** eMMC mount operation.
|
||||
*
|
||||
* Sequence is the following.
|
||||
* 1) Bus initialization (emmc_card_init())
|
||||
* 2) Switching to high speed mode. (emmc_high_speed())
|
||||
* 3) Changing the data bus width. (emmc_bus_width())
|
||||
*
|
||||
* - Pre-conditions:<BR>
|
||||
* eMMC driver is initialized. The power supply of MMC IF must be turning on.
|
||||
* - Post-conditions:<BR>
|
||||
* MMC card state changes to transfer state.
|
||||
*
|
||||
* return eMMC error code.
|
||||
*/
|
||||
EMMC_ERROR_CODE emmc_mount(void)
|
||||
{
|
||||
EMMC_ERROR_CODE result = EMMC_ERR;
|
||||
|
||||
/* state check */
|
||||
if ((mmc_drv_obj.initialize != TRUE) || (mmc_drv_obj.card_power_enable != TRUE)
|
||||
|| ((mem_read32(SD_INFO2) & SD_INFO2_CBSY) != 0U)) {
|
||||
ERROR("%s:0x%08x\n",__func__,EMMC_ERR_STATE);
|
||||
return EMMC_ERR_STATE;
|
||||
}
|
||||
|
||||
/* initialize card (IDLE state --> Transfer state) */
|
||||
result = emmc_card_init();
|
||||
if (result != EMMC_SUCCESS) {
|
||||
ERROR("%s\n",__func__);
|
||||
(void)emmc_clock_ctrl(FALSE);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Switching high speed mode */
|
||||
result = emmc_high_speed();
|
||||
if (result != EMMC_SUCCESS) {
|
||||
ERROR("%s\n",__func__);
|
||||
(void)emmc_clock_ctrl(FALSE);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Changing the data bus width */
|
||||
result = emmc_bus_width(8U);
|
||||
if (result != EMMC_SUCCESS) {
|
||||
ERROR("%s\n",__func__);
|
||||
(void)emmc_clock_ctrl(FALSE);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* mount complete */
|
||||
mmc_drv_obj.mount = TRUE;
|
||||
|
||||
return EMMC_SUCCESS;
|
||||
}
|
||||
|
||||
/** Bus initialization function
|
||||
*
|
||||
* - Pre-conditions:<BR>
|
||||
* eMMC driver is initialized. The power supply of MMC IF must be turning on.
|
||||
* - Post-conditions:<BR>
|
||||
* MMC card state changes to transfer state.
|
||||
*
|
||||
* retval EMMC_SUCCESS successful.
|
||||
* return eMMC error code.
|
||||
* attention upper layer must be check pre-conditions.
|
||||
*/
|
||||
static EMMC_ERROR_CODE emmc_card_init(void)
|
||||
{
|
||||
int32_t retry;
|
||||
uint32_t freq = MMC_400KHZ; /* 390KHz */
|
||||
EMMC_ERROR_CODE result = EMMC_ERR;
|
||||
uint32_t resultCalc = 0U;
|
||||
|
||||
/* state check */
|
||||
if ((mmc_drv_obj.initialize != TRUE) || (mmc_drv_obj.card_power_enable != TRUE)
|
||||
|| ((mem_read32(SD_INFO2) & SD_INFO2_CBSY) != 0U)) {
|
||||
ERROR("%s:0x%08x\n",__func__,EMMC_ERR_STATE);
|
||||
return EMMC_ERR_STATE;
|
||||
}
|
||||
|
||||
/* clock on (force change) */
|
||||
mmc_drv_obj.current_freq = 0U;
|
||||
mmc_drv_obj.max_freq = MMC_20MHZ; /* MMC_20MHZ = MMC_12MHZ = 12.187MHz */
|
||||
result = emmc_set_request_mmc_clock(&freq);
|
||||
if (result != EMMC_SUCCESS) {
|
||||
ERROR("%s\n",__func__);
|
||||
return EMMC_ERR;
|
||||
}
|
||||
|
||||
micro_wait(1000U); /* wait 1ms */
|
||||
|
||||
/* CMD0, arg=0x00000000 */
|
||||
result = emmc_send_idle_cmd (0x00000000U);
|
||||
if (result != EMMC_SUCCESS) {
|
||||
ERROR("%s\n",__func__);
|
||||
return result;
|
||||
}
|
||||
|
||||
micro_wait(200U); /* wait 74clock 390kHz(189.74us)*/
|
||||
|
||||
/* CMD1 */
|
||||
emmc_make_nontrans_cmd(CMD1_SEND_OP_COND, EMMC_HOST_OCR_VALUE);
|
||||
for (retry = 300; retry > 0; retry--) {
|
||||
result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response);
|
||||
if (result != EMMC_SUCCESS) {
|
||||
ERROR("%s\n",__func__);
|
||||
return result;
|
||||
}
|
||||
|
||||
if ((mmc_drv_obj.r3_ocr & EMMC_OCR_STATUS_BIT) != 0U) {
|
||||
break; /* card is ready. exit loop */
|
||||
}
|
||||
micro_wait(1000U); /* wait 1ms */
|
||||
}
|
||||
|
||||
if (retry == 0) {
|
||||
ERROR("%s:0x%08x\n",__func__,EMMC_ERR_TIMEOUT);
|
||||
return EMMC_ERR_TIMEOUT;
|
||||
}
|
||||
|
||||
if ((mmc_drv_obj.r3_ocr & EMMC_OCR_ACCESS_MODE_MASK) != EMMC_OCR_ACCESS_MODE_SECT) {
|
||||
/* unknown value */
|
||||
ERROR("%s:0x%08x\n",__func__,EMMC_ERR);
|
||||
return EMMC_ERR;
|
||||
}
|
||||
|
||||
/* CMD2 */
|
||||
emmc_make_nontrans_cmd(CMD2_ALL_SEND_CID_MMC, 0x00000000U);
|
||||
mmc_drv_obj.response = (uint32_t *)(&mmc_drv_obj.cid_data[0U]); /* use CID special buffer */
|
||||
result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response);
|
||||
if (result != EMMC_SUCCESS) {
|
||||
ERROR("%s\n",__func__);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* CMD3 */
|
||||
emmc_make_nontrans_cmd(CMD3_SET_RELATIVE_ADDR, EMMC_RCA << 16U);
|
||||
result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response);
|
||||
if (result != EMMC_SUCCESS) {
|
||||
ERROR("%s\n",__func__);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* CMD9 : CSD */
|
||||
emmc_make_nontrans_cmd(CMD9_SEND_CSD, EMMC_RCA << 16U);
|
||||
mmc_drv_obj.response = (uint32_t *)(&mmc_drv_obj.csd_data[0U]); /* use CSD special buffer */
|
||||
result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response);
|
||||
if (result != EMMC_SUCCESS) {
|
||||
ERROR("%s\n",__func__);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* card version check */
|
||||
if (EMMC_CSD_SPEC_VARS() < 4U) {
|
||||
ERROR("%s:0x%08x\n",__func__,EMMC_ERR_ILLEGAL_CARD);
|
||||
return EMMC_ERR_ILLEGAL_CARD;
|
||||
}
|
||||
|
||||
/* CMD7 (select card) */
|
||||
emmc_make_nontrans_cmd(CMD7_SELECT_CARD, EMMC_RCA << 16U);
|
||||
result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response);
|
||||
if (result != EMMC_SUCCESS) {
|
||||
ERROR("%s\n",__func__);
|
||||
return result;
|
||||
}
|
||||
|
||||
mmc_drv_obj.selected = TRUE;
|
||||
|
||||
/* card speed check */
|
||||
resultCalc = emmc_calc_tran_speed(&freq); /* Card spec is calculated from TRAN_SPEED(CSD). */
|
||||
if (resultCalc == 0U) {
|
||||
ERROR("%s:0x%08x\n",__func__,EMMC_ERR_ILLEGAL_CARD);
|
||||
return EMMC_ERR_ILLEGAL_CARD;
|
||||
}
|
||||
mmc_drv_obj.max_freq = freq; /* max frequency (card spec) */
|
||||
|
||||
result = emmc_set_request_mmc_clock(&freq);
|
||||
if (result != EMMC_SUCCESS) {
|
||||
ERROR("%s\n",__func__);
|
||||
return EMMC_ERR;
|
||||
}
|
||||
|
||||
/* set read/write timeout */
|
||||
mmc_drv_obj.data_timeout = emmc_set_timeout_register_value(freq);
|
||||
mem_write32(SD_OPTION, ((mem_read32(SD_OPTION) & ~(SD_OPTION_TIMEOUT_CNT_MASK)) | mmc_drv_obj.data_timeout));
|
||||
|
||||
/* SET_BLOCKLEN:512byte */
|
||||
/* CMD16 */
|
||||
emmc_make_nontrans_cmd(CMD16_SET_BLOCKLEN, EMMC_BLOCK_LENGTH);
|
||||
result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response);
|
||||
if (result != EMMC_SUCCESS) {
|
||||
ERROR("%s\n",__func__);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Transfer Data Length */
|
||||
mem_write32(SD_SIZE, EMMC_BLOCK_LENGTH);
|
||||
|
||||
/* CMD8 : EXT_CSD */
|
||||
emmc_make_trans_cmd(CMD8_SEND_EXT_CSD, 0x00000000U, (uint32_t *)(&mmc_drv_obj.ext_csd_data[0U]),
|
||||
EMMC_MAX_EXT_CSD_LENGTH, HAL_MEMCARD_READ, HAL_MEMCARD_NOT_DMA);
|
||||
result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response);
|
||||
if (result != EMMC_SUCCESS) {
|
||||
/* CMD12 is not send.
|
||||
* If BUS initialization is failed, user must be execute Bus initialization again.
|
||||
* Bus initialization is start CMD0(soft reset command).
|
||||
*/
|
||||
ERROR("%s\n",__func__);
|
||||
return result;
|
||||
}
|
||||
|
||||
return EMMC_SUCCESS;
|
||||
}
|
||||
|
||||
/** Switching to high-speed mode
|
||||
*
|
||||
* - Pre-conditions:<BR>
|
||||
* Executing Bus initializatin by emmc_card_init().
|
||||
* EXT_CSD data must be stored in mmc_drv_obj.ext_csd_data[].
|
||||
*
|
||||
* - Post-conditions:<BR>
|
||||
* Change the clock frequency to 26MHz or 52MHz.
|
||||
*
|
||||
* retval EMMC_SUCCESS successful or aleady switching.
|
||||
* retval EMMC_ERR_STATE state error.
|
||||
* retval EMMC_ERR unknown error.
|
||||
* return emmc error code.
|
||||
*/
|
||||
static EMMC_ERROR_CODE emmc_high_speed(void)
|
||||
{
|
||||
uint32_t freq; /**< High speed mode clock frequency */
|
||||
EMMC_ERROR_CODE result = EMMC_ERR;
|
||||
uint8_t cardType;
|
||||
|
||||
/* state check */
|
||||
if (mmc_drv_obj.selected != TRUE) {
|
||||
ERROR("%s:0x%08x\n",__func__,EMMC_ERR_STATE);
|
||||
return EMMC_ERR_STATE;
|
||||
}
|
||||
|
||||
/* max frequency */
|
||||
cardType = (uint8_t)mmc_drv_obj.ext_csd_data[EMMC_EXT_CSD_CARD_TYPE];
|
||||
if ((cardType & EMMC_EXT_CSD_CARD_TYPE_52MHZ) != 0U) {
|
||||
freq = MMC_52MHZ;
|
||||
} else if ((cardType & EMMC_EXT_CSD_CARD_TYPE_26MHZ) != 0U) {
|
||||
freq = MMC_26MHZ;
|
||||
} else {
|
||||
freq = MMC_20MHZ;
|
||||
}
|
||||
|
||||
/* Hi-Speed-mode selction */
|
||||
if (( MMC_52MHZ == freq) || ( MMC_26MHZ == freq)) {
|
||||
/* CMD6 */
|
||||
emmc_make_nontrans_cmd(CMD6_SWITCH, EMMC_SWITCH_HS_TIMING);
|
||||
result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response);
|
||||
if (result != EMMC_SUCCESS) {
|
||||
ERROR("%s\n",__func__);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* set mmc clock */
|
||||
mmc_drv_obj.max_freq = freq;
|
||||
result = emmc_set_request_mmc_clock(&freq);
|
||||
if (result != EMMC_SUCCESS) {
|
||||
ERROR("%s\n",__func__);
|
||||
return EMMC_ERR;
|
||||
}
|
||||
|
||||
/* set read/write timeout */
|
||||
mmc_drv_obj.data_timeout = emmc_set_timeout_register_value(freq);
|
||||
mem_write32(SD_OPTION, ((mem_read32(SD_OPTION) & ~(SD_OPTION_TIMEOUT_CNT_MASK)) | mmc_drv_obj.data_timeout));
|
||||
|
||||
/* CMD13 */
|
||||
emmc_make_nontrans_cmd(CMD13_SEND_STATUS, EMMC_RCA << 16U);
|
||||
result = emmc_exec_cmd(EMMC_R1_ERROR_MASK_WITHOUT_CRC, mmc_drv_obj.response);
|
||||
if (result != EMMC_SUCCESS) {
|
||||
ERROR("%s\n",__func__);
|
||||
return result;
|
||||
}
|
||||
|
||||
return EMMC_SUCCESS;
|
||||
}
|
||||
|
||||
/** Changing the data bus width
|
||||
*
|
||||
* if chinging the data bus width failed, card is reset by CMD0.
|
||||
* Please do Bus initialization over again.
|
||||
*
|
||||
* - Pre-conditions:<BR>
|
||||
* Executing Bus initializatin by emmc_card_init().
|
||||
*
|
||||
* - Post-conditions:<BR>
|
||||
* Change the data bus width to 8bit or 4bit.
|
||||
* mmc_drv_obj.ext_csd_data is updated.
|
||||
*
|
||||
* param[in] width bus width (8 or 4)
|
||||
* retval EMMC_SUCCESS successful.
|
||||
* retval EMMC_ERR_PARAM parameter error
|
||||
* retval EMMC_ERR_STATE state error.
|
||||
*
|
||||
*/
|
||||
static EMMC_ERROR_CODE emmc_bus_width(uint32_t width)
|
||||
{
|
||||
EMMC_ERROR_CODE result = EMMC_ERR;
|
||||
|
||||
/* parameter check */
|
||||
if ((width != 8U) && (width != 4U) && (width != 1U)) {
|
||||
ERROR("%s:0x%08x\n",__func__,EMMC_ERR_PARAM);
|
||||
return EMMC_ERR_PARAM;
|
||||
}
|
||||
|
||||
/* state check */
|
||||
if (mmc_drv_obj.selected != TRUE) {
|
||||
ERROR("%s:0x%08x\n",__func__,EMMC_ERR_STATE);
|
||||
return EMMC_ERR_STATE;
|
||||
}
|
||||
|
||||
mmc_drv_obj.bus_width = (HAL_MEMCARD_DATA_WIDTH)(width >> 2U); /* 2 = 8bit, 1 = 4bit, 0 =1bit */
|
||||
|
||||
/* CMD6 */
|
||||
emmc_make_nontrans_cmd(CMD6_SWITCH, ( EMMC_SWITCH_BUS_WIDTH_1 | ((uint32_t)(mmc_drv_obj.bus_width) << 8U)));
|
||||
result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response);
|
||||
if (result != EMMC_SUCCESS) {
|
||||
/* occurred error */
|
||||
mmc_drv_obj.bus_width = HAL_MEMCARD_DATA_WIDTH_1_BIT;
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
switch (mmc_drv_obj.bus_width) {
|
||||
case HAL_MEMCARD_DATA_WIDTH_1_BIT:
|
||||
mem_write32(SD_OPTION, ((mem_read32(SD_OPTION) & ~(SD_OPTION_WIDTH|SD_OPTION_WIDTH8)) | SD_OPTION_WIDTH ));
|
||||
break;
|
||||
case HAL_MEMCARD_DATA_WIDTH_4_BIT:
|
||||
mem_write32(SD_OPTION, (mem_read32(SD_OPTION) & ~(SD_OPTION_WIDTH|SD_OPTION_WIDTH8)));
|
||||
break;
|
||||
case HAL_MEMCARD_DATA_WIDTH_8_BIT:
|
||||
default:
|
||||
mem_write32(SD_OPTION, ((mem_read32(SD_OPTION) & ~(SD_OPTION_WIDTH|SD_OPTION_WIDTH8)) | SD_OPTION_WIDTH8 ));
|
||||
break;
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
/* CMD8 : EXT_CSD */
|
||||
emmc_make_trans_cmd(CMD8_SEND_EXT_CSD, 0x00000000U, (uint32_t *)(&mmc_drv_obj.ext_csd_data[0U]),
|
||||
EMMC_MAX_EXT_CSD_LENGTH, HAL_MEMCARD_READ, HAL_MEMCARD_NOT_DMA);
|
||||
result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response);
|
||||
if (result != EMMC_SUCCESS) {
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
return EMMC_SUCCESS;
|
||||
|
||||
EXIT:
|
||||
ERROR("%s:0x%08x\n",__func__,result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/** select access partition
|
||||
*
|
||||
* This function write the EXT_CSD register(PARTITION_ACCESS: PARTITION_CONFIG[2:0]).
|
||||
*
|
||||
* - Pre-conditions:<BR>
|
||||
* MMC card is mounted.
|
||||
*
|
||||
* - Post-conditions:<BR>
|
||||
* selected partition can access.
|
||||
*
|
||||
* param[in] id user selects partitions to access.
|
||||
* retval EMMC_SUCCESS successful.
|
||||
* retval EMMC_ERR_STATE state error.
|
||||
* retval EMMC_ERR_PARAM parameter error.
|
||||
* return emmc error code.
|
||||
*/
|
||||
EMMC_ERROR_CODE emmc_select_partition(EMMC_PARTITION_ID id)
|
||||
{
|
||||
EMMC_ERROR_CODE result = EMMC_ERR;
|
||||
uint32_t partition;
|
||||
uint32_t partition_config;
|
||||
|
||||
/* state check */
|
||||
if (mmc_drv_obj.mount != TRUE) {
|
||||
ERROR("%s:0x%08x\n",__func__,EMMC_ERR_STATE);
|
||||
return EMMC_ERR_STATE;
|
||||
}
|
||||
|
||||
/* id has PARTITION_ACCESS(Bit[2:0]) */
|
||||
if ((uint32_t)((uint32_t)id & ~(uint32_t)PARTITION_ID_MASK) != 0U) {
|
||||
ERROR("%s:0x%08x\n",__func__,EMMC_ERR_PARAM);
|
||||
return EMMC_ERR_PARAM;
|
||||
}
|
||||
|
||||
/* EXT_CSD[179] value */
|
||||
partition_config = (uint32_t)mmc_drv_obj.ext_csd_data[EMMC_EXT_CSD_PARTITION_CONFIG];
|
||||
if ((partition_config & (uint32_t)PARTITION_ID_MASK) == (uint32_t)id) {
|
||||
result = EMMC_SUCCESS;
|
||||
} else {
|
||||
|
||||
partition_config = ((partition_config & (~(uint32_t)PARTITION_ID_MASK)) | (uint32_t)id);
|
||||
partition = EMMC_SWITCH_PARTITION_CONFIG | (partition_config << 8U);
|
||||
|
||||
result = emmc_set_ext_csd(partition);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/** set EXT CSD data
|
||||
*
|
||||
* - Pre-conditions:<BR>
|
||||
* MMC card is mounted.
|
||||
*
|
||||
* - Post-conditions:<BR>
|
||||
* mmc_drv_obj.ext_csd_data[] is updated.
|
||||
*
|
||||
* param[in] arg argument of CMD6
|
||||
* return emmc error code.
|
||||
*/
|
||||
EMMC_ERROR_CODE emmc_set_ext_csd(uint32_t arg)
|
||||
{
|
||||
EMMC_ERROR_CODE result = EMMC_ERR;
|
||||
|
||||
/* CMD6 */
|
||||
emmc_make_nontrans_cmd(CMD6_SWITCH, arg);
|
||||
result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response);
|
||||
if (result != EMMC_SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* CMD8 : EXT_CSD */
|
||||
emmc_make_trans_cmd(CMD8_SEND_EXT_CSD, 0x00000000, (uint32_t *)(&mmc_drv_obj.ext_csd_data[0U]),
|
||||
EMMC_MAX_EXT_CSD_LENGTH, HAL_MEMCARD_READ, HAL_MEMCARD_NOT_DMA);
|
||||
result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response);
|
||||
if (result != EMMC_SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
return EMMC_SUCCESS;
|
||||
}
|
||||
|
||||
/** set request MMC clock frequency.
|
||||
*
|
||||
* Function returns EMMC_SUCCESS if clock is already running in the desired frequency.
|
||||
* EMMC_ERR is returned if the HW doesn't support requested clock frequency.
|
||||
* If matching frequence cannot be set the closest frequence below should be selected.
|
||||
* For example if 50MHz is requested, but HW supports only 48MHz then 48MHz should be returned in the freq parameter.
|
||||
*
|
||||
* - Pre-conditions:<BR>
|
||||
* initialized eMMC driver with emmc_init().
|
||||
* Memory card and MMCSDIO host controller needs to be powered up beforehand.
|
||||
*
|
||||
* - Post-conditions:<BR>
|
||||
* Desired clock frequency is set to memory card IF.
|
||||
*
|
||||
* param[in] freq frequency [Hz]
|
||||
* retval EMMC_SUCCESS successful.
|
||||
* retval EMMC_ERR_STATE state error.
|
||||
* retval EMMC_ERR busy
|
||||
*/
|
||||
EMMC_ERROR_CODE emmc_set_request_mmc_clock(const uint32_t *freq)
|
||||
{
|
||||
/* parameter check */
|
||||
if (freq == NULL) {
|
||||
ERROR("%s:0x%08x\n",__func__,EMMC_ERR_PARAM);
|
||||
return EMMC_ERR_PARAM;
|
||||
}
|
||||
|
||||
/* state check */
|
||||
if ((mmc_drv_obj.initialize != TRUE) || (mmc_drv_obj.card_power_enable != TRUE)) {
|
||||
ERROR("%s:0x%08x\n",__func__,EMMC_ERR_STATE);
|
||||
return EMMC_ERR_STATE;
|
||||
}
|
||||
|
||||
/* clock is already running in the desired frequency. */
|
||||
if ((mmc_drv_obj.clock_enable == TRUE) && (mmc_drv_obj.current_freq == *freq)) {
|
||||
return EMMC_SUCCESS;
|
||||
}
|
||||
|
||||
/* busy check */
|
||||
if ((mem_read32(SD_INFO2) & SD_INFO2_CBSY) != 0U) {
|
||||
ERROR("%s:0x%08x\n",__func__,EMMC_ERR_CARD_BUSY);
|
||||
return EMMC_ERR;
|
||||
}
|
||||
|
||||
set_sd_clk(*freq);
|
||||
mmc_drv_obj.clock_enable = FALSE;
|
||||
|
||||
return emmc_clock_ctrl(TRUE); /* clock on */
|
||||
}
|
||||
|
||||
/** set sd clock.
|
||||
*
|
||||
* - Pre-conditions:<BR>
|
||||
* CSD data must be stored in mmc_drv_obj.csd_data[].
|
||||
*
|
||||
* - Post-conditions:<BR>
|
||||
* set mmc clock.
|
||||
*
|
||||
* param[in] clkDiv request freq
|
||||
* return None.
|
||||
*/
|
||||
static void set_sd_clk(uint32_t clkDiv)
|
||||
{
|
||||
uint32_t dataL;
|
||||
|
||||
dataL = (mem_read32(SD_CLK_CTRL) & (~SD_CLK_CTRL_CLKDIV_MASK));
|
||||
|
||||
switch (clkDiv) {
|
||||
case 1U: /* 1/1 */
|
||||
dataL |= 0x000000FFU;
|
||||
break;
|
||||
case 2U: /* 1/2 */
|
||||
dataL |= 0x00000000U;
|
||||
break;
|
||||
case 4U: /* 1/4 */
|
||||
dataL |= 0x00000001U;
|
||||
break;
|
||||
case 8U: /* 1/8 */
|
||||
dataL |= 0x00000002U;
|
||||
break;
|
||||
case 16U: /* 1/16 */
|
||||
dataL |= 0x00000004U;
|
||||
break;
|
||||
case 32U:/* 1/32 */
|
||||
dataL |= 0x00000008U;
|
||||
break;
|
||||
case 64U:/* 1/64 */
|
||||
dataL |= 0x00000010U;
|
||||
break;
|
||||
case 128U:/* 1/128 */
|
||||
dataL |= 0x00000020U;
|
||||
break;
|
||||
case 256U: /* 1/256 */
|
||||
dataL |= 0x00000040U;
|
||||
break;
|
||||
case 512U:/* 1/512 */
|
||||
dataL |= 0x00000080U;
|
||||
break;
|
||||
default:
|
||||
/* nop */
|
||||
break;
|
||||
}
|
||||
|
||||
mem_write32(SD_CLK_CTRL, dataL);
|
||||
mmc_drv_obj.current_freq = (uint32_t)clkDiv;
|
||||
}
|
||||
|
||||
|
||||
/** Enable/Disable MMC clock
|
||||
*
|
||||
* - Pre-conditions:<BR>
|
||||
* Before enabling the clock for the first time the desired clock frequency must be set with
|
||||
* emmc_set_clock_freq().
|
||||
* Berore setting mmc_drv_obj.data_timeout with emmc_set_data_timeout().
|
||||
*
|
||||
* - Post-conditions:<BR>
|
||||
* After this function is called, clock to memory card IF is on/off.
|
||||
*
|
||||
* param[in] mode TRUE = clock on, FALSE = clock off
|
||||
* retval EMMC_SUCCESS succeeded
|
||||
* retval EMMC_ERR Busy
|
||||
*/
|
||||
static EMMC_ERROR_CODE emmc_clock_ctrl(uint32_t mode)
|
||||
{
|
||||
uint32_t value;
|
||||
|
||||
/* busy check */
|
||||
if ((mem_read32(SD_INFO2) & SD_INFO2_CBSY) != 0U) {
|
||||
ERROR("%s:0x%08x\n",__func__,EMMC_ERR_CARD_BUSY);
|
||||
return EMMC_ERR;
|
||||
}
|
||||
|
||||
if (mode == TRUE) {
|
||||
/* clock ON */
|
||||
value = ((mem_read32(SD_CLK_CTRL) | MMC_SD_CLK_START) & SD_CLK_WRITE_MASK);
|
||||
mem_write32(SD_CLK_CTRL, value); /* on */
|
||||
mmc_drv_obj.clock_enable = TRUE;
|
||||
} else {
|
||||
/* clock OFF */
|
||||
value = ((mem_read32(SD_CLK_CTRL) & MMC_SD_CLK_STOP) & SD_CLK_WRITE_MASK);
|
||||
mem_write32(SD_CLK_CTRL, value); /* off */
|
||||
mmc_drv_obj.clock_enable = FALSE;
|
||||
}
|
||||
|
||||
return EMMC_SUCCESS;
|
||||
}
|
||||
|
||||
/** Calculate Card support frequency.
|
||||
* TRAN_SPEED defines the clock frequency when not in high speed mode.
|
||||
*
|
||||
* - Pre-conditions:<BR>
|
||||
* CSD data must be stored in mmc_drv_obj.csd_data[].
|
||||
*
|
||||
* - Post-conditions:<BR>
|
||||
* None.
|
||||
* return Frquency[Hz]
|
||||
*/
|
||||
static uint32_t emmc_calc_tran_speed(uint32_t* freq)
|
||||
{
|
||||
const uint32_t unit[8U] = {10000U, 100000U, 1000000U, 10000000U, 0U, 0U, 0U, 0U}; /**< frequency unit (1/10) */
|
||||
const uint32_t mult[16U] = {0U, 10U, 12U, 13U, 15U, 20U, 26U, 30U, 35U, 40U, 45U, 52U, 55U, 60U, 70U, 80U}; /**< multiple factor (x10) */
|
||||
uint32_t maxFreq = 0U;
|
||||
uint32_t result = 0U;
|
||||
uint32_t tran_speed = EMMC_CSD_TRAN_SPEED();
|
||||
|
||||
/* tran_speed = 0x32
|
||||
* unit[tran_speed&0x7] = uint[0x2] = 1000000
|
||||
* mult[(tran_speed&0x78)>>3] = mult[0x30>>3] = mult[6] = 26
|
||||
* 1000000 * 26 = 26000000 (26MHz)
|
||||
*/
|
||||
|
||||
maxFreq = unit[tran_speed & EMMC_TRANSPEED_FREQ_UNIT_MASK]
|
||||
* mult[(tran_speed & EMMC_TRANSPEED_MULT_MASK) >> EMMC_TRANSPEED_MULT_SHIFT];
|
||||
|
||||
if (maxFreq == 0U) {
|
||||
result = 0U;
|
||||
} else if ( MMC_FREQ_52MHZ <= maxFreq) {
|
||||
*freq = MMC_52MHZ;
|
||||
result = 1U;
|
||||
} else if ( MMC_FREQ_26MHZ <= maxFreq) {
|
||||
*freq = MMC_26MHZ;
|
||||
result = 1U;
|
||||
} else if ( MMC_FREQ_20MHZ <= maxFreq) {
|
||||
*freq = MMC_20MHZ;
|
||||
result = 1U;
|
||||
} else {
|
||||
*freq = MMC_400KHZ;
|
||||
result = 1U;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Calculate read/write timeout.
|
||||
*
|
||||
* - Pre-conditions:<BR>
|
||||
* CSD data must be stored in mmc_drv_obj.csd_data[].
|
||||
*
|
||||
* - Post-conditions:<BR>
|
||||
* set mmc clock.
|
||||
*
|
||||
* param[in] freq Base clock Div
|
||||
* return SD_OPTION Timeout Counter
|
||||
*/
|
||||
static uint32_t emmc_set_timeout_register_value(uint32_t freq)
|
||||
{
|
||||
uint32_t timeoutCnt = 0U; /* SD_OPTION - Timeout Counter */
|
||||
|
||||
switch (freq) {
|
||||
case 1U:/* SDCLK * 2^27 */
|
||||
timeoutCnt = 0xE0U;
|
||||
break;
|
||||
case 2U:/* SDCLK * 2^27 */
|
||||
timeoutCnt = 0xE0U;
|
||||
break;
|
||||
case 4U:/* SDCLK * 2^26 */
|
||||
timeoutCnt = 0xD0U;
|
||||
break;
|
||||
case 8U:/* SDCLK * 2^25 */
|
||||
timeoutCnt = 0xC0U;
|
||||
break;
|
||||
case 16U:/* SDCLK * 2^24 */
|
||||
timeoutCnt = 0xB0U;
|
||||
break;
|
||||
case 32U:/* SDCLK * 2^23 */
|
||||
timeoutCnt = 0xA0U;
|
||||
break;
|
||||
case 64U:/* SDCLK * 2^22 */
|
||||
timeoutCnt = 0x90U;
|
||||
break;
|
||||
case 128U:/* SDCLK * 2^21 */
|
||||
timeoutCnt = 0x80U;
|
||||
break;
|
||||
case 256U:/* SDCLK * 2^20 */
|
||||
timeoutCnt = 0x70U;
|
||||
break;
|
||||
case 512U:/* SDCLK * 2^19 */
|
||||
timeoutCnt = 0x60U;
|
||||
break;
|
||||
default:
|
||||
/* nop */
|
||||
break;
|
||||
}
|
||||
|
||||
return timeoutCnt;
|
||||
}
|
||||
@@ -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 2021-2022 Renesas Electronics Corporation All rights reserved.
|
||||
*******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* DESCRIPTION : eMMC multi boot
|
||||
******************************************************************************/
|
||||
/******************************************************************************
|
||||
* @file emmc_multiboot.c
|
||||
* - Version : 0.04
|
||||
* @brief data access interface to emmc.
|
||||
* .
|
||||
*****************************************************************************/
|
||||
/******************************************************************************
|
||||
* History : DD.MM.YYYY Version Description
|
||||
* : 22.02.2022 0.01 First Release
|
||||
* : 22.10.2021 0.02 Remove unnecessary code
|
||||
* : 22.12.2021 0.03 Support static analysis
|
||||
* : 06.01.2022 0.04 Modify SDHI access from DMA to PIO.
|
||||
*****************************************************************************/
|
||||
|
||||
/* ************************ HEADER (INCLUDE) SECTION *********************** */
|
||||
#include "emmc_config.h"
|
||||
#include "emmc_hal.h"
|
||||
#include "emmc_std.h"
|
||||
#include "emmc_def.h"
|
||||
#include "emmc_multiboot.h"
|
||||
#include "rom_api.h"
|
||||
#include "types.h"
|
||||
|
||||
|
||||
/* ********************** STRUCTURES, TYPE DEFINITIONS ********************* */
|
||||
|
||||
/* ********************** DECLARATION OF EXTERNAL DATA ********************* */
|
||||
|
||||
/* ************************** FUNCTION PROTOTYPES ************************** */
|
||||
uint32_t emmc_check_result(uint32_t result);
|
||||
|
||||
/* ********************************* CODE ********************************** */
|
||||
|
||||
|
||||
#if defined(__RH850__)
|
||||
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;
|
||||
}
|
||||
#endif /* #if defined(__RH850__) */
|
||||
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 ************************************ */
|
||||
|
||||
204
IPL/Customer/Mobis/Gen4_ICUMX_Loader/ip/emmc/emmc_read.c
Normal file
204
IPL/Customer/Mobis/Gen4_ICUMX_Loader/ip/emmc/emmc_read.c
Normal file
@@ -0,0 +1,204 @@
|
||||
/*******************************************************************************
|
||||
* 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 2021-2022 Renesas Electronics Corporation All rights reserved.
|
||||
*******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* DESCRIPTION : eMMC Read data access driver
|
||||
******************************************************************************/
|
||||
/******************************************************************************
|
||||
* @file emmc_read.c
|
||||
* - Version : 0.04
|
||||
* @brief read data access function to emmc.
|
||||
* .
|
||||
*****************************************************************************/
|
||||
/******************************************************************************
|
||||
* History : DD.MM.YYYY Version Description
|
||||
* : 22.02.2022 0.01 First Release
|
||||
* : 22.10.2021 0.02 Remove unnecessary code
|
||||
* : 22.12.2021 0.03 Support static analysis
|
||||
* : 06.01.2022 0.04 Modify SDHI access from DMA to PIO.
|
||||
*****************************************************************************/
|
||||
|
||||
/* ************************ 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 <wdt.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%08x\n",__func__,EMMC_ERR_PARAM);
|
||||
return EMMC_ERR_PARAM;
|
||||
}
|
||||
|
||||
/* state check */
|
||||
if (mmc_drv_obj.mount != TRUE) {
|
||||
ERROR("%s:0x%08x\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;
|
||||
wdt_restart();
|
||||
}
|
||||
|
||||
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%08x\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%08x\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%08x\n",__func__,EMMC_ERR_CARD_STATE);
|
||||
return EMMC_ERR_CARD_STATE;
|
||||
}
|
||||
|
||||
return EMMC_SUCCESS;
|
||||
}
|
||||
|
||||
/* ******************************** END ************************************ */
|
||||
|
||||
301
IPL/Customer/Mobis/Gen4_ICUMX_Loader/ip/emmc/emmc_utility.c
Normal file
301
IPL/Customer/Mobis/Gen4_ICUMX_Loader/ip/emmc/emmc_utility.c
Normal file
@@ -0,0 +1,301 @@
|
||||
/*******************************************************************************
|
||||
* 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 2021-2022 Renesas Electronics Corporation All rights reserved.
|
||||
*******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* DESCRIPTION : eMMC Utility
|
||||
******************************************************************************/
|
||||
/******************************************************************************
|
||||
* @file emmc_utility.c
|
||||
* - Version : 0.04
|
||||
* @brief Analysis of SDHI data.
|
||||
* .
|
||||
*****************************************************************************/
|
||||
/******************************************************************************
|
||||
* History : DD.MM.YYYY Version Description
|
||||
* : 22.02.2022 0.01 First Release
|
||||
* : 22.10.2021 0.02 Remove unnecessary code
|
||||
* : 22.12.2021 0.03 Support static analysis
|
||||
* : 06.01.2022 0.04 Modify SDHI access from DMA to PIO.
|
||||
*****************************************************************************/
|
||||
|
||||
/* ************************ 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;
|
||||
uint32_t freq;
|
||||
|
||||
/* 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) */
|
||||
freq = MMC_400KHZ;
|
||||
result = emmc_set_request_mmc_clock(&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