Unverified Commit a51443fa authored by Soby Mathew's avatar Soby Mathew Committed by GitHub
Browse files

Merge pull request #1582 from ldts/rcar_gen3/upstream

rcar_gen3: initial support
parents 0059be2d 84433c50
/*
* Copyright (c) 2015-2018, Renesas Electronics Corporation. All rights
* reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "emmc_config.h"
#include "emmc_def.h"
#include "emmc_hal.h"
#include "emmc_registers.h"
#include "emmc_std.h"
#include "rcar_def.h"
#include <mmio.h>
#include <stddef.h>
static EMMC_ERROR_CODE emmc_trans_sector(uint32_t *buff_address_virtual);
uint32_t emmc_interrupt(void)
{
EMMC_ERROR_CODE result;
uint32_t prr_data;
uint32_t cut_ver;
uint32_t end_bit;
prr_data = mmio_read_32((uintptr_t) RCAR_PRR);
cut_ver = prr_data & RCAR_CUT_MASK;
if ((prr_data & RCAR_PRODUCT_MASK) == RCAR_PRODUCT_H3) {
if (cut_ver == RCAR_CUT_VER10) {
end_bit = BIT17;
} else if (cut_ver == RCAR_CUT_VER11) {
end_bit = BIT17;
} else {
end_bit = BIT20;
}
} else if ((prr_data & RCAR_PRODUCT_MASK) == RCAR_PRODUCT_M3) {
if (cut_ver == RCAR_CUT_VER10) {
end_bit = BIT17;
} else {
end_bit = BIT20;
}
} else {
end_bit = BIT20;
}
/* SD_INFO */
mmc_drv_obj.error_info.info1 = GETR_32(SD_INFO1);
mmc_drv_obj.error_info.info2 = GETR_32(SD_INFO2);
/* SD_INFO EVENT */
mmc_drv_obj.int_event1 =
mmc_drv_obj.error_info.info1 & GETR_32(SD_INFO1_MASK);
mmc_drv_obj.int_event2 =
mmc_drv_obj.error_info.info2 & GETR_32(SD_INFO2_MASK);
/* ERR_STS */
mmc_drv_obj.error_info.status1 = GETR_32(SD_ERR_STS1);
mmc_drv_obj.error_info.status2 = GETR_32(SD_ERR_STS2);
/* DM_CM_INFO */
mmc_drv_obj.error_info.dm_info1 = GETR_32(DM_CM_INFO1);
mmc_drv_obj.error_info.dm_info2 = GETR_32(DM_CM_INFO2);
/* DM_CM_INFO EVENT */
mmc_drv_obj.dm_event1 =
mmc_drv_obj.error_info.dm_info1 & GETR_32(DM_CM_INFO1_MASK);
mmc_drv_obj.dm_event2 =
mmc_drv_obj.error_info.dm_info2 & GETR_32(DM_CM_INFO2_MASK);
/* ERR SD_INFO2 */
if ((SD_INFO2_ALL_ERR & mmc_drv_obj.int_event2) != 0) {
SETR_32(SD_INFO1_MASK, 0x00000000U); /* interrupt disable */
SETR_32(SD_INFO2_MASK, SD_INFO2_CLEAR); /* interrupt disable */
SETR_32(SD_INFO1, 0x00000000U); /* interrupt clear */
SETR_32(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)) {
/* BWE */
if (SD_INFO2_BWE & mmc_drv_obj.int_event2) {
SETR_32(SD_INFO2, (GETR_32(SD_INFO2) & ~SD_INFO2_BWE));
}
/* BRE */
else {
SETR_32(SD_INFO2, (GETR_32(SD_INFO2) & ~SD_INFO2_BRE));
}
result = emmc_trans_sector(mmc_drv_obj.buff_address_virtual);
mmc_drv_obj.buff_address_virtual += EMMC_BLOCK_LENGTH;
mmc_drv_obj.remain_size -= EMMC_BLOCK_LENGTH;
if (result != EMMC_SUCCESS) {
/* data transfer error */
emmc_write_error_info(EMMC_FUNCNO_NONE, result);
/* Panic */
SETR_32(SD_INFO1_MASK, 0x00000000U);
SETR_32(SD_INFO2_MASK, SD_INFO2_CLEAR);
SETR_32(SD_INFO1, 0x00000000U);
/* interrupt clear */
SETR_32(SD_INFO2, SD_INFO2_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 occurred */
else if ((BIT16 & mmc_drv_obj.dm_event1) != 0) {
SETR_32(DM_CM_INFO1, 0x00000000U);
SETR_32(DM_CM_INFO2, 0x00000000U);
/* interrupt clear */
SETR_32(SD_INFO2, (GETR_32(SD_INFO2) & ~SD_INFO2_BWE));
/* DM_CM_INFO2: DMA-ch0 error occured */
if ((BIT16 & mmc_drv_obj.dm_event2) != 0) {
mmc_drv_obj.dma_error_flag = TRUE;
} else {
mmc_drv_obj.during_dma_transfer = FALSE;
mmc_drv_obj.during_transfer = FALSE;
}
/* wait next interrupt */
mmc_drv_obj.state_machine_blocking = FALSE;
}
/* DM_CM_INFO1: DMA-ch1 transfer complete or error occured */
else if ((end_bit & mmc_drv_obj.dm_event1) != 0U) {
SETR_32(DM_CM_INFO1, 0x00000000U);
SETR_32(DM_CM_INFO2, 0x00000000U);
/* interrupt clear */
SETR_32(SD_INFO2, (GETR_32(SD_INFO2) & ~SD_INFO2_BRE));
/* DM_CM_INFO2: DMA-ch1 error occured */
if ((BIT17 & mmc_drv_obj.dm_event2) != 0) {
mmc_drv_obj.dma_error_flag = TRUE;
} else {
mmc_drv_obj.during_dma_transfer = FALSE;
mmc_drv_obj.during_transfer = FALSE;
}
/* wait next interrupt */
mmc_drv_obj.state_machine_blocking = FALSE;
}
/* Response end */
else if ((SD_INFO1_INFO0 & mmc_drv_obj.int_event1) != 0) {
/* interrupt clear */
SETR_32(SD_INFO1, (GETR_32(SD_INFO1) & ~SD_INFO1_INFO0));
mmc_drv_obj.state_machine_blocking = FALSE;
}
/* Access end */
else if ((SD_INFO1_INFO2 & mmc_drv_obj.int_event1) != 0) {
/* interrupt clear */
SETR_32(SD_INFO1, (GETR_32(SD_INFO1) & ~SD_INFO1_INFO2));
mmc_drv_obj.state_machine_blocking = FALSE;
} else {
/* nothing to do. */
}
return (uint32_t) 0;
}
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 == 0)) {
return EMMC_ERR_STATE;
}
bufPtrLL = (uint64_t *) buff_address_virtual;
length = mmc_drv_obj.remain_size;
/* data transefer */
for (i = 0; i < (length >> 3); i++) {
/* Write */
if (mmc_drv_obj.cmd_info.dir == HAL_MEMCARD_WRITE) {
SETR_64(SD_BUF0, *bufPtrLL); /* buffer --> FIFO */
}
/* Read */
else {
/* Checks when the read data reaches SD_SIZE. */
/* The BRE bit is cleared at emmc_interrupt function. */
if (((i %
(uint32_t) (EMMC_BLOCK_LENGTH >>
EMMC_BUF_SIZE_SHIFT)) == 0U)
&& (i != 0U)) {
/* BRE check */
while (((GETR_32(SD_INFO2)) & SD_INFO2_BRE) ==
0U) {
/* ERROR check */
if (((GETR_32(SD_INFO2)) &
SD_INFO2_ALL_ERR) != 0U) {
return EMMC_ERR_TRANSFER;
}
}
/* BRE clear */
SETR_32(SD_INFO2,
(uint32_t) (GETR_32(SD_INFO2) &
~SD_INFO2_BRE));
}
*bufPtrLL = GETR_64(SD_BUF0); /* FIFO --> buffer */
}
bufPtrLL++;
}
return EMMC_SUCCESS;
}
/*
* Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <debug.h>
#include <mmio.h>
#include "emmc_config.h"
#include "emmc_hal.h"
#include "emmc_std.h"
#include "emmc_registers.h"
#include "emmc_def.h"
#include "micro_delay.h"
#include "rcar_def.h"
static EMMC_ERROR_CODE emmc_clock_ctrl(uint8_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);
static void emmc_get_partition_access(void);
static void emmc_set_bootpartition(void);
static void emmc_set_bootpartition(void)
{
uint32_t reg;
reg = mmio_read_32(RCAR_PRR) & (RCAR_PRODUCT_MASK | RCAR_CUT_MASK);
if (reg == RCAR_PRODUCT_M3_CUT10) {
mmc_drv_obj.boot_partition_en =
(EMMC_PARTITION_ID) ((mmc_drv_obj.ext_csd_data[179] &
EMMC_BOOT_PARTITION_EN_MASK) >>
EMMC_BOOT_PARTITION_EN_SHIFT);
} else if ((reg == RCAR_PRODUCT_H3_CUT20)
|| (reg == RCAR_PRODUCT_M3_CUT11)) {
mmc_drv_obj.boot_partition_en = mmc_drv_obj.partition_access;
} else {
if ((mmio_read_32(MFISBTSTSR) & MFISBTSTSR_BOOT_PARTITION) !=
0U) {
mmc_drv_obj.boot_partition_en = PARTITION_ID_BOOT_2;
} else {
mmc_drv_obj.boot_partition_en = PARTITION_ID_BOOT_1;
}
}
}
static EMMC_ERROR_CODE emmc_card_init(void)
{
int32_t retry;
uint32_t freq = MMC_400KHZ; /* 390KHz */
EMMC_ERROR_CODE result;
uint32_t resultCalc;
/* state check */
if ((mmc_drv_obj.initialize != TRUE)
|| (mmc_drv_obj.card_power_enable != TRUE)
|| ((GETR_32(SD_INFO2) & SD_INFO2_CBSY) != 0)
) {
emmc_write_error_info(EMMC_FUNCNO_CARD_INIT, EMMC_ERR_STATE);
return EMMC_ERR_STATE;
}
/* clock on (force change) */
mmc_drv_obj.current_freq = 0;
mmc_drv_obj.max_freq = MMC_20MHZ;
result = emmc_set_request_mmc_clock(&freq);
if (result != EMMC_SUCCESS) {
emmc_write_error_info_func_no(EMMC_FUNCNO_CARD_INIT);
return EMMC_ERR;
}
rcar_micro_delay(1000U); /* wait 1ms */
/* Get current access partition */
emmc_get_partition_access();
/* CMD0, arg=0x00000000 */
result = emmc_send_idle_cmd(0x00000000);
if (result != EMMC_SUCCESS) {
emmc_write_error_info_func_no(EMMC_FUNCNO_CARD_INIT);
return result;
}
rcar_micro_delay(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) {
emmc_write_error_info_func_no(EMMC_FUNCNO_CARD_INIT);
return result;
}
if ((mmc_drv_obj.r3_ocr & EMMC_OCR_STATUS_BIT) != 0) {
break; /* card is ready. exit loop */
}
rcar_micro_delay(1000U); /* wait 1ms */
}
if (retry == 0) {
emmc_write_error_info(EMMC_FUNCNO_CARD_INIT, EMMC_ERR_TIMEOUT);
return EMMC_ERR_TIMEOUT;
}
switch (mmc_drv_obj.r3_ocr & EMMC_OCR_ACCESS_MODE_MASK) {
case EMMC_OCR_ACCESS_MODE_SECT:
mmc_drv_obj.access_mode = TRUE; /* sector mode */
break;
default:
/* unknown value */
emmc_write_error_info(EMMC_FUNCNO_CARD_INIT, EMMC_ERR);
return EMMC_ERR;
}
/* CMD2 */
emmc_make_nontrans_cmd(CMD2_ALL_SEND_CID_MMC, 0x00000000);
mmc_drv_obj.response = (uint32_t *) (&mmc_drv_obj.cid_data[0]); /* use CID special buffer */
result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response);
if (result != EMMC_SUCCESS) {
emmc_write_error_info_func_no(EMMC_FUNCNO_CARD_INIT);
return result;
}
/* CMD3 */
emmc_make_nontrans_cmd(CMD3_SET_RELATIVE_ADDR, EMMC_RCA << 16);
result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response);
if (result != EMMC_SUCCESS) {
emmc_write_error_info_func_no(EMMC_FUNCNO_CARD_INIT);
return result;
}
/* CMD9 (CSD) */
emmc_make_nontrans_cmd(CMD9_SEND_CSD, EMMC_RCA << 16);
mmc_drv_obj.response = (uint32_t *) (&mmc_drv_obj.csd_data[0]); /* use CSD special buffer */
result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response);
if (result != EMMC_SUCCESS) {
emmc_write_error_info_func_no(EMMC_FUNCNO_CARD_INIT);
return result;
}
/* card version check */
if (EMMC_CSD_SPEC_VARS() < 4) {
emmc_write_error_info(EMMC_FUNCNO_CARD_INIT,
EMMC_ERR_ILLEGAL_CARD);
return EMMC_ERR_ILLEGAL_CARD;
}
/* CMD7 (select card) */
emmc_make_nontrans_cmd(CMD7_SELECT_CARD, EMMC_RCA << 16);
result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response);
if (result != EMMC_SUCCESS) {
emmc_write_error_info_func_no(EMMC_FUNCNO_CARD_INIT);
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 == 0) {
emmc_write_error_info(EMMC_FUNCNO_CARD_INIT,
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) {
emmc_write_error_info_func_no(EMMC_FUNCNO_CARD_INIT);
return EMMC_ERR;
}
/* set read/write timeout */
mmc_drv_obj.data_timeout = emmc_set_timeout_register_value(freq);
SETR_32(SD_OPTION,
((GETR_32(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) {
emmc_write_error_info_func_no(EMMC_FUNCNO_CARD_INIT);
return result;
}
/* Transfer Data Length */
SETR_32(SD_SIZE, EMMC_BLOCK_LENGTH);
/* CMD8 (EXT_CSD) */
emmc_make_trans_cmd(CMD8_SEND_EXT_CSD, 0x00000000,
(uint32_t *) (&mmc_drv_obj.ext_csd_data[0]),
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).
*/
emmc_write_error_info_func_no(EMMC_FUNCNO_CARD_INIT);
return result;
}
/* Set boot partition */
emmc_set_bootpartition();
return EMMC_SUCCESS;
}
static EMMC_ERROR_CODE emmc_high_speed(void)
{
uint32_t freq; /**< High speed mode clock frequency */
EMMC_ERROR_CODE result;
uint8_t cardType;
/* state check */
if (mmc_drv_obj.selected != TRUE) {
emmc_write_error_info(EMMC_FUNCNO_HIGH_SPEED, 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) != 0)
freq = MMC_52MHZ;
else if ((cardType & EMMC_EXT_CSD_CARD_TYPE_26MHZ) != 0)
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) {
emmc_write_error_info_func_no(EMMC_FUNCNO_HIGH_SPEED);
return result;
}
mmc_drv_obj.hs_timing = TIMING_HIGH_SPEED; /* High-Speed */
}
/* set mmc clock */
mmc_drv_obj.max_freq = freq;
result = emmc_set_request_mmc_clock(&freq);
if (result != EMMC_SUCCESS) {
emmc_write_error_info_func_no(EMMC_FUNCNO_HIGH_SPEED);
return EMMC_ERR;
}
/* set read/write timeout */
mmc_drv_obj.data_timeout = emmc_set_timeout_register_value(freq);
SETR_32(SD_OPTION,
((GETR_32(SD_OPTION) & ~(SD_OPTION_TIMEOUT_CNT_MASK)) |
mmc_drv_obj.data_timeout));
/* CMD13 */
emmc_make_nontrans_cmd(CMD13_SEND_STATUS, EMMC_RCA << 16);
result =
emmc_exec_cmd(EMMC_R1_ERROR_MASK_WITHOUT_CRC, mmc_drv_obj.response);
if (result != EMMC_SUCCESS) {
emmc_write_error_info_func_no(EMMC_FUNCNO_HIGH_SPEED);
return result;
}
return EMMC_SUCCESS;
}
static EMMC_ERROR_CODE emmc_clock_ctrl(uint8_t mode)
{
uint32_t value;
/* busy check */
if ((GETR_32(SD_INFO2) & SD_INFO2_CBSY) != 0) {
emmc_write_error_info(EMMC_FUNCNO_SET_CLOCK,
EMMC_ERR_CARD_BUSY);
return EMMC_ERR;
}
if (mode == TRUE) {
/* clock ON */
value =
((GETR_32(SD_CLK_CTRL) | MMC_SD_CLK_START) &
SD_CLK_WRITE_MASK);
SETR_32(SD_CLK_CTRL, value); /* on */
mmc_drv_obj.clock_enable = TRUE;
} else {
/* clock OFF */
value =
((GETR_32(SD_CLK_CTRL) & MMC_SD_CLK_STOP) &
SD_CLK_WRITE_MASK);
SETR_32(SD_CLK_CTRL, value); /* off */
mmc_drv_obj.clock_enable = FALSE;
}
return EMMC_SUCCESS;
}
static EMMC_ERROR_CODE emmc_bus_width(uint32_t width)
{
EMMC_ERROR_CODE result = EMMC_ERR;
/* parameter check */
if ((width != 8) && (width != 4) && (width != 1)) {
emmc_write_error_info(EMMC_FUNCNO_BUS_WIDTH, EMMC_ERR_PARAM);
return EMMC_ERR_PARAM;
}
/* state check */
if (mmc_drv_obj.selected != TRUE) {
emmc_write_error_info(EMMC_FUNCNO_BUS_WIDTH, EMMC_ERR_STATE);
return EMMC_ERR_STATE;
}
mmc_drv_obj.bus_width = (HAL_MEMCARD_DATA_WIDTH) (width >> 2); /* 2 = 8bit, 1 = 4bit, 0 =1bit */
/* CMD6 */
emmc_make_nontrans_cmd(CMD6_SWITCH,
(EMMC_SWITCH_BUS_WIDTH_1 |
(mmc_drv_obj.bus_width << 8)));
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:
SETR_32(SD_OPTION,
((GETR_32(SD_OPTION) & ~(BIT15 | BIT13)) | BIT15));
break;
case HAL_MEMCARD_DATA_WIDTH_4_BIT:
SETR_32(SD_OPTION, (GETR_32(SD_OPTION) & ~(BIT15 | BIT13)));
break;
case HAL_MEMCARD_DATA_WIDTH_8_BIT:
SETR_32(SD_OPTION,
((GETR_32(SD_OPTION) & ~(BIT15 | BIT13)) | BIT13));
break;
default:
goto EXIT;
}
/* CMD13 */
emmc_make_nontrans_cmd(CMD13_SEND_STATUS, EMMC_RCA << 16);
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, 0x00000000,
(uint32_t *) (&mmc_drv_obj.ext_csd_data[0]),
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:
emmc_write_error_info(EMMC_FUNCNO_BUS_WIDTH, result);
ERROR("BL2: emmc bus_width error end\n");
return result;
}
EMMC_ERROR_CODE emmc_select_partition(EMMC_PARTITION_ID id)
{
EMMC_ERROR_CODE result;
uint32_t arg;
uint32_t partition_config;
/* state check */
if (mmc_drv_obj.mount != TRUE) {
emmc_write_error_info(EMMC_FUNCNO_NONE, EMMC_ERR_STATE);
return EMMC_ERR_STATE;
}
/* id = PARTITION_ACCESS(Bit[2:0]) */
if ((id & ~PARTITION_ID_MASK) != 0) {
emmc_write_error_info(EMMC_FUNCNO_NONE, 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 & PARTITION_ID_MASK) == id) {
result = EMMC_SUCCESS;
} else {
partition_config =
(uint32_t) ((partition_config & ~PARTITION_ID_MASK) | id);
arg = EMMC_SWITCH_PARTITION_CONFIG | (partition_config << 8);
result = emmc_set_ext_csd(arg);
}
return result;
}
static void set_sd_clk(uint32_t clkDiv)
{
uint32_t dataL;
dataL = (GETR_32(SD_CLK_CTRL) & (~SD_CLK_CTRL_CLKDIV_MASK));
switch (clkDiv) {
case 1:
dataL |= 0x000000FFU;
break; /* 1/1 */
case 2:
dataL |= 0x00000000U;
break; /* 1/2 */
case 4:
dataL |= 0x00000001U;
break; /* 1/4 */
case 8:
dataL |= 0x00000002U;
break; /* 1/8 */
case 16:
dataL |= 0x00000004U;
break; /* 1/16 */
case 32:
dataL |= 0x00000008U;
break; /* 1/32 */
case 64:
dataL |= 0x00000010U;
break; /* 1/64 */
case 128:
dataL |= 0x00000020U;
break; /* 1/128 */
case 256:
dataL |= 0x00000040U;
break; /* 1/256 */
case 512:
dataL |= 0x00000080U;
break; /* 1/512 */
}
SETR_32(SD_CLK_CTRL, dataL);
mmc_drv_obj.current_freq = (uint32_t) clkDiv;
}
static void emmc_get_partition_access(void)
{
uint32_t reg;
EMMC_ERROR_CODE result;
reg = mmio_read_32(RCAR_PRR) & (RCAR_PRODUCT_MASK | RCAR_CUT_MASK);
if ((reg == RCAR_PRODUCT_H3_CUT20) || (reg == RCAR_PRODUCT_M3_CUT11)) {
SETR_32(SD_OPTION, 0x000060EEU); /* 8 bits width */
/* CMD8 (EXT_CSD) */
emmc_make_trans_cmd(CMD8_SEND_EXT_CSD, 0x00000000U,
(uint32_t *) (&mmc_drv_obj.ext_csd_data[0]),
EMMC_MAX_EXT_CSD_LENGTH,
HAL_MEMCARD_READ, HAL_MEMCARD_NOT_DMA);
mmc_drv_obj.get_partition_access_flag = TRUE;
result =
emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response);
mmc_drv_obj.get_partition_access_flag = FALSE;
if (result == EMMC_SUCCESS) {
mmc_drv_obj.partition_access =
(EMMC_PARTITION_ID) (mmc_drv_obj.ext_csd_data[179]
& PARTITION_ID_MASK);
} else if (result == EMMC_ERR_CMD_TIMEOUT) {
mmc_drv_obj.partition_access = PARTITION_ID_BOOT_1;
} else {
emmc_write_error_info(EMMC_FUNCNO_GET_PERTITION_ACCESS,
result);
panic();
}
SETR_32(SD_OPTION, 0x0000C0EEU); /* Initialize */
}
}
static uint32_t emmc_calc_tran_speed(uint32_t *freq)
{
const uint32_t unit[8] = { 10000, 100000, 1000000, 10000000,
0, 0, 0, 0 }; /**< frequency unit (1/10) */
const uint32_t mult[16] = { 0, 10, 12, 13, 15, 20, 26, 30, 35, 40, 45,
52, 55, 60, 70, 80 };
uint32_t maxFreq;
uint32_t result;
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)
*/
result = 1;
maxFreq =
unit[tran_speed & EMMC_TRANSPEED_FREQ_UNIT_MASK] *
mult[(tran_speed & EMMC_TRANSPEED_MULT_MASK) >>
EMMC_TRANSPEED_MULT_SHIFT];
if (maxFreq == 0) {
result = 0;
} else if (MMC_FREQ_52MHZ <= maxFreq)
*freq = MMC_52MHZ;
else if (MMC_FREQ_26MHZ <= maxFreq)
*freq = MMC_26MHZ;
else if (MMC_FREQ_20MHZ <= maxFreq)
*freq = MMC_20MHZ;
else
*freq = MMC_400KHZ;
return result;
}
static uint32_t emmc_set_timeout_register_value(uint32_t freq)
{
uint32_t timeoutCnt; /* SD_OPTION - Timeout Counter */
switch (freq) {
case 1U:
timeoutCnt = 0xE0U;
break; /* SDCLK * 2^27 */
case 2U:
timeoutCnt = 0xE0U;
break; /* SDCLK * 2^27 */
case 4U:
timeoutCnt = 0xD0U;
break; /* SDCLK * 2^26 */
case 8U:
timeoutCnt = 0xC0U;
break; /* SDCLK * 2^25 */
case 16U:
timeoutCnt = 0xB0U;
break; /* SDCLK * 2^24 */
case 32U:
timeoutCnt = 0xA0U;
break; /* SDCLK * 2^23 */
case 64U:
timeoutCnt = 0x90U;
break; /* SDCLK * 2^22 */
case 128U:
timeoutCnt = 0x80U;
break; /* SDCLK * 2^21 */
case 256U:
timeoutCnt = 0x70U;
break; /* SDCLK * 2^20 */
case 512U:
timeoutCnt = 0x70U;
break; /* SDCLK * 2^20 */
default:
timeoutCnt = 0xE0U;
break; /* SDCLK * 2^27 */
}
return timeoutCnt;
}
EMMC_ERROR_CODE emmc_set_ext_csd(uint32_t arg)
{
EMMC_ERROR_CODE result;
/* 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 << 16);
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[0]),
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;
}
EMMC_ERROR_CODE emmc_set_request_mmc_clock(uint32_t *freq)
{
/* parameter check */
if (freq == NULL) {
emmc_write_error_info(EMMC_FUNCNO_SET_CLOCK, EMMC_ERR_PARAM);
return EMMC_ERR_PARAM;
}
/* state check */
if ((mmc_drv_obj.initialize != TRUE)
|| (mmc_drv_obj.card_power_enable != TRUE)) {
emmc_write_error_info(EMMC_FUNCNO_SET_CLOCK, 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 ((GETR_32(SD_INFO2) & SD_INFO2_CBSY) != 0) {
emmc_write_error_info(EMMC_FUNCNO_SET_CLOCK,
EMMC_ERR_CARD_BUSY);
return EMMC_ERR;
}
set_sd_clk(*freq);
mmc_drv_obj.clock_enable = FALSE;
return emmc_clock_ctrl(TRUE); /* clock on */
}
EMMC_ERROR_CODE rcar_emmc_mount(void)
{
EMMC_ERROR_CODE result;
/* state check */
if ((mmc_drv_obj.initialize != TRUE)
|| (mmc_drv_obj.card_power_enable != TRUE)
|| ((GETR_32(SD_INFO2) & SD_INFO2_CBSY) != 0)
) {
emmc_write_error_info(EMMC_FUNCNO_MOUNT, EMMC_ERR_STATE);
return EMMC_ERR_STATE;
}
/* initialize card (IDLE state --> Transfer state) */
result = emmc_card_init();
if (result != EMMC_SUCCESS) {
emmc_write_error_info_func_no(EMMC_FUNCNO_CARD_INIT);
if (emmc_clock_ctrl(FALSE) != EMMC_SUCCESS) {
/* nothing to do. */
}
return result;
}
/* Switching high speed mode */
result = emmc_high_speed();
if (result != EMMC_SUCCESS) {
emmc_write_error_info_func_no(EMMC_FUNCNO_HIGH_SPEED);
if (emmc_clock_ctrl(FALSE) != EMMC_SUCCESS) {
/* nothing to do. */
}
return result;
}
/* Changing the data bus width */
result = emmc_bus_width(8);
if (result != EMMC_SUCCESS) {
emmc_write_error_info_func_no(EMMC_FUNCNO_BUS_WIDTH);
if (emmc_clock_ctrl(FALSE) != EMMC_SUCCESS) {
/* nothing to do. */
}
return result;
}
/* mount complete */
mmc_drv_obj.mount = TRUE;
return EMMC_SUCCESS;
}
/*
* Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch_helpers.h>
#include "emmc_config.h"
#include "emmc_hal.h"
#include "emmc_std.h"
#include "emmc_registers.h"
#include "emmc_def.h"
#define MIN_EMMC(a, b) (((a) < (b)) ? (a) : (b))
#define EMMC_RW_SECTOR_COUNT_MAX 0x0000ffffU
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;
/* parameter check */
if ((count > EMMC_RW_SECTOR_COUNT_MAX)
|| (count == 0)
|| ((transfer_mode != HAL_MEMCARD_DMA)
&& (transfer_mode != HAL_MEMCARD_NOT_DMA))
) {
emmc_write_error_info(EMMC_FUNCNO_READ_SECTOR, 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;
}
SETR_32(SD_SECCNT, count);
SETR_32(SD_STOP, 0x00000100);
SETR_32(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 << 16);
result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response);
if (result != EMMC_SUCCESS) {
return result;
}
#if RCAR_BL2_DCACHE == 1
if (transfer_mode == HAL_MEMCARD_NOT_DMA) {
flush_dcache_range((uint64_t) buff_address_virtual,
((size_t) count << EMMC_SECTOR_SIZE_SHIFT));
}
#endif /* RCAR_BL2_DCACHE == 1 */
/* ready status check */
if ((mmc_drv_obj.r1_card_status & EMMC_R1_READY) == 0) {
emmc_write_error_info(EMMC_FUNCNO_READ_SECTOR,
EMMC_ERR_CARD_BUSY);
return EMMC_ERR_CARD_BUSY;
}
/* state check */
if (mmc_drv_obj.current_state != EMMC_R1_STATE_TRAN) {
emmc_write_error_info(EMMC_FUNCNO_READ_SECTOR,
EMMC_ERR_CARD_STATE);
return EMMC_ERR_CARD_STATE;
}
return EMMC_SUCCESS;
}
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;
HAL_MEMCARD_DATA_TRANSFER_MODE transfer_mode;
/* parameter check */
if (count == 0) {
emmc_write_error_info(EMMC_FUNCNO_READ_SECTOR, EMMC_ERR_PARAM);
return EMMC_ERR_PARAM;
}
/* state check */
if (mmc_drv_obj.mount != TRUE) {
emmc_write_error_info(EMMC_FUNCNO_READ_SECTOR, EMMC_ERR_STATE);
return EMMC_ERR_STATE;
}
/* DMA? */
if ((feature_flags & LOADIMAGE_FLAGS_DMA_ENABLE) != 0) {
transfer_mode = HAL_MEMCARD_DMA;
} else {
transfer_mode = HAL_MEMCARD_NOT_DMA;
}
remain = count;
while (remain != 0) {
trans_count = MIN_EMMC(remain, EMMC_RW_SECTOR_COUNT_MAX);
result =
emmc_multiple_block_read(buff_address_virtual,
sector_number, trans_count,
transfer_mode);
if (result != EMMC_SUCCESS) {
return result;
}
buff_address_virtual += (EMMC_BLOCK_LENGTH_DW * trans_count);
sector_number += trans_count;
remain -= trans_count;
}
return EMMC_SUCCESS;
}
/*
* Copyright (c) 2015-2018, Renesas Electronics Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/**
* @file emmc_registers.h
* @brief emmc boot driver is expecting this header file. HS-MMC module header file.
*
*/
#ifndef __EMMC_REGISTERS_H__
#define __EMMC_REGISTERS_H__
/* ************************ HEADER (INCLUDE) SECTION *********************** */
/* ***************** MACROS, CONSTANTS, COMPILATION FLAGS ****************** */
/* MMC channel select */
#define MMC_CH0 (0U) /* SDHI2/MMC0 */
#define MMC_CH1 (1U) /* SDHI3/MMC1 */
#if RCAR_LSI == RCAR_E3
#define USE_MMC_CH (MMC_CH1) /* R-Car E3 */
#else /* RCAR_LSI == RCAR_E3 */
#define USE_MMC_CH (MMC_CH0) /* R-Car H3/M3/M3N */
#endif /* RCAR_LSI == RCAR_E3 */
#define BIT0 (0x00000001U)
#define BIT1 (0x00000002U)
#define BIT2 (0x00000004U)
#define BIT3 (0x00000008U)
#define BIT4 (0x00000010U)
#define BIT5 (0x00000020U)
#define BIT6 (0x00000040U)
#define BIT7 (0x00000080U)
#define BIT8 (0x00000100U)
#define BIT9 (0x00000200U)
#define BIT10 (0x00000400U)
#define BIT11 (0x00000800U)
#define BIT12 (0x00001000U)
#define BIT13 (0x00002000U)
#define BIT14 (0x00004000U)
#define BIT15 (0x00008000U)
#define BIT16 (0x00010000U)
#define BIT17 (0x00020000U)
#define BIT18 (0x00040000U)
#define BIT19 (0x00080000U)
#define BIT20 (0x00100000U)
#define BIT21 (0x00200000U)
#define BIT22 (0x00400000U)
#define BIT23 (0x00800000U)
#define BIT24 (0x01000000U)
#define BIT25 (0x02000000U)
#define BIT26 (0x04000000U)
#define BIT27 (0x08000000U)
#define BIT28 (0x10000000U)
#define BIT29 (0x20000000U)
#define BIT30 (0x40000000U)
#define BIT31 (0x80000000U)
/** @brief Clock Pulse Generator (CPG) registers
*/
#define CPG_BASE (0xE6150000U)
#define CPG_MSTPSR3 (CPG_BASE+0x0048U) /* Module stop status register 3 */
#define CPG_SMSTPCR3 (CPG_BASE+0x013CU) /* System module stop control register 3 */
#define CPG_SD2CKCR (CPG_BASE+0x0268U) /* SDHI2 clock frequency control register */
#define CPG_SD3CKCR (CPG_BASE+0x026CU) /* SDHI3 clock frequency control register */
#define CPG_CPGWPR (CPG_BASE+0x0900U) /* CPG Write Protect Register */
#if USE_MMC_CH == MMC_CH0
#define CPG_SDxCKCR (CPG_SD2CKCR) /* SDHI2/MMC0 */
#else /* USE_MMC_CH == MMC_CH0 */
#define CPG_SDxCKCR (CPG_SD3CKCR) /* SDHI3/MMC1 */
#endif /* USE_MMC_CH == MMC_CH0 */
/** Boot Status register
*/
#define MFISBTSTSR (0xE6260604U)
#define MFISBTSTSR_BOOT_PARTITION (0x00000010U)
/** brief eMMC registers
*/
#define MMC0_SD_BASE (0xEE140000U)
#define MMC1_SD_BASE (0xEE160000U)
#if USE_MMC_CH == MMC_CH0
#define MMC_SD_BASE (MMC0_SD_BASE)
#else /* USE_MMC_CH == MMC_CH0 */
#define MMC_SD_BASE (MMC1_SD_BASE)
#endif /* USE_MMC_CH == MMC_CH0 */
#define SD_CMD (MMC_SD_BASE + 0x0000U)
#define SD_PORTSEL (MMC_SD_BASE + 0x0008U)
#define SD_ARG (MMC_SD_BASE + 0x0010U)
#define SD_ARG1 (MMC_SD_BASE + 0x0018U)
#define SD_STOP (MMC_SD_BASE + 0x0020U)
#define SD_SECCNT (MMC_SD_BASE + 0x0028U)
#define SD_RSP10 (MMC_SD_BASE + 0x0030U)
#define SD_RSP1 (MMC_SD_BASE + 0x0038U)
#define SD_RSP32 (MMC_SD_BASE + 0x0040U)
#define SD_RSP3 (MMC_SD_BASE + 0x0048U)
#define SD_RSP54 (MMC_SD_BASE + 0x0050U)
#define SD_RSP5 (MMC_SD_BASE + 0x0058U)
#define SD_RSP76 (MMC_SD_BASE + 0x0060U)
#define SD_RSP7 (MMC_SD_BASE + 0x0068U)
#define SD_INFO1 (MMC_SD_BASE + 0x0070U)
#define SD_INFO2 (MMC_SD_BASE + 0x0078U)
#define SD_INFO1_MASK (MMC_SD_BASE + 0x0080U)
#define SD_INFO2_MASK (MMC_SD_BASE + 0x0088U)
#define SD_CLK_CTRL (MMC_SD_BASE + 0x0090U)
#define SD_SIZE (MMC_SD_BASE + 0x0098U)
#define SD_OPTION (MMC_SD_BASE + 0x00A0U)
#define SD_ERR_STS1 (MMC_SD_BASE + 0x00B0U)
#define SD_ERR_STS2 (MMC_SD_BASE + 0x00B8U)
#define SD_BUF0 (MMC_SD_BASE + 0x00C0U)
#define SDIO_MODE (MMC_SD_BASE + 0x00D0U)
#define SDIO_INFO1 (MMC_SD_BASE + 0x00D8U)
#define SDIO_INFO1_MASK (MMC_SD_BASE + 0x00E0U)
#define CC_EXT_MODE (MMC_SD_BASE + 0x0360U)
#define SOFT_RST (MMC_SD_BASE + 0x0380U)
#define VERSION (MMC_SD_BASE + 0x0388U)
#define HOST_MODE (MMC_SD_BASE + 0x0390U)
#define DM_CM_DTRAN_MODE (MMC_SD_BASE + 0x0820U)
#define DM_CM_DTRAN_CTRL (MMC_SD_BASE + 0x0828U)
#define DM_CM_RST (MMC_SD_BASE + 0x0830U)
#define DM_CM_INFO1 (MMC_SD_BASE + 0x0840U)
#define DM_CM_INFO1_MASK (MMC_SD_BASE + 0x0848U)
#define DM_CM_INFO2 (MMC_SD_BASE + 0x0850U)
#define DM_CM_INFO2_MASK (MMC_SD_BASE + 0x0858U)
#define DM_DTRAN_ADDR (MMC_SD_BASE + 0x0880U)
/** @brief SD_INFO1 Registers
*/
#define SD_INFO1_HPIRES 0x00010000UL /* Response Reception Completion */
#define SD_INFO1_INFO10 0x00000400UL /* Indicates the SDDAT3 state */
#define SD_INFO1_INFO9 0x00000200UL /* SDDAT3 Card Insertion */
#define SD_INFO1_INFO8 0x00000100UL /* SDDAT3 Card Removal */
#define SD_INFO1_INFO7 0x00000080UL /* Write Protect */
#define SD_INFO1_INFO5 0x00000020UL /* Indicates the ISDCD state */
#define SD_INFO1_INFO4 0x00000010UL /* ISDCD Card Insertion */
#define SD_INFO1_INFO3 0x00000008UL /* ISDCD Card Removal */
#define SD_INFO1_INFO2 0x00000004UL /* Access end */
#define SD_INFO1_INFO0 0x00000001UL /* Response end */
/** @brief SD_INFO2 Registers
*/
#define SD_INFO2_ILA 0x00008000UL /* Illegal Access Error */
#define SD_INFO2_CBSY 0x00004000UL /* Command Type Register Busy */
#define SD_INFO2_SCLKDIVEN 0x00002000UL
#define SD_INFO2_BWE 0x00000200UL /* SD_BUF Write Enable */
#define SD_INFO2_BRE 0x00000100UL /* SD_BUF Read Enable */
#define SD_INFO2_DAT0 0x00000080UL /* SDDAT0 */
#define SD_INFO2_ERR6 0x00000040UL /* Response Timeout */
#define SD_INFO2_ERR5 0x00000020UL /* SD_BUF Illegal Read Access */
#define SD_INFO2_ERR4 0x00000010UL /* SD_BUF Illegal Write Access */
#define SD_INFO2_ERR3 0x00000008UL /* Data Timeout */
#define SD_INFO2_ERR2 0x00000004UL /* END Error */
#define SD_INFO2_ERR1 0x00000002UL /* CRC Error */
#define SD_INFO2_ERR0 0x00000001UL /* CMD Error */
#define SD_INFO2_ALL_ERR 0x0000807FUL
#define SD_INFO2_CLEAR 0x00000800UL /* BIT11 The write value should always be 1. HWM_0003 */
/** @brief SOFT_RST
*/
#define SOFT_RST_SDRST 0x00000001UL
/** @brief SD_CLK_CTRL
*/
#define SD_CLK_CTRL_SDCLKOFFEN 0x00000200UL
#define SD_CLK_CTRL_SCLKEN 0x00000100UL
#define SD_CLK_CTRL_CLKDIV_MASK 0x000000FFUL
#define SD_CLOCK_ENABLE 0x00000100UL
#define SD_CLOCK_DISABLE 0x00000000UL
#define SD_CLK_WRITE_MASK 0x000003FFUL
#define SD_CLK_CLKDIV_CLEAR_MASK 0xFFFFFF0FUL
/** @brief SD_OPTION
*/
#define SD_OPTION_TIMEOUT_CNT_MASK 0x000000F0UL
/** @brief MMC Clock Frequency
* 200MHz * 1/x = output clock
*/
#define MMC_CLK_OFF 0UL /* Clock output is disabled */
#define MMC_400KHZ 512UL /* 200MHz * 1/512 = 390 KHz */
#define MMC_20MHZ 16UL /* 200MHz * 1/16 = 12.5 MHz Normal speed mode */
#define MMC_26MHZ 8UL /* 200MHz * 1/8 = 25 MHz High speed mode 26Mhz */
#define MMC_52MHZ 4UL /* 200MHz * 1/4 = 50 MHz High speed mode 52Mhz */
#define MMC_100MHZ 2UL /* 200MHz * 1/2 = 100 MHz */
#define MMC_200MHZ 1UL /* 200MHz * 1/1 = 200 MHz */
#define MMC_FREQ_52MHZ 52000000UL
#define MMC_FREQ_26MHZ 26000000UL
#define MMC_FREQ_20MHZ 20000000UL
/** @brief MMC Clock DIV
*/
#define MMC_SD_CLK_START 0x00000100UL /* CLOCK On */
#define MMC_SD_CLK_STOP (~0x00000100UL) /* CLOCK stop */
#define MMC_SD_CLK_DIV1 0x000000FFUL /* 1/1 */
#define MMC_SD_CLK_DIV2 0x00000000UL /* 1/2 */
#define MMC_SD_CLK_DIV4 0x00000001UL /* 1/4 */
#define MMC_SD_CLK_DIV8 0x00000002UL /* 1/8 */
#define MMC_SD_CLK_DIV16 0x00000004UL /* 1/16 */
#define MMC_SD_CLK_DIV32 0x00000008UL /* 1/32 */
#define MMC_SD_CLK_DIV64 0x00000010UL /* 1/64 */
#define MMC_SD_CLK_DIV128 0x00000020UL /* 1/128 */
#define MMC_SD_CLK_DIV256 0x00000040UL /* 1/256 */
#define MMC_SD_CLK_DIV512 0x00000080UL /* 1/512 */
/** @brief DM_CM_DTRAN_MODE
*/
#define DM_CM_DTRAN_MODE_CH0 0x00000000UL /* CH0(downstream) */
#define DM_CM_DTRAN_MODE_CH1 0x00010000UL /* CH1(upstream) */
#define DM_CM_DTRAN_MODE_BIT_WIDTH 0x00000030UL
/** @brief CC_EXT_MODE
*/
#define CC_EXT_MODE_DMASDRW_ENABLE 0x00000002UL /* SD_BUF Read/Write DMA Transfer */
#define CC_EXT_MODE_CLEAR 0x00001010UL /* BIT 12 & 4 always 1. */
/** @brief DM_CM_INFO_MASK
*/
#define DM_CM_INFO_MASK_CLEAR 0xFFFCFFFEUL
#define DM_CM_INFO_CH0_ENABLE 0x00010001UL
#define DM_CM_INFO_CH1_ENABLE 0x00020001UL
/** @brief DM_DTRAN_ADDR
*/
#define DM_DTRAN_ADDR_WRITE_MASK 0xFFFFFFF8UL
/** @brief DM_CM_DTRAN_CTRL
*/
#define DM_CM_DTRAN_CTRL_START 0x00000001UL
/** @brief SYSC Registers
*/
#if USE_MMC_CH == MMC_CH0
#define CPG_MSTP_MMC (BIT12) /* SDHI2/MMC0 */
#else /* USE_MMC_CH == MMC_CH0 */
#define CPG_MSTP_MMC (BIT11) /* SDHI3/MMC1 */
#endif /* USE_MMC_CH == MMC_CH0 */
/* ********************** STRUCTURES, TYPE DEFINITIONS ********************* */
/* ********************** DECLARATION OF EXTERNAL DATA ********************* */
/* ************************** FUNCTION PROTOTYPES ************************** */
/* ********************************* CODE ********************************** */
#endif /* __EMMC_REGISTERS_H__ */
/* ******************************** END ************************************ */
This diff is collapsed.
/*
* Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <debug.h>
#include "emmc_config.h"
#include "emmc_hal.h"
#include "emmc_std.h"
#include "emmc_registers.h"
#include "emmc_def.h"
static const uint32_t cmd_reg_hw[EMMC_CMD_MAX + 1] = {
0x00000000, /* CMD0 */
0x00000701, /* CMD1 */
0x00000002, /* CMD2 */
0x00000003, /* CMD3 */
0x00000004, /* CMD4 */
0x00000505, /* CMD5 */
0x00000406, /* CMD6 */
0x00000007, /* CMD7 */
0x00001C08, /* CMD8 */
0x00000009, /* CMD9 */
0x0000000A, /* CMD10 */
0x00000000, /* reserved */
0x0000000C, /* CMD12 */
0x0000000D, /* CMD13 */
0x00001C0E, /* CMD14 */
0x0000000F, /* CMD15 */
0x00000010, /* CMD16 */
0x00000011, /* CMD17 */
0x00007C12, /* CMD18 */
0x00000C13, /* CMD19 */
0x00000000,
0x00001C15, /* CMD21 */
0x00000000,
0x00000017, /* CMD23 */
0x00000018, /* CMD24 */
0x00006C19, /* CMD25 */
0x00000C1A, /* CMD26 */
0x0000001B, /* CMD27 */
0x0000001C, /* CMD28 */
0x0000001D, /* CMD29 */
0x0000001E, /* CMD30 */
0x00001C1F, /* CMD31 */
0x00000000,
0x00000000,
0x00000000,
0x00000423, /* CMD35 */
0x00000424, /* CMD36 */
0x00000000,
0x00000026, /* CMD38 */
0x00000427, /* CMD39 */
0x00000428, /* CMD40(send cmd) */
0x00000000,
0x0000002A, /* CMD42 */
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000C31,
0x00000000,
0x00000000,
0x00000000,
0x00007C35,
0x00006C36,
0x00000037, /* CMD55 */
0x00000038, /* CMD56(Read) */
0x00000000,
0x00000000,
0x00000000,
0x00000000
};
uint32_t emmc_bit_field(uint8_t *data, uint32_t top, uint32_t bottom)
{
uint32_t value;
uint32_t index_top = (uint32_t) (15 - (top >> 3));
uint32_t index_bottom = (uint32_t) (15 - (bottom >> 3));
if (index_top == index_bottom) {
value = data[index_top];
} else if ((index_top + 1) == index_bottom) {
value =
(uint32_t) ((data[index_top] << 8) | data[index_bottom]);
} else if ((index_top + 2) == index_bottom) {
value =
(uint32_t) ((data[index_top] << 16) |
(data[index_top + 1] << 8) | data[index_top +
2]);
} else {
value =
(uint32_t) ((data[index_top] << 24) |
(data[index_top + 1] << 16) |
(data[index_top + 2] << 8) | data[index_top +
3]);
}
value = ((value >> (bottom & 0x07)) & ((1 << (top - bottom + 1)) - 1));
return value;
}
void emmc_write_error_info(uint16_t func_no, EMMC_ERROR_CODE error_code)
{
mmc_drv_obj.error_info.num = func_no;
mmc_drv_obj.error_info.code = (uint16_t) error_code;
ERROR("BL2: emmc err:func_no=0x%x code=0x%x\n", func_no, error_code);
}
void emmc_write_error_info_func_no(uint16_t func_no)
{
mmc_drv_obj.error_info.num = func_no;
ERROR("BL2: emmc err:func_no=0x%x\n", func_no);
}
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[cmd & HAL_MEMCARD_COMMAND_INDEX_MASK];
/* clear data transfer information */
mmc_drv_obj.trans_size = 0;
mmc_drv_obj.remain_size = 0;
mmc_drv_obj.buff_address_virtual = NULL;
mmc_drv_obj.buff_address_physical = NULL;
/* response information */
mmc_drv_obj.response_length = 6;
switch (mmc_drv_obj.cmd_info.cmd & 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 = 0;
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 |= BIT10; /* 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 = 17;
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;
}
}
void emmc_make_trans_cmd(HAL_MEMCARD_COMMAND cmd, uint32_t arg,
uint32_t *buff_address_virtual,
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;
}
EMMC_ERROR_CODE emmc_send_idle_cmd(uint32_t arg)
{
EMMC_ERROR_CODE result;
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_cmd_processing = 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;
}
This diff is collapsed.
/*
* Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef IIC_DVFS_H__
#define IIC_DVFS_H__
/* PMIC slave */
#define PMIC (0x30)
#define BKUP_MODE_CNT (0x20)
#define DVFS_SET_VID (0x54)
#define REG_KEEP10 (0x79)
/* EEPROM slave */
#define EEPROM (0x50)
#define BOARD_ID (0x70)
int32_t rcar_iic_dvfs_receive(uint8_t slave, uint8_t reg, uint8_t *data);
int32_t rcar_iic_dvfs_send(uint8_t slave, uint8_t regr, uint8_t data);
#endif
/*
* Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef IO_COMMON_H__
#define IO_COMMON_H__
typedef struct io_drv_spec {
size_t offset;
size_t length;
uint32_t partition;
} io_drv_spec_t;
#endif
This diff is collapsed.
/*
* Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef IO_EMMCDRV_H__
#define IO_EMMCDRV_H__
struct io_dev_connector;
int32_t rcar_register_io_dev_emmcdrv(const io_dev_connector_t **connector);
#endif
This diff is collapsed.
/*
* Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef IO_MEMDRV_H__
#define IO_MEMDRV_H__
struct io_dev_connector;
int32_t rcar_register_io_dev_memdrv(const io_dev_connector_t **connector);
#endif
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment