"git@web.lueluesay.top:root/oh-my-zsh.git" did not exist on "bd9cd052f156f606a8f9ccccfeacf3125d06fd91"
Commit bffde63d authored by Sheetal Tigadoli's avatar Sheetal Tigadoli
Browse files

drivers: Add emmc driver for Broadcom platforms



Add emmc driver for Broadcom platforms

Change-Id: I126a6dfccd41062cb0b856f2c2fb1f724730b95e
Signed-off-by: default avatarSheetal Tigadoli <sheetal.tigadoli@broadcom.com>
parent 3942d3a8
/*
* Copyright (c) 2016 - 2020, Broadcom
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <string.h>
#include <lib/mmio.h>
#include <platform_def.h>
#include "bcm_emmc.h"
#include "emmc_chal_types.h"
#include "emmc_chal_sd.h"
#include "emmc_pboot_hal_memory_drv.h"
extern void emmc_soft_reset(void);
#define SD_VDD_WINDOW_1_6_TO_1_7 0x00000010 // 1.6 V to 1.7 Volts
#define SD_VDD_WINDOW_1_7_TO_1_8 0x00000020 // 1.7 V to 1.8 Volts
#define SD_VDD_WINDOW_1_8_TO_1_9 0x00000040 // 1.8 V to 1.9 Volts
#define SD_VDD_WINDOW_1_9_TO_2_0 0x00000080 // 1.9 V to 2.0 Volts
#define SD_VDD_WINDOW_2_0_TO_2_1 0x00000100 // 2.0 V to 2.1 Volts
#define SD_VDD_WINDOW_2_1_TO_2_2 0x00000200 // 2.1 V to 2.2 Volts
#define SD_VDD_WINDOW_2_2_TO_2_3 0x00000400 // 2.2 V to 2.3 Volts
#define SD_VDD_WINDOW_2_3_TO_2_4 0x00000800 // 2.3 V to 2.4 Volts
#define SD_VDD_WINDOW_2_4_TO_2_5 0x00001000 // 2.4 V to 2.5 Volts
#define SD_VDD_WINDOW_2_5_TO_2_6 0x00002000 // 2.5 V to 2.6 Volts
#define SD_VDD_WINDOW_2_6_TO_2_7 0x00004000 // 2.6 V to 2.7 Volts
#define SD_VDD_WINDOW_2_7_TO_2_8 0x00008000 // 2.7 V to 2.8 Volts
#define SD_VDD_WINDOW_2_8_TO_2_9 0x00010000 // 2.8 V to 2.9 Volts
#define SD_VDD_WINDOW_2_9_TO_3_0 0x00020000 // 2.9 V to 3.0 Volts
#define SD_VDD_WINDOW_3_0_TO_3_1 0x00040000 // 3.0 V to 3.1 Volts
#define SD_VDD_WINDOW_3_1_TO_3_2 0x00080000 // 3.1 V to 3.2 Volts
#define SD_VDD_WINDOW_3_2_TO_3_3 0x00100000 // 3.2 V to 3.3 Volts
#define SD_VDD_WINDOW_3_3_TO_3_4 0x00200000 // 3.3 V to 3.4 Volts
#define SD_VDD_WINDOW_3_4_TO_3_5 0x00400000 // 3.4 V to 3.5 Volts
#define SD_VDD_WINDOW_3_5_TO_3_6 0x00800000 // 3.5 V to 3.6 Volts
#define SD_VDD_WINDOW_1_6_TO_2_6 (SD_VDD_WINDOW_1_6_TO_1_7 | \
SD_VDD_WINDOW_1_7_TO_1_8 | \
SD_VDD_WINDOW_1_8_TO_1_9 | \
SD_VDD_WINDOW_1_9_TO_2_0 | \
SD_VDD_WINDOW_2_0_TO_2_1 | \
SD_VDD_WINDOW_2_1_TO_2_2 | \
SD_VDD_WINDOW_2_2_TO_2_3 | \
SD_VDD_WINDOW_2_3_TO_2_4 | \
SD_VDD_WINDOW_2_4_TO_2_5 | \
SD_VDD_WINDOW_2_5_TO_2_6)
#define SD_VDD_WINDOW_2_6_TO_3_2 (SD_VDD_WINDOW_2_6_TO_2_7 | \
SD_VDD_WINDOW_2_7_TO_2_8 | \
SD_VDD_WINDOW_2_8_TO_2_9 | \
SD_VDD_WINDOW_2_9_TO_3_0 | \
SD_VDD_WINDOW_3_0_TO_3_1 | \
SD_VDD_WINDOW_3_1_TO_3_2)
#define SD_VDD_WINDOW_3_2_TO_3_6 (SD_VDD_WINDOW_3_2_TO_3_3 | \
SD_VDD_WINDOW_3_3_TO_3_4 | \
SD_VDD_WINDOW_3_4_TO_3_5 | \
SD_VDD_WINDOW_3_5_TO_3_6)
static int32_t chal_sd_set_power(struct sd_dev *handle,
uint32_t voltage, uint32_t state);
static void chal_sd_set_dma_boundary(struct sd_dev *handle, uint32_t boundary);
static int32_t chal_sd_setup_handler(struct sd_dev *handle,
uint32_t sdBbase, uint32_t hostBase);
/*
* Configure host controller pwr settings,
* to match voltage requirements by SD Card
*/
static int32_t chal_sd_set_power(struct sd_dev *handle,
uint32_t voltage, uint32_t state)
{
int32_t rc, rval = SD_FAIL;
uint32_t time = 0;
if (handle == NULL)
return SD_INVALID_HANDLE;
mmio_clrsetbits_32(handle->ctrl.sdRegBaseAddr +
SD4_EMMC_TOP_CTRL_OFFSET,
(SD4_EMMC_TOP_CTRL_SDVSELVDD1_MASK |
SD4_EMMC_TOP_CTRL_SDPWR_MASK),
(voltage << 9));
/*
* Long delay is required here in emulation. Without this, the initial
* commands sent to the eMMC card timeout. We don't know if this
* delay is necessary with silicon, leaving in for safety.
* It is observed that 403ms on emulation system and as per the clock
* calculations it is expected to complete with in 1ms on chip
*/
do {
rc = mmio_read_32(handle->ctrl.sdRegBaseAddr +
SD4_EMMC_TOP_INTR_OFFSET);
if ((rc & SD4_EMMC_TOP_INTR_CRDINS_MASK) ==
SD4_EMMC_TOP_INTR_CRDINS_MASK)
break;
mdelay(1);
} while (time++ < EMMC_CARD_DETECT_TIMEOUT_MS);
if (time >= EMMC_CARD_DETECT_TIMEOUT_MS) {
ERROR("EMMC: Card insert event detection timeout\n");
return rval;
}
VERBOSE("EMMC: Card detection delay: %dms\n", time);
if (state)
mmio_setbits_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_CTRL_OFFSET,
SD4_EMMC_TOP_CTRL_SDPWR_MASK);
/* dummy write & ack to verify if the sdio is ready to send commads */
mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_ARG_OFFSET, 0);
mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_CMD_OFFSET, 0);
/*
* 63ms observed on emulation system, As per clock calculations
* it will complete < 1ms on chip.
*/
time = 0;
do {
rc = mmio_read_32(handle->ctrl.sdRegBaseAddr +
SD4_EMMC_TOP_INTR_OFFSET);
if (rc & SD4_EMMC_TOP_INTR_ERRIRQ_MASK)
break;
if ((rc & SD4_EMMC_TOP_INTR_CMDDONE_MASK) ==
SD4_EMMC_TOP_INTR_CMDDONE_MASK)
break;
mdelay(1);
} while (time++ < EMMC_CMD_TIMEOUT_MS);
if (time >= EMMC_CMD_TIMEOUT_MS) {
WARN("%s %d Initial dummy command timeout is happened\n",
__func__, __LINE__);
return rval;
}
VERBOSE("EMMC: Dummy Command delay: %dms\n", time);
return SD_OK;
}
/*
* Configure DMA Boundaries
*/
static void chal_sd_set_dma_boundary(struct sd_dev *handle, uint32_t boundary)
{
if (handle == NULL)
return;
mmio_clrsetbits_32(handle->ctrl.sdRegBaseAddr +
SD4_EMMC_TOP_BLOCK_OFFSET,
SD4_EMMC_TOP_BLOCK_HSBS_MASK, boundary);
}
static int32_t chal_sd_setup_handler(struct sd_dev *handle, uint32_t sdBase,
uint32_t hostBase)
{
if (handle == NULL)
return SD_INVALID_HANDLE;
handle->ctrl.sdRegBaseAddr = sdBase;
handle->ctrl.hostRegBaseAddr = hostBase;
handle->ctrl.present = 0;
handle->ctrl.rca = 0;
handle->ctrl.blkGapEnable = 0;
handle->ctrl.cmdStatus = 0;
return SD_OK;
}
/*
* Initialize SD Host controller
*/
int32_t chal_sd_init(CHAL_HANDLE *sd_handle)
{
uint32_t cap_val_l = 0;
uint32_t ctl_val, voltage;
uint32_t timeout_val;
struct sd_dev *handle;
uint32_t reg_val;
int32_t rval = SD_FAIL;
if (sd_handle == NULL)
return SD_INVALID_HANDLE;
handle = (struct sd_dev *)sd_handle;
/*
* Set SDIO Host Controller capabilities register
*/
EMMC_TRACE("Set Host Controller Capabilities register\n");
reg_val = 0;
reg_val |= (1 << ICFG_SDIO0_CAP0__SLOT_TYPE_R);
reg_val |= (0 << ICFG_SDIO0_CAP0__INT_MODE_R);
reg_val |= (0 << ICFG_SDIO0_CAP0__SYS_BUS_64BIT_R);
reg_val |= (1 << ICFG_SDIO0_CAP0__VOLTAGE_1P8V_R);
reg_val |= (1 << ICFG_SDIO0_CAP0__VOLTAGE_3P0V_R);
reg_val |= (1 << ICFG_SDIO0_CAP0__VOLTAGE_3P3V_R);
reg_val |= (1 << ICFG_SDIO0_CAP0__SUSPEND_RESUME_R);
reg_val |= (1 << ICFG_SDIO0_CAP0__SDMA_R);
reg_val |= (1 << ICFG_SDIO0_CAP0__HIGH_SPEED_R);
reg_val |= (1 << ICFG_SDIO0_CAP0__ADMA2_R);
reg_val |= (1 << ICFG_SDIO0_CAP0__EXTENDED_MEDIA_R);
reg_val |= (2 << ICFG_SDIO0_CAP0__MAX_BLOCK_LEN_R);
reg_val |= (0xd0 << ICFG_SDIO0_CAP0__BASE_CLK_FREQ_R);
reg_val |= (1 << ICFG_SDIO0_CAP0__TIMEOUT_UNIT_R);
reg_val |= (0x30 << ICFG_SDIO0_CAP0__TIMEOUT_CLK_FREQ_R);
mmio_write_32(ICFG_SDIO0_CAP0, reg_val);
reg_val = 0;
reg_val |= (1 << ICFG_SDIO0_CAP1__SPI_BLOCK_MODE_R);
reg_val |= (1 << ICFG_SDIO0_CAP1__SPI_MODE_R);
reg_val |= (0 << ICFG_SDIO0_CAP1__CLK_MULT_R);
reg_val |= (0 << ICFG_SDIO0_CAP1__RETUNING_MODE_R);
reg_val |= (1 << ICFG_SDIO0_CAP1__TUNE_SDR50_R);
reg_val |= (1 << ICFG_SDIO0_CAP1__TIME_RETUNE_R);
reg_val |= (1 << ICFG_SDIO0_CAP1__DRIVER_D_R);
reg_val |= (1 << ICFG_SDIO0_CAP1__DRIVER_C_R);
reg_val |= (1 << ICFG_SDIO0_CAP1__DRIVER_A_R);
reg_val |= (1 << ICFG_SDIO0_CAP1__DDR50_R);
reg_val |= (1 << ICFG_SDIO0_CAP1__SDR104_R);
reg_val |= (1 << ICFG_SDIO0_CAP1__SDR50_R);
mmio_write_32(ICFG_SDIO0_CAP1, reg_val);
/* Reset the SDIO controller */
chal_sd_stop();
/* Turn on SD clock */
chal_sd_set_clock(sd_handle,
chal_sd_freq_2_div_ctrl_setting(INIT_CLK_FREQ), 1);
/* program data time out value to the max */
timeout_val = SD_HOST_CORE_TIMEOUT;
ctl_val = mmio_read_32(handle->ctrl.sdRegBaseAddr +
SD4_EMMC_TOP_CTRL1_OFFSET);
ctl_val |= ((timeout_val & 0xf) << SD4_EMMC_TOP_CTRL1_DTCNT_SHIFT);
mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_CTRL1_OFFSET,
ctl_val);
/* enable all interrupt status */
mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_INTREN1_OFFSET,
0);
mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_INTREN2_OFFSET,
0);
SD_US_DELAY(100);
mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_INTREN1_OFFSET,
SD_NOR_INTERRUPTS | SD_ERR_INTERRUPTS);
mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_INTREN2_OFFSET,
SD_NOR_INTERRUPTS | SD_ERR_INTERRUPTS);
/* Select SD bus voltage */
cap_val_l = mmio_read_32(handle->ctrl.sdRegBaseAddr +
SD4_EMMC_TOP_CAPABILITIES1_OFFSET);
handle->cfg.voltage = 0;
voltage = 0x7;
if (cap_val_l & SD4_EMMC_TOP_CAPABILITIES1_V33_MASK) {
handle->cfg.voltage |= SD_VDD_WINDOW_3_3_TO_3_4;
voltage = 0x7;
} else if (cap_val_l & SD4_EMMC_TOP_CAPABILITIES1_V3_MASK) {
handle->cfg.voltage |= SD_VDD_WINDOW_3_0_TO_3_1;
voltage = 0x6;
} else if (cap_val_l & SD4_EMMC_TOP_CAPABILITIES1_V18_MASK) {
handle->cfg.voltage |= SD_VDD_WINDOW_1_8_TO_1_9;
voltage = 0x5;
}
rval = chal_sd_set_power(handle, voltage, SD4_EMMC_TOP_CTRL_SDPWR_MASK);
ctl_val = mmio_read_32(handle->ctrl.sdRegBaseAddr +
SD4_EMMC_TOP_HCVERSIRQ_OFFSET);
handle->ctrl.version = ((ctl_val >> 16) & 0xFF);
return rval;
}
void chal_sd_set_speed(CHAL_HANDLE *sd_handle, uint32_t speed)
{
struct sd_dev *handle;
if (sd_handle == NULL)
return;
handle = (struct sd_dev *) sd_handle;
if (speed) {
EMMC_TRACE("enable HighSpeed\n");
mmio_setbits_32(handle->ctrl.sdRegBaseAddr +
SD4_EMMC_TOP_CTRL_OFFSET,
SD4_EMMC_TOP_CTRL_HSEN_MASK);
} else {
EMMC_TRACE("disable HighSpeed\n");
mmio_clrbits_32(handle->ctrl.sdRegBaseAddr +
SD4_EMMC_TOP_CTRL_OFFSET,
SD4_EMMC_TOP_CTRL_HSEN_MASK);
}
}
int32_t chal_sd_stop(void)
{
uintptr_t idm_rst_ctrl_addr = EMMC_IDM_RESET_CTRL_ADDR;
/* Configure IO pins */
emmc_soft_reset();
/* Reset the SDIO controller */
mmio_write_32(idm_rst_ctrl_addr, 1);
SD_US_DELAY(100);
mmio_write_32(idm_rst_ctrl_addr, 0);
SD_US_DELAY(100);
return SD_OK;
}
/*
* Check if host supports specified capability
* returns -ve val on error, 0 if capability not supported else 1.
*/
int32_t chal_sd_check_cap(CHAL_HANDLE *sd_handle, uint32_t caps)
{
struct sd_dev *handle;
if (sd_handle == NULL)
return SD_INVALID_HANDLE;
handle = (struct sd_dev *) sd_handle;
if (caps & mmio_read_32(handle->ctrl.sdRegBaseAddr +
SD4_EMMC_TOP_CAPABILITIES1_OFFSET))
return 1;
else
return 0;
}
int32_t chal_sd_start(CHAL_HANDLE *sd_handle,
uint32_t mode, uint32_t sd_base, uint32_t host_base)
{
struct sd_dev *handle;
int32_t rval = SD_FAIL;
if (sd_handle == NULL)
return SD_INVALID_HANDLE;
handle = (struct sd_dev *) sd_handle;
handle->cfg.mode = SD_PIO_MODE; /* set to PIO mode first for init */
handle->cfg.dma = SD_DMA_OFF;
chal_sd_setup_handler(handle, sd_base, host_base);
/* init and start hw */
rval = chal_sd_init(sd_handle);
if (rval != SD_OK)
return rval;
chal_sd_clear_pending_irq(sd_handle);
handle->ctrl.eventList = 0;
handle->cfg.mode = mode;
return SD_OK;
}
/*
* Function to check 8bits of err generated from auto CMD12
*/
int32_t chal_sd_get_atuo12_error(CHAL_HANDLE *sd_handle)
{
struct sd_dev *handle;
if (sd_handle == NULL)
return SD_INVALID_HANDLE;
handle = (struct sd_dev *) sd_handle;
return (mmio_read_32(handle->ctrl.sdRegBaseAddr +
SD4_EMMC_TOP_ERRSTAT_OFFSET) & 0xFF);
}
/*
* Read present state register
*/
uint32_t chal_sd_get_present_status(CHAL_HANDLE *sd_handle)
{
struct sd_dev *handle;
if (sd_handle == NULL)
return SD_INVALID_HANDLE;
handle = (struct sd_dev *) sd_handle;
return mmio_read_32(handle->ctrl.sdRegBaseAddr +
SD4_EMMC_TOP_PSTATE_OFFSET);
}
/*
* Set SD bus width
*/
int32_t chal_sd_config_bus_width(CHAL_HANDLE *sd_handle, int32_t width)
{
uint32_t ctl_val;
struct sd_dev *handle;
if (sd_handle == NULL)
return SD_INVALID_HANDLE;
handle = (struct sd_dev *)sd_handle;
ctl_val = mmio_read_32(handle->ctrl.sdRegBaseAddr +
SD4_EMMC_TOP_CTRL_OFFSET);
switch (width) {
#ifdef DRIVER_EMMC_ENABLE_DATA_WIDTH_8BIT
case SD_BUS_DATA_WIDTH_8BIT:
ctl_val &= ~SD_BUS_DATA_WIDTH_4BIT;
ctl_val |= SD_BUS_DATA_WIDTH_8BIT;
break;
#endif
case SD_BUS_DATA_WIDTH_4BIT:
ctl_val &= ~SD_BUS_DATA_WIDTH_8BIT;
ctl_val |= SD_BUS_DATA_WIDTH_4BIT;
break;
case SD_BUS_DATA_WIDTH_1BIT:
ctl_val &= ~(SD_BUS_DATA_WIDTH_4BIT | SD_BUS_DATA_WIDTH_8BIT);
break;
default:
return SD_INV_DATA_WIDTH;
};
mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_CTRL_OFFSET,
ctl_val);
return SD_OK;
}
/*
* Function to enable or disable DMA control.
*/
int32_t chal_sd_set_dma(CHAL_HANDLE *sd_handle, uint32_t mode)
{
uint32_t val;
struct sd_dev *handle;
int32_t rc;
if (sd_handle == NULL)
return SD_INVALID_HANDLE;
handle = (struct sd_dev *)sd_handle;
if (mode) {
rc = chal_sd_check_cap(sd_handle,
SD4_EMMC_TOP_CAPABILITIES1_SDMA_MASK |
SD4_EMMC_TOP_CAPABILITIES1_ADMA2_MASK);
if (rc < 0)
return rc;
if (rc) {
handle->cfg.dma = mode;
val = mmio_read_32(handle->ctrl.sdRegBaseAddr +
SD4_EMMC_TOP_CTRL_OFFSET);
val &= ~(SD4_EMMC_TOP_CTRL_DMASEL_MASK);
val |= handle->cfg.dma - 1;
mmio_write_32(handle->ctrl.sdRegBaseAddr +
SD4_EMMC_TOP_CTRL_OFFSET, val);
return SD_OK;
}
}
handle->cfg.dma = 0;
return SD_FAIL;
}
/*
* Get current DMA address.
* Called only when there is no data transaction activity.
*/
uintptr_t chal_sd_get_dma_addr(CHAL_HANDLE *sd_handle)
{
struct sd_dev *handle;
if (sd_handle == NULL)
return SD_INVALID_HANDLE;
handle = (struct sd_dev *) sd_handle;
if (handle->cfg.dma == SD_DMA_OFF)
return 0;
return (uintptr_t)mmio_read_32(handle->ctrl.sdRegBaseAddr +
SD4_EMMC_TOP_SYSADDR_OFFSET);
}
int32_t chal_sd_send_cmd(CHAL_HANDLE *sd_handle, uint32_t cmd_idx,
uint32_t argument, uint32_t options)
{
uint32_t cmd_mode_reg = 0;
struct sd_dev *handle;
if (sd_handle == NULL)
return SD_INVALID_HANDLE;
handle = (struct sd_dev *) sd_handle;
EMMC_TRACE("%s %d cmd:%d argReg:%x options:%x\n",
__func__, __LINE__, cmd_idx, argument, options);
/* Configure the value for command and mode registers */
cmd_mode_reg = (cmd_idx << 24) | options;
/*
* 1. Write block size reg & block count reg,
* this is done in the tx or rx setup
*/
mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_BLOCK_OFFSET,
handle->ctrl.blkReg);
/* 2. Write argument reg */
mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_ARG_OFFSET,
argument);
handle->ctrl.argReg = argument;
/*
* 3. Write transfer mode reg & command reg, check the DMA bit which is
* set before this function call if it is selected.
*/
if (cmd_idx == 24 || cmd_idx == 25 || cmd_idx == 18 || cmd_idx == 17 ||
cmd_idx == 42 || cmd_idx == 51 || cmd_idx == 53)
cmd_mode_reg |= ((handle->cfg.dma) ? 1 : 0);
mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_CMD_OFFSET,
cmd_mode_reg);
handle->ctrl.cmdIndex = cmd_idx;
return SD_OK;
}
int32_t chal_sd_set_dma_addr(CHAL_HANDLE *sd_handle, uintptr_t address)
{
struct sd_dev *handle;
if (sd_handle == NULL)
return SD_INVALID_HANDLE;
handle = (struct sd_dev *) sd_handle;
if (handle->cfg.dma == SD_DMA_OFF)
return SD_FAIL;
mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_SYSADDR_OFFSET,
address);
return SD_OK;
}
uint32_t chal_sd_freq_2_div_ctrl_setting(uint32_t desired_freq)
{
/*
* Divider control setting represents 1/2 of the actual divider value.
*
* DesiredFreq = BaseClockFreq / (2 * div_ctrl_setting)
*
* ==> div_ctrl_setting = BaseClockFreq / (2 * DesiredFreq)
*/
uint32_t div_ctrl_setting;
uint32_t actual_freq;
assert(desired_freq != 0);
/* Special case, 0 = divider of 1. */
if (desired_freq >= BASE_CLK_FREQ)
return 0;
/* Normal case, desired_freq < BASE_CLK_FREQ */
div_ctrl_setting = BASE_CLK_FREQ / (2 * desired_freq);
actual_freq = BASE_CLK_FREQ / (2 * div_ctrl_setting);
if (actual_freq > desired_freq) {
/*
* Division does not result in exact freqency match.
* Make sure resulting frequency does not exceed requested freq.
*/
div_ctrl_setting++;
}
return div_ctrl_setting;
}
int32_t chal_sd_set_clock(CHAL_HANDLE *sd_handle, uint32_t div_ctrl_setting,
uint32_t on)
{
uint32_t value;
struct sd_dev *handle;
uint32_t time;
uint32_t clk_sel_high_byte = 0xFF & (div_ctrl_setting >> 8);
uint32_t clk_sel_low_byte = 0xFF & div_ctrl_setting;
if (sd_handle == NULL)
return SD_INVALID_HANDLE;
EMMC_TRACE("set_clock(div_ctrl_setting=%d,on=%d)\n",
div_ctrl_setting, on);
handle = (struct sd_dev *) sd_handle;
/* Read control register content. */
value = mmio_read_32(handle->ctrl.sdRegBaseAddr +
SD4_EMMC_TOP_CTRL1_OFFSET);
/* Disable Clock */
value &= ~(SD4_EMMC_TOP_CTRL1_SDCLKEN_MASK);
mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_CTRL1_OFFSET,
value);
/* Clear bits of interest. */
value &= ~(SD4_EMMC_TOP_CTRL1_SDCLKSEL_MASK |
SD4_EMMC_TOP_CTRL1_SDCLKSEL_UP_MASK);
/* Set bits of interest to new value. */
value |= (SD4_EMMC_TOP_CTRL1_SDCLKSEL_MASK &
(clk_sel_low_byte << SD4_EMMC_TOP_CTRL1_SDCLKSEL_SHIFT));
value |= (SD4_EMMC_TOP_CTRL1_SDCLKSEL_UP_MASK &
(clk_sel_high_byte << SD4_EMMC_TOP_CTRL1_SDCLKSEL_UP_SHIFT));
value |= SD4_EMMC_TOP_CTRL1_ICLKEN_MASK;
/* Write updated value back to control register. */
mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_CTRL1_OFFSET,
value);
time = 0;
do {
value = mmio_read_32(handle->ctrl.sdRegBaseAddr +
SD4_EMMC_TOP_CTRL1_OFFSET);
if ((value & SD4_EMMC_TOP_CTRL1_ICLKSTB_MASK) ==
SD4_EMMC_TOP_CTRL1_ICLKSTB_MASK)
break;
mdelay(1);
} while (time++ < EMMC_CLOCK_SETTING_TIMEOUT_MS);
if (time >= EMMC_CLOCK_SETTING_TIMEOUT_MS)
WARN("%s %d clock settings timeout happenedi (%dms)\n",
__func__, __LINE__, time);
VERBOSE("EMMC: clock settings delay: %dms\n", time);
value = mmio_read_32(handle->ctrl.sdRegBaseAddr +
SD4_EMMC_TOP_CTRL1_OFFSET);
if (on)
value |= SD4_EMMC_TOP_CTRL1_SDCLKEN_MASK;
mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_CTRL1_OFFSET,
value);
return SD_OK;
}
/*
* function to setup DMA buffer and data length, calculates block
* size and the number of blocks to be transferred and return
* the DMA buffer address.
*/
int32_t chal_sd_setup_xfer(CHAL_HANDLE *sd_handle,
uint8_t *data, uint32_t length, int32_t dir)
{
uint32_t blocks = 0;
struct sd_dev *handle;
if (sd_handle == NULL)
return SD_INVALID_HANDLE;
handle = (struct sd_dev *) sd_handle;
if (length <= handle->cfg.blockSize) {
handle->ctrl.blkReg = length | handle->cfg.dmaBoundary;
} else {
blocks = length / handle->cfg.blockSize;
handle->ctrl.blkReg = (blocks << 16) | handle->cfg.blockSize |
handle->cfg.dmaBoundary;
}
if (handle->cfg.dma != SD_DMA_OFF) {
/* For DMA target address setting, physical address should be used */
mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_SYSADDR_OFFSET,
(uintptr_t)data);
}
return SD_OK;
}
#ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE
/*
* function to write one block data directly to the
* host controller's FIFO which is 1K uint8_t or
* 2K uint8_t in size.
* It is used in Non-DMA mode for data transmission.
*/
int32_t chal_sd_write_buffer(CHAL_HANDLE *sd_handle, uint32_t length,
uint8_t *data)
{
uint32_t i, leftOver = 0, blockSize, size, value = 0;
struct sd_dev *handle;
if (sd_handle == NULL)
return SD_INVALID_HANDLE;
handle = (struct sd_dev *) sd_handle;
blockSize = handle->cfg.blockSize;
if (length == 0)
return SD_OK;
/* PIO mode, push into fifo word by word */
if (length >= blockSize) {
size = blockSize;
} else {
size = ((length >> 2) << 2);
leftOver = length % 4;
}
for (i = 0; i < size; i += 4) {
value = *(uint32_t *)(data + i);
mmio_write_32(handle->ctrl.sdRegBaseAddr +
SD4_EMMC_TOP_BUFDAT_OFFSET, value);
}
/*
* BUG ALERT:
* This implementation has TWO issues that must be addressed before you
* can safely INCLUDE_EMMC_DRIVER_WRITE_CODE.
*
* (1) For the last leftOver bytes, driver writes full word, which means
* some of the eMMC content (i.e. "4 - leftOver" will be erroneously
* overwritten).
* (2) eMMC is a block device. What happens when less than a full block of
* data is submitted???
*/
if (leftOver > 0) {
value = ((*(uint32_t *)(data + i)) << (4 - leftOver));
mmio_write_32(handle->ctrl.sdRegBaseAddr +
SD4_EMMC_TOP_BUFDAT_OFFSET, value);
}
return SD_OK;
}
#endif /* INCLUDE_EMMC_DRIVER_WRITE_CODE */
/*
* Function to read maximal one block data directly
* from the data port of the host controller (FIFO). It is used
* in Non-DMA mode for data transmission.
*/
int32_t chal_sd_read_buffer(CHAL_HANDLE *sd_handle, uint32_t length,
uint8_t *data)
{
uint32_t i, size, leftOver, blockSize, value;
struct sd_dev *handle;
if (sd_handle == NULL)
return SD_INVALID_HANDLE;
handle = (struct sd_dev *)sd_handle;
value = 0;
blockSize = handle->cfg.blockSize;
/* PIO mode, extract fifo word by word */
if (length >= blockSize) {
size = blockSize;
leftOver = 0;
} else {
leftOver = length % 4;
size = ((length >> 2) << 2);
}
for (i = 0; i < size; i += 4) {
value =
mmio_read_32(handle->ctrl.sdRegBaseAddr +
SD4_EMMC_TOP_BUFDAT_OFFSET);
memcpy((void *)(data + i), &value, sizeof(uint32_t));
}
if (leftOver > 0) {
value = mmio_read_32(handle->ctrl.sdRegBaseAddr +
SD4_EMMC_TOP_BUFDAT_OFFSET);
/*
* Copy remaining non-full word bytes.
* (We run ARM as Little Endian)
*/
uint8_t j = 0;
for (j = 0; j < leftOver; j++) {
data[i + j] = (value >> (j * 8)) & 0xFF;
}
}
return SD_OK;
}
/*
* Resets both DAT or CMD line.
*/
int32_t chal_sd_reset_line(CHAL_HANDLE *sd_handle, uint32_t line)
{
uint32_t control, flag;
struct sd_dev *handle;
if (sd_handle == NULL)
return SD_INVALID_HANDLE;
handle = (struct sd_dev *) sd_handle;
flag = SD4_EMMC_TOP_CTRL1_CMDRST_MASK | SD4_EMMC_TOP_CTRL1_DATRST_MASK;
if (flag != (line | flag))
return SD_FAIL;
control = mmio_read_32(handle->ctrl.sdRegBaseAddr +
SD4_EMMC_TOP_CTRL1_OFFSET);
control |= line;
mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_CTRL1_OFFSET,
control);
/* reset CMD and DATA line should always work, no need to timed out */
do {
control = mmio_read_32(handle->ctrl.sdRegBaseAddr +
SD4_EMMC_TOP_CTRL1_OFFSET);
} while (control & line);
return SD_OK;
}
/*
* Function to be called once a SD command is done to read
* back it's response data.
*/
int32_t chal_sd_get_response(CHAL_HANDLE *sd_handle, uint32_t *resp)
{
struct sd_dev *handle;
if (sd_handle == NULL)
return SD_INVALID_HANDLE;
handle = (struct sd_dev *) sd_handle;
resp[0] = mmio_read_32(handle->ctrl.sdRegBaseAddr +
SD4_EMMC_TOP_RESP0_OFFSET);
resp[1] = mmio_read_32(handle->ctrl.sdRegBaseAddr +
SD4_EMMC_TOP_RESP2_OFFSET);
resp[2] = mmio_read_32(handle->ctrl.sdRegBaseAddr +
SD4_EMMC_TOP_RESP4_OFFSET);
resp[3] = mmio_read_32(handle->ctrl.sdRegBaseAddr +
SD4_EMMC_TOP_RESP6_OFFSET);
return SD_OK;
}
/*
* The function is called to clean all the pending interrupts.
*/
int32_t chal_sd_clear_pending_irq(CHAL_HANDLE *sd_handle)
{
uint32_t status = SD_OK;
struct sd_dev *handle;
if (sd_handle == NULL)
return SD_INVALID_HANDLE;
handle = (struct sd_dev *)sd_handle;
/* Make sure clean all interrupts */
do {
mmio_write_32(handle->ctrl.sdRegBaseAddr +
SD4_EMMC_TOP_INTR_OFFSET, 0xFFFFFFFF);
SD_US_DELAY(10);
} while (mmio_read_32(handle->ctrl.sdRegBaseAddr +
SD4_EMMC_TOP_INTR_OFFSET));
return status;
}
/*
* The function returns interrupt status register value.
*/
int32_t chal_sd_get_irq_status(CHAL_HANDLE *sd_handle)
{
struct sd_dev *handle;
if (sd_handle == NULL)
return SD_INVALID_HANDLE;
handle = (struct sd_dev *) sd_handle;
return (mmio_read_32(handle->ctrl.sdRegBaseAddr +
SD4_EMMC_TOP_INTR_OFFSET));
}
/*
* The function clears interrupt(s) specified in the mask.
*/
int32_t chal_sd_clear_irq(CHAL_HANDLE *sd_handle, uint32_t mask)
{
struct sd_dev *handle;
if (sd_handle == NULL)
return SD_INVALID_HANDLE;
handle = (struct sd_dev *) sd_handle;
/* Make sure clean masked interrupts */
do {
mmio_write_32(handle->ctrl.sdRegBaseAddr +
SD4_EMMC_TOP_INTR_OFFSET, mask);
SD_US_DELAY(10);
} while (mask &
mmio_read_32(handle->ctrl.sdRegBaseAddr +
SD4_EMMC_TOP_INTR_OFFSET));
return SD_OK;
}
/*
* Description: The function configures the SD host controller.
*/
int32_t chal_sd_config(CHAL_HANDLE *sd_handle, uint32_t speed, uint32_t retry,
uint32_t boundary, uint32_t blkSize, uint32_t dma)
{
struct sd_dev *handle;
if (sd_handle == NULL)
return SD_INVALID_HANDLE;
handle = (struct sd_dev *) sd_handle;
handle->cfg.speedMode = speed;
handle->cfg.retryLimit = retry;
handle->cfg.dmaBoundary = boundary;
handle->cfg.blockSize = blkSize;
chal_sd_set_dma(sd_handle, dma);
SD_US_DELAY(100);
chal_sd_set_dma_boundary(handle, boundary);
SD_US_DELAY(100);
chal_sd_set_speed(sd_handle, speed);
SD_US_DELAY(100);
return SD_OK;
}
/*
* Cleans up HC FIFO.
*/
void chal_sd_dump_fifo(CHAL_HANDLE *sd_handle)
{
struct sd_dev *handle;
if (sd_handle == NULL)
return;
handle = (struct sd_dev *)sd_handle;
/* in case there still data in the host buffer */
while (mmio_read_32(handle->ctrl.sdRegBaseAddr +
SD4_EMMC_TOP_PSTATE_OFFSET) & 0x800) {
mmio_read_32(handle->ctrl.sdRegBaseAddr +
SD4_EMMC_TOP_BUFDAT_OFFSET);
};
}
/*
* Enable or disable a SD interrupt signal.
*/
void chal_sd_set_irq_signal(CHAL_HANDLE *sd_handle, uint32_t mask,
uint32_t state)
{
struct sd_dev *handle;
if (sd_handle == NULL)
return;
handle = (struct sd_dev *)sd_handle;
if (state)
mmio_setbits_32(handle->ctrl.sdRegBaseAddr +
SD4_EMMC_TOP_INTREN2_OFFSET, mask);
else
mmio_clrbits_32(handle->ctrl.sdRegBaseAddr +
SD4_EMMC_TOP_INTREN2_OFFSET, mask);
}
/*
* Copyright (c) 2016 - 2020, Broadcom
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#include <arch_helpers.h>
#include <lib/mmio.h>
#include "bcm_emmc.h"
#include "emmc_chal_types.h"
#include "emmc_csl_sdprot.h"
#include "emmc_chal_sd.h"
#include "emmc_csl_sdcmd.h"
#include "emmc_csl_sd.h"
#include "emmc_pboot_hal_memory_drv.h"
#define SD_CARD_BUSY 0x80000000
#define SD_CARD_RETRY_LIMIT 1000
#define SD_CARD_HIGH_SPEED_PS 13
#define SD_CHK_HIGH_SPEED_MODE 0x00FFFFF1
#define SD_SET_HIGH_SPEED_MODE 0x80FFFFF1
#define SD_MMC_ENABLE_HIGH_SPEED 0x03b90100 //0x03b90103
#define SD_MMC_8BIT_MODE 0x03b70200
#define SD_MMC_4BIT_MODE 0x03b70100
#define SD_MMC_1BIT_MODE 0x03b70000
#define SD_MMC_BOOT_8BIT_MODE 0x03b10200
#define SD_MMC_BOOT_4BIT_MODE 0x03b10100
#define SD_MMC_BOOT_1BIT_MODE 0x03b10000
#define SDIO_HW_EMMC_EXT_CSD_BOOT_CNF 0X03B30000
#ifdef USE_EMMC_FIP_TOC_CACHE
/*
* Cache size mirrors the size of the global eMMC temp buffer
* which is used for non-image body reads such as headers, ToC etc.
*/
#define CACHE_SIZE ((EMMC_BLOCK_SIZE) * 2)
#define PARTITION_BLOCK_ADDR ((PLAT_FIP_ATTEMPT_OFFSET)/(EMMC_BLOCK_SIZE))
static uint32_t cached_partition_block;
static uint8_t cached_block[CACHE_SIZE];
#endif
static int set_card_data_width(struct sd_handle *handle, int width);
static int abort_err(struct sd_handle *handle);
static int err_recovery(struct sd_handle *handle, uint32_t errors);
static int xfer_data(struct sd_handle *handle, uint32_t mode, uint32_t addr,
uint32_t length, uint8_t *base);
int set_boot_config(struct sd_handle *handle, uint32_t config)
{
return mmc_cmd6(handle, SDIO_HW_EMMC_EXT_CSD_BOOT_CNF | config);
}
void process_csd_mmc_speed(struct sd_handle *handle, uint32_t csd_mmc_speed)
{
uint32_t div_ctrl_setting;
/* CSD field TRAN_SPEED:
* Bits [2:0] 0 = 100 KHz
* 1 = 1 MHz
* 2 = 10 MHz
* 3 = 100 MHz
* 4...7 Reserved.
* Bits [6:3] 0 = Reserved
* 1 = 1.0
* 2 = 1.2
* 3 = 1.3
* 4 = 1.5
* 5 = 2.0
* 6 = 2.6
* 7 = 3.0
* 8 = 3.5
* 9 = 4.0
* A = 4.5
* B = 5.2
* C = 5.5
* D = 6.0
* E = 7.0
* F = 8.0
* For cards supporting version 4.0, 4.1, and 4.2 of the standard,
* the value shall be 20 MHz (0x2A).
* For cards supporting version 4.3 , the value shall be 26 MHz (0x32)
*/
switch (csd_mmc_speed & 0x7F) {
case 0x2A:
EMMC_TRACE("Speeding up eMMC clock to 20MHz\n");
div_ctrl_setting =
chal_sd_freq_2_div_ctrl_setting(20 * 1000 * 1000);
break;
case 0x32:
EMMC_TRACE("Speeding up eMMC clock to 26MHz\n");
div_ctrl_setting =
chal_sd_freq_2_div_ctrl_setting(26 * 1000 * 1000);
break;
default:
/* Unknown */
return;
}
chal_sd_set_clock((CHAL_HANDLE *) handle->device, div_ctrl_setting, 0);
chal_sd_set_clock((CHAL_HANDLE *) handle->device, div_ctrl_setting, 1);
SD_US_DELAY(1000);
}
/*
* The function changes SD/SDIO/MMC card data width if
* the card support configurable data width. The host controller
* and the card has to be in the same bus data width.
*/
int set_card_data_width(struct sd_handle *handle, int width)
{
uint32_t data_width = 0;
int is_valid_arg = 1;
int rc = SD_FAIL;
char *bitwidth_str = " ";
char *result_str = "failed";
switch (width) {
#ifdef DRIVER_EMMC_ENABLE_DATA_WIDTH_8BIT
case SD_BUS_DATA_WIDTH_8BIT:
data_width = SD_MMC_8BIT_MODE;
#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
bitwidth_str = "8_BIT";
#endif
break;
#endif
case SD_BUS_DATA_WIDTH_4BIT:
data_width = SD_MMC_4BIT_MODE;
#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
bitwidth_str = "4_BIT";
#endif
break;
case SD_BUS_DATA_WIDTH_1BIT:
data_width = SD_MMC_1BIT_MODE;
#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
bitwidth_str = "1_BIT";
#endif
break;
default:
is_valid_arg = 0;
#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
bitwidth_str = "unknown";
#endif
break;
}
if (is_valid_arg) {
rc = mmc_cmd6(handle, data_width);
if (rc == SD_OK) {
#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
result_str = "succeeded";
#endif
chal_sd_config_bus_width((CHAL_HANDLE *) handle->device,
width);
} else {
#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
result_str = "failed";
#endif
}
} else {
rc = SD_FAIL;
#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
result_str = "ignored";
#endif
}
VERBOSE("SDIO Data Width(%s) %s.\n", bitwidth_str, result_str);
return rc;
}
/*
* Error handling routine. Does abort data
* transmission if error is found.
*/
static int abort_err(struct sd_handle *handle)
{
uint32_t present, options, event, rel = 0;
struct sd_resp cmdRsp;
handle->device->ctrl.argReg = 0;
handle->device->ctrl.cmdIndex = SD_CMD_STOP_TRANSMISSION;
options = (SD_CMD_STOP_TRANSMISSION << 24) |
(SD_CMDR_RSP_TYPE_R1b_5b << SD_CMDR_RSP_TYPE_S) |
SD4_EMMC_TOP_CMD_CRC_EN_MASK |
SD4_EMMC_TOP_CMD_CCHK_EN_MASK;
chal_sd_send_cmd((CHAL_HANDLE *) handle->device,
handle->device->ctrl.cmdIndex,
handle->device->ctrl.argReg, options);
event = wait_for_event(handle,
SD4_EMMC_TOP_INTR_CMDDONE_MASK |
SD_ERR_INTERRUPTS,
handle->device->cfg.wfe_retry);
if (event & SD_CMD_ERROR_INT) {
rel = SD_ERROR_NON_RECOVERABLE;
} else {
if (event & SD_DAT_TIMEOUT) {
return SD_ERROR_NON_RECOVERABLE;
}
chal_sd_get_response((CHAL_HANDLE *) handle->device,
(uint32_t *)&cmdRsp);
process_cmd_response(handle, handle->device->ctrl.cmdIndex,
cmdRsp.data.r2.rsp1, cmdRsp.data.r2.rsp2,
cmdRsp.data.r2.rsp3, cmdRsp.data.r2.rsp4,
&cmdRsp);
SD_US_DELAY(2000);
present =
chal_sd_get_present_status((CHAL_HANDLE *) handle->device);
if ((present & 0x00F00000) == 0x00F00000)
rel = SD_ERROR_RECOVERABLE;
else
rel = SD_ERROR_NON_RECOVERABLE;
}
return rel;
}
/*
* The function handles real data transmission on both DMA and
* none DMA mode, In None DMA mode the data transfer starts
* when the command is sent to the card, data has to be written
* into the host contollers buffer at this time one block
* at a time.
* In DMA mode, the real data transfer is done by the DMA engine
* and this functions just waits for the data transfer to complete.
*
*/
int process_data_xfer(struct sd_handle *handle, uint8_t *buffer, uint32_t addr,
uint32_t length, int dir)
{
if (dir == SD_XFER_HOST_TO_CARD) {
#ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE
if (handle->device->cfg.dma == SD_DMA_OFF) {
/*
* In NON DMA mode, the real data xfer starts from here
*/
if (write_buffer(handle, length, buffer))
return SD_WRITE_ERROR;
} else {
wait_for_event(handle,
SD4_EMMC_TOP_INTR_TXDONE_MASK |
SD_ERR_INTERRUPTS,
handle->device->cfg.wfe_retry);
if (handle->device->ctrl.cmdStatus == SD_OK)
return SD_OK;
check_error(handle, handle->device->ctrl.cmdStatus);
return SD_WRITE_ERROR;
}
#else
return SD_WRITE_ERROR;
#endif
} else { /* SD_XFER_CARD_TO_HOST */
if (handle->device->cfg.dma == SD_DMA_OFF) {
/* In NON DMA mode, the real data
* transfer starts from here
*/
if (read_buffer(handle, length, buffer))
return SD_READ_ERROR;
} else { /* for DMA mode */
/*
* once the data transmission is done
* copy data to the host buffer.
*/
wait_for_event(handle,
SD4_EMMC_TOP_INTR_TXDONE_MASK |
SD_ERR_INTERRUPTS,
handle->device->cfg.wfe_retry);
if (handle->device->ctrl.cmdStatus == SD_OK)
return SD_OK;
check_error(handle, handle->device->ctrl.cmdStatus);
return SD_READ_ERROR;
}
}
return SD_OK;
}
/*
* The function sets block size for the next SD/SDIO/MMC
* card read/write command.
*/
int select_blk_sz(struct sd_handle *handle, uint16_t size)
{
return sd_cmd16(handle, size);
}
/*
* The function initalizes the SD/SDIO/MMC/CEATA and detects
* the card according to the flag of detection.
* Once this function is called, the card is put into ready state
* so application can do data transfer to and from the card.
*/
int init_card(struct sd_handle *handle, int detection)
{
/*
* After Reset, eMMC comes up in 1 Bit Data Width by default.
* Set host side to match.
*/
chal_sd_config_bus_width((CHAL_HANDLE *) handle->device,
SD_BUS_DATA_WIDTH_1BIT);
#ifdef USE_EMMC_FIP_TOC_CACHE
cached_partition_block = 0;
#endif
handle->device->ctrl.present = 0; /* init card present to be no card */
init_mmc_card(handle);
handle->device->ctrl.present = 1; /* card is detected */
/* switch the data width back */
if (handle->card->type != SD_CARD_MMC)
return SD_FAIL;
/*
* Dynamically set Data Width to highest supported value.
* Try different data width settings (highest to lowest).
* Verify each setting by reading EXT_CSD and comparing
* against the EXT_CSD contents previously read in call to
* init_mmc_card() earlier. Stop at first verified data width
* setting.
*/
{
#define EXT_CSD_PROPERTIES_SECTION_START_INDEX 192
#define EXT_CSD_PROPERTIES_SECTION_END_INDEX 511
uint8_t buffer[EXT_CSD_SIZE];
#ifdef DRIVER_EMMC_ENABLE_DATA_WIDTH_8BIT
/* Try 8 Bit Data Width */
chal_sd_config_bus_width((CHAL_HANDLE *) handle->device,
SD_BUS_DATA_WIDTH_8BIT);
if ((!set_card_data_width(handle, SD_BUS_DATA_WIDTH_8BIT)) &&
(!mmc_cmd8(handle, buffer)) &&
(!memcmp(&buffer[EXT_CSD_PROPERTIES_SECTION_START_INDEX],
&(emmc_global_buf_ptr->u.Ext_CSD_storage[EXT_CSD_PROPERTIES_SECTION_START_INDEX]),
EXT_CSD_PROPERTIES_SECTION_END_INDEX - EXT_CSD_PROPERTIES_SECTION_START_INDEX + 1)))
return SD_OK;
#endif
/* Fall back to 4 Bit Data Width */
chal_sd_config_bus_width((CHAL_HANDLE *) handle->device,
SD_BUS_DATA_WIDTH_4BIT);
if ((!set_card_data_width(handle, SD_BUS_DATA_WIDTH_4BIT)) &&
(!mmc_cmd8(handle, buffer)) &&
(!memcmp(&buffer[EXT_CSD_PROPERTIES_SECTION_START_INDEX],
&(emmc_global_buf_ptr->u.Ext_CSD_storage[EXT_CSD_PROPERTIES_SECTION_START_INDEX]),
EXT_CSD_PROPERTIES_SECTION_END_INDEX - EXT_CSD_PROPERTIES_SECTION_START_INDEX + 1)))
return SD_OK;
/* Fall back to 1 Bit Data Width */
chal_sd_config_bus_width((CHAL_HANDLE *) handle->device,
SD_BUS_DATA_WIDTH_1BIT);
/* Just use 1 Bit Data Width then. */
if (!set_card_data_width(handle, SD_BUS_DATA_WIDTH_1BIT))
return SD_OK;
}
return SD_CARD_INIT_ERROR;
}
/*
* The function handles MMC/CEATA card initalization.
*/
int init_mmc_card(struct sd_handle *handle)
{
uint32_t ocr = 0, newOcr, rc, limit = 0;
uint32_t cmd1_option = 0x40300000;
uint32_t sec_count;
handle->card->type = SD_CARD_MMC;
do {
SD_US_DELAY(1000);
newOcr = 0;
ocr = 0;
rc = sd_cmd1(handle, cmd1_option, &newOcr);
limit++;
if (rc == SD_OK)
ocr = newOcr;
} while (((ocr & SD_CARD_BUSY) == 0) && (limit < SD_CARD_RETRY_LIMIT));
if (limit >= SD_CARD_RETRY_LIMIT) {
handle->card->type = SD_CARD_UNKNOWN;
EMMC_TRACE("CMD1 Timeout: Device is not ready\n");
return SD_CARD_UNKNOWN;
}
/* Save the ocr register */
handle->device->ctrl.ocr = ocr;
/* Ready State */
rc = sd_cmd2(handle);
if (rc != SD_OK) {
handle->card->type = SD_CARD_UNKNOWN;
return SD_CARD_UNKNOWN;
}
rc = sd_cmd3(handle);
if (rc != SD_OK) {
handle->card->type = SD_CARD_UNKNOWN;
return SD_CARD_UNKNOWN;
}
/* read CSD */
rc = sd_cmd9(handle, &emmc_global_vars_ptr->cardData);
if (rc != SD_OK) {
handle->card->type = SD_CARD_UNKNOWN;
return SD_CARD_UNKNOWN;
}
/* Increase clock frequency according to what the card advertises */
EMMC_TRACE("From CSD... cardData.csd.mmc.speed = 0x%X\n",
emmc_global_vars_ptr->cardData.csd.mmc.speed);
process_csd_mmc_speed(handle,
emmc_global_vars_ptr->cardData.csd.mmc.speed);
/* goto transfer mode */
rc = sd_cmd7(handle, handle->device->ctrl.rca);
if (rc != SD_OK) {
handle->card->type = SD_CARD_UNKNOWN;
return SD_CARD_UNKNOWN;
}
rc = mmc_cmd8(handle, emmc_global_buf_ptr->u.Ext_CSD_storage);
if (rc == SD_OK) {
/* calcul real capacity */
sec_count = emmc_global_buf_ptr->u.Ext_CSD_storage[212] |
emmc_global_buf_ptr->u.Ext_CSD_storage[213] << 8 |
emmc_global_buf_ptr->u.Ext_CSD_storage[214] << 16 |
emmc_global_buf_ptr->u.Ext_CSD_storage[215] << 24;
EMMC_TRACE("Device density = %ldMBytes\n",
handle->card->size / (1024 * 1024));
if (sec_count > 0) {
handle->card->size = (uint64_t)sec_count * 512;
EMMC_TRACE("Updated Device density = %ldMBytes\n",
handle->card->size / (1024 * 1024));
}
if (sec_count > (2u * 1024 * 1024 * 1024) / 512) {
handle->device->ctrl.ocr |= SD_CARD_HIGH_CAPACITY;
handle->device->cfg.blockSize = 512;
}
if (handle->device->ctrl.ocr & SD_CARD_HIGH_CAPACITY)
EMMC_TRACE("Sector addressing\n");
else
EMMC_TRACE("Byte addressing\n");
EMMC_TRACE("Ext_CSD_storage[162]: 0x%02X Ext_CSD_storage[179]: 0x%02X\n",
emmc_global_buf_ptr->u.Ext_CSD_storage[162],
emmc_global_buf_ptr->u.Ext_CSD_storage[179]);
}
return handle->card->type;
}
/*
* The function send reset command to the card.
* The card will be in ready status after the reset.
*/
int reset_card(struct sd_handle *handle)
{
int res = SD_OK;
/* on reset, card's RCA should return to 0 */
handle->device->ctrl.rca = 0;
res = sd_cmd0(handle);
if (res != SD_OK)
return SD_RESET_ERROR;
return res;
}
/*
* The function sends command to the card and starts
* data transmission.
*/
static int xfer_data(struct sd_handle *handle,
uint32_t mode,
uint32_t addr, uint32_t length, uint8_t *base)
{
int rc = SD_OK;
VERBOSE("XFER: dest: 0x%llx, addr: 0x%x, size: 0x%x bytes\n",
(uint64_t)base, addr, length);
if ((length / handle->device->cfg.blockSize) > 1) {
if (mode == SD_OP_READ) {
inv_dcache_range((uintptr_t)base, (uint64_t)length);
rc = sd_cmd18(handle, addr, length, base);
} else {
#ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE
flush_dcache_range((uintptr_t)base, (uint64_t)length);
rc = sd_cmd25(handle, addr, length, base);
#else
rc = SD_DATA_XFER_ERROR;
#endif
}
} else {
if (mode == SD_OP_READ) {
inv_dcache_range((uintptr_t)base, (uint64_t)length);
rc = sd_cmd17(handle, addr,
handle->device->cfg.blockSize, base);
} else {
#ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE
flush_dcache_range((uintptr_t)base, (uint64_t)length);
rc = sd_cmd24(handle, addr,
handle->device->cfg.blockSize, base);
#else
rc = SD_DATA_XFER_ERROR;
#endif
}
}
if (rc != SD_OK)
return SD_DATA_XFER_ERROR;
return SD_OK;
}
#ifdef INCLUDE_EMMC_DRIVER_ERASE_CODE
int erase_card(struct sd_handle *handle, uint32_t addr, uint32_t blocks)
{
uint32_t end_addr;
INFO("ERASE: addr: 0x%x, num of sectors: 0x%x\n", addr, blocks);
if (sd_cmd35(handle, addr) != SD_OK)
return SD_FAIL;
end_addr = addr + blocks - 1;
if (sd_cmd36(handle, end_addr) != SD_OK)
return SD_FAIL;
if (sd_cmd38(handle) != SD_OK)
return SD_FAIL;
return SD_OK;
}
#endif
/*
* The function reads block data from a card.
*/
#ifdef USE_EMMC_FIP_TOC_CACHE
int read_block(struct sd_handle *handle,
uint8_t *dst, uint32_t addr, uint32_t len)
{
int rel = SD_OK;
/*
* Avoid doing repeated reads of the partition block
* by caching.
*/
if (cached_partition_block &&
addr == PARTITION_BLOCK_ADDR &&
len == CACHE_SIZE) {
memcpy(dst, cached_block, len);
} else {
rel = xfer_data(handle, SD_OP_READ, addr, len, dst);
if (len == CACHE_SIZE && addr == PARTITION_BLOCK_ADDR) {
cached_partition_block = 1;
memcpy(cached_block, dst, len);
}
}
return rel;
}
#else
int read_block(struct sd_handle *handle,
uint8_t *dst, uint32_t addr, uint32_t len)
{
return xfer_data(handle, SD_OP_READ, addr, len, dst);
}
#endif
#ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE
/*
* The function writes block data to a card.
*/
int write_block(struct sd_handle *handle,
uint8_t *src, uint32_t addr, uint32_t len)
{
int rel = SD_OK;
/*
* Current HC has problem to get response of cmd16 after cmd12,
* the delay is necessary to sure the next cmd16 will not be timed out.
* The delay has to be at least 4 ms.
* The code removed cmd16 and use cmd13 to get card status before
* sending cmd18 or cmd25 to make sure the card is ready and thus
* no need to have delay here.
*/
rel = xfer_data(handle, SD_OP_WRITE, addr, len, src);
EMMC_TRACE("wr_blk addr:0x%08X src:0x%08X len:0x%08X result:%d\n",
addr, src, len, rel);
return rel;
}
/*
* The function is called to write one block data directly to
* a card's data buffer.
* it is used in Non-DMA mode for card data transmission.
*/
int write_buffer(struct sd_handle *handle, uint32_t length, uint8_t *data)
{
uint32_t rem, blockSize, event;
uint8_t *pData = data;
blockSize = handle->device->cfg.blockSize;
rem = length;
if (rem == 0)
return SD_OK;
while (rem > 0) {
event = wait_for_event(handle,
SD4_EMMC_TOP_INTR_BWRDY_MASK |
SD_ERR_INTERRUPTS,
handle->device->cfg.wfe_retry);
if (handle->device->ctrl.cmdStatus) {
check_error(handle, handle->device->ctrl.cmdStatus);
return SD_WRITE_ERROR;
}
if (rem >= blockSize)
chal_sd_write_buffer((CHAL_HANDLE *) handle->device,
blockSize, pData);
else
chal_sd_write_buffer((CHAL_HANDLE *) handle->device,
rem, pData);
if (rem > blockSize) {
rem -= blockSize;
pData += blockSize;
} else {
pData += rem;
rem = 0;
}
}
if ((event & SD4_EMMC_TOP_INTR_TXDONE_MASK) !=
SD4_EMMC_TOP_INTR_TXDONE_MASK) {
event = wait_for_event(handle,
SD4_EMMC_TOP_INTR_TXDONE_MASK |
SD_ERR_INTERRUPTS,
handle->device->cfg.wfe_retry);
if (handle->device->ctrl.cmdStatus != SD_OK) {
check_error(handle, handle->device->ctrl.cmdStatus);
return SD_WRITE_ERROR;
}
} else {
handle->device->ctrl.eventList &= ~SD4_EMMC_TOP_INTR_TXDONE_MASK;
}
return SD_OK;
}
#endif /* INCLUDE_EMMC_DRIVER_WRITE_CODE */
/*
* The function is called to read maximal one block data
* directly from a card
* It is used in Non-DMA mode for card data transmission.
*/
int read_buffer(struct sd_handle *handle, uint32_t length, uint8_t *data)
{
uint32_t rem, blockSize, event = 0;
uint8_t *pData = data;
blockSize = handle->device->cfg.blockSize;
rem = length;
if (rem == 0)
return SD_OK;
while (rem > 0) {
event = wait_for_event(handle,
SD4_EMMC_TOP_INTR_BRRDY_MASK |
SD_ERR_INTERRUPTS,
handle->device->cfg.wfe_retry);
if (handle->device->ctrl.cmdStatus) {
check_error(handle, handle->device->ctrl.cmdStatus);
return SD_READ_ERROR;
}
if (rem >= blockSize)
chal_sd_read_buffer((CHAL_HANDLE *) handle->device,
blockSize, pData);
else
chal_sd_read_buffer((CHAL_HANDLE *) handle->device, rem,
pData);
if (rem > blockSize) {
rem -= blockSize;
pData += blockSize;
} else {
pData += rem;
rem = 0;
}
}
/* In case, there are extra data in the SD FIFO, just dump them. */
chal_sd_dump_fifo((CHAL_HANDLE *) handle->device);
if ((event & SD4_EMMC_TOP_INTR_TXDONE_MASK) !=
SD4_EMMC_TOP_INTR_TXDONE_MASK) {
event = wait_for_event(handle, SD4_EMMC_TOP_INTR_TXDONE_MASK,
handle->device->cfg.wfe_retry);
if (handle->device->ctrl.cmdStatus) {
check_error(handle, handle->device->ctrl.cmdStatus);
return SD_READ_ERROR;
}
} else {
handle->device->ctrl.eventList &= ~SD4_EMMC_TOP_INTR_TXDONE_MASK;
}
return SD_OK;
}
/*
* Error handling routine.
* The function just reset the DAT
* and CMD line if an error occures during data transmission.
*/
int check_error(struct sd_handle *handle, uint32_t ints)
{
uint32_t rel;
chal_sd_set_irq_signal((CHAL_HANDLE *) handle->device,
SD_ERR_INTERRUPTS, 0);
if (ints & SD4_EMMC_TOP_INTR_CMDERROR_MASK) {
chal_sd_reset_line((CHAL_HANDLE *) handle->device,
SD4_EMMC_TOP_CTRL1_CMDRST_MASK);
rel = abort_err(handle);
chal_sd_reset_line((CHAL_HANDLE *) handle->device,
SD4_EMMC_TOP_CTRL1_DATRST_MASK);
chal_sd_set_irq_signal((CHAL_HANDLE *) handle->device,
SD_ERR_INTERRUPTS, 1);
return (rel == SD_ERROR_NON_RECOVERABLE) ?
SD_ERROR_NON_RECOVERABLE : SD_ERROR_RECOVERABLE;
} else {
rel = err_recovery(handle, ints);
}
chal_sd_set_irq_signal((CHAL_HANDLE *) handle->device,
SD_ERR_INTERRUPTS, 1);
return rel;
}
/*
* Error recovery routine.
* Try to recover from the error.
*/
static int err_recovery(struct sd_handle *handle, uint32_t errors)
{
uint32_t rel = 0;
/*
* In case of timeout error, the cmd line and data line maybe
* still active or stuck at atcitve so it is needed to reset
* either data line or cmd line to make sure a new cmd can be sent.
*/
if (errors & SD_CMD_ERROR_INT)
chal_sd_reset_line((CHAL_HANDLE *) handle->device,
SD4_EMMC_TOP_CTRL1_CMDRST_MASK);
if (errors & SD_DAT_ERROR_INT)
chal_sd_reset_line((CHAL_HANDLE *) handle->device,
SD4_EMMC_TOP_CTRL1_DATRST_MASK);
/* Abort transaction by sending out stop command */
if ((handle->device->ctrl.cmdIndex == 18) ||
(handle->device->ctrl.cmdIndex == 25))
rel = abort_err(handle);
return rel;
}
/*
* The function is called to read one block data directly from a card.
* It is used in Non-DMA mode for card data transmission.
*/
int process_cmd_response(struct sd_handle *handle,
uint32_t cmdIndex,
uint32_t rsp0,
uint32_t rsp1,
uint32_t rsp2, uint32_t rsp3, struct sd_resp *resp)
{
int result = SD_OK;
/* R6 */
uint32_t rca = (rsp0 >> 16) & 0xffff;
uint32_t cardStatus = rsp0;
/* R4 */
uint32_t cBit = (rsp0 >> 31) & 0x1;
uint32_t funcs = (rsp0 >> 28) & 0x7;
uint32_t memPresent = (rsp0 >> 27) & 0x1;
resp->r1 = 0x3f;
resp->cardStatus = cardStatus;
if (cmdIndex == SD_CMD_IO_SEND_OP_COND) {
resp->data.r4.cardReady = cBit;
resp->data.r4.funcs = funcs;
resp->data.r4.memPresent = memPresent;
resp->data.r4.ocr = cardStatus;
}
if (cmdIndex == SD_CMD_MMC_SET_RCA) {
resp->data.r6.rca = rca;
resp->data.r6.cardStatus = cardStatus & 0xFFFF;
}
if (cmdIndex == SD_CMD_SELECT_DESELECT_CARD) {
resp->data.r7.rca = rca;
}
if (cmdIndex == SD_CMD_IO_RW_DIRECT) {
if (((rsp0 >> 16) & 0xffff) != 0)
result = SD_CMD_ERR_INVALID_RESPONSE;
resp->data.r5.data = rsp0 & 0xff;
}
if (cmdIndex == SD_CMD_IO_RW_EXTENDED) {
if (((rsp0 >> 16) & 0xffff) != 0)
result = SD_CMD_ERR_INVALID_RESPONSE;
resp->data.r5.data = rsp0 & 0xff;
}
if (cmdIndex == SD_ACMD_SD_SEND_OP_COND ||
cmdIndex == SD_CMD_SEND_OPCOND)
resp->data.r3.ocr = cardStatus;
if (cmdIndex == SD_CMD_SEND_CSD ||
cmdIndex == SD_CMD_SEND_CID ||
cmdIndex == SD_CMD_ALL_SEND_CID) {
resp->data.r2.rsp4 = rsp3;
resp->data.r2.rsp3 = rsp2;
resp->data.r2.rsp2 = rsp1;
resp->data.r2.rsp1 = rsp0;
}
if ((cmdIndex == SD_CMD_READ_EXT_CSD) &&
(handle->card->type == SD_CARD_SD)) {
if ((resp->cardStatus & 0xAA) != 0xAA) {
result = SD_CMD_ERR_INVALID_RESPONSE;
}
}
return result;
}
/*
* The function sets DMA buffer and data length, process
* block size and the number of blocks to be transferred.
* It returns the DMA buffer address.
* It copies dma data from user buffer to the DMA buffer
* if the operation is to write data to the SD card.
*/
void data_xfer_setup(struct sd_handle *handle, uint8_t *data, uint32_t length,
int dir)
{
chal_sd_setup_xfer((CHAL_HANDLE *)handle->device, data, length, dir);
}
/*
* The function does soft reset the host SD controller. After
* the function call all host controller's register are reset
* to default vallue;
*
* Note This function only resets the host controller it does not
* reset the controller's handler.
*/
int reset_host_ctrl(struct sd_handle *handle)
{
chal_sd_stop();
return SD_OK;
}
static void pstate_log(struct sd_handle *handle)
{
ERROR("PSTATE: 0x%x\n", mmio_read_32
(handle->device->ctrl.sdRegBaseAddr +
SD4_EMMC_TOP_PSTATE_SD4_OFFSET));
ERROR("ERRSTAT: 0x%x\n", mmio_read_32
(handle->device->ctrl.sdRegBaseAddr +
SD4_EMMC_TOP_ERRSTAT_OFFSET));
}
/*
* The function waits for one or a group of interrupts specified
* by mask. The function returns if any one the interrupt status
* is set. If interrupt mode is not enabled then it will poll
* the interrupt status register until a interrupt status is set
* an error interrupt happens. If interrupt mode is enabled then
* this function should be called after the interrupt
* is received by ISR routine.
*/
uint32_t wait_for_event(struct sd_handle *handle,
uint32_t mask, uint32_t retry)
{
uint32_t regval, cmd12, time = 0;
handle->device->ctrl.cmdStatus = 0; /* no error */
EMMC_TRACE("%s %d mask:0x%x timeout:%d irq_status:0x%x\n",
__func__, __LINE__, mask, retry,
chal_sd_get_irq_status((CHAL_HANDLE *)handle->device));
/* Polling mode */
do {
regval = chal_sd_get_irq_status((CHAL_HANDLE *)handle->device);
if (regval & SD4_EMMC_TOP_INTR_DMAIRQ_MASK) {
chal_sd_set_dma_addr((CHAL_HANDLE *)handle->device,
(uintptr_t)
chal_sd_get_dma_addr((CHAL_HANDLE *)
handle->device));
chal_sd_clear_irq((CHAL_HANDLE *)handle->device,
SD4_EMMC_TOP_INTR_DMAIRQ_MASK);
}
if (time++ > retry) {
ERROR("EMMC: No response (cmd%d) after %dus.\n",
handle->device->ctrl.cmdIndex,
time * EMMC_WFE_RETRY_DELAY_US);
handle->device->ctrl.cmdStatus = SD_CMD_MISSING;
pstate_log(handle);
ERROR("EMMC: INT[0x%x]\n", regval);
break;
}
if (regval & SD4_EMMC_TOP_INTR_CTOERR_MASK) {
ERROR("EMMC: Cmd%d timeout INT[0x%x]\n",
handle->device->ctrl.cmdIndex, regval);
handle->device->ctrl.cmdStatus =
SD4_EMMC_TOP_INTR_CTOERR_MASK;
pstate_log(handle);
break;
}
if (regval & SD_CMD_ERROR_FLAGS) {
ERROR("EMMC: Cmd%d error INT[0x%x]\n",
handle->device->ctrl.cmdIndex, regval);
handle->device->ctrl.cmdStatus = SD_CMD_ERROR_FLAGS;
pstate_log(handle);
break;
}
cmd12 = chal_sd_get_atuo12_error((CHAL_HANDLE *)handle->device);
if (cmd12) {
ERROR("EMMC: Cmd%d auto cmd12 err:0x%x\n",
handle->device->ctrl.cmdIndex, cmd12);
handle->device->ctrl.cmdStatus = cmd12;
pstate_log(handle);
break;
}
if (SD_DATA_ERROR_FLAGS & regval) {
ERROR("EMMC: Data for cmd%d error, INT[0x%x]\n",
handle->device->ctrl.cmdIndex, regval);
handle->device->ctrl.cmdStatus =
(SD_DATA_ERROR_FLAGS & regval);
pstate_log(handle);
break;
}
if ((regval & mask) == 0)
udelay(EMMC_WFE_RETRY_DELAY_US);
} while ((regval & mask) == 0);
/* clear the interrupt since it is processed */
chal_sd_clear_irq((CHAL_HANDLE *)handle->device, (regval & mask));
return (regval & mask);
}
int32_t set_config(struct sd_handle *handle, uint32_t speed, uint32_t retry,
uint32_t dma, uint32_t dmaBound, uint32_t blkSize,
uint32_t wfe_retry)
{
int32_t rel = 0;
if (handle == NULL)
return SD_FAIL;
handle->device->cfg.wfe_retry = wfe_retry;
rel = chal_sd_config((CHAL_HANDLE *)handle->device, speed, retry,
dmaBound, blkSize, dma);
return rel;
}
int mmc_cmd1(struct sd_handle *handle)
{
uint32_t newOcr, res;
uint32_t cmd1_option = MMC_OCR_OP_VOLT | MMC_OCR_SECTOR_ACCESS_MODE;
/*
* After Reset, eMMC comes up in 1 Bit Data Width by default.
* Set host side to match.
*/
chal_sd_config_bus_width((CHAL_HANDLE *) handle->device,
SD_BUS_DATA_WIDTH_1BIT);
#ifdef USE_EMMC_FIP_TOC_CACHE
cached_partition_block = 0;
#endif
handle->device->ctrl.present = 0; /* init card present to be no card */
handle->card->type = SD_CARD_MMC;
res = sd_cmd1(handle, cmd1_option, &newOcr);
if (res != SD_OK) {
EMMC_TRACE("CMD1 Timeout: Device is not ready\n");
res = SD_CARD_UNKNOWN;
}
return res;
}
/*
* Copyright (c) 2016 - 2020, Broadcom
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdlib.h>
#include <stddef.h>
#include "bcm_emmc.h"
#include "emmc_chal_types.h"
#include "emmc_chal_sd.h"
#include "emmc_csl_sdprot.h"
#include "emmc_csl_sdcmd.h"
#include "emmc_csl_sd.h"
#include "emmc_chal_sd.h"
#include "emmc_pboot_hal_memory_drv.h"
int sd_cmd0(struct sd_handle *handle)
{
int res;
uint32_t argument = 0x0; /* Go to IDLE state. */
/* send cmd and parse result */
res = send_cmd(handle, SD_CMD_GO_IDLE_STATE, argument, 0, NULL);
if (res == SD_OK) {
/* Clear all other interrupts */
chal_sd_clear_irq((void *)handle->device, 0xffffffff);
}
return res;
}
int sd_cmd1(struct sd_handle *handle, uint32_t ocr, uint32_t *ocr_output)
{
int res;
uint32_t options;
struct sd_resp resp;
options = SD_CMDR_RSP_TYPE_R3_4 << SD_CMDR_RSP_TYPE_S;
if (ocr_output == NULL) {
EMMC_TRACE("Invalid args\n");
return SD_FAIL;
}
/* send cmd and parse result */
res = send_cmd(handle, SD_CMD_SEND_OPCOND, ocr, options, &resp);
if (res == SD_OK)
*ocr_output = resp.data.r3.ocr;
return res;
}
int sd_cmd2(struct sd_handle *handle)
{
uint32_t options;
struct sd_resp resp;
/* send cmd and parse result */
options = SD_CMDR_RSP_TYPE_R2 << SD_CMDR_RSP_TYPE_S;
return send_cmd(handle, SD_CMD_ALL_SEND_CID, 0, options, &resp);
}
int sd_cmd3(struct sd_handle *handle)
{
int res;
uint32_t options = 0;
uint32_t argument;
struct sd_resp resp;
/* use non zero and non 0x1 value for rca */
handle->device->ctrl.rca = 0x5;
argument = handle->device->ctrl.rca << SD_CMD7_ARG_RCA_SHIFT;
options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S |
SD4_EMMC_TOP_CMD_CCHK_EN_MASK |
SD4_EMMC_TOP_CMD_CRC_EN_MASK;
/* send cmd and parse result */
res = send_cmd(handle, SD_CMD_MMC_SET_RCA, argument, options, &resp);
if (res != SD_OK)
handle->device->ctrl.rca = 0;
return res;
}
int sd_cmd7(struct sd_handle *handle, uint32_t rca)
{
int res;
uint32_t argument, options;
struct sd_resp resp;
argument = (rca << SD_CMD7_ARG_RCA_SHIFT);
/*
* Response to CMD7 is:
* R1 while selectiing from Stand-By State to Transfer State
* R1b while selecting from Disconnected State to Programming State.
*
* In this driver, we only issue a CMD7 once, to go to transfer mode
* during init_mmc_card().
*/
options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S |
SD4_EMMC_TOP_CMD_CCHK_EN_MASK |
SD4_EMMC_TOP_CMD_CRC_EN_MASK;
/* send cmd and parse result */
res = send_cmd(handle, SD_CMD_SELECT_DESELECT_CARD, argument, options,
&resp);
if (res == SD_OK)
/* Clear all other interrupts */
chal_sd_clear_irq((void *)handle->device, 0xffffffff);
return res;
}
/*
* CMD8 Get CSD_EXT
*/
int mmc_cmd8(struct sd_handle *handle, uint8_t *extCsdReg)
{
uint32_t res, options;
struct sd_resp resp;
data_xfer_setup(handle, extCsdReg, CEATA_EXT_CSDBLOCK_SIZE,
SD_XFER_CARD_TO_HOST);
options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S |
SD4_EMMC_TOP_CMD_DPS_MASK | SD4_EMMC_TOP_CMD_DTDS_MASK |
SD4_EMMC_TOP_CMD_CCHK_EN_MASK | SD4_EMMC_TOP_CMD_CRC_EN_MASK;
/* send cmd and parse result */
res = send_cmd(handle, SD_CMD_READ_EXT_CSD, 0, options, &resp);
if (res == SD_OK)
res = process_data_xfer(handle, extCsdReg, 0,
CEATA_EXT_CSDBLOCK_SIZE,
SD_XFER_CARD_TO_HOST);
return res;
}
int sd_cmd9(struct sd_handle *handle, struct sd_card_data *card)
{
int res;
uint32_t argument, options, iBlkNum, multiFactor = 1;
uint32_t maxReadBlockLen = 1, maxWriteBlockLen = 1;
struct sd_resp resp;
argument = handle->device->ctrl.rca << SD_CMD7_ARG_RCA_SHIFT;
options = SD_CMDR_RSP_TYPE_R2 << SD_CMDR_RSP_TYPE_S |
SD4_EMMC_TOP_CMD_CRC_EN_MASK;
/* send cmd and parse result */
res = send_cmd(handle, SD_CMD_SEND_CSD, argument, options, &resp);
if (res != SD_OK)
return res;
if (handle->card->type == SD_CARD_MMC) {
card->csd.mmc.structure = (resp.data.r2.rsp4 >> 22) & 0x3;
card->csd.mmc.csdSpecVer = (resp.data.r2.rsp4 >> 18) & 0x0f;
card->csd.mmc.taac = (resp.data.r2.rsp4 >> 8) & 0xff;
card->csd.mmc.nsac = resp.data.r2.rsp4 & 0xff;
card->csd.mmc.speed = resp.data.r2.rsp3 >> 24;
card->csd.mmc.classes = (resp.data.r2.rsp3 >> 12) & 0xfff;
card->csd.mmc.rdBlkLen = (resp.data.r2.rsp3 >> 8) & 0xf;
card->csd.mmc.rdBlkPartial = (resp.data.r2.rsp3 >> 7) & 0x01;
card->csd.mmc.wrBlkMisalign = (resp.data.r2.rsp3 >> 6) & 0x1;
card->csd.mmc.rdBlkMisalign = (resp.data.r2.rsp3 >> 5) & 0x1;
card->csd.mmc.dsr = (resp.data.r2.rsp2 >> 4) & 0x01;
card->csd.mmc.size =
((resp.data.r2.rsp3 & 0x3) << 10) +
((resp.data.r2.rsp2 >> 22) & 0x3ff);
card->csd.mmc.vddRdCurrMin = (resp.data.r2.rsp2 >> 19) & 0x7;
card->csd.mmc.vddRdCurrMax = (resp.data.r2.rsp2 >> 16) & 0x7;
card->csd.mmc.vddWrCurrMin = (resp.data.r2.rsp2 >> 13) & 0x7;
card->csd.mmc.vddWrCurrMax = (resp.data.r2.rsp2 >> 10) & 0x7;
card->csd.mmc.devSizeMulti = (resp.data.r2.rsp2 >> 7) & 0x7;
card->csd.mmc.eraseGrpSize = (resp.data.r2.rsp2 >> 2) & 0x1f;
card->csd.mmc.eraseGrpSizeMulti =
((resp.data.r2.rsp2 & 0x3) << 3) +
((resp.data.r2.rsp1 >> 29) & 0x7);
card->csd.mmc.wrProtGroupSize =
((resp.data.r2.rsp1 >> 24) & 0x1f);
card->csd.mmc.wrProtGroupEnable =
(resp.data.r2.rsp1 >> 23) & 0x1;
card->csd.mmc.manuDefEcc = (resp.data.r2.rsp1 >> 21) & 0x3;
card->csd.mmc.wrSpeedFactor = (resp.data.r2.rsp1 >> 18) & 0x7;
card->csd.mmc.wrBlkLen = (resp.data.r2.rsp1 >> 14) & 0xf;
card->csd.mmc.wrBlkPartial = (resp.data.r2.rsp1 >> 13) & 0x1;
card->csd.mmc.protAppl = (resp.data.r2.rsp1 >> 8) & 0x1;
card->csd.mmc.copyFlag = (resp.data.r2.rsp1 >> 7) & 0x1;
card->csd.mmc.permWrProt = (resp.data.r2.rsp1 >> 6) & 0x1;
card->csd.mmc.tmpWrProt = (resp.data.r2.rsp1 >> 5) & 0x1;
card->csd.mmc.fileFormat = (resp.data.r2.rsp1 >> 4) & 0x03;
card->csd.mmc.eccCode = resp.data.r2.rsp1 & 0x03;
maxReadBlockLen <<= card->csd.mmc.rdBlkLen;
maxWriteBlockLen <<= card->csd.mmc.wrBlkLen;
iBlkNum = card->csd.mmc.size + 1;
multiFactor = (1 << (card->csd.mmc.devSizeMulti + 2));
handle->card->size =
iBlkNum * multiFactor * (1 << card->csd.mmc.rdBlkLen);
}
handle->card->maxRdBlkLen = maxReadBlockLen;
handle->card->maxWtBlkLen = maxWriteBlockLen;
if (handle->card->size < 0xA00000) {
/*
* 10MB Too small size mean, cmd9 response is wrong,
* Use default value 1G
*/
handle->card->size = 0x40000000;
handle->card->maxRdBlkLen = 512;
handle->card->maxWtBlkLen = 512;
}
if ((handle->card->maxRdBlkLen > 512) ||
(handle->card->maxWtBlkLen > 512)) {
handle->card->maxRdBlkLen = 512;
handle->card->maxWtBlkLen = 512;
} else if ((handle->card->maxRdBlkLen == 0) ||
(handle->card->maxWtBlkLen == 0)) {
handle->card->maxRdBlkLen = 512;
handle->card->maxWtBlkLen = 512;
}
handle->device->cfg.blockSize = handle->card->maxRdBlkLen;
return res;
}
int sd_cmd13(struct sd_handle *handle, uint32_t *status)
{
int res;
uint32_t argument, options;
struct sd_resp resp;
argument = handle->device->ctrl.rca << SD_CMD7_ARG_RCA_SHIFT;
options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S |
SD4_EMMC_TOP_CMD_CCHK_EN_MASK |
SD4_EMMC_TOP_CMD_CRC_EN_MASK;
/* send cmd and parse result */
res = send_cmd(handle, SD_CMD_SEND_STATUS, argument, options, &resp);
if (res == SD_OK) {
*status = resp.cardStatus;
}
return res;
}
int sd_cmd16(struct sd_handle *handle, uint32_t length)
{
int res;
uint32_t argument, options, ntry;
struct sd_resp resp;
argument = length;
options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S |
SD4_EMMC_TOP_CMD_CRC_EN_MASK |
SD4_EMMC_TOP_CMD_CCHK_EN_MASK;
ntry = 0;
do {
res = sd_cmd13(handle, &resp.cardStatus);
if (res != SD_OK) {
EMMC_TRACE(
"cmd13 failed before cmd16: rca 0x%0x, return %d, response 0x%0x\n",
handle->device->ctrl.rca, res, resp.cardStatus);
return res;
}
if (resp.cardStatus & 0x100)
break;
EMMC_TRACE("cmd13 rsp:0x%08x before cmd16\n", resp.cardStatus);
if (ntry > handle->device->cfg.retryLimit) {
EMMC_TRACE("cmd13 retry reach limit %d\n",
handle->device->cfg.retryLimit);
return SD_CMD_TIMEOUT;
}
ntry++;
EMMC_TRACE("cmd13 retry %d\n", ntry);
SD_US_DELAY(1000);
} while (1);
/* send cmd and parse result */
res = send_cmd(handle, SD_CMD_SET_BLOCKLEN, argument, options, &resp);
return res;
}
int sd_cmd17(struct sd_handle *handle,
uint32_t addr, uint32_t len, uint8_t *buffer)
{
int res;
uint32_t argument, options, ntry;
struct sd_resp resp;
ntry = 0;
do {
res = sd_cmd13(handle, &resp.cardStatus);
if (res != SD_OK) {
EMMC_TRACE(
"cmd 13 failed before cmd17: rca 0x%0x, return %d, response 0x%0x\n",
handle->device->ctrl.rca, res, resp.cardStatus);
return res;
}
if (resp.cardStatus & 0x100)
break;
EMMC_TRACE("cmd13 rsp:0x%08x before cmd17\n", resp.cardStatus);
if (ntry > handle->device->cfg.retryLimit) {
EMMC_TRACE("cmd13 retry reach limit %d\n",
handle->device->cfg.retryLimit);
return SD_CMD_TIMEOUT;
}
ntry++;
EMMC_TRACE("cmd13 retry %d\n", ntry);
SD_US_DELAY(1000);
} while (1);
data_xfer_setup(handle, buffer, len, SD_XFER_CARD_TO_HOST);
/* send cmd and parse result */
argument = addr;
options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S |
SD4_EMMC_TOP_CMD_DPS_MASK | SD4_EMMC_TOP_CMD_DTDS_MASK |
SD4_EMMC_TOP_CMD_CRC_EN_MASK | SD4_EMMC_TOP_CMD_CCHK_EN_MASK;
res = send_cmd(handle, SD_CMD_READ_SINGLE_BLOCK, argument, options,
&resp);
if (res != SD_OK)
return res;
res = process_data_xfer(handle, buffer, addr, len, SD_XFER_CARD_TO_HOST);
return res;
}
int sd_cmd18(struct sd_handle *handle,
uint32_t addr, uint32_t len, uint8_t *buffer)
{
int res;
uint32_t argument, options, ntry;
struct sd_resp resp;
ntry = 0;
do {
res = sd_cmd13(handle, &resp.cardStatus);
if (res != SD_OK) {
EMMC_TRACE(
"cmd 13 failed before cmd18: rca 0x%0x, return %d, response 0x%0x\n",
handle->device->ctrl.rca, res, resp.cardStatus);
return res;
}
if (resp.cardStatus & 0x100)
break;
EMMC_TRACE("cmd13 rsp:0x%08x before cmd18\n", resp.cardStatus);
if (ntry > handle->device->cfg.retryLimit) {
EMMC_TRACE("cmd13 retry reach limit %d\n",
handle->device->cfg.retryLimit);
return SD_CMD_TIMEOUT;
}
ntry++;
EMMC_TRACE("cmd13 retry %d\n", ntry);
SD_US_DELAY(1000);
} while (1);
data_xfer_setup(handle, buffer, len, SD_XFER_CARD_TO_HOST);
argument = addr;
options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S |
SD4_EMMC_TOP_CMD_DPS_MASK | SD4_EMMC_TOP_CMD_DTDS_MASK |
SD4_EMMC_TOP_CMD_MSBS_MASK | SD4_EMMC_TOP_CMD_CCHK_EN_MASK |
SD4_EMMC_TOP_CMD_BCEN_MASK | SD4_EMMC_TOP_CMD_CRC_EN_MASK |
BIT(SD4_EMMC_TOP_CMD_ACMDEN_SHIFT);
/* send cmd and parse result */
res = send_cmd(handle, SD_CMD_READ_MULTIPLE_BLOCK, argument, options,
&resp);
if (res != SD_OK)
return res;
res = process_data_xfer(handle, buffer, addr, len, SD_XFER_CARD_TO_HOST);
return res;
}
#ifdef INCLUDE_EMMC_DRIVER_ERASE_CODE
static int card_sts_resp(struct sd_handle *handle, uint32_t *status)
{
int res;
uint32_t ntry = 0;
do {
res = sd_cmd13(handle, status);
if (res != SD_OK) {
EMMC_TRACE(
"cmd 13 failed before cmd35: rca 0x%0x, return %d\n",
handle->device->ctrl.rca, res);
return res;
}
if (*status & 0x100)
break;
EMMC_TRACE("cmd13 rsp:0x%08x before cmd35\n", resp.cardStatus);
if (ntry > handle->device->cfg.retryLimit) {
EMMC_TRACE("cmd13 retry reach limit %d\n",
handle->device->cfg.retryLimit);
return SD_CMD_TIMEOUT;
}
ntry++;
EMMC_TRACE("cmd13 retry %d\n", ntry);
SD_US_DELAY(1000);
} while (1);
return SD_OK;
}
int sd_cmd35(struct sd_handle *handle, uint32_t start)
{
int res;
uint32_t argument, options;
struct sd_resp resp;
res = card_sts_resp(handle, &resp.cardStatus);
if (res != SD_OK)
return res;
argument = start;
options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S |
SD4_EMMC_TOP_CMD_CRC_EN_MASK |
SD4_EMMC_TOP_CMD_CCHK_EN_MASK;
/* send cmd and parse result */
res = send_cmd(handle, SD_CMD_ERASE_GROUP_START,
argument, options, &resp);
if (res != SD_OK)
return res;
return res;
}
int sd_cmd36(struct sd_handle *handle, uint32_t end)
{
int res;
uint32_t argument, options;
struct sd_resp resp;
res = card_sts_resp(handle, &resp.cardStatus);
if (res != SD_OK)
return res;
argument = end;
options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S |
SD4_EMMC_TOP_CMD_CRC_EN_MASK |
SD4_EMMC_TOP_CMD_CCHK_EN_MASK;
/* send cmd and parse result */
res = send_cmd(handle, SD_CMD_ERASE_GROUP_END,
argument, options, &resp);
if (res != SD_OK)
return res;
return res;
}
int sd_cmd38(struct sd_handle *handle)
{
int res;
uint32_t argument, options;
struct sd_resp resp;
res = card_sts_resp(handle, &resp.cardStatus);
if (res != SD_OK)
return res;
argument = 0;
options = (SD_CMDR_RSP_TYPE_R1b_5b << SD_CMDR_RSP_TYPE_S) |
SD4_EMMC_TOP_CMD_CRC_EN_MASK |
SD4_EMMC_TOP_CMD_CCHK_EN_MASK;
/* send cmd and parse result */
res = send_cmd(handle, SD_CMD_ERASE, argument, options, &resp);
if (res != SD_OK)
return res;
return res;
}
#endif
#ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE
int sd_cmd24(struct sd_handle *handle,
uint32_t addr, uint32_t len, uint8_t *buffer)
{
int res;
uint32_t argument, options, ntry;
struct sd_resp resp;
ntry = 0;
do {
res = sd_cmd13(handle, &resp.cardStatus);
if (res != SD_OK) {
EMMC_TRACE(
"cmd 13 failed before cmd24: rca 0x%0x, return %d, response 0x%0x\n",
handle->device->ctrl.rca, res, &resp.cardStatus);
return res;
}
if (resp.cardStatus & 0x100)
break;
EMMC_TRACE("cmd13 rsp:0x%08x before cmd24\n", resp.cardStatus);
if (ntry > handle->device->cfg.retryLimit) {
EMMC_TRACE("cmd13 retry reach limit %d\n",
handle->device->cfg.retryLimit);
return SD_CMD_TIMEOUT;
}
ntry++;
EMMC_TRACE("cmd13 retry %d\n", ntry);
SD_US_DELAY(1000);
} while (1);
data_xfer_setup(handle, buffer, len, SD_XFER_HOST_TO_CARD);
argument = addr;
options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S |
SD4_EMMC_TOP_CMD_DPS_MASK | SD4_EMMC_TOP_CMD_CRC_EN_MASK |
SD4_EMMC_TOP_CMD_CCHK_EN_MASK;
/* send cmd and parse result */
res = send_cmd(handle, SD_CMD_WRITE_BLOCK, argument, options, &resp);
if (res != SD_OK)
return res;
res = process_data_xfer(handle, buffer, addr, len, SD_XFER_HOST_TO_CARD);
return res;
}
int sd_cmd25(struct sd_handle *handle,
uint32_t addr, uint32_t len, uint8_t *buffer)
{
int res = SD_OK;
uint32_t argument, options, ntry;
struct sd_resp resp;
ntry = 0;
do {
res = sd_cmd13(handle, &resp.cardStatus);
if (res != SD_OK) {
EMMC_TRACE(
"cmd 13 failed before cmd25: rca 0x%0x, return %d, response 0x%0x\n",
handle->device->ctrl.rca, res, &resp.cardStatus);
return res;
}
if (resp.cardStatus & 0x100)
break;
EMMC_TRACE("cmd13 rsp:0x%08x before cmd25\n", resp.cardStatus);
if (ntry > handle->device->cfg.retryLimit) {
EMMC_TRACE("cmd13 retry reach limit %d\n",
handle->device->cfg.retryLimit);
return SD_CMD_TIMEOUT;
}
ntry++;
EMMC_TRACE("cmd13 retry %d\n", ntry);
SD_US_DELAY(1000);
} while (1);
data_xfer_setup(handle, buffer, len, SD_XFER_HOST_TO_CARD);
argument = addr;
options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S |
SD4_EMMC_TOP_CMD_DPS_MASK | SD4_EMMC_TOP_CMD_MSBS_MASK |
SD4_EMMC_TOP_CMD_CCHK_EN_MASK | SD4_EMMC_TOP_CMD_BCEN_MASK |
SD4_EMMC_TOP_CMD_CRC_EN_MASK |
BIT(SD4_EMMC_TOP_CMD_ACMDEN_SHIFT);
/* send cmd and parse result */
res = send_cmd(handle, SD_CMD_WRITE_MULTIPLE_BLOCK,
argument, options, &resp);
if (res != SD_OK)
return res;
res = process_data_xfer(handle, buffer, addr, len, SD_XFER_HOST_TO_CARD);
return res;
}
#endif /* INCLUDE_EMMC_DRIVER_WRITE_CODE */
int mmc_cmd6(struct sd_handle *handle, uint32_t argument)
{
int res;
uint32_t options;
struct sd_resp resp;
options = SD_CMDR_RSP_TYPE_R1b_5b << SD_CMDR_RSP_TYPE_S |
SD4_EMMC_TOP_CMD_CCHK_EN_MASK | SD4_EMMC_TOP_CMD_CRC_EN_MASK;
EMMC_TRACE("Sending CMD6 with argument 0x%X\n", argument);
/* send cmd and parse result */
res = send_cmd(handle, SD_ACMD_SET_BUS_WIDTH, argument, options, &resp);
/*
* For R1b type response:
* controller issues a COMMAND COMPLETE interrupt when the R1
* response is received,
* then controller monitors DAT0 for busy status,
* controller issues a TRANSFER COMPLETE interrupt when busy signal
* clears.
*/
wait_for_event(handle,
SD4_EMMC_TOP_INTR_TXDONE_MASK | SD_ERR_INTERRUPTS,
handle->device->cfg.wfe_retry);
if (res == SD_OK) {
/* Check result of Cmd6 using Cmd13 to check card status */
/* Check status using Cmd13 */
res = sd_cmd13(handle, &resp.cardStatus);
if (res == SD_OK) {
/* Check bit 7 (SWITCH_ERROR) in card status */
if ((resp.cardStatus & 0x80) != 0) {
EMMC_TRACE("cmd6 failed: SWITCH_ERROR\n");
res = SD_FAIL;
}
} else {
EMMC_TRACE("cmd13 failed after cmd6: ");
EMMC_TRACE("rca 0x%0x, return %d, response 0x%0x\n",
handle->device->ctrl.rca, res, resp.cardStatus);
}
}
return res;
}
#define SD_BUSY_CHECK 0x00203000
#define DAT0_LEVEL_MASK 0x100000 /* bit20 in PSTATE */
#define DEV_BUSY_TIMEOUT 600000 /* 60 Sec : 600000 * 100us */
int send_cmd(struct sd_handle *handle, uint32_t cmdIndex, uint32_t argument,
uint32_t options, struct sd_resp *resp)
{
int status = SD_OK;
uint32_t event = 0, present, timeout = 0, retry = 0, mask = 3;
uint32_t temp_resp[4];
if (handle == NULL) {
EMMC_TRACE("Invalid handle for cmd%d\n", cmdIndex);
return SD_INVALID_HANDLE;
}
mask = (SD_BUSY_CHECK & options) ? 3 : 1;
RETRY_WRITE_CMD:
do {
/* Make sure it is ok to send command */
present =
chal_sd_get_present_status((CHAL_HANDLE *) handle->device);
timeout++;
if (present & mask)
SD_US_DELAY(1000);
else
break;
} while (timeout < EMMC_BUSY_CMD_TIMEOUT_MS);
if (timeout >= EMMC_BUSY_CMD_TIMEOUT_MS) {
status = SD_CMD_MISSING;
EMMC_TRACE("cmd%d timedout %dms\n", cmdIndex, timeout);
}
/* Reset both DAT and CMD line if only of them are stuck */
if (present & mask)
check_error(handle, SD4_EMMC_TOP_INTR_CMDERROR_MASK);
handle->device->ctrl.argReg = argument;
chal_sd_send_cmd((CHAL_HANDLE *) handle->device, cmdIndex,
handle->device->ctrl.argReg, options);
handle->device->ctrl.cmdIndex = cmdIndex;
event = wait_for_event(handle,
(SD4_EMMC_TOP_INTR_CMDDONE_MASK |
SD_ERR_INTERRUPTS),
handle->device->cfg.wfe_retry);
if (handle->device->ctrl.cmdStatus == SD_CMD_MISSING) {
retry++;
if (retry >= handle->device->cfg.retryLimit) {
status = SD_CMD_MISSING;
EMMC_TRACE("cmd%d retry reaches the limit %d\n",
cmdIndex, retry);
} else {
/* reset both DAT & CMD line if one of them is stuck */
present = chal_sd_get_present_status((CHAL_HANDLE *)
handle->device);
if (present & mask)
check_error(handle,
SD4_EMMC_TOP_INTR_CMDERROR_MASK);
EMMC_TRACE("cmd%d retry %d PSTATE[0x%08x]\n",
cmdIndex, retry,
chal_sd_get_present_status((CHAL_HANDLE *)
handle->device));
goto RETRY_WRITE_CMD;
}
}
if (handle->device->ctrl.cmdStatus == SD_OK) {
if (resp != NULL) {
status =
chal_sd_get_response((CHAL_HANDLE *) handle->device,
temp_resp);
process_cmd_response(handle,
handle->device->ctrl.cmdIndex,
temp_resp[0], temp_resp[1],
temp_resp[2], temp_resp[3], resp);
}
/* Check Device busy after CMD */
if ((cmdIndex == 5) || (cmdIndex == 6) || (cmdIndex == 7) ||
(cmdIndex == 28) || (cmdIndex == 29) || (cmdIndex == 38)) {
timeout = 0;
do {
present =
chal_sd_get_present_status((CHAL_HANDLE *)
handle->device);
timeout++;
/* Dat[0]:bit20 low means device busy */
if ((present & DAT0_LEVEL_MASK) == 0) {
EMMC_TRACE("Device busy: ");
EMMC_TRACE(
"cmd%d arg:0x%08x: PSTATE[0x%08x]\n",
cmdIndex, argument, present);
SD_US_DELAY(100);
} else {
break;
}
} while (timeout < DEV_BUSY_TIMEOUT);
}
} else if (handle->device->ctrl.cmdStatus &&
handle->device->ctrl.cmdStatus != SD_CMD_MISSING) {
retry++;
status = check_error(handle, handle->device->ctrl.cmdStatus);
EMMC_TRACE(
"cmd%d error: cmdStatus:0x%08x error_status:0x%08x\n",
cmdIndex, handle->device->ctrl.cmdStatus, status);
if ((handle->device->ctrl.cmdIndex == 1) ||
(handle->device->ctrl.cmdIndex == 5)) {
status = event;
} else if ((handle->device->ctrl.cmdIndex == 7) ||
(handle->device->ctrl.cmdIndex == 41)) {
status = event;
} else if ((status == SD_ERROR_RECOVERABLE) &&
(retry < handle->device->cfg.retryLimit)) {
EMMC_TRACE("cmd%d recoverable error ", cmdIndex);
EMMC_TRACE("retry %d PSTATE[0x%08x].\n", retry,
chal_sd_get_present_status((CHAL_HANDLE *)
handle->device));
goto RETRY_WRITE_CMD;
} else {
EMMC_TRACE("cmd%d retry reaches the limit %d\n",
cmdIndex, retry);
status = event;
}
}
handle->device->ctrl.blkReg = 0;
/* clear error status for next command */
handle->device->ctrl.cmdStatus = 0;
return status;
}
/*
* Copyright (c) 2016 - 2020, Broadcom
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <string.h>
#include <emmc_api.h>
#include <cmn_plat_util.h>
#define MAX_CMD_RETRY 10
#if EMMC_USE_DMA
#define USE_DMA 1
#else
#define USE_DMA 0
#endif
struct emmc_global_buffer emmc_global_buf;
struct emmc_global_buffer *emmc_global_buf_ptr = &emmc_global_buf;
struct emmc_global_vars emmc_global_vars;
struct emmc_global_vars *emmc_global_vars_ptr = &emmc_global_vars;
static struct sd_handle *sdio_gethandle(void);
static uint32_t sdio_idle(struct sd_handle *p_sdhandle);
static uint32_t sdio_read(struct sd_handle *p_sdhandle,
uintptr_t mem_addr,
uintptr_t storage_addr,
size_t storage_size,
size_t bytes_to_read);
#ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE
static uint32_t sdio_write(struct sd_handle *p_sdhandle,
uintptr_t mem_addr,
uintptr_t data_addr,
size_t bytes_to_write);
#endif
static struct sd_handle *sdio_init(void);
static int32_t bcm_emmc_card_ready_state(struct sd_handle *p_sdhandle);
static void init_globals(void)
{
memset((void *)emmc_global_buf_ptr, 0, sizeof(*emmc_global_buf_ptr));
memset((void *)emmc_global_vars_ptr, 0, sizeof(*emmc_global_vars_ptr));
}
/*
* This function is used to change partition
*/
uint32_t emmc_partition_select(uint32_t partition)
{
int rc;
struct sd_handle *sd_handle = sdio_gethandle();
if (sd_handle->device == 0) {
EMMC_TRACE("eMMC init is not done");
return 0;
}
switch (partition) {
case EMMC_BOOT_PARTITION1:
rc = set_boot_config(sd_handle,
SDIO_HW_EMMC_EXT_CSD_BOOT_ACC_BOOT1);
EMMC_TRACE(
"Change to Boot Partition 1 result:%d (0 means SD_OK)\n",
rc);
break;
case EMMC_BOOT_PARTITION2:
rc = set_boot_config(sd_handle,
SDIO_HW_EMMC_EXT_CSD_BOOT_ACC_BOOT2);
EMMC_TRACE(
"Change to Boot Partition 2 result:%d (0 means SD_OK)\n",
rc);
break;
case EMMC_USE_CURRENT_PARTITION:
rc = SD_OK;
EMMC_TRACE("Stay on current partition");
break;
case EMMC_USER_AREA:
default:
rc = set_boot_config(sd_handle,
SDIO_HW_EMMC_EXT_CSD_BOOT_ACC_USER);
EMMC_TRACE("Change to User area result:%d (0 means SD_OK)\n",
rc);
break;
}
return (rc == SD_OK);
}
/*
* Initialize emmc controller for eMMC
* Returns 0 on fail condition
*/
uint32_t bcm_emmc_init(bool card_rdy_only)
{
struct sd_handle *p_sdhandle;
uint32_t result = 0;
EMMC_TRACE("Enter emmc_controller_init()\n");
/* If eMMC is already initialized, skip init */
if (emmc_global_vars_ptr->init_done)
return 1;
init_globals();
p_sdhandle = sdio_init();
if (p_sdhandle == NULL) {
ERROR("eMMC init failed");
return result;
}
if (card_rdy_only) {
/* Put the card in Ready state, Not complete init */
result = bcm_emmc_card_ready_state(p_sdhandle);
return !result;
}
if (sdio_idle(p_sdhandle) == EMMC_BOOT_OK) {
set_config(p_sdhandle, SD_NORMAL_SPEED, MAX_CMD_RETRY, USE_DMA,
SD_DMA_BOUNDARY_256K, EMMC_BLOCK_SIZE,
EMMC_WFE_RETRY);
if (!select_blk_sz(p_sdhandle,
p_sdhandle->device->cfg.blockSize)) {
emmc_global_vars_ptr->init_done = 1;
result = 1;
} else {
ERROR("Select Block Size failed\n");
}
} else {
ERROR("eMMC init failed");
}
/* Initialization is failed, so deinit HW setting */
if (result == 0)
emmc_deinit();
return result;
}
/*
* Function to de-init SDIO controller for eMMC
*/
void emmc_deinit(void)
{
emmc_global_vars_ptr->init_done = 0;
emmc_global_vars_ptr->sdHandle.card = 0;
emmc_global_vars_ptr->sdHandle.device = 0;
}
/*
* Read eMMC memory
* Returns read_size
*/
uint32_t emmc_read(uintptr_t mem_addr, uintptr_t storage_addr,
size_t storage_size, size_t bytes_to_read)
{
struct sd_handle *sd_handle = sdio_gethandle();
if (sd_handle->device == 0) {
EMMC_TRACE("eMMC init is not done");
return 0;
}
return sdio_read(sdio_gethandle(), mem_addr, storage_addr,
storage_size, bytes_to_read);
}
#ifdef INCLUDE_EMMC_DRIVER_ERASE_CODE
#define EXT_CSD_ERASE_GRP_SIZE 224
static int emmc_block_erase(uintptr_t mem_addr, size_t blocks)
{
struct sd_handle *sd_handle = sdio_gethandle();
if (sd_handle->device == 0) {
ERROR("eMMC init is not done");
return -1;
}
return erase_card(sdio_gethandle(), mem_addr, blocks);
}
int emmc_erase(uintptr_t mem_addr, size_t num_of_blocks, uint32_t partition)
{
int err = 0;
size_t block_count = 0, blocks = 0;
size_t erase_group = 0;
erase_group =
emmc_global_buf_ptr->u.Ext_CSD_storage[EXT_CSD_ERASE_GRP_SIZE]*1024;
INFO("eMMC Erase Group Size=0x%lx\n", erase_group);
emmc_partition_select(partition);
while (block_count < num_of_blocks) {
blocks = ((num_of_blocks - block_count) > erase_group) ?
erase_group : (num_of_blocks - block_count);
err = emmc_block_erase(mem_addr + block_count, blocks);
if (err)
break;
block_count += blocks;
}
if (err == 0)
INFO("eMMC Erase of partition %d successful\n", partition);
else
ERROR("eMMC Erase of partition %d Failed(%i)\n", partition, err);
return err;
}
#endif
#ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE
/*
* Write to eMMC memory
* Returns written_size
*/
uint32_t emmc_write(uintptr_t mem_addr, uintptr_t data_addr,
size_t bytes_to_write)
{
struct sd_handle *sd_handle = sdio_gethandle();
if (sd_handle->device == 0) {
EMMC_TRACE("eMMC init is not done");
return 0;
}
return sdio_write(sd_handle, mem_addr, data_addr, bytes_to_write);
}
#endif
/*
* Send SDIO Cmd
* Return 0 for pass condition
*/
uint32_t send_sdio_cmd(uint32_t cmdIndex, uint32_t argument,
uint32_t options, struct sd_resp *resp)
{
struct sd_handle *sd_handle = sdio_gethandle();
if (sd_handle->device == 0) {
EMMC_TRACE("eMMC init is not done");
return 1;
}
return send_cmd(sd_handle, cmdIndex, argument, options, resp);
}
/*
* This function return SDIO handle
*/
struct sd_handle *sdio_gethandle(void)
{
return &emmc_global_vars_ptr->sdHandle;
}
/*
* Initialize SDIO controller
*/
struct sd_handle *sdio_init(void)
{
uint32_t SDIO_base;
struct sd_handle *p_sdhandle = &emmc_global_vars_ptr->sdHandle;
SDIO_base = EMMC_CTRL_REGS_BASE_ADDR;
if (SDIO_base == SDIO0_EMMCSDXC_SYSADDR)
EMMC_TRACE(" ---> for SDIO 0 Controller\n\n");
memset(p_sdhandle, 0, sizeof(struct sd_handle));
p_sdhandle->device = &emmc_global_vars_ptr->sdDevice;
p_sdhandle->card = &emmc_global_vars_ptr->sdCard;
memset(p_sdhandle->device, 0, sizeof(struct sd_dev));
memset(p_sdhandle->card, 0, sizeof(struct sd_card_info));
if (chal_sd_start((CHAL_HANDLE *) p_sdhandle->device,
SD_PIO_MODE, SDIO_base, SDIO_base) != SD_OK)
return NULL;
set_config(p_sdhandle, SD_NORMAL_SPEED, MAX_CMD_RETRY, SD_DMA_OFF,
SD_DMA_BOUNDARY_4K, EMMC_BLOCK_SIZE, EMMC_WFE_RETRY);
return &emmc_global_vars_ptr->sdHandle;
}
uint32_t sdio_idle(struct sd_handle *p_sdhandle)
{
reset_card(p_sdhandle);
SD_US_DELAY(1000);
if (init_card(p_sdhandle, SD_CARD_DETECT_MMC) != SD_OK) {
reset_card(p_sdhandle);
reset_host_ctrl(p_sdhandle);
return EMMC_BOOT_NO_CARD;
}
return EMMC_BOOT_OK;
}
/*
* This function read eMMC
*/
uint32_t sdio_read(struct sd_handle *p_sdhandle,
uintptr_t mem_addr,
uintptr_t storage_addr,
size_t storage_size, size_t bytes_to_read)
{
uint32_t offset = 0, blockAddr, readLen = 0, rdCount;
uint32_t remSize, manual_copy_size;
uint8_t *outputBuf = (uint8_t *) storage_addr;
const size_t blockSize = p_sdhandle->device->cfg.blockSize;
VERBOSE("EMMC READ: dst=0x%lx, src=0x%lx, size=0x%lx\n",
storage_addr, mem_addr, bytes_to_read);
if (storage_size < bytes_to_read)
/* Don't have sufficient storage to complete the operation */
return 0;
/* Range check non high capacity memory */
if ((p_sdhandle->device->ctrl.ocr & SD_CARD_HIGH_CAPACITY) == 0) {
if (mem_addr > 0x80000000)
return 0;
}
/* High capacity card use block address mode */
if (p_sdhandle->device->ctrl.ocr & SD_CARD_HIGH_CAPACITY) {
blockAddr = (uint32_t) (mem_addr / blockSize);
offset = (uint32_t) (mem_addr - (blockAddr * blockSize));
} else {
blockAddr = (uint32_t) (mem_addr / blockSize) * blockSize;
offset = (uint32_t) (mem_addr - blockAddr);
}
remSize = bytes_to_read;
rdCount = 0;
/* Process first unaligned block of MAX_READ_LENGTH */
if (offset > 0) {
if (!read_block(p_sdhandle, emmc_global_buf_ptr->u.tempbuf,
blockAddr, SD_MAX_READ_LENGTH)) {
if (remSize < (blockSize - offset)) {
rdCount += remSize;
manual_copy_size = remSize;
remSize = 0; /* read is done */
} else {
remSize -= (blockSize - offset);
rdCount += (blockSize - offset);
manual_copy_size = blockSize - offset;
}
/* Check for overflow */
if (manual_copy_size > storage_size ||
(((uintptr_t)outputBuf + manual_copy_size) >
(storage_addr + storage_size))) {
ERROR("EMMC READ: Overflow 1\n");
return 0;
}
memcpy(outputBuf,
(void *)((uintptr_t)
(emmc_global_buf_ptr->u.tempbuf + offset)),
manual_copy_size);
/* Update Physical address */
outputBuf += manual_copy_size;
if (p_sdhandle->device->ctrl.ocr & SD_CARD_HIGH_CAPACITY)
blockAddr++;
else
blockAddr += blockSize;
} else {
return 0;
}
}
while (remSize >= blockSize) {
if (remSize >= SD_MAX_BLK_TRANSFER_LENGTH)
readLen = SD_MAX_BLK_TRANSFER_LENGTH;
else
readLen = (remSize / blockSize) * blockSize;
/* Check for overflow */
if ((rdCount + readLen) > storage_size ||
(((uintptr_t) outputBuf + readLen) >
(storage_addr + storage_size))) {
ERROR("EMMC READ: Overflow\n");
return 0;
}
if (!read_block(p_sdhandle, outputBuf, blockAddr, readLen)) {
if (p_sdhandle->device->ctrl.ocr & SD_CARD_HIGH_CAPACITY)
blockAddr += (readLen / blockSize);
else
blockAddr += readLen;
remSize -= readLen;
rdCount += readLen;
/* Update Physical address */
outputBuf += readLen;
} else {
return 0;
}
}
/* process the last unaligned block reading */
if (remSize > 0) {
if (!read_block(p_sdhandle, emmc_global_buf_ptr->u.tempbuf,
blockAddr, SD_MAX_READ_LENGTH)) {
rdCount += remSize;
/* Check for overflow */
if (rdCount > storage_size ||
(((uintptr_t) outputBuf + remSize) >
(storage_addr + storage_size))) {
ERROR("EMMC READ: Overflow\n");
return 0;
}
memcpy(outputBuf,
emmc_global_buf_ptr->u.tempbuf, remSize);
/* Update Physical address */
outputBuf += remSize;
} else {
rdCount = 0;
}
}
return rdCount;
}
#ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE
static uint32_t sdio_write(struct sd_handle *p_sdhandle, uintptr_t mem_addr,
uintptr_t data_addr, size_t bytes_to_write)
{
uint32_t offset, blockAddr, writeLen, wtCount = 0;
uint32_t remSize, manual_copy_size = 0;
uint8_t *inputBuf = (uint8_t *)data_addr;
/* range check non high capacity memory */
if ((p_sdhandle->device->ctrl.ocr & SD_CARD_HIGH_CAPACITY) == 0) {
if (mem_addr > 0x80000000)
return 0;
}
/* the high capacity card use block address mode */
if (p_sdhandle->device->ctrl.ocr & SD_CARD_HIGH_CAPACITY) {
blockAddr =
(uint32_t)(mem_addr / p_sdhandle->device->cfg.blockSize);
offset =
(uint32_t)(mem_addr -
blockAddr * p_sdhandle->device->cfg.blockSize);
} else {
blockAddr =
((uint32_t)mem_addr / p_sdhandle->device->cfg.blockSize) *
p_sdhandle->device->cfg.blockSize;
offset = (uint32_t) mem_addr - blockAddr;
}
remSize = bytes_to_write;
wtCount = 0;
/* process first unaligned block */
if (offset > 0) {
if (!read_block(p_sdhandle, emmc_global_buf_ptr->u.tempbuf,
blockAddr, p_sdhandle->device->cfg.blockSize)) {
if (remSize <
(p_sdhandle->device->cfg.blockSize - offset))
manual_copy_size = remSize;
else
manual_copy_size =
p_sdhandle->device->cfg.blockSize - offset;
memcpy((void *)((uintptr_t)
(emmc_global_buf_ptr->u.tempbuf + offset)),
inputBuf,
manual_copy_size);
/* Update Physical address */
if (!write_block(p_sdhandle,
emmc_global_buf_ptr->u.tempbuf,
blockAddr,
p_sdhandle->device->cfg.blockSize)) {
if (remSize <
(p_sdhandle->device->cfg.blockSize -
offset)) {
wtCount += remSize;
manual_copy_size = remSize;
remSize = 0; /* read is done */
} else {
remSize -=
(p_sdhandle->device->cfg.blockSize -
offset);
wtCount +=
(p_sdhandle->device->cfg.blockSize -
offset);
manual_copy_size =
p_sdhandle->device->cfg.blockSize -
offset;
}
inputBuf += manual_copy_size;
if (p_sdhandle->device->ctrl.ocr &
SD_CARD_HIGH_CAPACITY)
blockAddr++;
else
blockAddr +=
p_sdhandle->device->cfg.blockSize;
} else
return 0;
} else {
return 0;
}
}
/* process block writing */
while (remSize >= p_sdhandle->device->cfg.blockSize) {
if (remSize >= SD_MAX_READ_LENGTH) {
writeLen = SD_MAX_READ_LENGTH;
} else {
writeLen =
(remSize / p_sdhandle->device->cfg.blockSize) *
p_sdhandle->device->cfg.blockSize;
}
if (!write_block(p_sdhandle, inputBuf, blockAddr, writeLen)) {
if (p_sdhandle->device->ctrl.ocr & SD_CARD_HIGH_CAPACITY)
blockAddr +=
(writeLen /
p_sdhandle->device->cfg.blockSize);
else
blockAddr += writeLen;
remSize -= writeLen;
wtCount += writeLen;
inputBuf += writeLen;
} else {
return 0;
}
}
/* process the last unaligned block reading */
if (remSize > 0) {
if (!read_block(p_sdhandle,
emmc_global_buf_ptr->u.tempbuf,
blockAddr, p_sdhandle->device->cfg.blockSize)) {
memcpy(emmc_global_buf_ptr->u.tempbuf,
inputBuf, remSize);
/* Update Physical address */
if (!write_block(p_sdhandle,
emmc_global_buf_ptr->u.tempbuf,
blockAddr,
p_sdhandle->device->cfg.blockSize)) {
wtCount += remSize;
inputBuf += remSize;
} else {
return 0;
}
} else {
wtCount = 0;
}
}
return wtCount;
}
#endif
/*
* Function to put the card in Ready state by sending CMD0 and CMD1
*/
static int32_t bcm_emmc_card_ready_state(struct sd_handle *p_sdhandle)
{
int32_t result = 0;
uint32_t argument = MMC_CMD_IDLE_RESET_ARG; /* Exit from Boot mode */
if (p_sdhandle) {
send_sdio_cmd(SD_CMD_GO_IDLE_STATE, argument, 0, NULL);
result = reset_card(p_sdhandle);
if (result != SD_OK) {
EMMC_TRACE("eMMC Reset error\n");
return SD_RESET_ERROR;
}
SD_US_DELAY(2000);
result = mmc_cmd1(p_sdhandle);
}
return result;
}
/*
* Copyright (c) 2016 - 2020, Broadcom
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef EMMC_H
#define EMMC_H
#include <stdint.h>
#include <common/debug.h>
#include <platform_def.h>
#include "emmc_chal_types.h"
#include "emmc_chal_sd.h"
#include "emmc_csl_sdprot.h"
#include "emmc_csl_sdcmd.h"
#include "emmc_pboot_hal_memory_drv.h"
/* ------------------------------------------------------------------- */
#define EXT_CSD_SIZE 512
#ifdef PLAT_SD_MAX_READ_LENGTH
#define SD_MAX_READ_LENGTH PLAT_SD_MAX_READ_LENGTH
#ifdef USE_EMMC_LARGE_BLK_TRANSFER_LENGTH
#define SD_MAX_BLK_TRANSFER_LENGTH 0x10000000
#else
#define SD_MAX_BLK_TRANSFER_LENGTH 0x1000
#endif
#else
#define SD_MAX_READ_LENGTH EMMC_BLOCK_SIZE
#define SD_MAX_BLK_TRANSFER_LENGTH EMMC_BLOCK_SIZE
#endif
struct emmc_global_buffer {
union {
uint8_t Ext_CSD_storage[EXT_CSD_SIZE];
uint8_t tempbuf[SD_MAX_READ_LENGTH];
} u;
};
struct emmc_global_vars {
struct sd_card_data cardData;
struct sd_handle sdHandle;
struct sd_dev sdDevice;
struct sd_card_info sdCard;
unsigned int init_done;
};
#define ICFG_SDIO0_CAP0__SLOT_TYPE_R 27
#define ICFG_SDIO0_CAP0__INT_MODE_R 26
#define ICFG_SDIO0_CAP0__SYS_BUS_64BIT_R 25
#define ICFG_SDIO0_CAP0__VOLTAGE_1P8V_R 24
#define ICFG_SDIO0_CAP0__VOLTAGE_3P0V_R 23
#define ICFG_SDIO0_CAP0__VOLTAGE_3P3V_R 22
#define ICFG_SDIO0_CAP0__SUSPEND_RESUME_R 21
#define ICFG_SDIO0_CAP0__SDMA_R 20
#define ICFG_SDIO0_CAP0__HIGH_SPEED_R 19
#define ICFG_SDIO0_CAP0__ADMA2_R 18
#define ICFG_SDIO0_CAP0__EXTENDED_MEDIA_R 17
#define ICFG_SDIO0_CAP0__MAX_BLOCK_LEN_R 15
#define ICFG_SDIO0_CAP0__BASE_CLK_FREQ_R 7
#define ICFG_SDIO0_CAP0__TIMEOUT_UNIT_R 6
#define ICFG_SDIO0_CAP0__TIMEOUT_CLK_FREQ_R 0
#define ICFG_SDIO0_CAP1__SPI_BLOCK_MODE_R 22
#define ICFG_SDIO0_CAP1__SPI_MODE_R 21
#define ICFG_SDIO0_CAP1__CLK_MULT_R 13
#define ICFG_SDIO0_CAP1__RETUNING_MODE_R 11
#define ICFG_SDIO0_CAP1__TUNE_SDR50_R 10
#define ICFG_SDIO0_CAP1__TIME_RETUNE_R 6
#define ICFG_SDIO0_CAP1__DRIVER_D_R 5
#define ICFG_SDIO0_CAP1__DRIVER_C_R 4
#define ICFG_SDIO0_CAP1__DRIVER_A_R 3
#define ICFG_SDIO0_CAP1__DDR50_R 2
#define ICFG_SDIO0_CAP1__SDR104_R 1
#define ICFG_SDIO0_CAP1__SDR50_R 0
#define SDIO0_CTRL_REGS_BASE_ADDR (SDIO0_EMMCSDXC_SYSADDR)
#define SDIO0_IDM_RESET_CTRL_ADDR (SDIO_IDM0_IDM_RESET_CONTROL)
#define EMMC_CTRL_REGS_BASE_ADDR SDIO0_CTRL_REGS_BASE_ADDR
#define EMMC_IDM_RESET_CTRL_ADDR SDIO0_IDM_RESET_CTRL_ADDR
#define EMMC_IDM_IO_CTRL_DIRECT_ADDR SDIO_IDM0_IO_CONTROL_DIRECT
extern struct emmc_global_buffer *emmc_global_buf_ptr;
extern struct emmc_global_vars *emmc_global_vars_ptr;
#define EMMC_CARD_DETECT_TIMEOUT_MS 1200
#define EMMC_CMD_TIMEOUT_MS 200
#define EMMC_BUSY_CMD_TIMEOUT_MS 200
#define EMMC_CLOCK_SETTING_TIMEOUT_MS 100
#define EMMC_WFE_RETRY 40000
#define EMMC_WFE_RETRY_DELAY_US 10
#ifdef EMMC_DEBUG
#define EMMC_TRACE INFO
#else
#define EMMC_TRACE(...)
#endif
#endif /* EMMC_H */
/*
* Copyright (c) 2016 - 2020, Broadcom
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef EMMC_API_H
#define EMMC_API_H
#include "bcm_emmc.h"
#include "emmc_pboot_hal_memory_drv.h"
#ifdef INCLUDE_EMMC_DRIVER_ERASE_CODE
/*
* The erasable unit of the eMMC is the Erase Group
* Erase group is measured in write blocks which
* are the basic writable units of the Device
* EMMC_ERASE_GROUP_SIZE is the number of writeable
* units (each unit is 512 bytes)
*/
/* Start address (sector) */
#define EMMC_ERASE_START_BLOCK 0x0
/* Number of blocks to be erased */
#define EMMC_ERASE_BLOCK_COUNT 0x1
#define EMMC_ERASE_USER_AREA 0
#define EMMC_ERASE_BOOT_PARTITION1 1
#define EMMC_ERASE_BOOT_PARTITION2 2
/* eMMC partition to be erased */
#define EMMC_ERASE_PARTITION EMMC_ERASE_USER_AREA
#endif
uint32_t bcm_emmc_init(bool card_rdy_only);
void emmc_deinit(void);
#ifdef INCLUDE_EMMC_DRIVER_ERASE_CODE
int emmc_erase(uintptr_t mem_addr, size_t num_of_blocks, uint32_t partition);
#endif
uint32_t emmc_partition_select(uint32_t partition);
uint32_t emmc_read(uintptr_t mem_addr, uintptr_t storage_addr,
size_t storage_size, size_t bytes_to_read);
uint32_t emmc_write(uintptr_t mem_addr, uintptr_t data_addr,
size_t bytes_to_write);
#endif /* EMMC_API_H */
/*
* Copyright (c) 2016 - 2020, Broadcom
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef BRCM_RDB_SD4_EMMC_TOP_H
#define BRCM_RDB_SD4_EMMC_TOP_H
#define SD4_EMMC_TOP_SYSADDR_OFFSET 0x00000000
#define SD4_EMMC_TOP_SYSADDR_DEFAULT 0x00000000
#define SD4_EMMC_TOP_SYSADDR_TYPE uint32_t
#define SD4_EMMC_TOP_SYSADDR_RESERVED_MASK 0x00000000
#define SD4_EMMC_TOP_SYSADDR_SYSADDR_SHIFT 0
#define SD4_EMMC_TOP_SYSADDR_SYSADDR_MASK 0xFFFFFFFF
#define SD4_EMMC_TOP_BLOCK_OFFSET 0x00000004
#define SD4_EMMC_TOP_BLOCK_DEFAULT 0x00000000
#define SD4_EMMC_TOP_BLOCK_TYPE uint32_t
#define SD4_EMMC_TOP_BLOCK_RESERVED_MASK 0x00008000
#define SD4_EMMC_TOP_BLOCK_BCNT_SHIFT 16
#define SD4_EMMC_TOP_BLOCK_BCNT_MASK 0xFFFF0000
#define SD4_EMMC_TOP_BLOCK_HSBS_SHIFT 12
#define SD4_EMMC_TOP_BLOCK_HSBS_MASK 0x00007000
#define SD4_EMMC_TOP_BLOCK_TBS_SHIFT 0
#define SD4_EMMC_TOP_BLOCK_TBS_MASK 0x00000FFF
#define SD4_EMMC_TOP_ARG_OFFSET 0x00000008
#define SD4_EMMC_TOP_ARG_DEFAULT 0x00000000
#define SD4_EMMC_TOP_ARG_TYPE uint32_t
#define SD4_EMMC_TOP_ARG_RESERVED_MASK 0x00000000
#define SD4_EMMC_TOP_ARG_ARG_SHIFT 0
#define SD4_EMMC_TOP_ARG_ARG_MASK 0xFFFFFFFF
#define SD4_EMMC_TOP_CMD_OFFSET 0x0000000C
#define SD4_EMMC_TOP_CMD_DEFAULT 0x00000000
#define SD4_EMMC_TOP_CMD_TYPE uint32_t
#define SD4_EMMC_TOP_CMD_RESERVED_MASK 0xC004FFC0
#define SD4_EMMC_TOP_CMD_CIDX_SHIFT 24
#define SD4_EMMC_TOP_CMD_CIDX_MASK 0x3F000000
#define SD4_EMMC_TOP_CMD_CTYP_SHIFT 22
#define SD4_EMMC_TOP_CMD_CTYP_MASK 0x00C00000
#define SD4_EMMC_TOP_CMD_DPS_SHIFT 21
#define SD4_EMMC_TOP_CMD_DPS_MASK 0x00200000
#define SD4_EMMC_TOP_CMD_CCHK_EN_SHIFT 20
#define SD4_EMMC_TOP_CMD_CCHK_EN_MASK 0x00100000
#define SD4_EMMC_TOP_CMD_CRC_EN_SHIFT 19
#define SD4_EMMC_TOP_CMD_CRC_EN_MASK 0x00080000
#define SD4_EMMC_TOP_CMD_RTSEL_SHIFT 16
#define SD4_EMMC_TOP_CMD_RTSEL_MASK 0x00030000
#define SD4_EMMC_TOP_CMD_MSBS_SHIFT 5
#define SD4_EMMC_TOP_CMD_MSBS_MASK 0x00000020
#define SD4_EMMC_TOP_CMD_DTDS_SHIFT 4
#define SD4_EMMC_TOP_CMD_DTDS_MASK 0x00000010
#define SD4_EMMC_TOP_CMD_ACMDEN_SHIFT 2
#define SD4_EMMC_TOP_CMD_ACMDEN_MASK 0x0000000C
#define SD4_EMMC_TOP_CMD_BCEN_SHIFT 1
#define SD4_EMMC_TOP_CMD_BCEN_MASK 0x00000002
#define SD4_EMMC_TOP_CMD_DMA_SHIFT 0
#define SD4_EMMC_TOP_CMD_DMA_MASK 0x00000001
#define SD4_EMMC_TOP_CMD_SD4_OFFSET 0x0000000C
#define SD4_EMMC_TOP_CMD_SD4_DEFAULT 0x00000000
#define SD4_EMMC_TOP_CMD_SD4_TYPE uint32_t
#define SD4_EMMC_TOP_CMD_SD4_RESERVED_MASK 0xC004FE00
#define SD4_EMMC_TOP_CMD_SD4_CIDX_SHIFT 24
#define SD4_EMMC_TOP_CMD_SD4_CIDX_MASK 0x3F000000
#define SD4_EMMC_TOP_CMD_SD4_CTYP_SHIFT 22
#define SD4_EMMC_TOP_CMD_SD4_CTYP_MASK 0x00C00000
#define SD4_EMMC_TOP_CMD_SD4_DPS_SHIFT 21
#define SD4_EMMC_TOP_CMD_SD4_DPS_MASK 0x00200000
#define SD4_EMMC_TOP_CMD_SD4_CCHK_EN_SHIFT 20
#define SD4_EMMC_TOP_CMD_SD4_CCHK_EN_MASK 0x00100000
#define SD4_EMMC_TOP_CMD_SD4_CRC_EN_SHIFT 19
#define SD4_EMMC_TOP_CMD_SD4_CRC_EN_MASK 0x00080000
#define SD4_EMMC_TOP_CMD_SD4_RTSEL_SHIFT 16
#define SD4_EMMC_TOP_CMD_SD4_RTSEL_MASK 0x00030000
#define SD4_EMMC_TOP_CMD_SD4_RESPIRQDIS_SHIFT 8
#define SD4_EMMC_TOP_CMD_SD4_RESPIRQDIS_MASK 0x00000100
#define SD4_EMMC_TOP_CMD_SD4_RESPERRCHKEN_SHIFT 7
#define SD4_EMMC_TOP_CMD_SD4_RESPERRCHKEN_MASK 0x00000080
#define SD4_EMMC_TOP_CMD_SD4_RESPR1R5_SHIFT 6
#define SD4_EMMC_TOP_CMD_SD4_RESPR1R5_MASK 0x00000040
#define SD4_EMMC_TOP_CMD_SD4_MSBS_SHIFT 5
#define SD4_EMMC_TOP_CMD_SD4_MSBS_MASK 0x00000020
#define SD4_EMMC_TOP_CMD_SD4_DTDS_SHIFT 4
#define SD4_EMMC_TOP_CMD_SD4_DTDS_MASK 0x00000010
#define SD4_EMMC_TOP_CMD_SD4_ACMDEN_SHIFT 2
#define SD4_EMMC_TOP_CMD_SD4_ACMDEN_MASK 0x0000000C
#define SD4_EMMC_TOP_CMD_SD4_BCEN_SHIFT 1
#define SD4_EMMC_TOP_CMD_SD4_BCEN_MASK 0x00000002
#define SD4_EMMC_TOP_CMD_SD4_DMA_SHIFT 0
#define SD4_EMMC_TOP_CMD_SD4_DMA_MASK 0x00000001
#define SD4_EMMC_TOP_RESP0_OFFSET 0x00000010
#define SD4_EMMC_TOP_RESP0_DEFAULT 0x00000000
#define SD4_EMMC_TOP_RESP0_TYPE uint32_t
#define SD4_EMMC_TOP_RESP0_RESERVED_MASK 0x00000000
#define SD4_EMMC_TOP_RESP0_RESP0_SHIFT 0
#define SD4_EMMC_TOP_RESP0_RESP0_MASK 0xFFFFFFFF
#define SD4_EMMC_TOP_RESP2_OFFSET 0x00000014
#define SD4_EMMC_TOP_RESP2_DEFAULT 0x00000000
#define SD4_EMMC_TOP_RESP2_TYPE uint32_t
#define SD4_EMMC_TOP_RESP2_RESERVED_MASK 0x00000000
#define SD4_EMMC_TOP_RESP2_RESP2_SHIFT 0
#define SD4_EMMC_TOP_RESP2_RESP2_MASK 0xFFFFFFFF
#define SD4_EMMC_TOP_RESP4_OFFSET 0x00000018
#define SD4_EMMC_TOP_RESP4_DEFAULT 0x00000000
#define SD4_EMMC_TOP_RESP4_TYPE uint32_t
#define SD4_EMMC_TOP_RESP4_RESERVED_MASK 0x00000000
#define SD4_EMMC_TOP_RESP4_RESP4_SHIFT 0
#define SD4_EMMC_TOP_RESP4_RESP4_MASK 0xFFFFFFFF
#define SD4_EMMC_TOP_RESP6_OFFSET 0x0000001C
#define SD4_EMMC_TOP_RESP6_DEFAULT 0x00000000
#define SD4_EMMC_TOP_RESP6_TYPE uint32_t
#define SD4_EMMC_TOP_RESP6_RESERVED_MASK 0x00000000
#define SD4_EMMC_TOP_RESP6_RESP6_SHIFT 0
#define SD4_EMMC_TOP_RESP6_RESP6_MASK 0xFFFFFFFF
#define SD4_EMMC_TOP_BUFDAT_OFFSET 0x00000020
#define SD4_EMMC_TOP_BUFDAT_DEFAULT 0x00000000
#define SD4_EMMC_TOP_BUFDAT_TYPE uint32_t
#define SD4_EMMC_TOP_BUFDAT_RESERVED_MASK 0x00000000
#define SD4_EMMC_TOP_BUFDAT_BUFDAT_SHIFT 0
#define SD4_EMMC_TOP_BUFDAT_BUFDAT_MASK 0xFFFFFFFF
#define SD4_EMMC_TOP_PSTATE_OFFSET 0x00000024
#define SD4_EMMC_TOP_PSTATE_DEFAULT 0x1FFC0000
#define SD4_EMMC_TOP_PSTATE_TYPE uint32_t
#define SD4_EMMC_TOP_PSTATE_RESERVED_MASK 0xE000F0F0
#define SD4_EMMC_TOP_PSTATE_DLS7_4_SHIFT 25
#define SD4_EMMC_TOP_PSTATE_DLS7_4_MASK 0x1E000000
#define SD4_EMMC_TOP_PSTATE_CLSL_SHIFT 24
#define SD4_EMMC_TOP_PSTATE_CLSL_MASK 0x01000000
#define SD4_EMMC_TOP_PSTATE_DLS3_0_SHIFT 20
#define SD4_EMMC_TOP_PSTATE_DLS3_0_MASK 0x00F00000
#define SD4_EMMC_TOP_PSTATE_WPSL_SHIFT 19
#define SD4_EMMC_TOP_PSTATE_WPSL_MASK 0x00080000
#define SD4_EMMC_TOP_PSTATE_CDPL_SHIFT 18
#define SD4_EMMC_TOP_PSTATE_CDPL_MASK 0x00040000
#define SD4_EMMC_TOP_PSTATE_CSS_SHIFT 17
#define SD4_EMMC_TOP_PSTATE_CSS_MASK 0x00020000
#define SD4_EMMC_TOP_PSTATE_CINS_SHIFT 16
#define SD4_EMMC_TOP_PSTATE_CINS_MASK 0x00010000
#define SD4_EMMC_TOP_PSTATE_BREN_SHIFT 11
#define SD4_EMMC_TOP_PSTATE_BREN_MASK 0x00000800
#define SD4_EMMC_TOP_PSTATE_BWEN_SHIFT 10
#define SD4_EMMC_TOP_PSTATE_BWEN_MASK 0x00000400
#define SD4_EMMC_TOP_PSTATE_RXACT_SHIFT 9
#define SD4_EMMC_TOP_PSTATE_RXACT_MASK 0x00000200
#define SD4_EMMC_TOP_PSTATE_WXACT_SHIFT 8
#define SD4_EMMC_TOP_PSTATE_WXACT_MASK 0x00000100
#define SD4_EMMC_TOP_PSTATE_RETUNE_REQ_SHIFT 3
#define SD4_EMMC_TOP_PSTATE_RETUNE_REQ_MASK 0x00000008
#define SD4_EMMC_TOP_PSTATE_DATACT_SHIFT 2
#define SD4_EMMC_TOP_PSTATE_DATACT_MASK 0x00000004
#define SD4_EMMC_TOP_PSTATE_DATINH_SHIFT 1
#define SD4_EMMC_TOP_PSTATE_DATINH_MASK 0x00000002
#define SD4_EMMC_TOP_PSTATE_CMDINH_SHIFT 0
#define SD4_EMMC_TOP_PSTATE_CMDINH_MASK 0x00000001
#define SD4_EMMC_TOP_PSTATE_SD4_OFFSET 0x00000024
#define SD4_EMMC_TOP_PSTATE_SD4_DEFAULT 0x01FC00F0
#define SD4_EMMC_TOP_PSTATE_SD4_TYPE uint32_t
#define SD4_EMMC_TOP_PSTATE_SD4_RESERVED_MASK 0x1E00F000
#define SD4_EMMC_TOP_PSTATE_SD4_STBLDET_SHIFT 31
#define SD4_EMMC_TOP_PSTATE_SD4_STBLDET_MASK 0x80000000
#define SD4_EMMC_TOP_PSTATE_SD4_LANESYNC_SHIFT 30
#define SD4_EMMC_TOP_PSTATE_SD4_LANESYNC_MASK 0x40000000
#define SD4_EMMC_TOP_PSTATE_SD4_INDORMNTSTATE_SHIFT 29
#define SD4_EMMC_TOP_PSTATE_SD4_INDORMNTSTATE_MASK 0x20000000
#define SD4_EMMC_TOP_PSTATE_SD4_CLSL_SHIFT 24
#define SD4_EMMC_TOP_PSTATE_SD4_CLSL_MASK 0x01000000
#define SD4_EMMC_TOP_PSTATE_SD4_DLS3_0_SHIFT 20
#define SD4_EMMC_TOP_PSTATE_SD4_DLS3_0_MASK 0x00F00000
#define SD4_EMMC_TOP_PSTATE_SD4_WPSL_SHIFT 19
#define SD4_EMMC_TOP_PSTATE_SD4_WPSL_MASK 0x00080000
#define SD4_EMMC_TOP_PSTATE_SD4_CDPL_SHIFT 18
#define SD4_EMMC_TOP_PSTATE_SD4_CDPL_MASK 0x00040000
#define SD4_EMMC_TOP_PSTATE_SD4_CSS_SHIFT 17
#define SD4_EMMC_TOP_PSTATE_SD4_CSS_MASK 0x00020000
#define SD4_EMMC_TOP_PSTATE_SD4_CINS_SHIFT 16
#define SD4_EMMC_TOP_PSTATE_SD4_CINS_MASK 0x00010000
#define SD4_EMMC_TOP_PSTATE_SD4_BREN_SHIFT 11
#define SD4_EMMC_TOP_PSTATE_SD4_BREN_MASK 0x00000800
#define SD4_EMMC_TOP_PSTATE_SD4_BWEN_SHIFT 10
#define SD4_EMMC_TOP_PSTATE_SD4_BWEN_MASK 0x00000400
#define SD4_EMMC_TOP_PSTATE_SD4_RXACT_SHIFT 9
#define SD4_EMMC_TOP_PSTATE_SD4_RXACT_MASK 0x00000200
#define SD4_EMMC_TOP_PSTATE_SD4_WXACT_SHIFT 8
#define SD4_EMMC_TOP_PSTATE_SD4_WXACT_MASK 0x00000100
#define SD4_EMMC_TOP_PSTATE_SD4_DLS7_4_SHIFT 4
#define SD4_EMMC_TOP_PSTATE_SD4_DLS7_4_MASK 0x000000F0
#define SD4_EMMC_TOP_PSTATE_SD4_RETUNE_REQ_SHIFT 3
#define SD4_EMMC_TOP_PSTATE_SD4_RETUNE_REQ_MASK 0x00000008
#define SD4_EMMC_TOP_PSTATE_SD4_DATACT_SHIFT 2
#define SD4_EMMC_TOP_PSTATE_SD4_DATACT_MASK 0x00000004
#define SD4_EMMC_TOP_PSTATE_SD4_DATINH_SHIFT 1
#define SD4_EMMC_TOP_PSTATE_SD4_DATINH_MASK 0x00000002
#define SD4_EMMC_TOP_PSTATE_SD4_CMDINH_SHIFT 0
#define SD4_EMMC_TOP_PSTATE_SD4_CMDINH_MASK 0x00000001
#define SD4_EMMC_TOP_CTRL_OFFSET 0x00000028
#define SD4_EMMC_TOP_CTRL_DEFAULT 0x00000000
#define SD4_EMMC_TOP_CTRL_TYPE uint32_t
#define SD4_EMMC_TOP_CTRL_RESERVED_MASK 0xF800E000
#define SD4_EMMC_TOP_CTRL_WAKENRMV_SHIFT 26
#define SD4_EMMC_TOP_CTRL_WAKENRMV_MASK 0x04000000
#define SD4_EMMC_TOP_CTRL_WAKENINS_SHIFT 25
#define SD4_EMMC_TOP_CTRL_WAKENINS_MASK 0x02000000
#define SD4_EMMC_TOP_CTRL_WAKENIRQ_SHIFT 24
#define SD4_EMMC_TOP_CTRL_WAKENIRQ_MASK 0x01000000
#define SD4_EMMC_TOP_CTRL_BOOTACK_SHIFT 23
#define SD4_EMMC_TOP_CTRL_BOOTACK_MASK 0x00800000
#define SD4_EMMC_TOP_CTRL_ATLBOOTEN_SHIFT 22
#define SD4_EMMC_TOP_CTRL_ATLBOOTEN_MASK 0x00400000
#define SD4_EMMC_TOP_CTRL_BOOTEN_SHIFT 21
#define SD4_EMMC_TOP_CTRL_BOOTEN_MASK 0x00200000
#define SD4_EMMC_TOP_CTRL_SPIMODE_SHIFT 20
#define SD4_EMMC_TOP_CTRL_SPIMODE_MASK 0x00100000
#define SD4_EMMC_TOP_CTRL_BLKIRQ_SHIFT 19
#define SD4_EMMC_TOP_CTRL_BLKIRQ_MASK 0x00080000
#define SD4_EMMC_TOP_CTRL_RDWTCRTL_SHIFT 18
#define SD4_EMMC_TOP_CTRL_RDWTCRTL_MASK 0x00040000
#define SD4_EMMC_TOP_CTRL_CONTREQ_SHIFT 17
#define SD4_EMMC_TOP_CTRL_CONTREQ_MASK 0x00020000
#define SD4_EMMC_TOP_CTRL_BLKSTPREQ_SHIFT 16
#define SD4_EMMC_TOP_CTRL_BLKSTPREQ_MASK 0x00010000
#define SD4_EMMC_TOP_CTRL_HRESET_SHIFT 12
#define SD4_EMMC_TOP_CTRL_HRESET_MASK 0x00001000
#define SD4_EMMC_TOP_CTRL_SDVSELVDD1_SHIFT 9
#define SD4_EMMC_TOP_CTRL_SDVSELVDD1_MASK 0x00000E00
#define SD4_EMMC_TOP_CTRL_SDPWR_SHIFT 8
#define SD4_EMMC_TOP_CTRL_SDPWR_MASK 0x00000100
#define SD4_EMMC_TOP_CTRL_CDSD_SHIFT 7
#define SD4_EMMC_TOP_CTRL_CDSD_MASK 0x00000080
#define SD4_EMMC_TOP_CTRL_CDTL_SHIFT 6
#define SD4_EMMC_TOP_CTRL_CDTL_MASK 0x00000040
#define SD4_EMMC_TOP_CTRL_SDB_SHIFT 5
#define SD4_EMMC_TOP_CTRL_SDB_MASK 0x00000020
#define SD4_EMMC_TOP_CTRL_DMASEL_SHIFT 3
#define SD4_EMMC_TOP_CTRL_DMASEL_MASK 0x00000018
#define SD4_EMMC_TOP_CTRL_HSEN_SHIFT 2
#define SD4_EMMC_TOP_CTRL_HSEN_MASK 0x00000004
#define SD4_EMMC_TOP_CTRL_DXTW_SHIFT 1
#define SD4_EMMC_TOP_CTRL_DXTW_MASK 0x00000002
#define SD4_EMMC_TOP_CTRL_LEDCTL_SHIFT 0
#define SD4_EMMC_TOP_CTRL_LEDCTL_MASK 0x00000001
#define SD4_EMMC_TOP_CTRL_SD4_OFFSET 0x00000028
#define SD4_EMMC_TOP_CTRL_SD4_DEFAULT 0x00000000
#define SD4_EMMC_TOP_CTRL_SD4_TYPE uint32_t
#define SD4_EMMC_TOP_CTRL_SD4_RESERVED_MASK 0xF8F00000
#define SD4_EMMC_TOP_CTRL_SD4_WAKENRMV_SHIFT 26
#define SD4_EMMC_TOP_CTRL_SD4_WAKENRMV_MASK 0x04000000
#define SD4_EMMC_TOP_CTRL_SD4_WAKENINS_SHIFT 25
#define SD4_EMMC_TOP_CTRL_SD4_WAKENINS_MASK 0x02000000
#define SD4_EMMC_TOP_CTRL_SD4_WAKENIRQ_SHIFT 24
#define SD4_EMMC_TOP_CTRL_SD4_WAKENIRQ_MASK 0x01000000
#define SD4_EMMC_TOP_CTRL_SD4_BLKIRQ_SHIFT 19
#define SD4_EMMC_TOP_CTRL_SD4_BLKIRQ_MASK 0x00080000
#define SD4_EMMC_TOP_CTRL_SD4_RDWTCRTL_SHIFT 18
#define SD4_EMMC_TOP_CTRL_SD4_RDWTCRTL_MASK 0x00040000
#define SD4_EMMC_TOP_CTRL_SD4_CONTREQ_SHIFT 17
#define SD4_EMMC_TOP_CTRL_SD4_CONTREQ_MASK 0x00020000
#define SD4_EMMC_TOP_CTRL_SD4_BLKSTPREQ_SHIFT 16
#define SD4_EMMC_TOP_CTRL_SD4_BLKSTPREQ_MASK 0x00010000
#define SD4_EMMC_TOP_CTRL_SD4_SDVSELVDD2_SHIFT 13
#define SD4_EMMC_TOP_CTRL_SD4_SDVSELVDD2_MASK 0x0000E000
#define SD4_EMMC_TOP_CTRL_SD4_SDPWRVDD2_SHIFT 12
#define SD4_EMMC_TOP_CTRL_SD4_SDPWRVDD2_MASK 0x00001000
#define SD4_EMMC_TOP_CTRL_SD4_SDVSELVDD1_SHIFT 9
#define SD4_EMMC_TOP_CTRL_SD4_SDVSELVDD1_MASK 0x00000E00
#define SD4_EMMC_TOP_CTRL_SD4_SDPWR_SHIFT 8
#define SD4_EMMC_TOP_CTRL_SD4_SDPWR_MASK 0x00000100
#define SD4_EMMC_TOP_CTRL_SD4_CDSD_SHIFT 7
#define SD4_EMMC_TOP_CTRL_SD4_CDSD_MASK 0x00000080
#define SD4_EMMC_TOP_CTRL_SD4_CDTL_SHIFT 6
#define SD4_EMMC_TOP_CTRL_SD4_CDTL_MASK 0x00000040
#define SD4_EMMC_TOP_CTRL_SD4_SDB_SHIFT 5
#define SD4_EMMC_TOP_CTRL_SD4_SDB_MASK 0x00000020
#define SD4_EMMC_TOP_CTRL_SD4_DMASEL_SHIFT 3
#define SD4_EMMC_TOP_CTRL_SD4_DMASEL_MASK 0x00000018
#define SD4_EMMC_TOP_CTRL_SD4_HSEN_SHIFT 2
#define SD4_EMMC_TOP_CTRL_SD4_HSEN_MASK 0x00000004
#define SD4_EMMC_TOP_CTRL_SD4_DXTW_SHIFT 1
#define SD4_EMMC_TOP_CTRL_SD4_DXTW_MASK 0x00000002
#define SD4_EMMC_TOP_CTRL_SD4_LEDCTL_SHIFT 0
#define SD4_EMMC_TOP_CTRL_SD4_LEDCTL_MASK 0x00000001
#define SD4_EMMC_TOP_CTRL1_OFFSET 0x0000002C
#define SD4_EMMC_TOP_CTRL1_DEFAULT 0x00000000
#define SD4_EMMC_TOP_CTRL1_TYPE uint32_t
#define SD4_EMMC_TOP_CTRL1_RESERVED_MASK 0xF8F00018
#define SD4_EMMC_TOP_CTRL1_DATRST_SHIFT 26
#define SD4_EMMC_TOP_CTRL1_DATRST_MASK 0x04000000
#define SD4_EMMC_TOP_CTRL1_CMDRST_SHIFT 25
#define SD4_EMMC_TOP_CTRL1_CMDRST_MASK 0x02000000
#define SD4_EMMC_TOP_CTRL1_RST_SHIFT 24
#define SD4_EMMC_TOP_CTRL1_RST_MASK 0x01000000
#define SD4_EMMC_TOP_CTRL1_DTCNT_SHIFT 16
#define SD4_EMMC_TOP_CTRL1_DTCNT_MASK 0x000F0000
#define SD4_EMMC_TOP_CTRL1_SDCLKSEL_SHIFT 8
#define SD4_EMMC_TOP_CTRL1_SDCLKSEL_MASK 0x0000FF00
#define SD4_EMMC_TOP_CTRL1_SDCLKSEL_UP_SHIFT 6
#define SD4_EMMC_TOP_CTRL1_SDCLKSEL_UP_MASK 0x000000C0
#define SD4_EMMC_TOP_CTRL1_CLKGENSEL_SHIFT 5
#define SD4_EMMC_TOP_CTRL1_CLKGENSEL_MASK 0x00000020
#define SD4_EMMC_TOP_CTRL1_SDCLKEN_SHIFT 2
#define SD4_EMMC_TOP_CTRL1_SDCLKEN_MASK 0x00000004
#define SD4_EMMC_TOP_CTRL1_ICLKSTB_SHIFT 1
#define SD4_EMMC_TOP_CTRL1_ICLKSTB_MASK 0x00000002
#define SD4_EMMC_TOP_CTRL1_ICLKEN_SHIFT 0
#define SD4_EMMC_TOP_CTRL1_ICLKEN_MASK 0x00000001
#define SD4_EMMC_TOP_INTR_OFFSET 0x00000030
#define SD4_EMMC_TOP_INTR_DEFAULT 0x00000000
#define SD4_EMMC_TOP_INTR_TYPE uint32_t
#define SD4_EMMC_TOP_INTR_RESERVED_MASK 0xEC000000
#define SD4_EMMC_TOP_INTR_TRESPERR_SHIFT 28
#define SD4_EMMC_TOP_INTR_TRESPERR_MASK 0x10000000
#define SD4_EMMC_TOP_INTR_ADMAERR_SHIFT 25
#define SD4_EMMC_TOP_INTR_ADMAERR_MASK 0x02000000
#define SD4_EMMC_TOP_INTR_CMDERROR_SHIFT 24
#define SD4_EMMC_TOP_INTR_CMDERROR_MASK 0x01000000
#define SD4_EMMC_TOP_INTR_IERR_SHIFT 23
#define SD4_EMMC_TOP_INTR_IERR_MASK 0x00800000
#define SD4_EMMC_TOP_INTR_DEBERR_SHIFT 22
#define SD4_EMMC_TOP_INTR_DEBERR_MASK 0x00400000
#define SD4_EMMC_TOP_INTR_DCRCERR_SHIFT 21
#define SD4_EMMC_TOP_INTR_DCRCERR_MASK 0x00200000
#define SD4_EMMC_TOP_INTR_DTOERR_SHIFT 20
#define SD4_EMMC_TOP_INTR_DTOERR_MASK 0x00100000
#define SD4_EMMC_TOP_INTR_CMDIDXERR_SHIFT 19
#define SD4_EMMC_TOP_INTR_CMDIDXERR_MASK 0x00080000
#define SD4_EMMC_TOP_INTR_CEBERR_SHIFT 18
#define SD4_EMMC_TOP_INTR_CEBERR_MASK 0x00040000
#define SD4_EMMC_TOP_INTR_CCRCERR_SHIFT 17
#define SD4_EMMC_TOP_INTR_CCRCERR_MASK 0x00020000
#define SD4_EMMC_TOP_INTR_CTOERR_SHIFT 16
#define SD4_EMMC_TOP_INTR_CTOERR_MASK 0x00010000
#define SD4_EMMC_TOP_INTR_ERRIRQ_SHIFT 15
#define SD4_EMMC_TOP_INTR_ERRIRQ_MASK 0x00008000
#define SD4_EMMC_TOP_INTR_BTIRQ_SHIFT 14
#define SD4_EMMC_TOP_INTR_BTIRQ_MASK 0x00004000
#define SD4_EMMC_TOP_INTR_BTACKRX_SHIFT 13
#define SD4_EMMC_TOP_INTR_BTACKRX_MASK 0x00002000
#define SD4_EMMC_TOP_INTR_RETUNE_EVENT_SHIFT 12
#define SD4_EMMC_TOP_INTR_RETUNE_EVENT_MASK 0x00001000
#define SD4_EMMC_TOP_INTR_INT_C_SHIFT 11
#define SD4_EMMC_TOP_INTR_INT_C_MASK 0x00000800
#define SD4_EMMC_TOP_INTR_INT_B_SHIFT 10
#define SD4_EMMC_TOP_INTR_INT_B_MASK 0x00000400
#define SD4_EMMC_TOP_INTR_INT_A_SHIFT 9
#define SD4_EMMC_TOP_INTR_INT_A_MASK 0x00000200
#define SD4_EMMC_TOP_INTR_CRDIRQ_SHIFT 8
#define SD4_EMMC_TOP_INTR_CRDIRQ_MASK 0x00000100
#define SD4_EMMC_TOP_INTR_CRDRMV_SHIFT 7
#define SD4_EMMC_TOP_INTR_CRDRMV_MASK 0x00000080
#define SD4_EMMC_TOP_INTR_CRDINS_SHIFT 6
#define SD4_EMMC_TOP_INTR_CRDINS_MASK 0x00000040
#define SD4_EMMC_TOP_INTR_BRRDY_SHIFT 5
#define SD4_EMMC_TOP_INTR_BRRDY_MASK 0x00000020
#define SD4_EMMC_TOP_INTR_BWRDY_SHIFT 4
#define SD4_EMMC_TOP_INTR_BWRDY_MASK 0x00000010
#define SD4_EMMC_TOP_INTR_DMAIRQ_SHIFT 3
#define SD4_EMMC_TOP_INTR_DMAIRQ_MASK 0x00000008
#define SD4_EMMC_TOP_INTR_BLKENT_SHIFT 2
#define SD4_EMMC_TOP_INTR_BLKENT_MASK 0x00000004
#define SD4_EMMC_TOP_INTR_TXDONE_SHIFT 1
#define SD4_EMMC_TOP_INTR_TXDONE_MASK 0x00000002
#define SD4_EMMC_TOP_INTR_CMDDONE_SHIFT 0
#define SD4_EMMC_TOP_INTR_CMDDONE_MASK 0x00000001
#define SD4_EMMC_TOP_INTR_SD4_OFFSET 0x00000030
#define SD4_EMMC_TOP_INTR_SD4_DEFAULT 0x00000000
#define SD4_EMMC_TOP_INTR_SD4_TYPE uint32_t
#define SD4_EMMC_TOP_INTR_SD4_RESERVED_MASK 0xF0006000
#define SD4_EMMC_TOP_INTR_SD4_TRESPERR_SHIFT 27
#define SD4_EMMC_TOP_INTR_SD4_TRESPERR_MASK 0x08000000
#define SD4_EMMC_TOP_INTR_SD4_TUNEERR_SHIFT 26
#define SD4_EMMC_TOP_INTR_SD4_TUNEERR_MASK 0x04000000
#define SD4_EMMC_TOP_INTR_SD4_ADMAERR_SHIFT 25
#define SD4_EMMC_TOP_INTR_SD4_ADMAERR_MASK 0x02000000
#define SD4_EMMC_TOP_INTR_SD4_CMDERROR_SHIFT 24
#define SD4_EMMC_TOP_INTR_SD4_CMDERROR_MASK 0x01000000
#define SD4_EMMC_TOP_INTR_SD4_IERR_SHIFT 23
#define SD4_EMMC_TOP_INTR_SD4_IERR_MASK 0x00800000
#define SD4_EMMC_TOP_INTR_SD4_DEBERR_SHIFT 22
#define SD4_EMMC_TOP_INTR_SD4_DEBERR_MASK 0x00400000
#define SD4_EMMC_TOP_INTR_SD4_DCRCERR_SHIFT 21
#define SD4_EMMC_TOP_INTR_SD4_DCRCERR_MASK 0x00200000
#define SD4_EMMC_TOP_INTR_SD4_DTOERR_SHIFT 20
#define SD4_EMMC_TOP_INTR_SD4_DTOERR_MASK 0x00100000
#define SD4_EMMC_TOP_INTR_SD4_CMDIDXERR_SHIFT 19
#define SD4_EMMC_TOP_INTR_SD4_CMDIDXERR_MASK 0x00080000
#define SD4_EMMC_TOP_INTR_SD4_CEBERR_SHIFT 18
#define SD4_EMMC_TOP_INTR_SD4_CEBERR_MASK 0x00040000
#define SD4_EMMC_TOP_INTR_SD4_CCRCERR_SHIFT 17
#define SD4_EMMC_TOP_INTR_SD4_CCRCERR_MASK 0x00020000
#define SD4_EMMC_TOP_INTR_SD4_CTOERR_SHIFT 16
#define SD4_EMMC_TOP_INTR_SD4_CTOERR_MASK 0x00010000
#define SD4_EMMC_TOP_INTR_SD4_ERRIRQ_SHIFT 15
#define SD4_EMMC_TOP_INTR_SD4_ERRIRQ_MASK 0x00008000
#define SD4_EMMC_TOP_INTR_SD4_RETUNE_EVENT_SHIFT 12
#define SD4_EMMC_TOP_INTR_SD4_RETUNE_EVENT_MASK 0x00001000
#define SD4_EMMC_TOP_INTR_SD4_INT_C_SHIFT 11
#define SD4_EMMC_TOP_INTR_SD4_INT_C_MASK 0x00000800
#define SD4_EMMC_TOP_INTR_SD4_INT_B_SHIFT 10
#define SD4_EMMC_TOP_INTR_SD4_INT_B_MASK 0x00000400
#define SD4_EMMC_TOP_INTR_SD4_INT_A_SHIFT 9
#define SD4_EMMC_TOP_INTR_SD4_INT_A_MASK 0x00000200
#define SD4_EMMC_TOP_INTR_SD4_CRDIRQ_SHIFT 8
#define SD4_EMMC_TOP_INTR_SD4_CRDIRQ_MASK 0x00000100
#define SD4_EMMC_TOP_INTR_SD4_CRDRMV_SHIFT 7
#define SD4_EMMC_TOP_INTR_SD4_CRDRMV_MASK 0x00000080
#define SD4_EMMC_TOP_INTR_SD4_CRDINS_SHIFT 6
#define SD4_EMMC_TOP_INTR_SD4_CRDINS_MASK 0x00000040
#define SD4_EMMC_TOP_INTR_SD4_BRRDY_SHIFT 5
#define SD4_EMMC_TOP_INTR_SD4_BRRDY_MASK 0x00000020
#define SD4_EMMC_TOP_INTR_SD4_BWRDY_SHIFT 4
#define SD4_EMMC_TOP_INTR_SD4_BWRDY_MASK 0x00000010
#define SD4_EMMC_TOP_INTR_SD4_DMAIRQ_SHIFT 3
#define SD4_EMMC_TOP_INTR_SD4_DMAIRQ_MASK 0x00000008
#define SD4_EMMC_TOP_INTR_SD4_BLKENT_SHIFT 2
#define SD4_EMMC_TOP_INTR_SD4_BLKENT_MASK 0x00000004
#define SD4_EMMC_TOP_INTR_SD4_TXDONE_SHIFT 1
#define SD4_EMMC_TOP_INTR_SD4_TXDONE_MASK 0x00000002
#define SD4_EMMC_TOP_INTR_SD4_CMDDONE_SHIFT 0
#define SD4_EMMC_TOP_INTR_SD4_CMDDONE_MASK 0x00000001
#define SD4_EMMC_TOP_INTREN1_OFFSET 0x00000034
#define SD4_EMMC_TOP_INTREN1_DEFAULT 0x00000000
#define SD4_EMMC_TOP_INTREN1_TYPE uint32_t
#define SD4_EMMC_TOP_INTREN1_RESERVED_MASK 0xEC000000
#define SD4_EMMC_TOP_INTREN1_TRESPERREN_SHIFT 28
#define SD4_EMMC_TOP_INTREN1_TRESPERREN_MASK 0x10000000
#define SD4_EMMC_TOP_INTREN1_ADMAEREN_SHIFT 25
#define SD4_EMMC_TOP_INTREN1_ADMAEREN_MASK 0x02000000
#define SD4_EMMC_TOP_INTREN1_CMDERREN_SHIFT 24
#define SD4_EMMC_TOP_INTREN1_CMDERREN_MASK 0x01000000
#define SD4_EMMC_TOP_INTREN1_ILIMERREN_SHIFT 23
#define SD4_EMMC_TOP_INTREN1_ILIMERREN_MASK 0x00800000
#define SD4_EMMC_TOP_INTREN1_DEBERREN_SHIFT 22
#define SD4_EMMC_TOP_INTREN1_DEBERREN_MASK 0x00400000
#define SD4_EMMC_TOP_INTREN1_DCRCERREN_SHIFT 21
#define SD4_EMMC_TOP_INTREN1_DCRCERREN_MASK 0x00200000
#define SD4_EMMC_TOP_INTREN1_DTOERREN_SHIFT 20
#define SD4_EMMC_TOP_INTREN1_DTOERREN_MASK 0x00100000
#define SD4_EMMC_TOP_INTREN1_CIDXERREN_SHIFT 19
#define SD4_EMMC_TOP_INTREN1_CIDXERREN_MASK 0x00080000
#define SD4_EMMC_TOP_INTREN1_CEBERREN_SHIFT 18
#define SD4_EMMC_TOP_INTREN1_CEBERREN_MASK 0x00040000
#define SD4_EMMC_TOP_INTREN1_CMDCRCEN_SHIFT 17
#define SD4_EMMC_TOP_INTREN1_CMDCRCEN_MASK 0x00020000
#define SD4_EMMC_TOP_INTREN1_CMDTOEN_SHIFT 16
#define SD4_EMMC_TOP_INTREN1_CMDTOEN_MASK 0x00010000
#define SD4_EMMC_TOP_INTREN1_FIXZ_SHIFT 15
#define SD4_EMMC_TOP_INTREN1_FIXZ_MASK 0x00008000
#define SD4_EMMC_TOP_INTREN1_BTIRQEN_SHIFT 14
#define SD4_EMMC_TOP_INTREN1_BTIRQEN_MASK 0x00004000
#define SD4_EMMC_TOP_INTREN1_BTACKRXEN_SHIFT 13
#define SD4_EMMC_TOP_INTREN1_BTACKRXEN_MASK 0x00002000
#define SD4_EMMC_TOP_INTREN1_RETUNE_EVENTEN_SHIFT 12
#define SD4_EMMC_TOP_INTREN1_RETUNE_EVENTEN_MASK 0x00001000
#define SD4_EMMC_TOP_INTREN1_INT_C_EN_SHIFT 11
#define SD4_EMMC_TOP_INTREN1_INT_C_EN_MASK 0x00000800
#define SD4_EMMC_TOP_INTREN1_INT_B_EN_SHIFT 10
#define SD4_EMMC_TOP_INTREN1_INT_B_EN_MASK 0x00000400
#define SD4_EMMC_TOP_INTREN1_INT_A_EN_SHIFT 9
#define SD4_EMMC_TOP_INTREN1_INT_A_EN_MASK 0x00000200
#define SD4_EMMC_TOP_INTREN1_CIRQEN_SHIFT 8
#define SD4_EMMC_TOP_INTREN1_CIRQEN_MASK 0x00000100
#define SD4_EMMC_TOP_INTREN1_CRDRMVEN_SHIFT 7
#define SD4_EMMC_TOP_INTREN1_CRDRMVEN_MASK 0x00000080
#define SD4_EMMC_TOP_INTREN1_CRDINSEN_SHIFT 6
#define SD4_EMMC_TOP_INTREN1_CRDINSEN_MASK 0x00000040
#define SD4_EMMC_TOP_INTREN1_BUFRREN_SHIFT 5
#define SD4_EMMC_TOP_INTREN1_BUFRREN_MASK 0x00000020
#define SD4_EMMC_TOP_INTREN1_BUFWREN_SHIFT 4
#define SD4_EMMC_TOP_INTREN1_BUFWREN_MASK 0x00000010
#define SD4_EMMC_TOP_INTREN1_DMAIRQEN_SHIFT 3
#define SD4_EMMC_TOP_INTREN1_DMAIRQEN_MASK 0x00000008
#define SD4_EMMC_TOP_INTREN1_BLKEN_SHIFT 2
#define SD4_EMMC_TOP_INTREN1_BLKEN_MASK 0x00000004
#define SD4_EMMC_TOP_INTREN1_TXDONEEN_SHIFT 1
#define SD4_EMMC_TOP_INTREN1_TXDONEEN_MASK 0x00000002
#define SD4_EMMC_TOP_INTREN1_CMDDONEEN_SHIFT 0
#define SD4_EMMC_TOP_INTREN1_CMDDONEEN_MASK 0x00000001
#define SD4_EMMC_TOP_INTREN1_SD4_OFFSET 0x00000034
#define SD4_EMMC_TOP_INTREN1_SD4_DEFAULT 0x00000000
#define SD4_EMMC_TOP_INTREN1_SD4_TYPE uint32_t
#define SD4_EMMC_TOP_INTREN1_SD4_RESERVED_MASK 0x00006000
#define SD4_EMMC_TOP_INTREN1_SD4_VNDRERREN_SHIFT 28
#define SD4_EMMC_TOP_INTREN1_SD4_VNDRERREN_MASK 0xF0000000
#define SD4_EMMC_TOP_INTREN1_SD4_TRESPERREN_SHIFT 27
#define SD4_EMMC_TOP_INTREN1_SD4_TRESPERREN_MASK 0x08000000
#define SD4_EMMC_TOP_INTREN1_SD4_TUNEERREN_SHIFT 26
#define SD4_EMMC_TOP_INTREN1_SD4_TUNEERREN_MASK 0x04000000
#define SD4_EMMC_TOP_INTREN1_SD4_ADMAEREN_SHIFT 25
#define SD4_EMMC_TOP_INTREN1_SD4_ADMAEREN_MASK 0x02000000
#define SD4_EMMC_TOP_INTREN1_SD4_CMDERREN_SHIFT 24
#define SD4_EMMC_TOP_INTREN1_SD4_CMDERREN_MASK 0x01000000
#define SD4_EMMC_TOP_INTREN1_SD4_ILIMERREN_SHIFT 23
#define SD4_EMMC_TOP_INTREN1_SD4_ILIMERREN_MASK 0x00800000
#define SD4_EMMC_TOP_INTREN1_SD4_DEBERREN_SHIFT 22
#define SD4_EMMC_TOP_INTREN1_SD4_DEBERREN_MASK 0x00400000
#define SD4_EMMC_TOP_INTREN1_SD4_DCRCERREN_SHIFT 21
#define SD4_EMMC_TOP_INTREN1_SD4_DCRCERREN_MASK 0x00200000
#define SD4_EMMC_TOP_INTREN1_SD4_DTOERREN_SHIFT 20
#define SD4_EMMC_TOP_INTREN1_SD4_DTOERREN_MASK 0x00100000
#define SD4_EMMC_TOP_INTREN1_SD4_CIDXERREN_SHIFT 19
#define SD4_EMMC_TOP_INTREN1_SD4_CIDXERREN_MASK 0x00080000
#define SD4_EMMC_TOP_INTREN1_SD4_CEBERREN_SHIFT 18
#define SD4_EMMC_TOP_INTREN1_SD4_CEBERREN_MASK 0x00040000
#define SD4_EMMC_TOP_INTREN1_SD4_CMDCRCEN_SHIFT 17
#define SD4_EMMC_TOP_INTREN1_SD4_CMDCRCEN_MASK 0x00020000
#define SD4_EMMC_TOP_INTREN1_SD4_CMDTOEN_SHIFT 16
#define SD4_EMMC_TOP_INTREN1_SD4_CMDTOEN_MASK 0x00010000
#define SD4_EMMC_TOP_INTREN1_SD4_FIXZ_SHIFT 15
#define SD4_EMMC_TOP_INTREN1_SD4_FIXZ_MASK 0x00008000
#define SD4_EMMC_TOP_INTREN1_SD4_RETUNE_EVENTEN_SHIFT 12
#define SD4_EMMC_TOP_INTREN1_SD4_RETUNE_EVENTEN_MASK 0x00001000
#define SD4_EMMC_TOP_INTREN1_SD4_INT_C_EN_SHIFT 11
#define SD4_EMMC_TOP_INTREN1_SD4_INT_C_EN_MASK 0x00000800
#define SD4_EMMC_TOP_INTREN1_SD4_INT_B_EN_SHIFT 10
#define SD4_EMMC_TOP_INTREN1_SD4_INT_B_EN_MASK 0x00000400
#define SD4_EMMC_TOP_INTREN1_SD4_INT_A_EN_SHIFT 9
#define SD4_EMMC_TOP_INTREN1_SD4_INT_A_EN_MASK 0x00000200
#define SD4_EMMC_TOP_INTREN1_SD4_CIRQEN_SHIFT 8
#define SD4_EMMC_TOP_INTREN1_SD4_CIRQEN_MASK 0x00000100
#define SD4_EMMC_TOP_INTREN1_SD4_CRDRMVEN_SHIFT 7
#define SD4_EMMC_TOP_INTREN1_SD4_CRDRMVEN_MASK 0x00000080
#define SD4_EMMC_TOP_INTREN1_SD4_CRDINSEN_SHIFT 6
#define SD4_EMMC_TOP_INTREN1_SD4_CRDINSEN_MASK 0x00000040
#define SD4_EMMC_TOP_INTREN1_SD4_BUFRREN_SHIFT 5
#define SD4_EMMC_TOP_INTREN1_SD4_BUFRREN_MASK 0x00000020
#define SD4_EMMC_TOP_INTREN1_SD4_BUFWREN_SHIFT 4
#define SD4_EMMC_TOP_INTREN1_SD4_BUFWREN_MASK 0x00000010
#define SD4_EMMC_TOP_INTREN1_SD4_DMAIRQEN_SHIFT 3
#define SD4_EMMC_TOP_INTREN1_SD4_DMAIRQEN_MASK 0x00000008
#define SD4_EMMC_TOP_INTREN1_SD4_BLKEN_SHIFT 2
#define SD4_EMMC_TOP_INTREN1_SD4_BLKEN_MASK 0x00000004
#define SD4_EMMC_TOP_INTREN1_SD4_TXDONEEN_SHIFT 1
#define SD4_EMMC_TOP_INTREN1_SD4_TXDONEEN_MASK 0x00000002
#define SD4_EMMC_TOP_INTREN1_SD4_CMDDONEEN_SHIFT 0
#define SD4_EMMC_TOP_INTREN1_SD4_CMDDONEEN_MASK 0x00000001
#define SD4_EMMC_TOP_INTREN2_OFFSET 0x00000038
#define SD4_EMMC_TOP_INTREN2_DEFAULT 0x00000000
#define SD4_EMMC_TOP_INTREN2_TYPE uint32_t
#define SD4_EMMC_TOP_INTREN2_RESERVED_MASK 0xEC000000
#define SD4_EMMC_TOP_INTREN2_TRESPERRSEN_SHIFT 28
#define SD4_EMMC_TOP_INTREN2_TRESPERRSEN_MASK 0x10000000
#define SD4_EMMC_TOP_INTREN2_ADMASIGEN_SHIFT 25
#define SD4_EMMC_TOP_INTREN2_ADMASIGEN_MASK 0x02000000
#define SD4_EMMC_TOP_INTREN2_CMDSIGEN_SHIFT 24
#define SD4_EMMC_TOP_INTREN2_CMDSIGEN_MASK 0x01000000
#define SD4_EMMC_TOP_INTREN2_ILIMSIGEN_SHIFT 23
#define SD4_EMMC_TOP_INTREN2_ILIMSIGEN_MASK 0x00800000
#define SD4_EMMC_TOP_INTREN2_DEBSIGEN_SHIFT 22
#define SD4_EMMC_TOP_INTREN2_DEBSIGEN_MASK 0x00400000
#define SD4_EMMC_TOP_INTREN2_DCRCSIGEN_SHIFT 21
#define SD4_EMMC_TOP_INTREN2_DCRCSIGEN_MASK 0x00200000
#define SD4_EMMC_TOP_INTREN2_DTOSIGEN_SHIFT 20
#define SD4_EMMC_TOP_INTREN2_DTOSIGEN_MASK 0x00100000
#define SD4_EMMC_TOP_INTREN2_CIDXSIGEN_SHIFT 19
#define SD4_EMMC_TOP_INTREN2_CIDXSIGEN_MASK 0x00080000
#define SD4_EMMC_TOP_INTREN2_CEBSIGEN_SHIFT 18
#define SD4_EMMC_TOP_INTREN2_CEBSIGEN_MASK 0x00040000
#define SD4_EMMC_TOP_INTREN2_CMDCRCSIGEN_SHIFT 17
#define SD4_EMMC_TOP_INTREN2_CMDCRCSIGEN_MASK 0x00020000
#define SD4_EMMC_TOP_INTREN2_CMDTOSIGEN_SHIFT 16
#define SD4_EMMC_TOP_INTREN2_CMDTOSIGEN_MASK 0x00010000
#define SD4_EMMC_TOP_INTREN2_FIXZERO_SHIFT 15
#define SD4_EMMC_TOP_INTREN2_FIXZERO_MASK 0x00008000
#define SD4_EMMC_TOP_INTREN2_BTIRQSEN_SHIFT 14
#define SD4_EMMC_TOP_INTREN2_BTIRQSEN_MASK 0x00004000
#define SD4_EMMC_TOP_INTREN2_BTACKRXSEN_SHIFT 13
#define SD4_EMMC_TOP_INTREN2_BTACKRXSEN_MASK 0x00002000
#define SD4_EMMC_TOP_INTREN2_RETUNE_EVENTSIGEN_SHIFT 12
#define SD4_EMMC_TOP_INTREN2_RETUNE_EVENTSIGEN_MASK 0x00001000
#define SD4_EMMC_TOP_INTREN2_INT_C_SIGEN_SHIFT 11
#define SD4_EMMC_TOP_INTREN2_INT_C_SIGEN_MASK 0x00000800
#define SD4_EMMC_TOP_INTREN2_INT_B_SIGEN_SHIFT 10
#define SD4_EMMC_TOP_INTREN2_INT_B_SIGEN_MASK 0x00000400
#define SD4_EMMC_TOP_INTREN2_INT_A_SIGEN_SHIFT 9
#define SD4_EMMC_TOP_INTREN2_INT_A_SIGEN_MASK 0x00000200
#define SD4_EMMC_TOP_INTREN2_CRDIRQEN_SHIFT 8
#define SD4_EMMC_TOP_INTREN2_CRDIRQEN_MASK 0x00000100
#define SD4_EMMC_TOP_INTREN2_CRDRVMEN_SHIFT 7
#define SD4_EMMC_TOP_INTREN2_CRDRVMEN_MASK 0x00000080
#define SD4_EMMC_TOP_INTREN2_CRDINSEN_SHIFT 6
#define SD4_EMMC_TOP_INTREN2_CRDINSEN_MASK 0x00000040
#define SD4_EMMC_TOP_INTREN2_BUFRRDYEN_SHIFT 5
#define SD4_EMMC_TOP_INTREN2_BUFRRDYEN_MASK 0x00000020
#define SD4_EMMC_TOP_INTREN2_BUFWRDYEN_SHIFT 4
#define SD4_EMMC_TOP_INTREN2_BUFWRDYEN_MASK 0x00000010
#define SD4_EMMC_TOP_INTREN2_DMAIRQEN_SHIFT 3
#define SD4_EMMC_TOP_INTREN2_DMAIRQEN_MASK 0x00000008
#define SD4_EMMC_TOP_INTREN2_BLKGAPEN_SHIFT 2
#define SD4_EMMC_TOP_INTREN2_BLKGAPEN_MASK 0x00000004
#define SD4_EMMC_TOP_INTREN2_TXDONE_SHIFT 1
#define SD4_EMMC_TOP_INTREN2_TXDONE_MASK 0x00000002
#define SD4_EMMC_TOP_INTREN2_CMDDONE_SHIFT 0
#define SD4_EMMC_TOP_INTREN2_CMDDONE_MASK 0x00000001
#define SD4_EMMC_TOP_INTREN2_SD4_OFFSET 0x00000038
#define SD4_EMMC_TOP_INTREN2_SD4_DEFAULT 0x00000000
#define SD4_EMMC_TOP_INTREN2_SD4_TYPE uint32_t
#define SD4_EMMC_TOP_INTREN2_SD4_RESERVED_MASK 0xF0006000
#define SD4_EMMC_TOP_INTREN2_SD4_TRESPERRSEN_SHIFT 27
#define SD4_EMMC_TOP_INTREN2_SD4_TRESPERRSEN_MASK 0x08000000
#define SD4_EMMC_TOP_INTREN2_SD4_TUNERRSIGEN_SHIFT 26
#define SD4_EMMC_TOP_INTREN2_SD4_TUNERRSIGEN_MASK 0x04000000
#define SD4_EMMC_TOP_INTREN2_SD4_ADMASIGEN_SHIFT 25
#define SD4_EMMC_TOP_INTREN2_SD4_ADMASIGEN_MASK 0x02000000
#define SD4_EMMC_TOP_INTREN2_SD4_CMDSIGEN_SHIFT 24
#define SD4_EMMC_TOP_INTREN2_SD4_CMDSIGEN_MASK 0x01000000
#define SD4_EMMC_TOP_INTREN2_SD4_ILIMSIGEN_SHIFT 23
#define SD4_EMMC_TOP_INTREN2_SD4_ILIMSIGEN_MASK 0x00800000
#define SD4_EMMC_TOP_INTREN2_SD4_DEBSIGEN_SHIFT 22
#define SD4_EMMC_TOP_INTREN2_SD4_DEBSIGEN_MASK 0x00400000
#define SD4_EMMC_TOP_INTREN2_SD4_DCRCSIGEN_SHIFT 21
#define SD4_EMMC_TOP_INTREN2_SD4_DCRCSIGEN_MASK 0x00200000
#define SD4_EMMC_TOP_INTREN2_SD4_DTOSIGEN_SHIFT 20
#define SD4_EMMC_TOP_INTREN2_SD4_DTOSIGEN_MASK 0x00100000
#define SD4_EMMC_TOP_INTREN2_SD4_CIDXSIGEN_SHIFT 19
#define SD4_EMMC_TOP_INTREN2_SD4_CIDXSIGEN_MASK 0x00080000
#define SD4_EMMC_TOP_INTREN2_SD4_CEBSIGEN_SHIFT 18
#define SD4_EMMC_TOP_INTREN2_SD4_CEBSIGEN_MASK 0x00040000
#define SD4_EMMC_TOP_INTREN2_SD4_CMDCRCSIGEN_SHIFT 17
#define SD4_EMMC_TOP_INTREN2_SD4_CMDCRCSIGEN_MASK 0x00020000
#define SD4_EMMC_TOP_INTREN2_SD4_CMDTOSIGEN_SHIFT 16
#define SD4_EMMC_TOP_INTREN2_SD4_CMDTOSIGEN_MASK 0x00010000
#define SD4_EMMC_TOP_INTREN2_SD4_FIXZERO_SHIFT 15
#define SD4_EMMC_TOP_INTREN2_SD4_FIXZERO_MASK 0x00008000
#define SD4_EMMC_TOP_INTREN2_SD4_RETUNE_EVENTSIGEN_SHIFT 12
#define SD4_EMMC_TOP_INTREN2_SD4_RETUNE_EVENTSIGEN_MASK 0x00001000
#define SD4_EMMC_TOP_INTREN2_SD4_INT_C_SIGEN_SHIFT 11
#define SD4_EMMC_TOP_INTREN2_SD4_INT_C_SIGEN_MASK 0x00000800
#define SD4_EMMC_TOP_INTREN2_SD4_INT_B_SIGEN_SHIFT 10
#define SD4_EMMC_TOP_INTREN2_SD4_INT_B_SIGEN_MASK 0x00000400
#define SD4_EMMC_TOP_INTREN2_SD4_INT_A_SIGEN_SHIFT 9
#define SD4_EMMC_TOP_INTREN2_SD4_INT_A_SIGEN_MASK 0x00000200
#define SD4_EMMC_TOP_INTREN2_SD4_CRDIRQEN_SHIFT 8
#define SD4_EMMC_TOP_INTREN2_SD4_CRDIRQEN_MASK 0x00000100
#define SD4_EMMC_TOP_INTREN2_SD4_CRDRVMEN_SHIFT 7
#define SD4_EMMC_TOP_INTREN2_SD4_CRDRVMEN_MASK 0x00000080
#define SD4_EMMC_TOP_INTREN2_SD4_CRDINSEN_SHIFT 6
#define SD4_EMMC_TOP_INTREN2_SD4_CRDINSEN_MASK 0x00000040
#define SD4_EMMC_TOP_INTREN2_SD4_BUFRRDYEN_SHIFT 5
#define SD4_EMMC_TOP_INTREN2_SD4_BUFRRDYEN_MASK 0x00000020
#define SD4_EMMC_TOP_INTREN2_SD4_BUFWRDYEN_SHIFT 4
#define SD4_EMMC_TOP_INTREN2_SD4_BUFWRDYEN_MASK 0x00000010
#define SD4_EMMC_TOP_INTREN2_SD4_DMAIRQEN_SHIFT 3
#define SD4_EMMC_TOP_INTREN2_SD4_DMAIRQEN_MASK 0x00000008
#define SD4_EMMC_TOP_INTREN2_SD4_BLKGAPEN_SHIFT 2
#define SD4_EMMC_TOP_INTREN2_SD4_BLKGAPEN_MASK 0x00000004
#define SD4_EMMC_TOP_INTREN2_SD4_TXDONE_SHIFT 1
#define SD4_EMMC_TOP_INTREN2_SD4_TXDONE_MASK 0x00000002
#define SD4_EMMC_TOP_INTREN2_SD4_CMDDONE_SHIFT 0
#define SD4_EMMC_TOP_INTREN2_SD4_CMDDONE_MASK 0x00000001
#define SD4_EMMC_TOP_ERRSTAT_OFFSET 0x0000003C
#define SD4_EMMC_TOP_ERRSTAT_DEFAULT 0x00000000
#define SD4_EMMC_TOP_ERRSTAT_TYPE uint32_t
#define SD4_EMMC_TOP_ERRSTAT_RESERVED_MASK 0x3F00FF60
#define SD4_EMMC_TOP_ERRSTAT_PRESETEN_SHIFT 31
#define SD4_EMMC_TOP_ERRSTAT_PRESETEN_MASK 0x80000000
#define SD4_EMMC_TOP_ERRSTAT_ASYNC_INTREN_SHIFT 30
#define SD4_EMMC_TOP_ERRSTAT_ASYNC_INTREN_MASK 0x40000000
#define SD4_EMMC_TOP_ERRSTAT_SAMPLECLOCKSEL_SHIFT 23
#define SD4_EMMC_TOP_ERRSTAT_SAMPLECLOCKSEL_MASK 0x00800000
#define SD4_EMMC_TOP_ERRSTAT_EXECTUNE_SHIFT 22
#define SD4_EMMC_TOP_ERRSTAT_EXECTUNE_MASK 0x00400000
#define SD4_EMMC_TOP_ERRSTAT_DRVSTRESEL_SHIFT 20
#define SD4_EMMC_TOP_ERRSTAT_DRVSTRESEL_MASK 0x00300000
#define SD4_EMMC_TOP_ERRSTAT_EN1P8V_SHIFT 19
#define SD4_EMMC_TOP_ERRSTAT_EN1P8V_MASK 0x00080000
#define SD4_EMMC_TOP_ERRSTAT_UHSMODESEL_SHIFT 16
#define SD4_EMMC_TOP_ERRSTAT_UHSMODESEL_MASK 0x00070000
#define SD4_EMMC_TOP_ERRSTAT_NOCMD_SHIFT 7
#define SD4_EMMC_TOP_ERRSTAT_NOCMD_MASK 0x00000080
#define SD4_EMMC_TOP_ERRSTAT_CMDIDXERR_SHIFT 4
#define SD4_EMMC_TOP_ERRSTAT_CMDIDXERR_MASK 0x00000010
#define SD4_EMMC_TOP_ERRSTAT_CMDENDERR_SHIFT 3
#define SD4_EMMC_TOP_ERRSTAT_CMDENDERR_MASK 0x00000008
#define SD4_EMMC_TOP_ERRSTAT_CMDCRCERR_SHIFT 2
#define SD4_EMMC_TOP_ERRSTAT_CMDCRCERR_MASK 0x00000004
#define SD4_EMMC_TOP_ERRSTAT_CMDTOERR_SHIFT 1
#define SD4_EMMC_TOP_ERRSTAT_CMDTOERR_MASK 0x00000002
#define SD4_EMMC_TOP_ERRSTAT_CMDNOEXEC_SHIFT 0
#define SD4_EMMC_TOP_ERRSTAT_CMDNOEXEC_MASK 0x00000001
#define SD4_EMMC_TOP_ERRSTAT_SD4_OFFSET 0x0000003C
#define SD4_EMMC_TOP_ERRSTAT_SD4_DEFAULT 0x00000000
#define SD4_EMMC_TOP_ERRSTAT_SD4_TYPE uint32_t
#define SD4_EMMC_TOP_ERRSTAT_SD4_RESERVED_MASK 0x0E00FF40
#define SD4_EMMC_TOP_ERRSTAT_SD4_PRESETEN_SHIFT 31
#define SD4_EMMC_TOP_ERRSTAT_SD4_PRESETEN_MASK 0x80000000
#define SD4_EMMC_TOP_ERRSTAT_SD4_ASYNC_INTREN_SHIFT 30
#define SD4_EMMC_TOP_ERRSTAT_SD4_ASYNC_INTREN_MASK 0x40000000
#define SD4_EMMC_TOP_ERRSTAT_SD4_ADDR64_SHIFT 29
#define SD4_EMMC_TOP_ERRSTAT_SD4_ADDR64_MASK 0x20000000
#define SD4_EMMC_TOP_ERRSTAT_SD4_HOSTVER4_00_SHIFT 28
#define SD4_EMMC_TOP_ERRSTAT_SD4_HOSTVER4_00_MASK 0x10000000
#define SD4_EMMC_TOP_ERRSTAT_SD4_UHS2INTFEN_SHIFT 24
#define SD4_EMMC_TOP_ERRSTAT_SD4_UHS2INTFEN_MASK 0x01000000
#define SD4_EMMC_TOP_ERRSTAT_SD4_SAMPLECLOCKSEL_SHIFT 23
#define SD4_EMMC_TOP_ERRSTAT_SD4_SAMPLECLOCKSEL_MASK 0x00800000
#define SD4_EMMC_TOP_ERRSTAT_SD4_EXECTUNE_SHIFT 22
#define SD4_EMMC_TOP_ERRSTAT_SD4_EXECTUNE_MASK 0x00400000
#define SD4_EMMC_TOP_ERRSTAT_SD4_DRVSTRESEL_SHIFT 20
#define SD4_EMMC_TOP_ERRSTAT_SD4_DRVSTRESEL_MASK 0x00300000
#define SD4_EMMC_TOP_ERRSTAT_SD4_EN1P8V_SHIFT 19
#define SD4_EMMC_TOP_ERRSTAT_SD4_EN1P8V_MASK 0x00080000
#define SD4_EMMC_TOP_ERRSTAT_SD4_UHSMODESEL_SHIFT 16
#define SD4_EMMC_TOP_ERRSTAT_SD4_UHSMODESEL_MASK 0x00070000
#define SD4_EMMC_TOP_ERRSTAT_SD4_NOCMD_SHIFT 7
#define SD4_EMMC_TOP_ERRSTAT_SD4_NOCMD_MASK 0x00000080
#define SD4_EMMC_TOP_ERRSTAT_SD4_CMDRESPERR_SHIFT 5
#define SD4_EMMC_TOP_ERRSTAT_SD4_CMDRESPERR_MASK 0x00000020
#define SD4_EMMC_TOP_ERRSTAT_SD4_CMDIDXERR_SHIFT 4
#define SD4_EMMC_TOP_ERRSTAT_SD4_CMDIDXERR_MASK 0x00000010
#define SD4_EMMC_TOP_ERRSTAT_SD4_CMDENDERR_SHIFT 3
#define SD4_EMMC_TOP_ERRSTAT_SD4_CMDENDERR_MASK 0x00000008
#define SD4_EMMC_TOP_ERRSTAT_SD4_CMDCRCERR_SHIFT 2
#define SD4_EMMC_TOP_ERRSTAT_SD4_CMDCRCERR_MASK 0x00000004
#define SD4_EMMC_TOP_ERRSTAT_SD4_CMDTOERR_SHIFT 1
#define SD4_EMMC_TOP_ERRSTAT_SD4_CMDTOERR_MASK 0x00000002
#define SD4_EMMC_TOP_ERRSTAT_SD4_CMDNOEXEC_SHIFT 0
#define SD4_EMMC_TOP_ERRSTAT_SD4_CMDNOEXEC_MASK 0x00000001
#define SD4_EMMC_TOP_CAPABILITIES1_OFFSET 0x00000040
#define SD4_EMMC_TOP_CAPABILITIES1_DEFAULT 0x17EFD0B0
#define SD4_EMMC_TOP_CAPABILITIES1_TYPE uint32_t
#define SD4_EMMC_TOP_CAPABILITIES1_RESERVED_MASK 0x08100040
#define SD4_EMMC_TOP_CAPABILITIES1_SLOTTYPE_SHIFT 30
#define SD4_EMMC_TOP_CAPABILITIES1_SLOTTYPE_MASK 0xC0000000
#define SD4_EMMC_TOP_CAPABILITIES1_ASYNCHIRQ_SHIFT 29
#define SD4_EMMC_TOP_CAPABILITIES1_ASYNCHIRQ_MASK 0x20000000
#define SD4_EMMC_TOP_CAPABILITIES1_SYSBUS64_SHIFT 28
#define SD4_EMMC_TOP_CAPABILITIES1_SYSBUS64_MASK 0x10000000
#define SD4_EMMC_TOP_CAPABILITIES1_V18_SHIFT 26
#define SD4_EMMC_TOP_CAPABILITIES1_V18_MASK 0x04000000
#define SD4_EMMC_TOP_CAPABILITIES1_V3_SHIFT 25
#define SD4_EMMC_TOP_CAPABILITIES1_V3_MASK 0x02000000
#define SD4_EMMC_TOP_CAPABILITIES1_V33_SHIFT 24
#define SD4_EMMC_TOP_CAPABILITIES1_V33_MASK 0x01000000
#define SD4_EMMC_TOP_CAPABILITIES1_SUPRSM_SHIFT 23
#define SD4_EMMC_TOP_CAPABILITIES1_SUPRSM_MASK 0x00800000
#define SD4_EMMC_TOP_CAPABILITIES1_SDMA_SHIFT 22
#define SD4_EMMC_TOP_CAPABILITIES1_SDMA_MASK 0x00400000
#define SD4_EMMC_TOP_CAPABILITIES1_HSPEED_SHIFT 21
#define SD4_EMMC_TOP_CAPABILITIES1_HSPEED_MASK 0x00200000
#define SD4_EMMC_TOP_CAPABILITIES1_ADMA2_SHIFT 19
#define SD4_EMMC_TOP_CAPABILITIES1_ADMA2_MASK 0x00080000
#define SD4_EMMC_TOP_CAPABILITIES1_EXTBUSMED_SHIFT 18
#define SD4_EMMC_TOP_CAPABILITIES1_EXTBUSMED_MASK 0x00040000
#define SD4_EMMC_TOP_CAPABILITIES1_MAXBLK_SHIFT 16
#define SD4_EMMC_TOP_CAPABILITIES1_MAXBLK_MASK 0x00030000
#define SD4_EMMC_TOP_CAPABILITIES1_BCLK_SHIFT 8
#define SD4_EMMC_TOP_CAPABILITIES1_BCLK_MASK 0x0000FF00
#define SD4_EMMC_TOP_CAPABILITIES1_TOUT_SHIFT 7
#define SD4_EMMC_TOP_CAPABILITIES1_TOUT_MASK 0x00000080
#define SD4_EMMC_TOP_CAPABILITIES1_TOUTFREQ_SHIFT 0
#define SD4_EMMC_TOP_CAPABILITIES1_TOUTFREQ_MASK 0x0000003F
#define SD4_EMMC_TOP_CAPABILITIES1_SD4_OFFSET 0x00000040
#define SD4_EMMC_TOP_CAPABILITIES1_SD4_DEFAULT 0x10E934B4
#define SD4_EMMC_TOP_CAPABILITIES1_SD4_TYPE uint32_t
#define SD4_EMMC_TOP_CAPABILITIES1_SD4_RESERVED_MASK 0x08100040
#define SD4_EMMC_TOP_CAPABILITIES1_SD4_SLOTTYPE_SHIFT 30
#define SD4_EMMC_TOP_CAPABILITIES1_SD4_SLOTTYPE_MASK 0xC0000000
#define SD4_EMMC_TOP_CAPABILITIES1_SD4_ASYNCHIRQ_SHIFT 29
#define SD4_EMMC_TOP_CAPABILITIES1_SD4_ASYNCHIRQ_MASK 0x20000000
#define SD4_EMMC_TOP_CAPABILITIES1_SD4_SYSBUS64_SHIFT 28
#define SD4_EMMC_TOP_CAPABILITIES1_SD4_SYSBUS64_MASK 0x10000000
#define SD4_EMMC_TOP_CAPABILITIES1_SD4_V18_SHIFT 26
#define SD4_EMMC_TOP_CAPABILITIES1_SD4_V18_MASK 0x04000000
#define SD4_EMMC_TOP_CAPABILITIES1_SD4_V3_SHIFT 25
#define SD4_EMMC_TOP_CAPABILITIES1_SD4_V3_MASK 0x02000000
#define SD4_EMMC_TOP_CAPABILITIES1_SD4_V33_SHIFT 24
#define SD4_EMMC_TOP_CAPABILITIES1_SD4_V33_MASK 0x01000000
#define SD4_EMMC_TOP_CAPABILITIES1_SD4_SUPRSM_SHIFT 23
#define SD4_EMMC_TOP_CAPABILITIES1_SD4_SUPRSM_MASK 0x00800000
#define SD4_EMMC_TOP_CAPABILITIES1_SD4_SDMA_SHIFT 22
#define SD4_EMMC_TOP_CAPABILITIES1_SD4_SDMA_MASK 0x00400000
#define SD4_EMMC_TOP_CAPABILITIES1_SD4_HSPEED_SHIFT 21
#define SD4_EMMC_TOP_CAPABILITIES1_SD4_HSPEED_MASK 0x00200000
#define SD4_EMMC_TOP_CAPABILITIES1_SD4_ADMA2_SHIFT 19
#define SD4_EMMC_TOP_CAPABILITIES1_SD4_ADMA2_MASK 0x00080000
#define SD4_EMMC_TOP_CAPABILITIES1_SD4_EXTBUSMED_SHIFT 18
#define SD4_EMMC_TOP_CAPABILITIES1_SD4_EXTBUSMED_MASK 0x00040000
#define SD4_EMMC_TOP_CAPABILITIES1_SD4_MAXBLK_SHIFT 16
#define SD4_EMMC_TOP_CAPABILITIES1_SD4_MAXBLK_MASK 0x00030000
#define SD4_EMMC_TOP_CAPABILITIES1_SD4_BCLK_SHIFT 8
#define SD4_EMMC_TOP_CAPABILITIES1_SD4_BCLK_MASK 0x0000FF00
#define SD4_EMMC_TOP_CAPABILITIES1_SD4_TOUT_SHIFT 7
#define SD4_EMMC_TOP_CAPABILITIES1_SD4_TOUT_MASK 0x00000080
#define SD4_EMMC_TOP_CAPABILITIES1_SD4_TOUTFREQ_SHIFT 0
#define SD4_EMMC_TOP_CAPABILITIES1_SD4_TOUTFREQ_MASK 0x0000003F
#define SD4_EMMC_TOP_CAPABILITIES2_OFFSET 0x00000044
#define SD4_EMMC_TOP_CAPABILITIES2_DEFAULT 0x03002177
#define SD4_EMMC_TOP_CAPABILITIES2_TYPE uint32_t
#define SD4_EMMC_TOP_CAPABILITIES2_RESERVED_MASK 0xFC001088
#define SD4_EMMC_TOP_CAPABILITIES2_SPIBLOCKMODE_SHIFT 25
#define SD4_EMMC_TOP_CAPABILITIES2_SPIBLOCKMODE_MASK 0x02000000
#define SD4_EMMC_TOP_CAPABILITIES2_SPIMODE_CAP_SHIFT 24
#define SD4_EMMC_TOP_CAPABILITIES2_SPIMODE_CAP_MASK 0x01000000
#define SD4_EMMC_TOP_CAPABILITIES2_CLOCKMULT_SHIFT 16
#define SD4_EMMC_TOP_CAPABILITIES2_CLOCKMULT_MASK 0x00FF0000
#define SD4_EMMC_TOP_CAPABILITIES2_RETUNE_MODE_SHIFT 14
#define SD4_EMMC_TOP_CAPABILITIES2_RETUNE_MODE_MASK 0x0000C000
#define SD4_EMMC_TOP_CAPABILITIES2_USETUNE_SDR50_SHIFT 13
#define SD4_EMMC_TOP_CAPABILITIES2_USETUNE_SDR50_MASK 0x00002000
#define SD4_EMMC_TOP_CAPABILITIES2_TMRCNT_RETUNE_SHIFT 8
#define SD4_EMMC_TOP_CAPABILITIES2_TMRCNT_RETUNE_MASK 0x00000F00
#define SD4_EMMC_TOP_CAPABILITIES2_DRVR_TYPED_SHIFT 6
#define SD4_EMMC_TOP_CAPABILITIES2_DRVR_TYPED_MASK 0x00000040
#define SD4_EMMC_TOP_CAPABILITIES2_DRVR_TYPEC_SHIFT 5
#define SD4_EMMC_TOP_CAPABILITIES2_DRVR_TYPEC_MASK 0x00000020
#define SD4_EMMC_TOP_CAPABILITIES2_DRVR_TYPEA_SHIFT 4
#define SD4_EMMC_TOP_CAPABILITIES2_DRVR_TYPEA_MASK 0x00000010
#define SD4_EMMC_TOP_CAPABILITIES2_DDR50_SHIFT 2
#define SD4_EMMC_TOP_CAPABILITIES2_DDR50_MASK 0x00000004
#define SD4_EMMC_TOP_CAPABILITIES2_SDR104_SHIFT 1
#define SD4_EMMC_TOP_CAPABILITIES2_SDR104_MASK 0x00000002
#define SD4_EMMC_TOP_CAPABILITIES2_SDR50_SHIFT 0
#define SD4_EMMC_TOP_CAPABILITIES2_SDR50_MASK 0x00000001
#define SD4_EMMC_TOP_CAPABILITIES2_SD4_OFFSET 0x00000044
#define SD4_EMMC_TOP_CAPABILITIES2_SD4_DEFAULT 0x10000064
#define SD4_EMMC_TOP_CAPABILITIES2_SD4_TYPE uint32_t
#define SD4_EMMC_TOP_CAPABILITIES2_SD4_RESERVED_MASK 0xE7001080
#define SD4_EMMC_TOP_CAPABILITIES2_SD4_VDD2_18_SHIFT 28
#define SD4_EMMC_TOP_CAPABILITIES2_SD4_VDD2_18_MASK 0x10000000
#define SD4_EMMC_TOP_CAPABILITIES2_SD4_ADMA3_SHIFT 27
#define SD4_EMMC_TOP_CAPABILITIES2_SD4_ADMA3_MASK 0x08000000
#define SD4_EMMC_TOP_CAPABILITIES2_SD4_CLOCKMULT_SHIFT 16
#define SD4_EMMC_TOP_CAPABILITIES2_SD4_CLOCKMULT_MASK 0x00FF0000
#define SD4_EMMC_TOP_CAPABILITIES2_SD4_RETUNE_MODE_SHIFT 14
#define SD4_EMMC_TOP_CAPABILITIES2_SD4_RETUNE_MODE_MASK 0x0000C000
#define SD4_EMMC_TOP_CAPABILITIES2_SD4_USETUNE_SDR50_SHIFT 13
#define SD4_EMMC_TOP_CAPABILITIES2_SD4_USETUNE_SDR50_MASK 0x00002000
#define SD4_EMMC_TOP_CAPABILITIES2_SD4_TMRCNT_RETUNE_SHIFT 8
#define SD4_EMMC_TOP_CAPABILITIES2_SD4_TMRCNT_RETUNE_MASK 0x00000F00
#define SD4_EMMC_TOP_CAPABILITIES2_SD4_DRVR_TYPED_SHIFT 6
#define SD4_EMMC_TOP_CAPABILITIES2_SD4_DRVR_TYPED_MASK 0x00000040
#define SD4_EMMC_TOP_CAPABILITIES2_SD4_DRVR_TYPEC_SHIFT 5
#define SD4_EMMC_TOP_CAPABILITIES2_SD4_DRVR_TYPEC_MASK 0x00000020
#define SD4_EMMC_TOP_CAPABILITIES2_SD4_DRVR_TYPEA_SHIFT 4
#define SD4_EMMC_TOP_CAPABILITIES2_SD4_DRVR_TYPEA_MASK 0x00000010
#define SD4_EMMC_TOP_CAPABILITIES2_SD4_UHS_II_SHIFT 3
#define SD4_EMMC_TOP_CAPABILITIES2_SD4_UHS_II_MASK 0x00000008
#define SD4_EMMC_TOP_CAPABILITIES2_SD4_DDR50_SHIFT 2
#define SD4_EMMC_TOP_CAPABILITIES2_SD4_DDR50_MASK 0x00000004
#define SD4_EMMC_TOP_CAPABILITIES2_SD4_SDR104_SHIFT 1
#define SD4_EMMC_TOP_CAPABILITIES2_SD4_SDR104_MASK 0x00000002
#define SD4_EMMC_TOP_CAPABILITIES2_SD4_SDR50_SHIFT 0
#define SD4_EMMC_TOP_CAPABILITIES2_SD4_SDR50_MASK 0x00000001
#define SD4_EMMC_TOP_MAX_A1_OFFSET 0x00000048
#define SD4_EMMC_TOP_MAX_A1_DEFAULT 0x00000001
#define SD4_EMMC_TOP_MAX_A1_TYPE uint32_t
#define SD4_EMMC_TOP_MAX_A1_RESERVED_MASK 0xFF000000
#define SD4_EMMC_TOP_MAX_A1_MAXA18_SHIFT 16
#define SD4_EMMC_TOP_MAX_A1_MAXA18_MASK 0x00FF0000
#define SD4_EMMC_TOP_MAX_A1_MAXA30_SHIFT 8
#define SD4_EMMC_TOP_MAX_A1_MAXA30_MASK 0x0000FF00
#define SD4_EMMC_TOP_MAX_A1_MAXA33_SHIFT 0
#define SD4_EMMC_TOP_MAX_A1_MAXA33_MASK 0x000000FF
#define SD4_EMMC_TOP_MAX_A2_OFFSET 0x0000004C
#define SD4_EMMC_TOP_MAX_A2_DEFAULT 0x00000000
#define SD4_EMMC_TOP_MAX_A2_TYPE uint32_t
#define SD4_EMMC_TOP_MAX_A2_RESERVED_MASK 0xFFFFFFFF
#define SD4_EMMC_TOP_MAX_A2_SD4_OFFSET 0x0000004C
#define SD4_EMMC_TOP_MAX_A2_SD4_DEFAULT 0x00000001
#define SD4_EMMC_TOP_MAX_A2_SD4_TYPE uint32_t
#define SD4_EMMC_TOP_MAX_A2_SD4_RESERVED_MASK 0xFFFFFF00
#define SD4_EMMC_TOP_MAX_A2_SD4_MAXAVDD2_SHIFT 0
#define SD4_EMMC_TOP_MAX_A2_SD4_MAXAVDD2_MASK 0x000000FF
#define SD4_EMMC_TOP_CMDENTSTAT_OFFSET 0x00000050
#define SD4_EMMC_TOP_CMDENTSTAT_DEFAULT 0x00000000
#define SD4_EMMC_TOP_CMDENTSTAT_TYPE uint32_t
#define SD4_EMMC_TOP_CMDENTSTAT_RESERVED_MASK 0x2C00FF60
#define SD4_EMMC_TOP_CMDENTSTAT_VSES_SHIFT 30
#define SD4_EMMC_TOP_CMDENTSTAT_VSES_MASK 0xC0000000
#define SD4_EMMC_TOP_CMDENTSTAT_TRERR_SHIFT 28
#define SD4_EMMC_TOP_CMDENTSTAT_TRERR_MASK 0x10000000
#define SD4_EMMC_TOP_CMDENTSTAT_ADMAERR_SHIFT 25
#define SD4_EMMC_TOP_CMDENTSTAT_ADMAERR_MASK 0x02000000
#define SD4_EMMC_TOP_CMDENTSTAT_ACMDERR_SHIFT 24
#define SD4_EMMC_TOP_CMDENTSTAT_ACMDERR_MASK 0x01000000
#define SD4_EMMC_TOP_CMDENTSTAT_ILERR_SHIFT 23
#define SD4_EMMC_TOP_CMDENTSTAT_ILERR_MASK 0x00800000
#define SD4_EMMC_TOP_CMDENTSTAT_DENDERR_SHIFT 22
#define SD4_EMMC_TOP_CMDENTSTAT_DENDERR_MASK 0x00400000
#define SD4_EMMC_TOP_CMDENTSTAT_DCRCERR_SHIFT 21
#define SD4_EMMC_TOP_CMDENTSTAT_DCRCERR_MASK 0x00200000
#define SD4_EMMC_TOP_CMDENTSTAT_DTOUTERR_SHIFT 20
#define SD4_EMMC_TOP_CMDENTSTAT_DTOUTERR_MASK 0x00100000
#define SD4_EMMC_TOP_CMDENTSTAT_CIDXERR_SHIFT 19
#define SD4_EMMC_TOP_CMDENTSTAT_CIDXERR_MASK 0x00080000
#define SD4_EMMC_TOP_CMDENTSTAT_CENDERR_SHIFT 18
#define SD4_EMMC_TOP_CMDENTSTAT_CENDERR_MASK 0x00040000
#define SD4_EMMC_TOP_CMDENTSTAT_CCRCERR_SHIFT 17
#define SD4_EMMC_TOP_CMDENTSTAT_CCRCERR_MASK 0x00020000
#define SD4_EMMC_TOP_CMDENTSTAT_CTOUTERR_SHIFT 16
#define SD4_EMMC_TOP_CMDENTSTAT_CTOUTERR_MASK 0x00010000
#define SD4_EMMC_TOP_CMDENTSTAT_NOFRCENT_SHIFT 7
#define SD4_EMMC_TOP_CMDENTSTAT_NOFRCENT_MASK 0x00000080
#define SD4_EMMC_TOP_CMDENTSTAT_IDXERR_SHIFT 4
#define SD4_EMMC_TOP_CMDENTSTAT_IDXERR_MASK 0x00000010
#define SD4_EMMC_TOP_CMDENTSTAT_EBITERR_SHIFT 3
#define SD4_EMMC_TOP_CMDENTSTAT_EBITERR_MASK 0x00000008
#define SD4_EMMC_TOP_CMDENTSTAT_CRCERR_SHIFT 2
#define SD4_EMMC_TOP_CMDENTSTAT_CRCERR_MASK 0x00000004
#define SD4_EMMC_TOP_CMDENTSTAT_TOUTERR_SHIFT 1
#define SD4_EMMC_TOP_CMDENTSTAT_TOUTERR_MASK 0x00000002
#define SD4_EMMC_TOP_CMDENTSTAT_AUTONOEX_SHIFT 0
#define SD4_EMMC_TOP_CMDENTSTAT_AUTONOEX_MASK 0x00000001
#define SD4_EMMC_TOP_CMDENTSTAT_SD4_OFFSET 0x00000050
#define SD4_EMMC_TOP_CMDENTSTAT_SD4_DEFAULT 0x00000000
#define SD4_EMMC_TOP_CMDENTSTAT_SD4_TYPE uint32_t
#define SD4_EMMC_TOP_CMDENTSTAT_SD4_RESERVED_MASK 0x0000FF40
#define SD4_EMMC_TOP_CMDENTSTAT_SD4_VSES_SHIFT 28
#define SD4_EMMC_TOP_CMDENTSTAT_SD4_VSES_MASK 0xF0000000
#define SD4_EMMC_TOP_CMDENTSTAT_SD4_TRESPERR_SHIFT 27
#define SD4_EMMC_TOP_CMDENTSTAT_SD4_TRESPERR_MASK 0x08000000
#define SD4_EMMC_TOP_CMDENTSTAT_SD4_TUNERR_SHIFT 26
#define SD4_EMMC_TOP_CMDENTSTAT_SD4_TUNERR_MASK 0x04000000
#define SD4_EMMC_TOP_CMDENTSTAT_SD4_ADMAERR_SHIFT 25
#define SD4_EMMC_TOP_CMDENTSTAT_SD4_ADMAERR_MASK 0x02000000
#define SD4_EMMC_TOP_CMDENTSTAT_SD4_ACMDERR_SHIFT 24
#define SD4_EMMC_TOP_CMDENTSTAT_SD4_ACMDERR_MASK 0x01000000
#define SD4_EMMC_TOP_CMDENTSTAT_SD4_ILERR_SHIFT 23
#define SD4_EMMC_TOP_CMDENTSTAT_SD4_ILERR_MASK 0x00800000
#define SD4_EMMC_TOP_CMDENTSTAT_SD4_DENDERR_SHIFT 22
#define SD4_EMMC_TOP_CMDENTSTAT_SD4_DENDERR_MASK 0x00400000
#define SD4_EMMC_TOP_CMDENTSTAT_SD4_DCRCERR_SHIFT 21
#define SD4_EMMC_TOP_CMDENTSTAT_SD4_DCRCERR_MASK 0x00200000
#define SD4_EMMC_TOP_CMDENTSTAT_SD4_DTOUTERR_SHIFT 20
#define SD4_EMMC_TOP_CMDENTSTAT_SD4_DTOUTERR_MASK 0x00100000
#define SD4_EMMC_TOP_CMDENTSTAT_SD4_CIDXERR_SHIFT 19
#define SD4_EMMC_TOP_CMDENTSTAT_SD4_CIDXERR_MASK 0x00080000
#define SD4_EMMC_TOP_CMDENTSTAT_SD4_CENDERR_SHIFT 18
#define SD4_EMMC_TOP_CMDENTSTAT_SD4_CENDERR_MASK 0x00040000
#define SD4_EMMC_TOP_CMDENTSTAT_SD4_CCRCERR_SHIFT 17
#define SD4_EMMC_TOP_CMDENTSTAT_SD4_CCRCERR_MASK 0x00020000
#define SD4_EMMC_TOP_CMDENTSTAT_SD4_CTOUTERR_SHIFT 16
#define SD4_EMMC_TOP_CMDENTSTAT_SD4_CTOUTERR_MASK 0x00010000
#define SD4_EMMC_TOP_CMDENTSTAT_SD4_NOFRCENT_SHIFT 7
#define SD4_EMMC_TOP_CMDENTSTAT_SD4_NOFRCENT_MASK 0x00000080
#define SD4_EMMC_TOP_CMDENTSTAT_SD4_RESPERR_SHIFT 5
#define SD4_EMMC_TOP_CMDENTSTAT_SD4_RESPERR_MASK 0x00000020
#define SD4_EMMC_TOP_CMDENTSTAT_SD4_IDXERR_SHIFT 4
#define SD4_EMMC_TOP_CMDENTSTAT_SD4_IDXERR_MASK 0x00000010
#define SD4_EMMC_TOP_CMDENTSTAT_SD4_EBITERR_SHIFT 3
#define SD4_EMMC_TOP_CMDENTSTAT_SD4_EBITERR_MASK 0x00000008
#define SD4_EMMC_TOP_CMDENTSTAT_SD4_CRCERR_SHIFT 2
#define SD4_EMMC_TOP_CMDENTSTAT_SD4_CRCERR_MASK 0x00000004
#define SD4_EMMC_TOP_CMDENTSTAT_SD4_TOUTERR_SHIFT 1
#define SD4_EMMC_TOP_CMDENTSTAT_SD4_TOUTERR_MASK 0x00000002
#define SD4_EMMC_TOP_CMDENTSTAT_SD4_AUTONOEX_SHIFT 0
#define SD4_EMMC_TOP_CMDENTSTAT_SD4_AUTONOEX_MASK 0x00000001
#define SD4_EMMC_TOP_ADMAERR_OFFSET 0x00000054
#define SD4_EMMC_TOP_ADMAERR_DEFAULT 0x00000000
#define SD4_EMMC_TOP_ADMAERR_TYPE uint32_t
#define SD4_EMMC_TOP_ADMAERR_RESERVED_MASK 0xFFFFFFF8
#define SD4_EMMC_TOP_ADMAERR_ADMALERR_SHIFT 2
#define SD4_EMMC_TOP_ADMAERR_ADMALERR_MASK 0x00000004
#define SD4_EMMC_TOP_ADMAERR_ADMAERR_SHIFT 0
#define SD4_EMMC_TOP_ADMAERR_ADMAERR_MASK 0x00000003
#define SD4_EMMC_TOP_ADMAADDR0_OFFSET 0x00000058
#define SD4_EMMC_TOP_ADMAADDR0_DEFAULT 0x00000000
#define SD4_EMMC_TOP_ADMAADDR0_TYPE uint32_t
#define SD4_EMMC_TOP_ADMAADDR0_RESERVED_MASK 0x00000000
#define SD4_EMMC_TOP_ADMAADDR0_ADMAADDR0_SHIFT 0
#define SD4_EMMC_TOP_ADMAADDR0_ADMAADDR0_MASK 0xFFFFFFFF
#define SD4_EMMC_TOP_ADMAADDR1_OFFSET 0x0000005C
#define SD4_EMMC_TOP_ADMAADDR1_DEFAULT 0x00000000
#define SD4_EMMC_TOP_ADMAADDR1_TYPE uint32_t
#define SD4_EMMC_TOP_ADMAADDR1_RESERVED_MASK 0x00000000
#define SD4_EMMC_TOP_ADMAADDR1_ADMAADDR1_SHIFT 0
#define SD4_EMMC_TOP_ADMAADDR1_ADMAADDR1_MASK 0xFFFFFFFF
#define SD4_EMMC_TOP_PRESETVAL1_OFFSET 0x00000060
#define SD4_EMMC_TOP_PRESETVAL1_DEFAULT 0x00000000
#define SD4_EMMC_TOP_PRESETVAL1_TYPE uint32_t
#define SD4_EMMC_TOP_PRESETVAL1_RESERVED_MASK 0x38003800
#define SD4_EMMC_TOP_PRESETVAL1_DRVS_SEL_DFS_SHIFT 30
#define SD4_EMMC_TOP_PRESETVAL1_DRVS_SEL_DFS_MASK 0xC0000000
#define SD4_EMMC_TOP_PRESETVAL1_CLKGENSEL_DFS_SHIFT 26
#define SD4_EMMC_TOP_PRESETVAL1_CLKGENSEL_DFS_MASK 0x04000000
#define SD4_EMMC_TOP_PRESETVAL1_FREQ_SEL_DFS_SHIFT 16
#define SD4_EMMC_TOP_PRESETVAL1_FREQ_SEL_DFS_MASK 0x03FF0000
#define SD4_EMMC_TOP_PRESETVAL1_DRVS_SEL_INIT_SHIFT 14
#define SD4_EMMC_TOP_PRESETVAL1_DRVS_SEL_INIT_MASK 0x0000C000
#define SD4_EMMC_TOP_PRESETVAL1_CLKGENSEL_INIT_SHIFT 10
#define SD4_EMMC_TOP_PRESETVAL1_CLKGENSEL_INIT_MASK 0x00000400
#define SD4_EMMC_TOP_PRESETVAL1_FREQ_SEL_INIT_SHIFT 0
#define SD4_EMMC_TOP_PRESETVAL1_FREQ_SEL_INIT_MASK 0x000003FF
#define SD4_EMMC_TOP_PRESETVAL2_OFFSET 0x00000064
#define SD4_EMMC_TOP_PRESETVAL2_DEFAULT 0x00000000
#define SD4_EMMC_TOP_PRESETVAL2_TYPE uint32_t
#define SD4_EMMC_TOP_PRESETVAL2_RESERVED_MASK 0x38003800
#define SD4_EMMC_TOP_PRESETVAL2_DRVS_SEL_SDR12_SHIFT 30
#define SD4_EMMC_TOP_PRESETVAL2_DRVS_SEL_SDR12_MASK 0xC0000000
#define SD4_EMMC_TOP_PRESETVAL2_CLKGENSEL_SDR12_SHIFT 26
#define SD4_EMMC_TOP_PRESETVAL2_CLKGENSEL_SDR12_MASK 0x04000000
#define SD4_EMMC_TOP_PRESETVAL2_FREQ_SEL_SDR12_SHIFT 16
#define SD4_EMMC_TOP_PRESETVAL2_FREQ_SEL_SDR12_MASK 0x03FF0000
#define SD4_EMMC_TOP_PRESETVAL2_DRVS_SEL_HS_SHIFT 14
#define SD4_EMMC_TOP_PRESETVAL2_DRVS_SEL_HS_MASK 0x0000C000
#define SD4_EMMC_TOP_PRESETVAL2_CLKGENSEL_HS_SHIFT 10
#define SD4_EMMC_TOP_PRESETVAL2_CLKGENSEL_HS_MASK 0x00000400
#define SD4_EMMC_TOP_PRESETVAL2_FREQ_SEL_HS_SHIFT 0
#define SD4_EMMC_TOP_PRESETVAL2_FREQ_SEL_HS_MASK 0x000003FF
#define SD4_EMMC_TOP_PRESETVAL3_OFFSET 0x00000068
#define SD4_EMMC_TOP_PRESETVAL3_DEFAULT 0x00000000
#define SD4_EMMC_TOP_PRESETVAL3_TYPE uint32_t
#define SD4_EMMC_TOP_PRESETVAL3_RESERVED_MASK 0x38003800
#define SD4_EMMC_TOP_PRESETVAL3_DRVS_SEL_SDR50_SHIFT 30
#define SD4_EMMC_TOP_PRESETVAL3_DRVS_SEL_SDR50_MASK 0xC0000000
#define SD4_EMMC_TOP_PRESETVAL3_CLKGENSEL_SDR50_SHIFT 26
#define SD4_EMMC_TOP_PRESETVAL3_CLKGENSEL_SDR50_MASK 0x04000000
#define SD4_EMMC_TOP_PRESETVAL3_FREQ_SEL_SDR50_SHIFT 16
#define SD4_EMMC_TOP_PRESETVAL3_FREQ_SEL_SDR50_MASK 0x03FF0000
#define SD4_EMMC_TOP_PRESETVAL3_DRVS_SEL_SDR25_SHIFT 14
#define SD4_EMMC_TOP_PRESETVAL3_DRVS_SEL_SDR25_MASK 0x0000C000
#define SD4_EMMC_TOP_PRESETVAL3_CLKGENSEL_SDR25_SHIFT 10
#define SD4_EMMC_TOP_PRESETVAL3_CLKGENSEL_SDR25_MASK 0x00000400
#define SD4_EMMC_TOP_PRESETVAL3_FREQ_SEL_SDR25_SHIFT 0
#define SD4_EMMC_TOP_PRESETVAL3_FREQ_SEL_SDR25_MASK 0x000003FF
#define SD4_EMMC_TOP_PRESETVAL4_OFFSET 0x0000006C
#define SD4_EMMC_TOP_PRESETVAL4_DEFAULT 0x00000000
#define SD4_EMMC_TOP_PRESETVAL4_TYPE uint32_t
#define SD4_EMMC_TOP_PRESETVAL4_RESERVED_MASK 0x38003800
#define SD4_EMMC_TOP_PRESETVAL4_DRVS_SEL_DDR50_SHIFT 30
#define SD4_EMMC_TOP_PRESETVAL4_DRVS_SEL_DDR50_MASK 0xC0000000
#define SD4_EMMC_TOP_PRESETVAL4_CLKGENSEL_DDR50_SHIFT 26
#define SD4_EMMC_TOP_PRESETVAL4_CLKGENSEL_DDR50_MASK 0x04000000
#define SD4_EMMC_TOP_PRESETVAL4_FREQ_SEL_DDR50_SHIFT 16
#define SD4_EMMC_TOP_PRESETVAL4_FREQ_SEL_DDR50_MASK 0x03FF0000
#define SD4_EMMC_TOP_PRESETVAL4_DRVS_SEL_SDR104_SHIFT 14
#define SD4_EMMC_TOP_PRESETVAL4_DRVS_SEL_SDR104_MASK 0x0000C000
#define SD4_EMMC_TOP_PRESETVAL4_CLKGENSEL_SDR104_SHIFT 10
#define SD4_EMMC_TOP_PRESETVAL4_CLKGENSEL_SDR104_MASK 0x00000400
#define SD4_EMMC_TOP_PRESETVAL4_FREQ_SEL_SDR104_SHIFT 0
#define SD4_EMMC_TOP_PRESETVAL4_FREQ_SEL_SDR104_MASK 0x000003FF
#define SD4_EMMC_TOP_BOOTTIMEOUT_OFFSET 0x00000070
#define SD4_EMMC_TOP_BOOTTIMEOUT_DEFAULT 0x00000000
#define SD4_EMMC_TOP_BOOTTIMEOUT_TYPE uint32_t
#define SD4_EMMC_TOP_BOOTTIMEOUT_RESERVED_MASK 0x00000000
#define SD4_EMMC_TOP_BOOTTIMEOUT_BOOTDATATIMEOUTCTRVALUE_SHIFT 0
#define SD4_EMMC_TOP_BOOTTIMEOUT_BOOTDATATIMEOUTCTRVALUE_MASK 0xFFFFFFFF
#define SD4_EMMC_TOP_DBGSEL_OFFSET 0x00000074
#define SD4_EMMC_TOP_DBGSEL_DEFAULT 0x00000000
#define SD4_EMMC_TOP_DBGSEL_TYPE uint32_t
#define SD4_EMMC_TOP_DBGSEL_RESERVED_MASK 0xFFFFFFFE
#define SD4_EMMC_TOP_DBGSEL_DBGSEL_SHIFT 0
#define SD4_EMMC_TOP_DBGSEL_DBGSEL_MASK 0x00000001
#define SD4_EMMC_TOP_UHS2_PRESETVAL_OFFSET 0x00000074
#define SD4_EMMC_TOP_UHS2_PRESETVAL_DEFAULT 0x00000000
#define SD4_EMMC_TOP_UHS2_PRESETVAL_TYPE uint32_t
#define SD4_EMMC_TOP_UHS2_PRESETVAL_RESERVED_MASK 0xFFFF3800
#define SD4_EMMC_TOP_UHS2_PRESETVAL_DRVSTRVAL_SHIFT 14
#define SD4_EMMC_TOP_UHS2_PRESETVAL_DRVSTRVAL_MASK 0x0000C000
#define SD4_EMMC_TOP_UHS2_PRESETVAL_CLKGENSELVAL_SHIFT 10
#define SD4_EMMC_TOP_UHS2_PRESETVAL_CLKGENSELVAL_MASK 0x00000400
#define SD4_EMMC_TOP_UHS2_PRESETVAL_SDCLKFREQSELVAL_SHIFT 0
#define SD4_EMMC_TOP_UHS2_PRESETVAL_SDCLKFREQSELVAL_MASK 0x000003FF
#define SD4_EMMC_TOP_HCVERSIRQ_OFFSET 0x000000FC
#define SD4_EMMC_TOP_HCVERSIRQ_DEFAULT 0x10020000
#define SD4_EMMC_TOP_HCVERSIRQ_TYPE uint32_t
#define SD4_EMMC_TOP_HCVERSIRQ_RESERVED_MASK 0x0000FF00
#define SD4_EMMC_TOP_HCVERSIRQ_VENDVER_SHIFT 24
#define SD4_EMMC_TOP_HCVERSIRQ_VENDVER_MASK 0xFF000000
#define SD4_EMMC_TOP_HCVERSIRQ_SPECVER_SHIFT 16
#define SD4_EMMC_TOP_HCVERSIRQ_SPECVER_MASK 0x00FF0000
#define SD4_EMMC_TOP_HCVERSIRQ_SIRQ_SHIFT 0
#define SD4_EMMC_TOP_HCVERSIRQ_SIRQ_MASK 0x000000FF
#define SD4_EMMC_TOP_HCVERSIRQ_SD4_OFFSET 0x000000FC
#define SD4_EMMC_TOP_HCVERSIRQ_SD4_DEFAULT 0x01030000
#define SD4_EMMC_TOP_HCVERSIRQ_SD4_TYPE uint32_t
#define SD4_EMMC_TOP_HCVERSIRQ_SD4_RESERVED_MASK 0x0000FF00
#define SD4_EMMC_TOP_HCVERSIRQ_SD4_VENDVER_SHIFT 24
#define SD4_EMMC_TOP_HCVERSIRQ_SD4_VENDVER_MASK 0xFF000000
#define SD4_EMMC_TOP_HCVERSIRQ_SD4_SPECVER_SHIFT 16
#define SD4_EMMC_TOP_HCVERSIRQ_SD4_SPECVER_MASK 0x00FF0000
#define SD4_EMMC_TOP_HCVERSIRQ_SD4_SIRQ_SHIFT 0
#define SD4_EMMC_TOP_HCVERSIRQ_SD4_SIRQ_MASK 0x000000FF
#endif /* BRCM_RDB_SD4_EMMC_TOP_H */
/*
* Copyright (c) 2016 - 2020, Broadcom
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef CHAL_SD_H
#define CHAL_SD_H
#include <stddef.h>
#define BASE_CLK_FREQ (200 * 1000 * 1000)
#define INIT_CLK_FREQ (400 * 1000)
#define SD_ERROR_RECOVERABLE 0
#define SD_ERROR_NON_RECOVERABLE 1
#define SD_OK 0
#define SD_FAIL (-1)
#define SD_INVALID_HANDLE (-2)
#define SD_CEATA_INIT_ERROR (-3)
#define SD_RESET_ERROR (-4)
#define SD_CARD_INIT_ERROR (-5)
#define SD_INV_DATA_WIDTH (-6)
#define SD_SET_BUS_WIDTH_ERROR (-7)
#define SD_DMA_NOT_SUPPORT (-8)
#define SD_SDIO_READ_ERROR (-9)
#define SD_SDIO_WRITE_ERROR (-10)
#define SD_WRITE_ERROR (-11)
#define SD_READ_ERROR (-12)
#define SD_READ_SIZE_ERROR (-13)
#define SD_RW_ADDRESS_ERROR (-14)
#define SD_XFER_ADDRESS_ERROR (-15)
#define SD_DATA_XFER_ADDR_ERROR (-16)
#define SD_DATA_XFER_ERROR (-17)
#define SD_WRITE_SIZE_ERROR (-18)
#define SD_CMD_STATUS_UPDATE_ERR (-19)
#define SD_CMD12_ERROR (-20)
#define SD_CMD_DATA_ERROR (-21)
#define SD_CMD_TIMEOUT (-22)
#define SD_CMD_NO_RESPONSE (-22)
#define SD_CMD_ABORT_ERROR (-23)
#define SD_CMD_INVALID (-24)
#define SD_CMD_RESUME_ERROR (-25)
#define SD_CMD_ERR_INVALID_RESPONSE (-26)
#define SD_WAIT_TIMEOUT (-27)
#define SD_READ_TIMEOUT (-28)
#define SD_CEATA_REST_ERROR (-29)
#define SD_INIT_CAED_FAILED (-30)
#define SD_ERROR_CLOCK_OFFLIMIT (-31)
#define SD_INV_SLOT (-32)
#define SD_NOR_INTERRUPTS 0x000000FF
#define SD_ERR_INTERRUPTS 0x03FF0000
#define SD_CMD_ERROR_INT 0x010F0000
#define SD_DAT_ERROR_INT 0x02F00000
#define SD_DAT_TIMEOUT 0x00100000
/* Operation modes */
#define SD_PIO_MODE 0
#define SD_INT_MODE 1
/* Support both ADMA and SDMA (for version 2.0 and above) */
#define SD_DMA_OFF 0
#define SD_DMA_SDMA 1
#define SD_DMA_ADMA 2
#define SD_NORMAL_SPEED 0
#define SD_HIGH_SPEED 1
#define SD_XFER_CARD_TO_HOST 3
#define SD_XFER_HOST_TO_CARD 4
#define SD_CARD_DETECT_AUTO 0
#define SD_CARD_DETECT_SD 1
#define SD_CARD_DETECT_SDIO 2
#define SD_CARD_DETECT_MMC 3
#define SD_CARD_DETECT_CEATA 4
#define SD_ABORT_SYNC_MODE 0
#define SD_ABORT_ASYNC_MODE 1
#define SD_CMD_ERROR_FLAGS (0x18F << 16)
#define SD_DATA_ERROR_FLAGS (0x70 << 16)
#define SD_AUTO_CMD12_ERROR_FLAGS (0x9F)
#define SD_CARD_STATUS_ERROR 0x10000000
#define SD_CMD_MISSING 0x80000000
#define SD_ERROR_INT 0x8000
#define SD_TRAN_HIGH_SPEED 0x32
#define SD_CARD_HIGH_CAPACITY 0x40000000
#define SD_CARD_POWER_UP_STATUS 0x80000000
#define SD_HOST_CORE_TIMEOUT 0x0E
/* SD CARD and Host Controllers bus width */
#define SD_BUS_DATA_WIDTH_1BIT 0x00
#define SD_BUS_DATA_WIDTH_4BIT 0x02
#define SD_BUS_DATA_WIDTH_8BIT 0x20
/* dma boundary settings */
#define SD_DMA_BOUNDARY_4K 0
#define SD_DMA_BOUNDARY_8K (1 << 12)
#define SD_DMA_BOUNDARY_16K (2 << 12)
#define SD_DMA_BOUNDARY_32K (3 << 12)
#define SD_DMA_BOUNDARY_64K (4 << 12)
#define SD_DMA_BOUNDARY_128K (5 << 12)
#define SD_DMA_BOUNDARY_256K (6 << 12)
#define SD_DMA_BOUNDARY_512K (7 << 12)
#define SD_CMDR_CMD_NORMAL 0x00000000
#define SD_CMDR_CMD_SUSPEND 0x00400000
#define SD_CMDR_CMD_RESUME 0x00800000
#define SD_CMDR_CMD_ABORT 0x00c00000
#define SD_CMDR_RSP_TYPE_NONE 0x0
#define SD_CMDR_RSP_TYPE_R2 0x1
#define SD_CMDR_RSP_TYPE_R3_4 0x2
#define SD_CMDR_RSP_TYPE_R1_5_6 0x2
#define SD_CMDR_RSP_TYPE_R1b_5b 0x3
#define SD_CMDR_RSP_TYPE_S 16
struct sd_ctrl_info {
uint32_t blkReg; /* current block register cache value */
uint32_t cmdReg; /* current command register cache value */
uint32_t argReg; /* current argument register cache value */
uint32_t cmdIndex; /* current command index */
uint32_t cmdStatus; /* current command status, cmd/data compelete */
uint16_t rca; /* relative card address */
uint32_t ocr; /* operation codition */
uint32_t eventList; /* events list */
uint32_t blkGapEnable;
uint32_t capability; /* controller's capbilities */
uint32_t maxCurrent; /* maximum current supported */
uint32_t present; /* if card is inserted or removed */
uint32_t version; /* SD spec version 1.0 or 2.0 */
uint32_t vendor; /* vendor number */
uintptr_t sdRegBaseAddr; /* sdio control registers */
uintptr_t hostRegBaseAddr; /* SD Host control registers */
};
struct sd_cfg {
uint32_t mode; /* interrupt or polling */
uint32_t dma; /* dma enabled or disabled */
uint32_t retryLimit; /* command retry limit */
uint32_t speedMode; /* speed mode, 0 standard, 1 high speed */
uint32_t voltage; /* voltage level */
uint32_t blockSize; /* access block size (512 for HC card) */
uint32_t dmaBoundary; /* dma address boundary */
uint32_t detSignal; /* card det signal src, for test purpose only */
uint32_t rdWaiting;
uint32_t wakeupOut;
uint32_t wakeupIn;
uint32_t wakeupInt;
uint32_t wfe_retry;
uint32_t gapInt;
uint32_t readWait;
uint32_t led;
};
struct sd_dev {
struct sd_cfg cfg; /* SD configuration */
struct sd_ctrl_info ctrl; /* SD info */
};
int32_t chal_sd_start(CHAL_HANDLE *sdHandle, uint32_t mode,
uint32_t sdBase, uint32_t hostBase);
int32_t chal_sd_config(CHAL_HANDLE *sdHandle, uint32_t speed,
uint32_t retry, uint32_t boundary,
uint32_t blkSize, uint32_t dma);
int32_t chal_sd_stop(void);
int32_t chal_sd_set_dma(CHAL_HANDLE *sdHandle, uint32_t mode);
uintptr_t chal_sd_get_dma_addr(CHAL_HANDLE *handle);
int32_t chal_sd_config_bus_width(CHAL_HANDLE *sdHandle, int32_t width);
int32_t chal_sd_send_cmd(CHAL_HANDLE *sdHandle, uint32_t cmdIndex,
uint32_t arg, uint32_t options);
int32_t chal_sd_set_dma_addr(CHAL_HANDLE *sdHandle, uintptr_t address);
int32_t chal_sd_set_clock(CHAL_HANDLE *sdHandle,
uint32_t div_ctrl_setting, uint32_t on);
uint32_t chal_sd_freq_2_div_ctrl_setting(uint32_t desired_freq);
int32_t chal_sd_setup_xfer(CHAL_HANDLE *sdHandle, uint8_t *data,
uint32_t length, int32_t dir);
int32_t chal_sd_write_buffer(CHAL_HANDLE *sdHandle, uint32_t length,
uint8_t *data);
int32_t chal_sd_read_buffer(CHAL_HANDLE *sdHandle, uint32_t length,
uint8_t *data);
int32_t chal_sd_reset_line(CHAL_HANDLE *sdHandle, uint32_t line);
int32_t chal_sd_get_response(CHAL_HANDLE *sdHandle, uint32_t *resp);
int32_t chal_sd_clear_pending_irq(CHAL_HANDLE *sdHandle);
int32_t chal_sd_get_irq_status(CHAL_HANDLE *sdHandle);
int32_t chal_sd_clear_irq(CHAL_HANDLE *sdHandle, uint32_t mask);
uint32_t chal_sd_get_present_status(CHAL_HANDLE *sdHandle);
int32_t chal_sd_get_atuo12_error(CHAL_HANDLE *sdHandle);
void chal_sd_set_speed(CHAL_HANDLE *sdHandle, uint32_t speed);
int32_t chal_sd_check_cap(CHAL_HANDLE *sdHandle, uint32_t cap);
void chal_sd_set_irq_signal(CHAL_HANDLE *sdHandle, uint32_t mask,
uint32_t state);
void chal_sd_dump_fifo(CHAL_HANDLE *sdHandle);
#endif /* CHAL_SD_H */
/*
* Copyright (c) 2016 - 2020, Broadcom
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef CHAL_TYPES_H
#define CHAL_TYPES_H
#include <stdint.h>
//
// Generic cHAL handler
//
#ifndef CHAL_HANDLE
typedef void *CHAL_HANDLE; ///< void pointer (32 bits wide)
#endif
#endif /* _CHAL_TYPES_H_ */
/*
* Copyright (c) 2016 - 2020, Broadcom
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef CSL_SD_H
#define CSL_SD_H
#define SD_CLOCK_BASE 104000000
#define SD_CLOCK_52MHZ 52000000
#define SD_CLOCK_26MHZ 26000000
#define SD_CLOCK_17MHZ 17330000
#define SD_CLOCK_13MHZ 13000000
#define SD_CLOCK_10MHZ 10000000
#define SD_CLOCK_9MHZ 9000000
#define SD_CLOCK_7MHZ 7000000
#define SD_CLOCK_5MHZ 5000000
#define SD_CLOCK_1MHZ 1000000
#define SD_CLOCK_400KHZ 400000
#define SD_DRIVE_STRENGTH_MASK 0x38000000
#if defined(_BCM213x1_) || defined(_BCM21551_) || defined(_ATHENA_)
#define SD_DRIVE_STRENGTH 0x28000000
#elif defined(_BCM2153_)
#define SD_DRIVE_STRENGTH 0x38000000
#else
#define SD_DRIVE_STRENGTH 0x00000000
#endif
#define SD_NUM_HOST 2
#define SD_CARD_UNLOCK 0
#define SD_CARD_LOCK 0x4
#define SD_CARD_CLEAR_PWD 0x2
#define SD_CARD_SET_PWD 0x1
#define SD_CARD_ERASE_PWD 0x8
#define SD_CARD_LOCK_STATUS 0x02000000
#define SD_CARD_UNLOCK_STATUS 0x01000000
#define SD_CMD_ERROR_FLAGS (0x18F << 16)
#define SD_DATA_ERROR_FLAGS (0x70 << 16)
#define SD_AUTO_CMD12_ERROR_FLAGS (0x9F)
#define SD_CARD_STATUS_ERROR 0x10000000
#define SD_CMD_MISSING 0x80000000
#define SD_TRAN_HIGH_SPEED 0x32
#define SD_CARD_HIGH_CAPACITY 0x40000000
#define SD_CARD_POWER_UP_STATUS 0x80000000
struct sd_dev_info {
uint32_t mode; /* interrupt or polling */
uint32_t dma; /* dma enabled or disabled */
uint32_t voltage; /* voltage level */
uint32_t slot; /* if the HC is locatd at slot 0 or slot 1 */
uint32_t version; /* 1.0 or 2.0 */
uint32_t curSystemAddr; /* system address */
uint32_t dataWidth; /* data width for the controller */
uint32_t clock; /* clock rate */
uint32_t status; /* if device is active on transfer or not */
};
void data_xfer_setup(struct sd_handle *handle, uint8_t *data,
uint32_t length, int dir);
int reset_card(struct sd_handle *handle);
int reset_host_ctrl(struct sd_handle *handle);
int init_card(struct sd_handle *handle, int detection);
int init_mmc_card(struct sd_handle *handle);
int write_buffer(struct sd_handle *handle, uint32_t len, uint8_t *buffer);
int read_buffer(struct sd_handle *handle, uint32_t len, uint8_t *buffer);
int select_blk_sz(struct sd_handle *handle, uint16_t size);
int check_error(struct sd_handle *handle, uint32_t ints);
int process_data_xfer(struct sd_handle *handle, uint8_t *buffer,
uint32_t addr, uint32_t length, int dir);
int read_block(struct sd_handle *handle, uint8_t *dst, uint32_t addr,
uint32_t len);
#ifdef INCLUDE_EMMC_DRIVER_ERASE_CODE
int erase_card(struct sd_handle *handle, uint32_t addr, uint32_t blocks);
#endif
int write_block(struct sd_handle *handle, uint8_t *src, uint32_t addr,
uint32_t len);
int process_cmd_response(struct sd_handle *handle, uint32_t cmdIndex,
uint32_t rsp0, uint32_t rsp1, uint32_t rsp2,
uint32_t rsp3, struct sd_resp *resp);
int32_t set_config(struct sd_handle *handle, uint32_t speed,
uint32_t retry, uint32_t dma, uint32_t dmaBound,
uint32_t blkSize, uint32_t wfe_retry);
uint32_t wait_for_event(struct sd_handle *handle, uint32_t mask,
uint32_t retry);
int set_boot_config(struct sd_handle *handle, uint32_t config);
int mmc_cmd1(struct sd_handle *handle);
#endif /* CSL_SD_H */
/*
* Copyright (c) 2016 - 2020, Broadcom
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef CSL_SD_CMD_H
#define CSL_SD_CMD_H
#define SD_CMD_OK 0
#define SD_CMD_ERROR -1
#define SD_CMD_ERR_NO_IO_FUNC 5
#define SD_CMD_ERR_INVALID_PARAMETER 6
#define SD_CMD_ERR_R1_ILLEGAL_COMMAND 7
#define SD_CMD_ERR_R1_COM_CRC_ERROR 8
#define SD_CMD_ERR_R1_FUNC_NUM_ERROR 9
#define SD_CMD_ERR_R1_ADDRESS_ERROR 10
#define SD_CMD_ERR_R1_PARAMETER_ERROR 11
#define SD_CMD_ERR_DATA_ERROR_TOKEN 12
#define SD_CMD_ERR_DATA_NOT_ACCEPTED 13
#define SD_CMD7_ARG_RCA_SHIFT 16
#define SD_CARD_STATUS_PENDING 0x01
#define SD_CARD_STATUS_BUFFER_OVERFLOW 0x01
#define SD_CARD_STATUS_DEVICE_BUSY 0x02
#define SD_CARD_STATUS_UNSUCCESSFUL 0x03
#define SD_CARD_STATUS_NOT_IMPLEMENTED 0x04
#define SD_CARD_STATUS_ACCESS_VIOLATION 0x05
#define SD_CARD_STATUS_INVALID_HANDLE 0x06
#define SD_CARD_STATUS_INVALID_PARAMETER 0x07
#define SD_CARD_STATUS_NO_SUCH_DEVICE 0x08
#define SD_CARD_STATUS_INVALID_DEVICE_REQUEST 0x09
#define SD_CARD_STATUS_NO_MEMORY 0x0A
#define SD_CARD_STATUS_BUS_DRIVER_NOT_READY 0x0B
#define SD_CARD_STATUS_DATA_ERROR 0x0C
#define SD_CARD_STATUS_CRC_ERROR 0x0D
#define SD_CARD_STATUS_INSUFFICIENT_RESOURCES 0x0E
#define SD_CARD_STATUS_DEVICE_NOT_CONNECTED 0x10
#define SD_CARD_STATUS_DEVICE_REMOVED 0x11
#define SD_CARD_STATUS_DEVICE_NOT_RESPONDING 0x12
#define SD_CARD_STATUS_CANCELED 0x13
#define SD_CARD_STATUS_RESPONSE_TIMEOUT 0x14
#define SD_CARD_STATUS_DATA_TIMEOUT 0x15
#define SD_CARD_STATUS_DEVICE_RESPONSE_ERROR 0x16
#define SD_CARD_STATUS_DEVICE_UNSUPPORTED 0x17
/* Response structure */
struct sd_r2_resp {
uint32_t rsp4; /* 127:96 */
uint32_t rsp3; /* 95:64 */
uint32_t rsp2; /* 63:32 */
uint32_t rsp1; /* 31:0 */
};
struct sd_r3_resp {
uint32_t ocr;
};
struct sd_r4_resp {
uint8_t cardReady;
uint8_t funcs;
uint8_t memPresent;
uint32_t ocr;
};
struct sd_r5_resp {
uint8_t data;
};
struct sd_r6_resp {
uint16_t rca;
uint16_t cardStatus;
};
struct sd_r7_resp {
uint16_t rca;
};
struct sd_resp {
uint8_t r1;
uint32_t cardStatus;
uint32_t rawData[4];
union {
struct sd_r2_resp r2;
struct sd_r3_resp r3;
struct sd_r4_resp r4;
struct sd_r5_resp r5;
struct sd_r6_resp r6;
struct sd_r7_resp r7;
} data;
};
struct sd_card_info {
uint32_t type; /* card type SD, MMC or SDIO */
uint64_t size; /* card size */
uint32_t speed; /* card speed */
uint32_t voltage; /* voltage supported */
uint32_t mId; /* manufacturer ID */
uint32_t oId; /* OEM ID */
uint32_t classes; /* card class */
uint32_t name1; /* product name part 1 */
uint32_t name2; /* product name part 2 */
uint32_t revision; /* revison */
uint32_t sn; /* serial number */
uint32_t numIoFuns; /* total I/O function number */
uint32_t maxRdBlkLen; /* max read block length */
uint32_t maxWtBlkLen; /* max write block length */
uint32_t blkMode; /* sdio card block mode support */
uint32_t f0Cis; /* sdio card block mode support */
uint32_t f1Cis; /* sdio card block mode support */
uint8_t partRead; /* partial block read allowed */
uint8_t partWrite; /* partial block write allowed */
uint8_t dsr; /* card DSR */
uint8_t rdCurMin; /* min current for read */
uint8_t rdCurMax; /* max current for read */
uint8_t wtCurMin; /* min current for write */
uint8_t wtCurMax; /* max current for write */
uint8_t erase; /* erase enable */
uint8_t eraseSecSize; /* erase sector size */
uint8_t proGrpSize; /* write protection group size */
uint8_t protect; /* permanent write protection or not */
uint8_t tmpProt; /* temp write protection or not */
uint8_t wtSpeed; /* write speed relatively to read */
uint8_t version; /* card version 0:1.0 - 1.01, 1:1.10, 2:2.0 */
uint8_t eraseState; /* if the data will be 0 or 1 after erase */
uint8_t bus; /* data with supported */
uint8_t security; /* security support 0, 2:1.01 3:2.0 */
uint8_t format; /* file format */
uint8_t fileGrp; /* file group */
char pwd[20]; /* password */
};
struct sd_handle {
struct sd_dev *device;
struct sd_card_info *card;
};
int sd_cmd0(struct sd_handle *handle);
int sd_cmd1(struct sd_handle *handle, uint32_t initOcr, uint32_t *ocr);
int sd_cmd2(struct sd_handle *handle);
int sd_cmd3(struct sd_handle *handle);
int sd_cmd7(struct sd_handle *handle, uint32_t rca);
int sd_cmd9(struct sd_handle *handle, struct sd_card_data *card);
int sd_cmd13(struct sd_handle *handle, uint32_t *status);
int sd_cmd16(struct sd_handle *handle, uint32_t blockLen);
int sd_cmd17(struct sd_handle *handle,
uint32_t addr, uint32_t len, uint8_t *buffer);
int sd_cmd18(struct sd_handle *handle,
uint32_t addr, uint32_t len, uint8_t *buffer);
#ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE
int sd_cmd24(struct sd_handle *handle,
uint32_t addr, uint32_t len, uint8_t *buffer);
int sd_cmd25(struct sd_handle *handle,
uint32_t addr, uint32_t len, uint8_t *buffer);
#endif
#ifdef INCLUDE_EMMC_DRIVER_ERASE_CODE
int sd_cmd35(struct sd_handle *handle, uint32_t start);
int sd_cmd36(struct sd_handle *handle, uint32_t end);
int sd_cmd38(struct sd_handle *handle);
#endif
int mmc_cmd6(struct sd_handle *handle, uint32_t argument);
int mmc_cmd8(struct sd_handle *handle, uint8_t *extCsdReg);
int send_cmd(struct sd_handle *handle, uint32_t cmdIndex,
uint32_t argument, uint32_t options, struct sd_resp *resp);
#endif /* CSL_SD_CMD_H */
/*
* Copyright (c) 2016 - 2020, Broadcom
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef CSL_SD_PROT_H
#define CSL_SD_PROT_H
#define SD_CARD_UNKNOWN 0 /* bad type or unrecognized */
#define SD_CARD_SD 1 /* IO only card */
#define SD_CARD_SDIO 2 /* memory only card */
#define SD_CARD_COMBO 3 /* IO and memory combo card */
#define SD_CARD_MMC 4 /* memory only card */
#define SD_CARD_CEATA 5 /* IO and memory combo card */
#define SD_IO_FIXED_ADDRESS 0 /* fix Address */
#define SD_IO_INCREMENT_ADDRESS 1
#define SD_HIGH_CAPACITY_CARD 0x40000000
#define MMC_CMD_IDLE_RESET_ARG 0xF0F0F0F0
/* Supported operating voltages are 3.2-3.3 and 3.3-3.4 */
#define MMC_OCR_OP_VOLT 0x00300000
/* Enable sector access mode */
#define MMC_OCR_SECTOR_ACCESS_MODE 0x40000000
/* command index */
#define SD_CMD_GO_IDLE_STATE 0 /* mandatory for SDIO */
#define SD_CMD_SEND_OPCOND 1
#define SD_CMD_ALL_SEND_CID 2
#define SD_CMD_MMC_SET_RCA 3
#define SD_CMD_MMC_SET_DSR 4
#define SD_CMD_IO_SEND_OP_COND 5 /* mandatory for SDIO */
#define SD_ACMD_SET_BUS_WIDTH 6
#define SD_CMD_SWITCH_FUNC 6
#define SD_CMD_SELECT_DESELECT_CARD 7
#define SD_CMD_READ_EXT_CSD 8
#define SD_CMD_SEND_CSD 9
#define SD_CMD_SEND_CID 10
#define SD_CMD_STOP_TRANSMISSION 12
#define SD_CMD_SEND_STATUS 13
#define SD_ACMD_SD_STATUS 13
#define SD_CMD_GO_INACTIVE_STATE 15
#define SD_CMD_SET_BLOCKLEN 16
#define SD_CMD_READ_SINGLE_BLOCK 17
#define SD_CMD_READ_MULTIPLE_BLOCK 18
#define SD_CMD_WRITE_BLOCK 24
#define SD_CMD_WRITE_MULTIPLE_BLOCK 25
#define SD_CMD_PROGRAM_CSD 27
#define SD_CMD_SET_WRITE_PROT 28
#define SD_CMD_CLR_WRITE_PROT 29
#define SD_CMD_SEND_WRITE_PROT 30
#define SD_CMD_ERASE_WR_BLK_START 32
#define SD_CMD_ERASE_WR_BLK_END 33
#define SD_CMD_ERASE_GROUP_START 35
#define SD_CMD_ERASE_GROUP_END 36
#define SD_CMD_ERASE 38
#define SD_CMD_LOCK_UNLOCK 42
#define SD_CMD_IO_RW_DIRECT 52 /* mandatory for SDIO */
#define SD_CMD_IO_RW_EXTENDED 53 /* mandatory for SDIO */
#define SD_CMD_APP_CMD 55
#define SD_CMD_GEN_CMD 56
#define SD_CMD_READ_OCR 58
#define SD_CMD_CRC_ON_OFF 59 /* mandatory for SDIO */
#define SD_ACMD_SEND_NUM_WR_BLOCKS 22
#define SD_ACMD_SET_WR_BLOCK_ERASE_CNT 23
#define SD_ACMD_SD_SEND_OP_COND 41
#define SD_ACMD_SET_CLR_CARD_DETECT 42
#define SD_ACMD_SEND_SCR 51
/* response parameters */
#define SD_RSP_NO_NONE 0
#define SD_RSP_NO_1 1
#define SD_RSP_NO_2 2
#define SD_RSP_NO_3 3
#define SD_RSP_NO_4 4
#define SD_RSP_NO_5 5
#define SD_RSP_NO_6 6
/* Modified R6 response (to CMD3) */
#define SD_RSP_MR6_COM_CRC_ERROR 0x8000
#define SD_RSP_MR6_ILLEGAL_COMMAND 0x4000
#define SD_RSP_MR6_ERROR 0x2000
/* Modified R1 in R4 Response (to CMD5) */
#define SD_RSP_MR1_SBIT 0x80
#define SD_RSP_MR1_PARAMETER_ERROR 0x40
#define SD_RSP_MR1_RFU5 0x20
#define SD_RSP_MR1_FUNC_NUM_ERROR 0x10
#define SD_RSP_MR1_COM_CRC_ERROR 0x80
#define SD_RSP_MR1_ILLEGAL_COMMAND 0x40
#define SD_RSP_MR1_RFU1 0x20
#define SD_RSP_MR1_IDLE_STATE 0x01
/* R5 response (to CMD52 and CMD53) */
#define SD_RSP_R5_COM_CRC_ERROR 0x80
#define SD_RSP_R5_ILLEGAL_COMMAND 0x40
#define SD_RSP_R5_IO_CURRENTSTATE1 0x20
#define SD_RSP_R5_IO_CURRENTSTATE0 0x10
#define SD_RSP_R5_ERROR 0x80
#define SD_RSP_R5_RFU 0x40
#define SD_RSP_R5_FUNC_NUM_ERROR 0x20
#define SD_RSP_R5_OUT_OF_RANGE 0x01
/* argument for SD_CMD_IO_RW_DIRECT and SD_CMD_IO_RW_EXTENDED */
#define SD_OP_READ 0 /* Read_Write */
#define SD_OP_WRITE 1 /* Read_Write */
#define SD_RW_NORMAL 0 /* no RAW */
#define SD_RW_RAW 1 /* RAW */
#define SD_BYTE_MODE 0 /* Byte Mode */
#define SD_BLOCK_MODE 1 /* BlockMode */
#define SD_FIXED_ADDRESS 0 /* fix Address */
#define SD_INCREMENT_ADDRESS 1 /* IncrementAddress */
#define SD_CMD5_ARG_IO_OCR_MASK 0x00FFFFFF
#define SD_CMD5_ARG_IO_OCR_SHIFT 0
#define SD_CMD55_ARG_RCA_SHIFT 16
#define SD_CMD59_ARG_CRC_OPTION_MASK 0x01
#define SD_CMD59_ARG_CRC_OPTION_SHIFT 0
/* SD_CMD_IO_RW_DIRECT Argument */
#define SdioIoRWDirectArg(rw, raw, func, addr, data) \
(((rw & 1) << 31) | ((func & 0x7) << 28) | \
((raw & 1) << 27) | ((addr & 0x1FFFF) << 9) | \
(data & 0xFF))
/* build SD_CMD_IO_RW_EXTENDED Argument */
#define SdioIoRWExtArg(rw, blk, func, addr, inc_addr, count) \
(((rw & 1) << 31) | ((func & 0x7) << 28) | \
((blk & 1) << 27) | ((inc_addr & 1) << 26) | \
((addr & 0x1FFFF) << 9) | (count & 0x1FF))
/*
* The Common I/O area shall be implemented on all SDIO cards and
* is accessed the the host via I/O reads and writes to function 0,
* the registers within the CIA are provided to enable/disable
* the operationo fthe i/o funciton.
*/
/* cccr_sdio_rev */
#define SDIO_REV_SDIOID_MASK 0xf0 /* SDIO spec revision number */
#define SDIO_REV_CCCRID_MASK 0x0f /* CCCR format version number */
/* sd_rev */
#define SDIO_REV_PHY_MASK 0x0f /* SD format version number */
#define SDIO_FUNC_ENABLE_1 0x02 /* function 1 I/O enable */
#define SDIO_FUNC_READY_1 0x02 /* function 1 I/O ready */
#define SDIO_INTR_CTL_FUNC1_EN 0x2 /* interrupt enable for function 1 */
#define SDIO_INTR_CTL_MASTER_EN 0x1 /* interrupt enable master */
#define SDIO_INTR_STATUS_FUNC1 0x2 /* interrupt pending for function 1 */
#define SDIO_IO_ABORT_RESET_ALL 0x08 /* I/O card reset */
#define SDIO_IO_ABORT_FUNC_MASK 0x07 /* abort selection: function x */
#define SDIO_BUS_CARD_DETECT_DIS 0x80 /* Card Detect disable */
#define SDIO_BUS_SPI_CONT_INTR_CAP 0x40 /* support continuous SPI interrupt */
#define SDIO_BUS_SPI_CONT_INTR_EN 0x20 /* continuous SPI interrupt enable */
#define SDIO_BUS_DATA_WIDTH_MASK 0x03 /* bus width mask */
#define SDIO_BUS_DATA_WIDTH_4BIT 0x02 /* bus width 4-bit mode */
#define SDIO_BUS_DATA_WIDTH_1BIT 0x00 /* bus width 1-bit mode */
/* capability */
#define SDIO_CAP_4BLS 0x80 /* 4-bit support for low speed card */
#define SDIO_CAP_LSC 0x40 /* low speed card */
#define SDIO_CAP_E4MI 0x20 /* enable int between block in 4-bit mode */
#define SDIO_CAP_S4MI 0x10 /* support int between block in 4-bit mode */
#define SDIO_CAP_SBS 0x08 /* support suspend/resume */
#define SDIO_CAP_SRW 0x04 /* support read wait */
#define SDIO_CAP_SMB 0x02 /* support multi-block transfer */
#define SDIO_CAP_SDC 0x01 /* Support Direct cmd during multi-uint8 transfer */
/* CIA FBR1 registers */
#define SDIO_FUNC1_INFO 0x100 /* basic info for function 1 */
#define SDIO_FUNC1_EXT 0x101 /* extension of standard I/O device */
#define SDIO_CIS_FUNC1_BASE_LOW 0x109 /* function 1 cis address bit 0-7 */
#define SDIO_CIS_FUNC1_BASE_MID 0x10A /* function 1 cis address bit 8-15 */
#define SDIO_CIS_FUNC1_BASE_HIGH 0x10B /* function 1 cis address bit 16 */
#define SDIO_CSA_BASE_LOW 0x10C /* CSA base address uint8_t 0 */
#define SDIO_CSA_BASE_MID 0x10D /* CSA base address uint8_t 1 */
#define SDIO_CSA_BASE_HIGH 0x10E /* CSA base address uint8_t 2 */
#define SDIO_CSA_DATA_OFFSET 0x10F /* CSA data register */
#define SDIO_IO_BLK_SIZE_LOW 0x110 /* I/O block size uint8_t 0 */
#define SDIO_IO_BLK_SIZE_HIGH 0x111 /* I/O block size uint8_t 1 */
/* SD_SDIO_FUNC1_INFO bits */
#define SDIO_FUNC1_INFO_DIC 0x0f /* device interface code */
#define SDIO_FUNC1_INFO_CSA 0x40 /* CSA support flag */
#define SDIO_FUNC1_INFO_CSA_EN 0x80 /* CSA enabled */
/* SD_SDIO_FUNC1_EXT bits */
#define SDIO_FUNC1_EXT_SHP 0x03 /* support high power */
#define SDIO_FUNC1_EXT_EHP 0x04 /* enable high power */
/* devctr */
/* I/O device interface code */
#define SDIO_DEVCTR_DEVINTER 0x0f
/* support CSA */
#define SDIO_DEVCTR_CSA_SUP 0x40
/* enable CSA */
#define SDIO_DEVCTR_CSA_EN 0x80
/* ext_dev */
/* supports high-power mask */
#define SDIO_HIGHPWR_SUPPORT_M 0x3
/* enable high power */
#define SDIO_HIGHPWR_EN 0x4
/* standard power function(up to 200mA */
#define SDIO_HP_STD 0
/* need high power to operate */
#define SDIO_HP_REQUIRED 0x2
/* can work with standard power, but prefer high power */
#define SDIO_HP_DESIRED 0x3
/* misc define */
/* macro to calculate fbr register base */
#define FBR_REG_BASE(n) (n*0x100)
#define SDIO_FUNC_0 0
#define SDIO_FUNC_1 1
#define SDIO_FUNC_2 2
#define SDIO_FUNC_3 3
#define SDIO_FUNC_4 4
#define SDIO_FUNC_5 5
#define SDIO_FUNC_6 6
#define SDIO_FUNC_7 7
/* maximum block size for block mode operation */
#define SDIO_MAX_BLOCK_SIZE 2048
/* minimum block size for block mode operation */
#define SDIO_MIN_BLOCK_SIZE 1
/* Card registers: status bit position */
#define SDIO_STATUS_OUTOFRANGE 31
#define SDIO_STATUS_COMCRCERROR 23
#define SDIO_STATUS_ILLEGALCOMMAND 22
#define SDIO_STATUS_ERROR 19
#define SDIO_STATUS_IOCURRENTSTATE3 12
#define SDIO_STATUS_IOCURRENTSTATE2 11
#define SDIO_STATUS_IOCURRENTSTATE1 10
#define SDIO_STATUS_IOCURRENTSTATE0 9
#define SDIO_STATUS_FUN_NUM_ERROR 4
#define GET_SDIOCARD_STATUS(x) ((x >> 9) & 0x0f)
#define SDIO_STATUS_STATE_IDLE 0
#define SDIO_STATUS_STATE_READY 1
#define SDIO_STATUS_STATE_IDENT 2
#define SDIO_STATUS_STATE_STBY 3
#define SDIO_STATUS_STATE_TRAN 4
#define SDIO_STATUS_STATE_DATA 5
#define SDIO_STATUS_STATE_RCV 6
#define SDIO_STATUS_STATE_PRG 7
#define SDIO_STATUS_STATE_DIS 8
/* sprom */
#define SBSDIO_SPROM_CS 0x10000 /* command and status */
#define SBSDIO_SPROM_INFO 0x10001 /* info register */
#define SBSDIO_SPROM_DATA_LOW 0x10002 /* indirect access data uint8_t 0 */
#define SBSDIO_SPROM_DATA_HIGH 0x10003 /* indirect access data uint8_t 1 */
#define SBSDIO_SPROM_ADDR_LOW 0x10004 /* indirect access addr uint8_t 0 */
#define SBSDIO_SPROM_ADDR_HIGH 0x10005 /* indirect access addr uint8_t 0 */
#define SBSDIO_CHIP_CTRL_DATA 0x10006 /* xtal_pu data output */
#define SBSDIO_CHIP_CTRL_EN 0x10007 /* xtal_pu enable */
#define SBSDIO_WATERMARK 0x10008 /* retired in rev 7 */
#define SBSDIO_DEVICE_CTL 0x10009 /* control busy signal generation */
#define SBSDIO_SPROM_IDLE 0
#define SBSDIO_SPROM_WRITE 1
#define SBSDIO_SPROM_READ 2
#define SBSDIO_SPROM_WEN 4
#define SBSDIO_SPROM_WDS 7
#define SBSDIO_SPROM_DONE 8
/* SBSDIO_SPROM_INFO */
#define SBSDIO_SROM_SZ_MASK 0x03 /* SROM size, 1: 4k, 2: 16k */
#define SBSDIO_SROM_BLANK 0x04 /* depreciated in corerev 6 */
#define SBSDIO_SROM_OTP 0x80 /* OTP present */
/* SBSDIO_CHIP_CTRL */
/* or'd with onchip xtal_pu, 1: power on oscillator */
#define SBSDIO_CHIP_CTRL_XTAL 0x01
/* SBSDIO_WATERMARK */
/* number of bytes minus 1 for sd device to wait before sending data to host */
#define SBSDIO_WATERMARK_MASK 0x3f
/* SBSDIO_DEVICE_CTL */
/* 1: device will assert busy signal when receiving CMD53 */
#define SBSDIO_DEVCTL_SETBUSY 0x01
/* 1: assertion of sdio interrupt is synchronous to the sdio clock */
#define SBSDIO_DEVCTL_SPI_INTR_SYNC 0x02
/* function 1 OCP space */
/* sb offset addr is <= 15 bits, 32k */
#define SBSDIO_SB_OFT_ADDR_MASK 0x07FFF
#define SBSDIO_SB_OFT_ADDR_LIMIT 0x08000
/* sdsdio function 1 OCP space has 16/32 bit section */
#define SBSDIO_SB_ACCESS_2_4B_FLAG 0x08000
/* direct(mapped) cis space */
/* MAPPED common CIS address */
#define SBSDIO_CIS_BASE_COMMON 0x1000
/* function 0(common) cis size in bytes */
#define SBSDIO_CIS_FUNC0_LIMIT 0x020
/* funciton 1 cis size in bytes */
#define SBSDIO_CIS_SIZE_LIMIT 0x200
/* cis offset addr is < 17 bits */
#define SBSDIO_CIS_OFT_ADDR_MASK 0x1FFFF
/* manfid tuple length, include tuple, link bytes */
#define SBSDIO_CIS_MANFID_TUPLE_LEN 6
/* indirect cis access (in sprom) */
/* 8 control bytes first, CIS starts from 8th uint8_t */
#define SBSDIO_SPROM_CIS_OFFSET 0x8
/* sdio uint8_t mode: maximum length of one data comamnd */
#define SBSDIO_BYTEMODE_DATALEN_MAX 64
/* 4317 supports less */
#define SBSDIO_BYTEMODE_DATALEN_MAX_4317 52
/* sdio core function one address mask */
#define SBSDIO_CORE_ADDR_MASK 0x1FFFF
/* CEATA defines */
#define CEATA_EXT_CSDBLOCK_SIZE 512
#define CEATA_FAST_IO 39
#define CEATA_MULTIPLE_REGISTER_RW 60
#define CEATA_MULTIPLE_BLOCK_RW 61
/* defines CE ATA task file registers */
#define CEATA_SCT_CNT_EXP_REG 0x02
#define CEATA_LBA_LOW_EXP_REG 0x03
#define CEATA_LBA_MID_EXP_REG 0x04
#define CEATA_LBA_HIGH_EXP_REG 0x05
#define CEATA_CNTRL_REG 0x06
#define CEATA_FEATURE_REG 0x09 /* write */
#define CEATA_ERROR_REG 0x09 /* read */
#define CEATA_SCT_CNT_REG 0x0A
#define CEATA_LBA_LOW_REG 0x0B
#define CEATA_LBA_MID_REG 0x0C
#define CEATA_LBA_HIGH_REG 0x0D
#define CEATA_DEV_HEAD_REG 0x0E
#define CEATA_STA_REG 0x0F /* read */
#define CEATA_CMD_REG 0x0F /* write */
/* defines CEATA control and status registers for ce ata client driver */
#define CEATA_SCR_TEMPC_REG 0x80
#define CEATA_SCR_TEMPMAXP_REG 0x84
#define CEATA_TEMPMINP_REG 0x88
#define CEATA_SCR_STATUS_REG 0x8C
#define CEATA_SCR_REALLOCSA_REG 0x90
#define CEATA_SCR_ERETRACTSA_REG 0x94
#define CEATA_SCR_CAPABILITIES_REG 0x98
#define CEATA_SCR_CONTROL_REG 0xC0
/* defines for SCR capabilities register bits for ce ata client driver */
#define CEATA_SCR_CAP_512 0x00000001
#define CEATA_SCR_CAP_1K 0x00000002
#define CEATA_SCR_CAP_4K 0x00000004
/* defines CE ATA Control reg bits for ce ata client driver */
#define CEATA_CNTRL_ENABLE_INTR 0x00
#define CEATA_CNTRL_DISABLE_INTR 0x02
#define CEATA_CNTRL_SRST 0x04
#define CEATA_CNTRL_RSRST 0x00
/* define CE ATA Status reg bits for ce ata client driver */
#define CEATA_STA_ERROR_BIT 0x01
#define CEATA_STA_OVR_BIT 0x02
#define CEATA_STA_SPT_BIT 0x04
#define CEATA_STA_DRQ_BIT 0x08
#define CEATA_STA_DRDY_BIT 0x40
#define CEATA_STA_BSY_BIT 0x80
/* define CE ATA Error reg bits for ce ata client driver */
#define CEATA_ERROR_ABORTED_BIT 0x04
#define CEATA_ERROR_IDNF_BIT 0x10
#define CEATA_ERROR_UNCORRECTABLE_BIT 0x40
#define CEATA_ERROR_ICRC_BIT 0x80
/* define CE ATA Commands for ce ata client driver */
#define CEATA_CMD_IDENTIFY_DEVICE 0xEC
#define CEATA_CMD_READ_DMA_EXT 0x25
#define CEATA_CMD_WRITE_DMA_EXT 0x35
#define CEATA_CMD_STANDBY_IMMEDIATE 0xE0
#define CEATA_CMD_FLUSH_CACHE_EXT 0xEA
struct csd_mmc {
uint32_t padding:8;
uint32_t structure:2;
uint32_t csdSpecVer:4;
uint32_t reserved1:2;
uint32_t taac:8;
uint32_t nsac:8;
uint32_t speed:8;
uint32_t classes:12;
uint32_t rdBlkLen:4;
uint32_t rdBlkPartial:1;
uint32_t wrBlkMisalign:1;
uint32_t rdBlkMisalign:1;
uint32_t dsr:1;
uint32_t reserved2:2;
uint32_t size:12;
uint32_t vddRdCurrMin:3;
uint32_t vddRdCurrMax:3;
uint32_t vddWrCurrMin:3;
uint32_t vddWrCurrMax:3;
uint32_t devSizeMulti:3;
uint32_t eraseGrpSize:5;
uint32_t eraseGrpSizeMulti:5;
uint32_t wrProtGroupSize:5;
uint32_t wrProtGroupEnable:1;
uint32_t manuDefEcc:2;
uint32_t wrSpeedFactor:3;
uint32_t wrBlkLen:4;
uint32_t wrBlkPartial:1;
uint32_t reserved5:4;
uint32_t protAppl:1;
uint32_t fileFormatGrp:1;
uint32_t copyFlag:1;
uint32_t permWrProt:1;
uint32_t tmpWrProt:1;
uint32_t fileFormat:2;
uint32_t eccCode:2;
};
/* CSD register*/
union sd_csd {
uint32_t csd[4];
struct csd_mmc mmc;
};
struct sd_card_data {
union sd_csd csd;
};
#endif /* CSL_SD_PROT_H */
/*
* Copyright (c) 2016 - 2020, Broadcom
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef PBOOT_HAL_MEMORY_EMMC_DRV_H
#define PBOOT_HAL_MEMORY_EMMC_DRV_H
#include <drivers/delay_timer.h>
#include "emmc_chal_types.h"
#include "emmc_chal_sd.h"
#include "emmc_csl_sdprot.h"
#include "emmc_csl_sdcmd.h"
#include "emmc_csl_sd.h"
#include "emmc_brcm_rdb_sd4_top.h"
#define CLK_SDIO_DIV_52MHZ 0x0
#define SYSCFG_IOCR4_PAD_10MA 0x38000000
#define SDCLK_CNT_PER_MS 52000
#define BOOT_ACK_TIMEOUT (50 * SDCLK_CNT_PER_MS)
#define BOOT_DATA_TIMEOUT (1000 * SDCLK_CNT_PER_MS)
#define EMMC_BOOT_OK 0
#define EMMC_BOOT_ERROR 1
#define EMMC_BOOT_TIMEOUT 2
#define EMMC_BOOT_INVALIDIMAGE 3
#define EMMC_BOOT_NO_CARD 4
#define EMMC_USER_AREA 0
#define EMMC_BOOT_PARTITION1 1
#define EMMC_BOOT_PARTITION2 2
#define EMMC_USE_CURRENT_PARTITION 3
#define EMMC_BOOT_PARTITION_SIZE (128*1024)
#define EMMC_BLOCK_SIZE 512
#define EMMC_DMA_SIZE (4*1024)
/*
* EMMC4.3 definitions
* Table 6 EXT_CSD access mode
* Access
* Bits Access Name Operation
* 00 Command Set The command set is changed according to the Cmd Set field of
* the argument
* 01 Set Bits The bits in the pointed uint8_t are set,
* according to the 1 bits in the Value field.
* 10 Clear Bits The bits in the pointed uint8_t are cleared,
* according to the 1 bits in the Value field.
* 11 Write Byte The Value field is written into the pointed uint8_t.
*/
#define SDIO_HW_EMMC_EXT_CSD_WRITE_BYTE 0X03000000
/* Boot bus width1 BOOT_BUS_WIDTH 1 R/W [177] */
#define SDIO_HW_EMMC_EXT_CSD_BOOT_BUS_WIDTH_OFFSET 0X00B10000
/* Boot configuration BOOT_CONFIG 1 R/W [179] */
#define SDIO_HW_EMMC_EXT_CSD_BOOT_CONFIG_OFFSET 0X00B30000
/* Bus width mode BUS_WIDTH 1 WO [183] */
#define SDIO_HW_EMMC_EXT_CSD_BUS_WIDTH_OFFSET 0X00B70000
/*
* Bit 6: BOOT_ACK (non-volatile)
* 0x0 : No boot acknowledge sent (default)
* 0x1 : Boot acknowledge sent during boot operation
* Bit[5:3] : BOOT_PARTITION_ENABLE (non-volatile)
* User selects boot data that will be sent to master
* 0x0 : Device not boot enabled (default)
* 0x1 : Boot partition 1 enabled for boot
* 0x2 : Boot partition 2 enabled for boot
* 0x3-0x6 : Reserved
* 0x7 : User area enabled for boot
* Bit[2:0] : BOOT_PARTITION_ACCESS
* User selects boot partition for read and write operation
* 0x0 : No access to boot partition (default)
* 0x1 : R/W boot partition 1
* 0x2 : R/W boot partition 2
* 0x3-0x7 : Reserved
*/
#define SDIO_HW_EMMC_EXT_CSD_BOOT_ACC_BOOT1 0X00000100
#define SDIO_HW_EMMC_EXT_CSD_BOOT_ACC_BOOT2 0X00000200
#define SDIO_HW_EMMC_EXT_CSD_BOOT_ACC_USER 0X00000000
#define SDIO_HW_EMMC_EXT_CSD_BOOT_EN_BOOT1 0X00004800
#define SDIO_HW_EMMC_EXT_CSD_BOOT_EN_BOOT2 0X00005000
#define SDIO_HW_EMMC_EXT_CSD_BOOT_EN_USER 0X00007800
#define SD_US_DELAY(x) udelay(x)
#endif
...@@ -28,6 +28,10 @@ SYSCNT_FREQ := $(GENTIMER_ACTUAL_CLOCK) ...@@ -28,6 +28,10 @@ SYSCNT_FREQ := $(GENTIMER_ACTUAL_CLOCK)
$(eval $(call add_define,SYSCNT_FREQ)) $(eval $(call add_define,SYSCNT_FREQ))
endif endif
ifeq (${DRIVER_EMMC_ENABLE},)
DRIVER_EMMC_ENABLE :=1
endif
# By default, Trusted Watchdog is always enabled unless SPIN_ON_BL1_EXIT is set # By default, Trusted Watchdog is always enabled unless SPIN_ON_BL1_EXIT is set
ifeq (${BRCM_DISABLE_TRUSTED_WDOG},) ifeq (${BRCM_DISABLE_TRUSTED_WDOG},)
BRCM_DISABLE_TRUSTED_WDOG := 0 BRCM_DISABLE_TRUSTED_WDOG := 0
...@@ -89,6 +93,14 @@ ifneq (${USE_CRMU_SRAM},) ...@@ -89,6 +93,14 @@ ifneq (${USE_CRMU_SRAM},)
$(eval $(call add_define,USE_CRMU_SRAM)) $(eval $(call add_define,USE_CRMU_SRAM))
endif endif
# Use PIO mode if DDR is not used
ifeq (${USE_DDR},yes)
EMMC_USE_DMA := 1
else
EMMC_USE_DMA := 0
endif
$(eval $(call add_define,EMMC_USE_DMA))
# On BRCM platforms, separate the code and read-only data sections to allow # On BRCM platforms, separate the code and read-only data sections to allow
# mapping the former as executable and the latter as execute-never. # mapping the former as executable and the latter as execute-never.
SEPARATE_CODE_AND_RODATA := 1 SEPARATE_CODE_AND_RODATA := 1
...@@ -97,7 +109,8 @@ SEPARATE_CODE_AND_RODATA := 1 ...@@ -97,7 +109,8 @@ SEPARATE_CODE_AND_RODATA := 1
USE_TBBR_DEFS := 1 USE_TBBR_DEFS := 1
PLAT_INCLUDES += -Iplat/brcm/board/common \ PLAT_INCLUDES += -Iplat/brcm/board/common \
-Iinclude/drivers/brcm -Iinclude/drivers/brcm \
-Iinclude/drivers/brcm/emmc
PLAT_BL_COMMON_SOURCES += plat/brcm/common/brcm_common.c \ PLAT_BL_COMMON_SOURCES += plat/brcm/common/brcm_common.c \
plat/brcm/board/common/cmn_sec.c \ plat/brcm/board/common/cmn_sec.c \
...@@ -116,6 +129,22 @@ PLAT_BL_COMMON_SOURCES += plat/brcm/common/brcm_common.c \ ...@@ -116,6 +129,22 @@ PLAT_BL_COMMON_SOURCES += plat/brcm/common/brcm_common.c \
plat/brcm/board/common/sbl_util.c \ plat/brcm/board/common/sbl_util.c \
drivers/arm/sp805/sp805.c drivers/arm/sp805/sp805.c
# Add eMMC driver
ifeq (${DRIVER_EMMC_ENABLE},1)
$(eval $(call add_define,DRIVER_EMMC_ENABLE))
EMMC_SOURCES += drivers/brcm/emmc/emmc_chal_sd.c \
drivers/brcm/emmc/emmc_csl_sdcard.c \
drivers/brcm/emmc/emmc_csl_sdcmd.c \
drivers/brcm/emmc/emmc_pboot_hal_memory_drv.c
PLAT_BL_COMMON_SOURCES += ${EMMC_SOURCES}
ifeq (${DRIVER_EMMC_ENABLE_DATA_WIDTH_8BIT},)
$(eval $(call add_define,DRIVER_EMMC_ENABLE_DATA_WIDTH_8BIT))
endif
endif
BL2_SOURCES += plat/brcm/common/brcm_bl2_mem_params_desc.c \ BL2_SOURCES += plat/brcm/common/brcm_bl2_mem_params_desc.c \
plat/brcm/common/brcm_image_load.c \ plat/brcm/common/brcm_image_load.c \
common/desc_image_load.c common/desc_image_load.c
......
/*
* Copyright (c) 2016 - 2020, Broadcom
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdint.h>
#include <lib/mmio.h>
#include <platform_def.h>
#define ICFG_IPROC_IOPAD_CTRL_4 (IPROC_ROOT + 0x9c0)
#define ICFG_IPROC_IOPAD_CTRL_5 (IPROC_ROOT + 0x9c4)
#define ICFG_IPROC_IOPAD_CTRL_6 (IPROC_ROOT + 0x9c8)
#define ICFG_IPROC_IOPAD_CTRL_7 (IPROC_ROOT + 0x9cc)
#define IOPAD_CTRL4_SDIO0_CD_IND_R 30
#define IOPAD_CTRL4_SDIO0_CD_SRC_R 31
#define IOPAD_CTRL4_SDIO0_CD_HYS_R 29
#define IOPAD_CTRL4_SDIO0_CD_PULL_R 28
#define IOPAD_CTRL4_SDIO0_CD_DRIVE_R 24
#define IOPAD_CTRL4_SDIO0_CLK_SDCARD_SRC_R 23
#define IOPAD_CTRL4_SDIO0_CLK_SDCARD_HYS_R 21
#define IOPAD_CTRL4_SDIO0_CLK_SDCARD_DRIVE_R 17
#define IOPAD_CTRL4_SDIO0_DATA0_SRC_R 15
#define IOPAD_CTRL4_SDIO0_DATA0_HYS_R 13
#define IOPAD_CTRL4_SDIO0_DATA0_DRIVE_R 9
#define IOPAD_CTRL4_SDIO0_DATA1_SRC_R 7
#define IOPAD_CTRL4_SDIO0_DATA1_HYS_R 5
#define IOPAD_CTRL4_SDIO0_DATA1_DRIVE_R 1
#define IOPAD_CTRL5_SDIO0_DATA2_SRC_R 31
#define IOPAD_CTRL5_SDIO0_DATA2_HYS_R 29
#define IOPAD_CTRL5_SDIO0_DATA2_DRIVE_R 25
#define IOPAD_CTRL5_SDIO0_DATA3_SRC_R 23
#define IOPAD_CTRL5_SDIO0_DATA3_IND_R 22
#define IOPAD_CTRL5_SDIO0_DATA3_HYS_R 21
#define IOPAD_CTRL5_SDIO0_DATA3_DRIVE_R 17
#define IOPAD_CTRL5_SDIO0_DATA4_SRC_R 15
#define IOPAD_CTRL5_SDIO0_DATA4_HYS_R 13
#define IOPAD_CTRL5_SDIO0_DATA4_DRIVE_R 9
#define IOPAD_CTRL5_SDIO0_DATA5_SRC_R 7
#define IOPAD_CTRL5_SDIO0_DATA5_HYS_R 5
#define IOPAD_CTRL5_SDIO0_DATA5_DRIVE_R 1
#define IOPAD_CTRL6_SDIO0_DATA6_SRC_R 31
#define IOPAD_CTRL6_SDIO0_DATA6_HYS_R 29
#define IOPAD_CTRL6_SDIO0_DATA6_DRIVE_R 25
#define IOPAD_CTRL6_SDIO0_DATA7_SRC_R 23
#define IOPAD_CTRL6_SDIO0_DATA7_HYS_R 21
#define IOPAD_CTRL6_SDIO0_DATA7_DRIVE_R 17
void emmc_soft_reset(void)
{
uint32_t val = 0;
val = (BIT(IOPAD_CTRL6_SDIO0_DATA7_SRC_R) |
BIT(IOPAD_CTRL6_SDIO0_DATA7_HYS_R) |
BIT(IOPAD_CTRL6_SDIO0_DATA7_DRIVE_R) |
BIT(IOPAD_CTRL6_SDIO0_DATA6_SRC_R) |
BIT(IOPAD_CTRL6_SDIO0_DATA6_HYS_R) |
BIT(IOPAD_CTRL6_SDIO0_DATA6_DRIVE_R));
mmio_write_32(ICFG_IPROC_IOPAD_CTRL_6, val);
val = (BIT(IOPAD_CTRL5_SDIO0_DATA3_SRC_R) |
BIT(IOPAD_CTRL5_SDIO0_DATA3_HYS_R) |
BIT(IOPAD_CTRL5_SDIO0_DATA3_DRIVE_R) |
BIT(IOPAD_CTRL5_SDIO0_DATA4_SRC_R) |
BIT(IOPAD_CTRL5_SDIO0_DATA4_HYS_R) |
BIT(IOPAD_CTRL5_SDIO0_DATA4_DRIVE_R) |
BIT(IOPAD_CTRL5_SDIO0_DATA5_SRC_R) |
BIT(IOPAD_CTRL5_SDIO0_DATA5_HYS_R) |
BIT(IOPAD_CTRL5_SDIO0_DATA5_DRIVE_R));
mmio_write_32(ICFG_IPROC_IOPAD_CTRL_5, val);
val = (BIT(IOPAD_CTRL4_SDIO0_DATA0_SRC_R) |
BIT(IOPAD_CTRL4_SDIO0_DATA0_HYS_R) |
BIT(IOPAD_CTRL4_SDIO0_DATA0_DRIVE_R) |
BIT(IOPAD_CTRL4_SDIO0_DATA1_SRC_R) |
BIT(IOPAD_CTRL4_SDIO0_DATA1_HYS_R) |
BIT(IOPAD_CTRL4_SDIO0_DATA1_DRIVE_R) |
BIT(IOPAD_CTRL5_SDIO0_DATA2_SRC_R) |
BIT(IOPAD_CTRL5_SDIO0_DATA2_HYS_R) |
BIT(IOPAD_CTRL5_SDIO0_DATA2_DRIVE_R));
mmio_write_32(ICFG_IPROC_IOPAD_CTRL_6, val);
val = (BIT(IOPAD_CTRL4_SDIO0_CLK_SDCARD_SRC_R) |
BIT(IOPAD_CTRL4_SDIO0_CLK_SDCARD_HYS_R) |
BIT(IOPAD_CTRL4_SDIO0_CLK_SDCARD_DRIVE_R) |
BIT(IOPAD_CTRL4_SDIO0_CD_SRC_R) |
BIT(IOPAD_CTRL4_SDIO0_CD_HYS_R));
/*
* set pull-down, clear pull-up=0
* bit 12: pull-down bit 11: pull-up
* Note: In emulation, this pull-down setting was not
* sufficient. Board design likely requires pull down on
* this pin for eMMC.
*/
val |= BIT(IOPAD_CTRL4_SDIO0_CD_PULL_R);
mmio_write_32(ICFG_IPROC_IOPAD_CTRL_4, val);
}
...@@ -24,6 +24,13 @@ ERRATA_A72_859971 := 1 ...@@ -24,6 +24,13 @@ ERRATA_A72_859971 := 1
DRIVER_CC_ENABLE := 1 DRIVER_CC_ENABLE := 1
$(eval $(call add_define,DRIVER_CC_ENABLE)) $(eval $(call add_define,DRIVER_CC_ENABLE))
# Enable to erase eMMC
INCLUDE_EMMC_DRIVER_ERASE_CODE := 0
ifeq (${INCLUDE_EMMC_DRIVER_ERASE_CODE},1)
$(eval $(call add_define,INCLUDE_EMMC_DRIVER_ERASE_CODE))
endif
# BL31 is in DRAM # BL31 is in DRAM
ARM_BL31_IN_DRAM := 1 ARM_BL31_IN_DRAM := 1
...@@ -178,6 +185,7 @@ PLAT_BL_COMMON_SOURCES += lib/cpus/aarch64/cortex_a72.S \ ...@@ -178,6 +185,7 @@ PLAT_BL_COMMON_SOURCES += lib/cpus/aarch64/cortex_a72.S \
drivers/ti/uart/aarch64/16550_console.S \ drivers/ti/uart/aarch64/16550_console.S \
plat/${SOC_DIR}/src/tz_sec.c \ plat/${SOC_DIR}/src/tz_sec.c \
drivers/arm/tzc/tzc400.c \ drivers/arm/tzc/tzc400.c \
plat/${SOC_DIR}/driver/plat_emmc.c \
plat/${SOC_DIR}/src/topology.c plat/${SOC_DIR}/src/topology.c
ifeq (${USE_CHIMP},yes) ifeq (${USE_CHIMP},yes)
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <chip_id.h> #include <chip_id.h>
#include <cmn_plat_util.h> #include <cmn_plat_util.h>
#include <dmu.h> #include <dmu.h>
#include <emmc_api.h>
#include <fru.h> #include <fru.h>
#ifdef USE_GPIO #ifdef USE_GPIO
#include <drivers/gpio.h> #include <drivers/gpio.h>
......
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