diff --git a/drivers/brcm/emmc/emmc_chal_sd.c b/drivers/brcm/emmc/emmc_chal_sd.c new file mode 100644 index 0000000..34d761c --- /dev/null +++ b/drivers/brcm/emmc/emmc_chal_sd.c @@ -0,0 +1,1017 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#include + +#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); +} diff --git a/drivers/brcm/emmc/emmc_csl_sdcard.c b/drivers/brcm/emmc/emmc_csl_sdcard.c new file mode 100644 index 0000000..d6ad4bc --- /dev/null +++ b/drivers/brcm/emmc/emmc_csl_sdcard.c @@ -0,0 +1,1087 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include + +#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; +} diff --git a/drivers/brcm/emmc/emmc_csl_sdcmd.c b/drivers/brcm/emmc/emmc_csl_sdcmd.c new file mode 100644 index 0000000..c62886c --- /dev/null +++ b/drivers/brcm/emmc/emmc_csl_sdcmd.c @@ -0,0 +1,842 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#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; +} diff --git a/drivers/brcm/emmc/emmc_pboot_hal_memory_drv.c b/drivers/brcm/emmc/emmc_pboot_hal_memory_drv.c new file mode 100644 index 0000000..68f93e7 --- /dev/null +++ b/drivers/brcm/emmc/emmc_pboot_hal_memory_drv.c @@ -0,0 +1,621 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +#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; +} diff --git a/include/drivers/brcm/emmc/bcm_emmc.h b/include/drivers/brcm/emmc/bcm_emmc.h new file mode 100644 index 0000000..67f0602 --- /dev/null +++ b/include/drivers/brcm/emmc/bcm_emmc.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef EMMC_H +#define EMMC_H + +#include + +#include + +#include + +#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 */ diff --git a/include/drivers/brcm/emmc/emmc_api.h b/include/drivers/brcm/emmc/emmc_api.h new file mode 100644 index 0000000..c4c2a58 --- /dev/null +++ b/include/drivers/brcm/emmc/emmc_api.h @@ -0,0 +1,47 @@ +/* + * 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 */ diff --git a/include/drivers/brcm/emmc/emmc_brcm_rdb_sd4_top.h b/include/drivers/brcm/emmc/emmc_brcm_rdb_sd4_top.h new file mode 100644 index 0000000..96c333d --- /dev/null +++ b/include/drivers/brcm/emmc/emmc_brcm_rdb_sd4_top.h @@ -0,0 +1,1116 @@ +/* + * 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 */ diff --git a/include/drivers/brcm/emmc/emmc_chal_sd.h b/include/drivers/brcm/emmc/emmc_chal_sd.h new file mode 100644 index 0000000..8d223f9 --- /dev/null +++ b/include/drivers/brcm/emmc/emmc_chal_sd.h @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CHAL_SD_H +#define CHAL_SD_H + +#include + +#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 */ diff --git a/include/drivers/brcm/emmc/emmc_chal_types.h b/include/drivers/brcm/emmc/emmc_chal_types.h new file mode 100644 index 0000000..9563273 --- /dev/null +++ b/include/drivers/brcm/emmc/emmc_chal_types.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + +#ifndef CHAL_TYPES_H +#define CHAL_TYPES_H + +#include + +// +// Generic cHAL handler +// +#ifndef CHAL_HANDLE + typedef void *CHAL_HANDLE; ///< void pointer (32 bits wide) +#endif + +#endif /* _CHAL_TYPES_H_ */ diff --git a/include/drivers/brcm/emmc/emmc_csl_sd.h b/include/drivers/brcm/emmc/emmc_csl_sd.h new file mode 100644 index 0000000..52b8bc8 --- /dev/null +++ b/include/drivers/brcm/emmc/emmc_csl_sd.h @@ -0,0 +1,96 @@ +/* + * 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 */ diff --git a/include/drivers/brcm/emmc/emmc_csl_sdcmd.h b/include/drivers/brcm/emmc/emmc_csl_sdcmd.h new file mode 100644 index 0000000..425603f --- /dev/null +++ b/include/drivers/brcm/emmc/emmc_csl_sdcmd.h @@ -0,0 +1,168 @@ +/* + * 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 */ diff --git a/include/drivers/brcm/emmc/emmc_csl_sdprot.h b/include/drivers/brcm/emmc/emmc_csl_sdprot.h new file mode 100644 index 0000000..597e1e0 --- /dev/null +++ b/include/drivers/brcm/emmc/emmc_csl_sdprot.h @@ -0,0 +1,435 @@ +/* + * 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 */ diff --git a/include/drivers/brcm/emmc/emmc_pboot_hal_memory_drv.h b/include/drivers/brcm/emmc/emmc_pboot_hal_memory_drv.h new file mode 100644 index 0000000..8e61b51 --- /dev/null +++ b/include/drivers/brcm/emmc/emmc_pboot_hal_memory_drv.h @@ -0,0 +1,94 @@ +/* + * 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 + +#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 diff --git a/plat/brcm/board/common/board_common.mk b/plat/brcm/board/common/board_common.mk index a0112c5..2a7ebdf 100644 --- a/plat/brcm/board/common/board_common.mk +++ b/plat/brcm/board/common/board_common.mk @@ -28,6 +28,10 @@ $(eval $(call add_define,SYSCNT_FREQ)) endif +ifeq (${DRIVER_EMMC_ENABLE},) +DRIVER_EMMC_ENABLE :=1 +endif + # By default, Trusted Watchdog is always enabled unless SPIN_ON_BL1_EXIT is set ifeq (${BRCM_DISABLE_TRUSTED_WDOG},) BRCM_DISABLE_TRUSTED_WDOG := 0 @@ -89,6 +93,14 @@ $(eval $(call add_define,USE_CRMU_SRAM)) 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 # mapping the former as executable and the latter as execute-never. SEPARATE_CODE_AND_RODATA := 1 @@ -97,7 +109,8 @@ USE_TBBR_DEFS := 1 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/brcm/board/common/cmn_sec.c \ @@ -116,6 +129,22 @@ plat/brcm/board/common/sbl_util.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 \ plat/brcm/common/brcm_image_load.c \ common/desc_image_load.c diff --git a/plat/brcm/board/stingray/driver/plat_emmc.c b/plat/brcm/board/stingray/driver/plat_emmc.c new file mode 100644 index 0000000..82085e1 --- /dev/null +++ b/plat/brcm/board/stingray/driver/plat_emmc.c @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include + +#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); +} diff --git a/plat/brcm/board/stingray/platform.mk b/plat/brcm/board/stingray/platform.mk index cc7ae53..8d2119d 100644 --- a/plat/brcm/board/stingray/platform.mk +++ b/plat/brcm/board/stingray/platform.mk @@ -24,6 +24,13 @@ DRIVER_CC_ENABLE := 1 $(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 ARM_BL31_IN_DRAM := 1 @@ -178,6 +185,7 @@ drivers/ti/uart/aarch64/16550_console.S \ plat/${SOC_DIR}/src/tz_sec.c \ drivers/arm/tzc/tzc400.c \ + plat/${SOC_DIR}/driver/plat_emmc.c \ plat/${SOC_DIR}/src/topology.c ifeq (${USE_CHIMP},yes) diff --git a/plat/brcm/board/stingray/src/bl2_setup.c b/plat/brcm/board/stingray/src/bl2_setup.c index 0b0a3ff..9a79744 100644 --- a/plat/brcm/board/stingray/src/bl2_setup.c +++ b/plat/brcm/board/stingray/src/bl2_setup.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #ifdef USE_GPIO #include