/* * 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); }