1bffde63dSSheetal Tigadoli /* 2bffde63dSSheetal Tigadoli * Copyright (c) 2016 - 2020, Broadcom 3bffde63dSSheetal Tigadoli * 4bffde63dSSheetal Tigadoli * SPDX-License-Identifier: BSD-3-Clause 5bffde63dSSheetal Tigadoli */ 6bffde63dSSheetal Tigadoli 7bffde63dSSheetal Tigadoli #include <assert.h> 8bffde63dSSheetal Tigadoli #include <string.h> 9bffde63dSSheetal Tigadoli 10bffde63dSSheetal Tigadoli #include <lib/mmio.h> 11bffde63dSSheetal Tigadoli 12bffde63dSSheetal Tigadoli #include <platform_def.h> 13bffde63dSSheetal Tigadoli 14bffde63dSSheetal Tigadoli #include "bcm_emmc.h" 15bffde63dSSheetal Tigadoli #include "emmc_chal_types.h" 16bffde63dSSheetal Tigadoli #include "emmc_chal_sd.h" 17bffde63dSSheetal Tigadoli #include "emmc_pboot_hal_memory_drv.h" 18bffde63dSSheetal Tigadoli 19bffde63dSSheetal Tigadoli extern void emmc_soft_reset(void); 20bffde63dSSheetal Tigadoli 21bffde63dSSheetal Tigadoli #define SD_VDD_WINDOW_1_6_TO_1_7 0x00000010 // 1.6 V to 1.7 Volts 22bffde63dSSheetal Tigadoli #define SD_VDD_WINDOW_1_7_TO_1_8 0x00000020 // 1.7 V to 1.8 Volts 23bffde63dSSheetal Tigadoli #define SD_VDD_WINDOW_1_8_TO_1_9 0x00000040 // 1.8 V to 1.9 Volts 24bffde63dSSheetal Tigadoli #define SD_VDD_WINDOW_1_9_TO_2_0 0x00000080 // 1.9 V to 2.0 Volts 25bffde63dSSheetal Tigadoli #define SD_VDD_WINDOW_2_0_TO_2_1 0x00000100 // 2.0 V to 2.1 Volts 26bffde63dSSheetal Tigadoli #define SD_VDD_WINDOW_2_1_TO_2_2 0x00000200 // 2.1 V to 2.2 Volts 27bffde63dSSheetal Tigadoli #define SD_VDD_WINDOW_2_2_TO_2_3 0x00000400 // 2.2 V to 2.3 Volts 28bffde63dSSheetal Tigadoli #define SD_VDD_WINDOW_2_3_TO_2_4 0x00000800 // 2.3 V to 2.4 Volts 29bffde63dSSheetal Tigadoli #define SD_VDD_WINDOW_2_4_TO_2_5 0x00001000 // 2.4 V to 2.5 Volts 30bffde63dSSheetal Tigadoli #define SD_VDD_WINDOW_2_5_TO_2_6 0x00002000 // 2.5 V to 2.6 Volts 31bffde63dSSheetal Tigadoli #define SD_VDD_WINDOW_2_6_TO_2_7 0x00004000 // 2.6 V to 2.7 Volts 32bffde63dSSheetal Tigadoli #define SD_VDD_WINDOW_2_7_TO_2_8 0x00008000 // 2.7 V to 2.8 Volts 33bffde63dSSheetal Tigadoli #define SD_VDD_WINDOW_2_8_TO_2_9 0x00010000 // 2.8 V to 2.9 Volts 34bffde63dSSheetal Tigadoli #define SD_VDD_WINDOW_2_9_TO_3_0 0x00020000 // 2.9 V to 3.0 Volts 35bffde63dSSheetal Tigadoli #define SD_VDD_WINDOW_3_0_TO_3_1 0x00040000 // 3.0 V to 3.1 Volts 36bffde63dSSheetal Tigadoli #define SD_VDD_WINDOW_3_1_TO_3_2 0x00080000 // 3.1 V to 3.2 Volts 37bffde63dSSheetal Tigadoli #define SD_VDD_WINDOW_3_2_TO_3_3 0x00100000 // 3.2 V to 3.3 Volts 38bffde63dSSheetal Tigadoli #define SD_VDD_WINDOW_3_3_TO_3_4 0x00200000 // 3.3 V to 3.4 Volts 39bffde63dSSheetal Tigadoli #define SD_VDD_WINDOW_3_4_TO_3_5 0x00400000 // 3.4 V to 3.5 Volts 40bffde63dSSheetal Tigadoli #define SD_VDD_WINDOW_3_5_TO_3_6 0x00800000 // 3.5 V to 3.6 Volts 41bffde63dSSheetal Tigadoli 42bffde63dSSheetal Tigadoli #define SD_VDD_WINDOW_1_6_TO_2_6 (SD_VDD_WINDOW_1_6_TO_1_7 | \ 43bffde63dSSheetal Tigadoli SD_VDD_WINDOW_1_7_TO_1_8 | \ 44bffde63dSSheetal Tigadoli SD_VDD_WINDOW_1_8_TO_1_9 | \ 45bffde63dSSheetal Tigadoli SD_VDD_WINDOW_1_9_TO_2_0 | \ 46bffde63dSSheetal Tigadoli SD_VDD_WINDOW_2_0_TO_2_1 | \ 47bffde63dSSheetal Tigadoli SD_VDD_WINDOW_2_1_TO_2_2 | \ 48bffde63dSSheetal Tigadoli SD_VDD_WINDOW_2_2_TO_2_3 | \ 49bffde63dSSheetal Tigadoli SD_VDD_WINDOW_2_3_TO_2_4 | \ 50bffde63dSSheetal Tigadoli SD_VDD_WINDOW_2_4_TO_2_5 | \ 51bffde63dSSheetal Tigadoli SD_VDD_WINDOW_2_5_TO_2_6) 52bffde63dSSheetal Tigadoli 53bffde63dSSheetal Tigadoli #define SD_VDD_WINDOW_2_6_TO_3_2 (SD_VDD_WINDOW_2_6_TO_2_7 | \ 54bffde63dSSheetal Tigadoli SD_VDD_WINDOW_2_7_TO_2_8 | \ 55bffde63dSSheetal Tigadoli SD_VDD_WINDOW_2_8_TO_2_9 | \ 56bffde63dSSheetal Tigadoli SD_VDD_WINDOW_2_9_TO_3_0 | \ 57bffde63dSSheetal Tigadoli SD_VDD_WINDOW_3_0_TO_3_1 | \ 58bffde63dSSheetal Tigadoli SD_VDD_WINDOW_3_1_TO_3_2) 59bffde63dSSheetal Tigadoli 60bffde63dSSheetal Tigadoli #define SD_VDD_WINDOW_3_2_TO_3_6 (SD_VDD_WINDOW_3_2_TO_3_3 | \ 61bffde63dSSheetal Tigadoli SD_VDD_WINDOW_3_3_TO_3_4 | \ 62bffde63dSSheetal Tigadoli SD_VDD_WINDOW_3_4_TO_3_5 | \ 63bffde63dSSheetal Tigadoli SD_VDD_WINDOW_3_5_TO_3_6) 64bffde63dSSheetal Tigadoli 65bffde63dSSheetal Tigadoli 66bffde63dSSheetal Tigadoli static int32_t chal_sd_set_power(struct sd_dev *handle, 67bffde63dSSheetal Tigadoli uint32_t voltage, uint32_t state); 68bffde63dSSheetal Tigadoli 69bffde63dSSheetal Tigadoli static void chal_sd_set_dma_boundary(struct sd_dev *handle, uint32_t boundary); 70bffde63dSSheetal Tigadoli 71bffde63dSSheetal Tigadoli static int32_t chal_sd_setup_handler(struct sd_dev *handle, 72bffde63dSSheetal Tigadoli uint32_t sdBbase, uint32_t hostBase); 73bffde63dSSheetal Tigadoli 74bffde63dSSheetal Tigadoli /* 75bffde63dSSheetal Tigadoli * Configure host controller pwr settings, 76bffde63dSSheetal Tigadoli * to match voltage requirements by SD Card 77bffde63dSSheetal Tigadoli */ 78bffde63dSSheetal Tigadoli static int32_t chal_sd_set_power(struct sd_dev *handle, 79bffde63dSSheetal Tigadoli uint32_t voltage, uint32_t state) 80bffde63dSSheetal Tigadoli { 81bffde63dSSheetal Tigadoli int32_t rc, rval = SD_FAIL; 82bffde63dSSheetal Tigadoli uint32_t time = 0; 83bffde63dSSheetal Tigadoli 84bffde63dSSheetal Tigadoli if (handle == NULL) 85bffde63dSSheetal Tigadoli return SD_INVALID_HANDLE; 86bffde63dSSheetal Tigadoli 87bffde63dSSheetal Tigadoli mmio_clrsetbits_32(handle->ctrl.sdRegBaseAddr + 88bffde63dSSheetal Tigadoli SD4_EMMC_TOP_CTRL_OFFSET, 89bffde63dSSheetal Tigadoli (SD4_EMMC_TOP_CTRL_SDVSELVDD1_MASK | 90bffde63dSSheetal Tigadoli SD4_EMMC_TOP_CTRL_SDPWR_MASK), 91bffde63dSSheetal Tigadoli (voltage << 9)); 92bffde63dSSheetal Tigadoli 93bffde63dSSheetal Tigadoli /* 94bffde63dSSheetal Tigadoli * Long delay is required here in emulation. Without this, the initial 95bffde63dSSheetal Tigadoli * commands sent to the eMMC card timeout. We don't know if this 96bffde63dSSheetal Tigadoli * delay is necessary with silicon, leaving in for safety. 97bffde63dSSheetal Tigadoli * It is observed that 403ms on emulation system and as per the clock 98bffde63dSSheetal Tigadoli * calculations it is expected to complete with in 1ms on chip 99bffde63dSSheetal Tigadoli */ 100bffde63dSSheetal Tigadoli do { 101bffde63dSSheetal Tigadoli rc = mmio_read_32(handle->ctrl.sdRegBaseAddr + 102bffde63dSSheetal Tigadoli SD4_EMMC_TOP_INTR_OFFSET); 103bffde63dSSheetal Tigadoli 104bffde63dSSheetal Tigadoli if ((rc & SD4_EMMC_TOP_INTR_CRDINS_MASK) == 105bffde63dSSheetal Tigadoli SD4_EMMC_TOP_INTR_CRDINS_MASK) 106bffde63dSSheetal Tigadoli break; 107bffde63dSSheetal Tigadoli 108bffde63dSSheetal Tigadoli mdelay(1); 109bffde63dSSheetal Tigadoli } while (time++ < EMMC_CARD_DETECT_TIMEOUT_MS); 110bffde63dSSheetal Tigadoli 111bffde63dSSheetal Tigadoli if (time >= EMMC_CARD_DETECT_TIMEOUT_MS) { 112bffde63dSSheetal Tigadoli ERROR("EMMC: Card insert event detection timeout\n"); 113bffde63dSSheetal Tigadoli return rval; 114bffde63dSSheetal Tigadoli } 115bffde63dSSheetal Tigadoli 116bffde63dSSheetal Tigadoli VERBOSE("EMMC: Card detection delay: %dms\n", time); 117bffde63dSSheetal Tigadoli 118bffde63dSSheetal Tigadoli if (state) 119bffde63dSSheetal Tigadoli mmio_setbits_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_CTRL_OFFSET, 120bffde63dSSheetal Tigadoli SD4_EMMC_TOP_CTRL_SDPWR_MASK); 121bffde63dSSheetal Tigadoli 122*1b491eeaSElyes Haouas /* dummy write & ack to verify if the sdio is ready to send commands */ 123bffde63dSSheetal Tigadoli mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_ARG_OFFSET, 0); 124bffde63dSSheetal Tigadoli mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_CMD_OFFSET, 0); 125bffde63dSSheetal Tigadoli 126bffde63dSSheetal Tigadoli /* 127bffde63dSSheetal Tigadoli * 63ms observed on emulation system, As per clock calculations 128bffde63dSSheetal Tigadoli * it will complete < 1ms on chip. 129bffde63dSSheetal Tigadoli */ 130bffde63dSSheetal Tigadoli time = 0; 131bffde63dSSheetal Tigadoli do { 132bffde63dSSheetal Tigadoli rc = mmio_read_32(handle->ctrl.sdRegBaseAddr + 133bffde63dSSheetal Tigadoli SD4_EMMC_TOP_INTR_OFFSET); 134bffde63dSSheetal Tigadoli 135bffde63dSSheetal Tigadoli if (rc & SD4_EMMC_TOP_INTR_ERRIRQ_MASK) 136bffde63dSSheetal Tigadoli break; 137bffde63dSSheetal Tigadoli 138bffde63dSSheetal Tigadoli if ((rc & SD4_EMMC_TOP_INTR_CMDDONE_MASK) == 139bffde63dSSheetal Tigadoli SD4_EMMC_TOP_INTR_CMDDONE_MASK) 140bffde63dSSheetal Tigadoli break; 141bffde63dSSheetal Tigadoli 142bffde63dSSheetal Tigadoli mdelay(1); 143bffde63dSSheetal Tigadoli } while (time++ < EMMC_CMD_TIMEOUT_MS); 144bffde63dSSheetal Tigadoli 145bffde63dSSheetal Tigadoli if (time >= EMMC_CMD_TIMEOUT_MS) { 146bffde63dSSheetal Tigadoli WARN("%s %d Initial dummy command timeout is happened\n", 147bffde63dSSheetal Tigadoli __func__, __LINE__); 148bffde63dSSheetal Tigadoli return rval; 149bffde63dSSheetal Tigadoli } 150bffde63dSSheetal Tigadoli 151bffde63dSSheetal Tigadoli VERBOSE("EMMC: Dummy Command delay: %dms\n", time); 152bffde63dSSheetal Tigadoli 153bffde63dSSheetal Tigadoli return SD_OK; 154bffde63dSSheetal Tigadoli } 155bffde63dSSheetal Tigadoli 156bffde63dSSheetal Tigadoli /* 157bffde63dSSheetal Tigadoli * Configure DMA Boundaries 158bffde63dSSheetal Tigadoli */ 159bffde63dSSheetal Tigadoli static void chal_sd_set_dma_boundary(struct sd_dev *handle, uint32_t boundary) 160bffde63dSSheetal Tigadoli { 161bffde63dSSheetal Tigadoli if (handle == NULL) 162bffde63dSSheetal Tigadoli return; 163bffde63dSSheetal Tigadoli 164bffde63dSSheetal Tigadoli mmio_clrsetbits_32(handle->ctrl.sdRegBaseAddr + 165bffde63dSSheetal Tigadoli SD4_EMMC_TOP_BLOCK_OFFSET, 166bffde63dSSheetal Tigadoli SD4_EMMC_TOP_BLOCK_HSBS_MASK, boundary); 167bffde63dSSheetal Tigadoli } 168bffde63dSSheetal Tigadoli 169bffde63dSSheetal Tigadoli static int32_t chal_sd_setup_handler(struct sd_dev *handle, uint32_t sdBase, 170bffde63dSSheetal Tigadoli uint32_t hostBase) 171bffde63dSSheetal Tigadoli { 172bffde63dSSheetal Tigadoli if (handle == NULL) 173bffde63dSSheetal Tigadoli return SD_INVALID_HANDLE; 174bffde63dSSheetal Tigadoli 175bffde63dSSheetal Tigadoli handle->ctrl.sdRegBaseAddr = sdBase; 176bffde63dSSheetal Tigadoli handle->ctrl.hostRegBaseAddr = hostBase; 177bffde63dSSheetal Tigadoli handle->ctrl.present = 0; 178bffde63dSSheetal Tigadoli handle->ctrl.rca = 0; 179bffde63dSSheetal Tigadoli handle->ctrl.blkGapEnable = 0; 180bffde63dSSheetal Tigadoli handle->ctrl.cmdStatus = 0; 181bffde63dSSheetal Tigadoli 182bffde63dSSheetal Tigadoli return SD_OK; 183bffde63dSSheetal Tigadoli } 184bffde63dSSheetal Tigadoli 185bffde63dSSheetal Tigadoli /* 186bffde63dSSheetal Tigadoli * Initialize SD Host controller 187bffde63dSSheetal Tigadoli */ 188bffde63dSSheetal Tigadoli int32_t chal_sd_init(CHAL_HANDLE *sd_handle) 189bffde63dSSheetal Tigadoli { 190bffde63dSSheetal Tigadoli uint32_t cap_val_l = 0; 191bffde63dSSheetal Tigadoli uint32_t ctl_val, voltage; 192bffde63dSSheetal Tigadoli uint32_t timeout_val; 193bffde63dSSheetal Tigadoli struct sd_dev *handle; 194bffde63dSSheetal Tigadoli uint32_t reg_val; 195bffde63dSSheetal Tigadoli int32_t rval = SD_FAIL; 196bffde63dSSheetal Tigadoli 197bffde63dSSheetal Tigadoli if (sd_handle == NULL) 198bffde63dSSheetal Tigadoli return SD_INVALID_HANDLE; 199bffde63dSSheetal Tigadoli 200bffde63dSSheetal Tigadoli handle = (struct sd_dev *)sd_handle; 201bffde63dSSheetal Tigadoli 202bffde63dSSheetal Tigadoli /* 203bffde63dSSheetal Tigadoli * Set SDIO Host Controller capabilities register 204bffde63dSSheetal Tigadoli */ 205bffde63dSSheetal Tigadoli EMMC_TRACE("Set Host Controller Capabilities register\n"); 206bffde63dSSheetal Tigadoli 207bffde63dSSheetal Tigadoli reg_val = 0; 208bffde63dSSheetal Tigadoli reg_val |= (1 << ICFG_SDIO0_CAP0__SLOT_TYPE_R); 209bffde63dSSheetal Tigadoli reg_val |= (0 << ICFG_SDIO0_CAP0__INT_MODE_R); 210bffde63dSSheetal Tigadoli reg_val |= (0 << ICFG_SDIO0_CAP0__SYS_BUS_64BIT_R); 211bffde63dSSheetal Tigadoli reg_val |= (1 << ICFG_SDIO0_CAP0__VOLTAGE_1P8V_R); 212bffde63dSSheetal Tigadoli reg_val |= (1 << ICFG_SDIO0_CAP0__VOLTAGE_3P0V_R); 213bffde63dSSheetal Tigadoli reg_val |= (1 << ICFG_SDIO0_CAP0__VOLTAGE_3P3V_R); 214bffde63dSSheetal Tigadoli reg_val |= (1 << ICFG_SDIO0_CAP0__SUSPEND_RESUME_R); 215bffde63dSSheetal Tigadoli reg_val |= (1 << ICFG_SDIO0_CAP0__SDMA_R); 216bffde63dSSheetal Tigadoli reg_val |= (1 << ICFG_SDIO0_CAP0__HIGH_SPEED_R); 217bffde63dSSheetal Tigadoli reg_val |= (1 << ICFG_SDIO0_CAP0__ADMA2_R); 218bffde63dSSheetal Tigadoli reg_val |= (1 << ICFG_SDIO0_CAP0__EXTENDED_MEDIA_R); 219bffde63dSSheetal Tigadoli reg_val |= (2 << ICFG_SDIO0_CAP0__MAX_BLOCK_LEN_R); 220bffde63dSSheetal Tigadoli reg_val |= (0xd0 << ICFG_SDIO0_CAP0__BASE_CLK_FREQ_R); 221bffde63dSSheetal Tigadoli reg_val |= (1 << ICFG_SDIO0_CAP0__TIMEOUT_UNIT_R); 222bffde63dSSheetal Tigadoli reg_val |= (0x30 << ICFG_SDIO0_CAP0__TIMEOUT_CLK_FREQ_R); 223bffde63dSSheetal Tigadoli 224bffde63dSSheetal Tigadoli mmio_write_32(ICFG_SDIO0_CAP0, reg_val); 225bffde63dSSheetal Tigadoli 226bffde63dSSheetal Tigadoli reg_val = 0; 227bffde63dSSheetal Tigadoli reg_val |= (1 << ICFG_SDIO0_CAP1__SPI_BLOCK_MODE_R); 228bffde63dSSheetal Tigadoli reg_val |= (1 << ICFG_SDIO0_CAP1__SPI_MODE_R); 229bffde63dSSheetal Tigadoli reg_val |= (0 << ICFG_SDIO0_CAP1__CLK_MULT_R); 230bffde63dSSheetal Tigadoli reg_val |= (0 << ICFG_SDIO0_CAP1__RETUNING_MODE_R); 231bffde63dSSheetal Tigadoli reg_val |= (1 << ICFG_SDIO0_CAP1__TUNE_SDR50_R); 232bffde63dSSheetal Tigadoli reg_val |= (1 << ICFG_SDIO0_CAP1__TIME_RETUNE_R); 233bffde63dSSheetal Tigadoli reg_val |= (1 << ICFG_SDIO0_CAP1__DRIVER_D_R); 234bffde63dSSheetal Tigadoli reg_val |= (1 << ICFG_SDIO0_CAP1__DRIVER_C_R); 235bffde63dSSheetal Tigadoli reg_val |= (1 << ICFG_SDIO0_CAP1__DRIVER_A_R); 236bffde63dSSheetal Tigadoli reg_val |= (1 << ICFG_SDIO0_CAP1__DDR50_R); 237bffde63dSSheetal Tigadoli reg_val |= (1 << ICFG_SDIO0_CAP1__SDR104_R); 238bffde63dSSheetal Tigadoli reg_val |= (1 << ICFG_SDIO0_CAP1__SDR50_R); 239bffde63dSSheetal Tigadoli 240bffde63dSSheetal Tigadoli mmio_write_32(ICFG_SDIO0_CAP1, reg_val); 241bffde63dSSheetal Tigadoli 242bffde63dSSheetal Tigadoli /* Reset the SDIO controller */ 243bffde63dSSheetal Tigadoli chal_sd_stop(); 244bffde63dSSheetal Tigadoli 245bffde63dSSheetal Tigadoli /* Turn on SD clock */ 246bffde63dSSheetal Tigadoli chal_sd_set_clock(sd_handle, 247bffde63dSSheetal Tigadoli chal_sd_freq_2_div_ctrl_setting(INIT_CLK_FREQ), 1); 248bffde63dSSheetal Tigadoli 249bffde63dSSheetal Tigadoli /* program data time out value to the max */ 250bffde63dSSheetal Tigadoli timeout_val = SD_HOST_CORE_TIMEOUT; 251bffde63dSSheetal Tigadoli 252bffde63dSSheetal Tigadoli ctl_val = mmio_read_32(handle->ctrl.sdRegBaseAddr + 253bffde63dSSheetal Tigadoli SD4_EMMC_TOP_CTRL1_OFFSET); 254bffde63dSSheetal Tigadoli ctl_val |= ((timeout_val & 0xf) << SD4_EMMC_TOP_CTRL1_DTCNT_SHIFT); 255bffde63dSSheetal Tigadoli 256bffde63dSSheetal Tigadoli mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_CTRL1_OFFSET, 257bffde63dSSheetal Tigadoli ctl_val); 258bffde63dSSheetal Tigadoli 259bffde63dSSheetal Tigadoli /* enable all interrupt status */ 260bffde63dSSheetal Tigadoli mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_INTREN1_OFFSET, 261bffde63dSSheetal Tigadoli 0); 262bffde63dSSheetal Tigadoli mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_INTREN2_OFFSET, 263bffde63dSSheetal Tigadoli 0); 264bffde63dSSheetal Tigadoli 265bffde63dSSheetal Tigadoli SD_US_DELAY(100); 266bffde63dSSheetal Tigadoli 267bffde63dSSheetal Tigadoli mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_INTREN1_OFFSET, 268bffde63dSSheetal Tigadoli SD_NOR_INTERRUPTS | SD_ERR_INTERRUPTS); 269bffde63dSSheetal Tigadoli mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_INTREN2_OFFSET, 270bffde63dSSheetal Tigadoli SD_NOR_INTERRUPTS | SD_ERR_INTERRUPTS); 271bffde63dSSheetal Tigadoli 272bffde63dSSheetal Tigadoli /* Select SD bus voltage */ 273bffde63dSSheetal Tigadoli cap_val_l = mmio_read_32(handle->ctrl.sdRegBaseAddr + 274bffde63dSSheetal Tigadoli SD4_EMMC_TOP_CAPABILITIES1_OFFSET); 275bffde63dSSheetal Tigadoli handle->cfg.voltage = 0; 276bffde63dSSheetal Tigadoli voltage = 0x7; 277bffde63dSSheetal Tigadoli 278bffde63dSSheetal Tigadoli if (cap_val_l & SD4_EMMC_TOP_CAPABILITIES1_V33_MASK) { 279bffde63dSSheetal Tigadoli handle->cfg.voltage |= SD_VDD_WINDOW_3_3_TO_3_4; 280bffde63dSSheetal Tigadoli voltage = 0x7; 281bffde63dSSheetal Tigadoli } else if (cap_val_l & SD4_EMMC_TOP_CAPABILITIES1_V3_MASK) { 282bffde63dSSheetal Tigadoli handle->cfg.voltage |= SD_VDD_WINDOW_3_0_TO_3_1; 283bffde63dSSheetal Tigadoli voltage = 0x6; 284bffde63dSSheetal Tigadoli } else if (cap_val_l & SD4_EMMC_TOP_CAPABILITIES1_V18_MASK) { 285bffde63dSSheetal Tigadoli handle->cfg.voltage |= SD_VDD_WINDOW_1_8_TO_1_9; 286bffde63dSSheetal Tigadoli voltage = 0x5; 287bffde63dSSheetal Tigadoli } 288bffde63dSSheetal Tigadoli 289bffde63dSSheetal Tigadoli rval = chal_sd_set_power(handle, voltage, SD4_EMMC_TOP_CTRL_SDPWR_MASK); 290bffde63dSSheetal Tigadoli 291bffde63dSSheetal Tigadoli ctl_val = mmio_read_32(handle->ctrl.sdRegBaseAddr + 292bffde63dSSheetal Tigadoli SD4_EMMC_TOP_HCVERSIRQ_OFFSET); 293bffde63dSSheetal Tigadoli handle->ctrl.version = ((ctl_val >> 16) & 0xFF); 294bffde63dSSheetal Tigadoli 295bffde63dSSheetal Tigadoli return rval; 296bffde63dSSheetal Tigadoli } 297bffde63dSSheetal Tigadoli 298bffde63dSSheetal Tigadoli void chal_sd_set_speed(CHAL_HANDLE *sd_handle, uint32_t speed) 299bffde63dSSheetal Tigadoli { 300bffde63dSSheetal Tigadoli struct sd_dev *handle; 301bffde63dSSheetal Tigadoli 302bffde63dSSheetal Tigadoli if (sd_handle == NULL) 303bffde63dSSheetal Tigadoli return; 304bffde63dSSheetal Tigadoli 305bffde63dSSheetal Tigadoli handle = (struct sd_dev *) sd_handle; 306bffde63dSSheetal Tigadoli 307bffde63dSSheetal Tigadoli if (speed) { 308bffde63dSSheetal Tigadoli EMMC_TRACE("enable HighSpeed\n"); 309bffde63dSSheetal Tigadoli mmio_setbits_32(handle->ctrl.sdRegBaseAddr + 310bffde63dSSheetal Tigadoli SD4_EMMC_TOP_CTRL_OFFSET, 311bffde63dSSheetal Tigadoli SD4_EMMC_TOP_CTRL_HSEN_MASK); 312bffde63dSSheetal Tigadoli } else { 313bffde63dSSheetal Tigadoli EMMC_TRACE("disable HighSpeed\n"); 314bffde63dSSheetal Tigadoli mmio_clrbits_32(handle->ctrl.sdRegBaseAddr + 315bffde63dSSheetal Tigadoli SD4_EMMC_TOP_CTRL_OFFSET, 316bffde63dSSheetal Tigadoli SD4_EMMC_TOP_CTRL_HSEN_MASK); 317bffde63dSSheetal Tigadoli } 318bffde63dSSheetal Tigadoli } 319bffde63dSSheetal Tigadoli 320bffde63dSSheetal Tigadoli int32_t chal_sd_stop(void) 321bffde63dSSheetal Tigadoli { 322bffde63dSSheetal Tigadoli uintptr_t idm_rst_ctrl_addr = EMMC_IDM_RESET_CTRL_ADDR; 323bffde63dSSheetal Tigadoli 324bffde63dSSheetal Tigadoli /* Configure IO pins */ 325bffde63dSSheetal Tigadoli emmc_soft_reset(); 326bffde63dSSheetal Tigadoli 327bffde63dSSheetal Tigadoli /* Reset the SDIO controller */ 328bffde63dSSheetal Tigadoli mmio_write_32(idm_rst_ctrl_addr, 1); 329bffde63dSSheetal Tigadoli SD_US_DELAY(100); 330bffde63dSSheetal Tigadoli mmio_write_32(idm_rst_ctrl_addr, 0); 331bffde63dSSheetal Tigadoli SD_US_DELAY(100); 332bffde63dSSheetal Tigadoli 333bffde63dSSheetal Tigadoli return SD_OK; 334bffde63dSSheetal Tigadoli } 335bffde63dSSheetal Tigadoli 336bffde63dSSheetal Tigadoli /* 337bffde63dSSheetal Tigadoli * Check if host supports specified capability 338bffde63dSSheetal Tigadoli * returns -ve val on error, 0 if capability not supported else 1. 339bffde63dSSheetal Tigadoli */ 340bffde63dSSheetal Tigadoli int32_t chal_sd_check_cap(CHAL_HANDLE *sd_handle, uint32_t caps) 341bffde63dSSheetal Tigadoli { 342bffde63dSSheetal Tigadoli struct sd_dev *handle; 343bffde63dSSheetal Tigadoli 344bffde63dSSheetal Tigadoli if (sd_handle == NULL) 345bffde63dSSheetal Tigadoli return SD_INVALID_HANDLE; 346bffde63dSSheetal Tigadoli 347bffde63dSSheetal Tigadoli handle = (struct sd_dev *) sd_handle; 348bffde63dSSheetal Tigadoli 349bffde63dSSheetal Tigadoli if (caps & mmio_read_32(handle->ctrl.sdRegBaseAddr + 350bffde63dSSheetal Tigadoli SD4_EMMC_TOP_CAPABILITIES1_OFFSET)) 351bffde63dSSheetal Tigadoli return 1; 352bffde63dSSheetal Tigadoli else 353bffde63dSSheetal Tigadoli return 0; 354bffde63dSSheetal Tigadoli } 355bffde63dSSheetal Tigadoli 356bffde63dSSheetal Tigadoli int32_t chal_sd_start(CHAL_HANDLE *sd_handle, 357bffde63dSSheetal Tigadoli uint32_t mode, uint32_t sd_base, uint32_t host_base) 358bffde63dSSheetal Tigadoli { 359bffde63dSSheetal Tigadoli 360bffde63dSSheetal Tigadoli struct sd_dev *handle; 361bffde63dSSheetal Tigadoli int32_t rval = SD_FAIL; 362bffde63dSSheetal Tigadoli 363bffde63dSSheetal Tigadoli if (sd_handle == NULL) 364bffde63dSSheetal Tigadoli return SD_INVALID_HANDLE; 365bffde63dSSheetal Tigadoli 366bffde63dSSheetal Tigadoli handle = (struct sd_dev *) sd_handle; 367bffde63dSSheetal Tigadoli 368bffde63dSSheetal Tigadoli handle->cfg.mode = SD_PIO_MODE; /* set to PIO mode first for init */ 369bffde63dSSheetal Tigadoli handle->cfg.dma = SD_DMA_OFF; 370bffde63dSSheetal Tigadoli 371bffde63dSSheetal Tigadoli chal_sd_setup_handler(handle, sd_base, host_base); 372bffde63dSSheetal Tigadoli 373bffde63dSSheetal Tigadoli /* init and start hw */ 374bffde63dSSheetal Tigadoli rval = chal_sd_init(sd_handle); 375bffde63dSSheetal Tigadoli if (rval != SD_OK) 376bffde63dSSheetal Tigadoli return rval; 377bffde63dSSheetal Tigadoli 378bffde63dSSheetal Tigadoli chal_sd_clear_pending_irq(sd_handle); 379bffde63dSSheetal Tigadoli 380bffde63dSSheetal Tigadoli handle->ctrl.eventList = 0; 381bffde63dSSheetal Tigadoli handle->cfg.mode = mode; 382bffde63dSSheetal Tigadoli 383bffde63dSSheetal Tigadoli return SD_OK; 384bffde63dSSheetal Tigadoli } 385bffde63dSSheetal Tigadoli 386bffde63dSSheetal Tigadoli /* 387bffde63dSSheetal Tigadoli * Function to check 8bits of err generated from auto CMD12 388bffde63dSSheetal Tigadoli */ 389bffde63dSSheetal Tigadoli int32_t chal_sd_get_atuo12_error(CHAL_HANDLE *sd_handle) 390bffde63dSSheetal Tigadoli { 391bffde63dSSheetal Tigadoli struct sd_dev *handle; 392bffde63dSSheetal Tigadoli 393bffde63dSSheetal Tigadoli if (sd_handle == NULL) 394bffde63dSSheetal Tigadoli return SD_INVALID_HANDLE; 395bffde63dSSheetal Tigadoli 396bffde63dSSheetal Tigadoli handle = (struct sd_dev *) sd_handle; 397bffde63dSSheetal Tigadoli 398bffde63dSSheetal Tigadoli return (mmio_read_32(handle->ctrl.sdRegBaseAddr + 399bffde63dSSheetal Tigadoli SD4_EMMC_TOP_ERRSTAT_OFFSET) & 0xFF); 400bffde63dSSheetal Tigadoli } 401bffde63dSSheetal Tigadoli 402bffde63dSSheetal Tigadoli /* 403bffde63dSSheetal Tigadoli * Read present state register 404bffde63dSSheetal Tigadoli */ 405bffde63dSSheetal Tigadoli uint32_t chal_sd_get_present_status(CHAL_HANDLE *sd_handle) 406bffde63dSSheetal Tigadoli { 407bffde63dSSheetal Tigadoli struct sd_dev *handle; 408bffde63dSSheetal Tigadoli 409bffde63dSSheetal Tigadoli if (sd_handle == NULL) 410bffde63dSSheetal Tigadoli return SD_INVALID_HANDLE; 411bffde63dSSheetal Tigadoli 412bffde63dSSheetal Tigadoli handle = (struct sd_dev *) sd_handle; 413bffde63dSSheetal Tigadoli 414bffde63dSSheetal Tigadoli return mmio_read_32(handle->ctrl.sdRegBaseAddr + 415bffde63dSSheetal Tigadoli SD4_EMMC_TOP_PSTATE_OFFSET); 416bffde63dSSheetal Tigadoli } 417bffde63dSSheetal Tigadoli 418bffde63dSSheetal Tigadoli /* 419bffde63dSSheetal Tigadoli * Set SD bus width 420bffde63dSSheetal Tigadoli */ 421bffde63dSSheetal Tigadoli int32_t chal_sd_config_bus_width(CHAL_HANDLE *sd_handle, int32_t width) 422bffde63dSSheetal Tigadoli { 423bffde63dSSheetal Tigadoli uint32_t ctl_val; 424bffde63dSSheetal Tigadoli struct sd_dev *handle; 425bffde63dSSheetal Tigadoli 426bffde63dSSheetal Tigadoli if (sd_handle == NULL) 427bffde63dSSheetal Tigadoli return SD_INVALID_HANDLE; 428bffde63dSSheetal Tigadoli 429bffde63dSSheetal Tigadoli handle = (struct sd_dev *)sd_handle; 430bffde63dSSheetal Tigadoli 431bffde63dSSheetal Tigadoli ctl_val = mmio_read_32(handle->ctrl.sdRegBaseAddr + 432bffde63dSSheetal Tigadoli SD4_EMMC_TOP_CTRL_OFFSET); 433bffde63dSSheetal Tigadoli 434bffde63dSSheetal Tigadoli switch (width) { 435bffde63dSSheetal Tigadoli #ifdef DRIVER_EMMC_ENABLE_DATA_WIDTH_8BIT 436bffde63dSSheetal Tigadoli case SD_BUS_DATA_WIDTH_8BIT: 437bffde63dSSheetal Tigadoli ctl_val &= ~SD_BUS_DATA_WIDTH_4BIT; 438bffde63dSSheetal Tigadoli ctl_val |= SD_BUS_DATA_WIDTH_8BIT; 439bffde63dSSheetal Tigadoli break; 440bffde63dSSheetal Tigadoli #endif 441bffde63dSSheetal Tigadoli case SD_BUS_DATA_WIDTH_4BIT: 442bffde63dSSheetal Tigadoli ctl_val &= ~SD_BUS_DATA_WIDTH_8BIT; 443bffde63dSSheetal Tigadoli ctl_val |= SD_BUS_DATA_WIDTH_4BIT; 444bffde63dSSheetal Tigadoli break; 445bffde63dSSheetal Tigadoli case SD_BUS_DATA_WIDTH_1BIT: 446bffde63dSSheetal Tigadoli ctl_val &= ~(SD_BUS_DATA_WIDTH_4BIT | SD_BUS_DATA_WIDTH_8BIT); 447bffde63dSSheetal Tigadoli break; 448bffde63dSSheetal Tigadoli default: 449bffde63dSSheetal Tigadoli return SD_INV_DATA_WIDTH; 450bffde63dSSheetal Tigadoli }; 451bffde63dSSheetal Tigadoli 452bffde63dSSheetal Tigadoli mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_CTRL_OFFSET, 453bffde63dSSheetal Tigadoli ctl_val); 454bffde63dSSheetal Tigadoli 455bffde63dSSheetal Tigadoli return SD_OK; 456bffde63dSSheetal Tigadoli } 457bffde63dSSheetal Tigadoli 458bffde63dSSheetal Tigadoli /* 459bffde63dSSheetal Tigadoli * Function to enable or disable DMA control. 460bffde63dSSheetal Tigadoli */ 461bffde63dSSheetal Tigadoli int32_t chal_sd_set_dma(CHAL_HANDLE *sd_handle, uint32_t mode) 462bffde63dSSheetal Tigadoli { 463bffde63dSSheetal Tigadoli uint32_t val; 464bffde63dSSheetal Tigadoli struct sd_dev *handle; 465bffde63dSSheetal Tigadoli int32_t rc; 466bffde63dSSheetal Tigadoli 467bffde63dSSheetal Tigadoli if (sd_handle == NULL) 468bffde63dSSheetal Tigadoli return SD_INVALID_HANDLE; 469bffde63dSSheetal Tigadoli 470bffde63dSSheetal Tigadoli handle = (struct sd_dev *)sd_handle; 471bffde63dSSheetal Tigadoli 472bffde63dSSheetal Tigadoli if (mode) { 473bffde63dSSheetal Tigadoli rc = chal_sd_check_cap(sd_handle, 474bffde63dSSheetal Tigadoli SD4_EMMC_TOP_CAPABILITIES1_SDMA_MASK | 475bffde63dSSheetal Tigadoli SD4_EMMC_TOP_CAPABILITIES1_ADMA2_MASK); 476bffde63dSSheetal Tigadoli if (rc < 0) 477bffde63dSSheetal Tigadoli return rc; 478bffde63dSSheetal Tigadoli 479bffde63dSSheetal Tigadoli if (rc) { 480bffde63dSSheetal Tigadoli 481bffde63dSSheetal Tigadoli handle->cfg.dma = mode; 482bffde63dSSheetal Tigadoli val = mmio_read_32(handle->ctrl.sdRegBaseAddr + 483bffde63dSSheetal Tigadoli SD4_EMMC_TOP_CTRL_OFFSET); 484bffde63dSSheetal Tigadoli val &= ~(SD4_EMMC_TOP_CTRL_DMASEL_MASK); 485bffde63dSSheetal Tigadoli val |= handle->cfg.dma - 1; 486bffde63dSSheetal Tigadoli mmio_write_32(handle->ctrl.sdRegBaseAddr + 487bffde63dSSheetal Tigadoli SD4_EMMC_TOP_CTRL_OFFSET, val); 488bffde63dSSheetal Tigadoli return SD_OK; 489bffde63dSSheetal Tigadoli } 490bffde63dSSheetal Tigadoli } 491bffde63dSSheetal Tigadoli handle->cfg.dma = 0; 492bffde63dSSheetal Tigadoli 493bffde63dSSheetal Tigadoli return SD_FAIL; 494bffde63dSSheetal Tigadoli } 495bffde63dSSheetal Tigadoli 496bffde63dSSheetal Tigadoli /* 497bffde63dSSheetal Tigadoli * Get current DMA address. 498bffde63dSSheetal Tigadoli * Called only when there is no data transaction activity. 499bffde63dSSheetal Tigadoli */ 500bffde63dSSheetal Tigadoli uintptr_t chal_sd_get_dma_addr(CHAL_HANDLE *sd_handle) 501bffde63dSSheetal Tigadoli { 502bffde63dSSheetal Tigadoli struct sd_dev *handle; 503bffde63dSSheetal Tigadoli 504bffde63dSSheetal Tigadoli if (sd_handle == NULL) 505bffde63dSSheetal Tigadoli return SD_INVALID_HANDLE; 506bffde63dSSheetal Tigadoli 507bffde63dSSheetal Tigadoli handle = (struct sd_dev *) sd_handle; 508bffde63dSSheetal Tigadoli 509bffde63dSSheetal Tigadoli if (handle->cfg.dma == SD_DMA_OFF) 510bffde63dSSheetal Tigadoli return 0; 511bffde63dSSheetal Tigadoli 512bffde63dSSheetal Tigadoli return (uintptr_t)mmio_read_32(handle->ctrl.sdRegBaseAddr + 513bffde63dSSheetal Tigadoli SD4_EMMC_TOP_SYSADDR_OFFSET); 514bffde63dSSheetal Tigadoli } 515bffde63dSSheetal Tigadoli 516bffde63dSSheetal Tigadoli int32_t chal_sd_send_cmd(CHAL_HANDLE *sd_handle, uint32_t cmd_idx, 517bffde63dSSheetal Tigadoli uint32_t argument, uint32_t options) 518bffde63dSSheetal Tigadoli { 519bffde63dSSheetal Tigadoli uint32_t cmd_mode_reg = 0; 520bffde63dSSheetal Tigadoli struct sd_dev *handle; 521bffde63dSSheetal Tigadoli 522bffde63dSSheetal Tigadoli if (sd_handle == NULL) 523bffde63dSSheetal Tigadoli return SD_INVALID_HANDLE; 524bffde63dSSheetal Tigadoli 525bffde63dSSheetal Tigadoli handle = (struct sd_dev *) sd_handle; 526bffde63dSSheetal Tigadoli 527bffde63dSSheetal Tigadoli EMMC_TRACE("%s %d cmd:%d argReg:%x options:%x\n", 528bffde63dSSheetal Tigadoli __func__, __LINE__, cmd_idx, argument, options); 529bffde63dSSheetal Tigadoli 530bffde63dSSheetal Tigadoli /* Configure the value for command and mode registers */ 531bffde63dSSheetal Tigadoli cmd_mode_reg = (cmd_idx << 24) | options; 532bffde63dSSheetal Tigadoli 533bffde63dSSheetal Tigadoli /* 534bffde63dSSheetal Tigadoli * 1. Write block size reg & block count reg, 535bffde63dSSheetal Tigadoli * this is done in the tx or rx setup 536bffde63dSSheetal Tigadoli */ 537bffde63dSSheetal Tigadoli mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_BLOCK_OFFSET, 538bffde63dSSheetal Tigadoli handle->ctrl.blkReg); 539bffde63dSSheetal Tigadoli 540bffde63dSSheetal Tigadoli /* 2. Write argument reg */ 541bffde63dSSheetal Tigadoli mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_ARG_OFFSET, 542bffde63dSSheetal Tigadoli argument); 543bffde63dSSheetal Tigadoli handle->ctrl.argReg = argument; 544bffde63dSSheetal Tigadoli 545bffde63dSSheetal Tigadoli /* 546bffde63dSSheetal Tigadoli * 3. Write transfer mode reg & command reg, check the DMA bit which is 547bffde63dSSheetal Tigadoli * set before this function call if it is selected. 548bffde63dSSheetal Tigadoli */ 549bffde63dSSheetal Tigadoli if (cmd_idx == 24 || cmd_idx == 25 || cmd_idx == 18 || cmd_idx == 17 || 550bffde63dSSheetal Tigadoli cmd_idx == 42 || cmd_idx == 51 || cmd_idx == 53) 551bffde63dSSheetal Tigadoli cmd_mode_reg |= ((handle->cfg.dma) ? 1 : 0); 552bffde63dSSheetal Tigadoli 553bffde63dSSheetal Tigadoli mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_CMD_OFFSET, 554bffde63dSSheetal Tigadoli cmd_mode_reg); 555bffde63dSSheetal Tigadoli 556bffde63dSSheetal Tigadoli handle->ctrl.cmdIndex = cmd_idx; 557bffde63dSSheetal Tigadoli 558bffde63dSSheetal Tigadoli return SD_OK; 559bffde63dSSheetal Tigadoli } 560bffde63dSSheetal Tigadoli 561bffde63dSSheetal Tigadoli int32_t chal_sd_set_dma_addr(CHAL_HANDLE *sd_handle, uintptr_t address) 562bffde63dSSheetal Tigadoli { 563bffde63dSSheetal Tigadoli struct sd_dev *handle; 564bffde63dSSheetal Tigadoli 565bffde63dSSheetal Tigadoli if (sd_handle == NULL) 566bffde63dSSheetal Tigadoli return SD_INVALID_HANDLE; 567bffde63dSSheetal Tigadoli 568bffde63dSSheetal Tigadoli handle = (struct sd_dev *) sd_handle; 569bffde63dSSheetal Tigadoli 570bffde63dSSheetal Tigadoli if (handle->cfg.dma == SD_DMA_OFF) 571bffde63dSSheetal Tigadoli return SD_FAIL; 572bffde63dSSheetal Tigadoli 573bffde63dSSheetal Tigadoli mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_SYSADDR_OFFSET, 574bffde63dSSheetal Tigadoli address); 575bffde63dSSheetal Tigadoli return SD_OK; 576bffde63dSSheetal Tigadoli } 577bffde63dSSheetal Tigadoli 578bffde63dSSheetal Tigadoli uint32_t chal_sd_freq_2_div_ctrl_setting(uint32_t desired_freq) 579bffde63dSSheetal Tigadoli { 580bffde63dSSheetal Tigadoli /* 581bffde63dSSheetal Tigadoli * Divider control setting represents 1/2 of the actual divider value. 582bffde63dSSheetal Tigadoli * 583bffde63dSSheetal Tigadoli * DesiredFreq = BaseClockFreq / (2 * div_ctrl_setting) 584bffde63dSSheetal Tigadoli * 585bffde63dSSheetal Tigadoli * ==> div_ctrl_setting = BaseClockFreq / (2 * DesiredFreq) 586bffde63dSSheetal Tigadoli */ 587bffde63dSSheetal Tigadoli uint32_t div_ctrl_setting; 588bffde63dSSheetal Tigadoli uint32_t actual_freq; 589bffde63dSSheetal Tigadoli 590bffde63dSSheetal Tigadoli assert(desired_freq != 0); 591bffde63dSSheetal Tigadoli 592bffde63dSSheetal Tigadoli /* Special case, 0 = divider of 1. */ 593bffde63dSSheetal Tigadoli if (desired_freq >= BASE_CLK_FREQ) 594bffde63dSSheetal Tigadoli return 0; 595bffde63dSSheetal Tigadoli 596bffde63dSSheetal Tigadoli /* Normal case, desired_freq < BASE_CLK_FREQ */ 597bffde63dSSheetal Tigadoli div_ctrl_setting = BASE_CLK_FREQ / (2 * desired_freq); 598bffde63dSSheetal Tigadoli 599bffde63dSSheetal Tigadoli actual_freq = BASE_CLK_FREQ / (2 * div_ctrl_setting); 600bffde63dSSheetal Tigadoli 601bffde63dSSheetal Tigadoli if (actual_freq > desired_freq) { 602bffde63dSSheetal Tigadoli /* 603*1b491eeaSElyes Haouas * Division does not result in exact frequency match. 604bffde63dSSheetal Tigadoli * Make sure resulting frequency does not exceed requested freq. 605bffde63dSSheetal Tigadoli */ 606bffde63dSSheetal Tigadoli div_ctrl_setting++; 607bffde63dSSheetal Tigadoli } 608bffde63dSSheetal Tigadoli 609bffde63dSSheetal Tigadoli return div_ctrl_setting; 610bffde63dSSheetal Tigadoli } 611bffde63dSSheetal Tigadoli 612bffde63dSSheetal Tigadoli int32_t chal_sd_set_clock(CHAL_HANDLE *sd_handle, uint32_t div_ctrl_setting, 613bffde63dSSheetal Tigadoli uint32_t on) 614bffde63dSSheetal Tigadoli { 615bffde63dSSheetal Tigadoli uint32_t value; 616bffde63dSSheetal Tigadoli struct sd_dev *handle; 617bffde63dSSheetal Tigadoli uint32_t time; 618bffde63dSSheetal Tigadoli uint32_t clk_sel_high_byte = 0xFF & (div_ctrl_setting >> 8); 619bffde63dSSheetal Tigadoli uint32_t clk_sel_low_byte = 0xFF & div_ctrl_setting; 620bffde63dSSheetal Tigadoli 621bffde63dSSheetal Tigadoli if (sd_handle == NULL) 622bffde63dSSheetal Tigadoli return SD_INVALID_HANDLE; 623bffde63dSSheetal Tigadoli 624bffde63dSSheetal Tigadoli EMMC_TRACE("set_clock(div_ctrl_setting=%d,on=%d)\n", 625bffde63dSSheetal Tigadoli div_ctrl_setting, on); 626bffde63dSSheetal Tigadoli 627bffde63dSSheetal Tigadoli handle = (struct sd_dev *) sd_handle; 628bffde63dSSheetal Tigadoli 629bffde63dSSheetal Tigadoli /* Read control register content. */ 630bffde63dSSheetal Tigadoli value = mmio_read_32(handle->ctrl.sdRegBaseAddr + 631bffde63dSSheetal Tigadoli SD4_EMMC_TOP_CTRL1_OFFSET); 632bffde63dSSheetal Tigadoli 633bffde63dSSheetal Tigadoli /* Disable Clock */ 634bffde63dSSheetal Tigadoli value &= ~(SD4_EMMC_TOP_CTRL1_SDCLKEN_MASK); 635bffde63dSSheetal Tigadoli 636bffde63dSSheetal Tigadoli mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_CTRL1_OFFSET, 637bffde63dSSheetal Tigadoli value); 638bffde63dSSheetal Tigadoli 639bffde63dSSheetal Tigadoli /* Clear bits of interest. */ 640bffde63dSSheetal Tigadoli value &= ~(SD4_EMMC_TOP_CTRL1_SDCLKSEL_MASK | 641bffde63dSSheetal Tigadoli SD4_EMMC_TOP_CTRL1_SDCLKSEL_UP_MASK); 642bffde63dSSheetal Tigadoli 643bffde63dSSheetal Tigadoli /* Set bits of interest to new value. */ 644bffde63dSSheetal Tigadoli value |= (SD4_EMMC_TOP_CTRL1_SDCLKSEL_MASK & 645bffde63dSSheetal Tigadoli (clk_sel_low_byte << SD4_EMMC_TOP_CTRL1_SDCLKSEL_SHIFT)); 646bffde63dSSheetal Tigadoli value |= (SD4_EMMC_TOP_CTRL1_SDCLKSEL_UP_MASK & 647bffde63dSSheetal Tigadoli (clk_sel_high_byte << SD4_EMMC_TOP_CTRL1_SDCLKSEL_UP_SHIFT)); 648bffde63dSSheetal Tigadoli value |= SD4_EMMC_TOP_CTRL1_ICLKEN_MASK; 649bffde63dSSheetal Tigadoli 650bffde63dSSheetal Tigadoli /* Write updated value back to control register. */ 651bffde63dSSheetal Tigadoli mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_CTRL1_OFFSET, 652bffde63dSSheetal Tigadoli value); 653bffde63dSSheetal Tigadoli 654bffde63dSSheetal Tigadoli time = 0; 655bffde63dSSheetal Tigadoli do { 656bffde63dSSheetal Tigadoli value = mmio_read_32(handle->ctrl.sdRegBaseAddr + 657bffde63dSSheetal Tigadoli SD4_EMMC_TOP_CTRL1_OFFSET); 658bffde63dSSheetal Tigadoli 659bffde63dSSheetal Tigadoli if ((value & SD4_EMMC_TOP_CTRL1_ICLKSTB_MASK) == 660bffde63dSSheetal Tigadoli SD4_EMMC_TOP_CTRL1_ICLKSTB_MASK) 661bffde63dSSheetal Tigadoli break; 662bffde63dSSheetal Tigadoli 663bffde63dSSheetal Tigadoli mdelay(1); 664bffde63dSSheetal Tigadoli } while (time++ < EMMC_CLOCK_SETTING_TIMEOUT_MS); 665bffde63dSSheetal Tigadoli 666bffde63dSSheetal Tigadoli if (time >= EMMC_CLOCK_SETTING_TIMEOUT_MS) 667bffde63dSSheetal Tigadoli WARN("%s %d clock settings timeout happenedi (%dms)\n", 668bffde63dSSheetal Tigadoli __func__, __LINE__, time); 669bffde63dSSheetal Tigadoli 670bffde63dSSheetal Tigadoli VERBOSE("EMMC: clock settings delay: %dms\n", time); 671bffde63dSSheetal Tigadoli 672bffde63dSSheetal Tigadoli value = mmio_read_32(handle->ctrl.sdRegBaseAddr + 673bffde63dSSheetal Tigadoli SD4_EMMC_TOP_CTRL1_OFFSET); 674bffde63dSSheetal Tigadoli 675bffde63dSSheetal Tigadoli if (on) 676bffde63dSSheetal Tigadoli value |= SD4_EMMC_TOP_CTRL1_SDCLKEN_MASK; 677bffde63dSSheetal Tigadoli 678bffde63dSSheetal Tigadoli mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_CTRL1_OFFSET, 679bffde63dSSheetal Tigadoli value); 680bffde63dSSheetal Tigadoli 681bffde63dSSheetal Tigadoli return SD_OK; 682bffde63dSSheetal Tigadoli } 683bffde63dSSheetal Tigadoli 684bffde63dSSheetal Tigadoli /* 685bffde63dSSheetal Tigadoli * function to setup DMA buffer and data length, calculates block 686bffde63dSSheetal Tigadoli * size and the number of blocks to be transferred and return 687bffde63dSSheetal Tigadoli * the DMA buffer address. 688bffde63dSSheetal Tigadoli */ 689bffde63dSSheetal Tigadoli int32_t chal_sd_setup_xfer(CHAL_HANDLE *sd_handle, 690bffde63dSSheetal Tigadoli uint8_t *data, uint32_t length, int32_t dir) 691bffde63dSSheetal Tigadoli { 692bffde63dSSheetal Tigadoli uint32_t blocks = 0; 693bffde63dSSheetal Tigadoli struct sd_dev *handle; 694bffde63dSSheetal Tigadoli 695bffde63dSSheetal Tigadoli if (sd_handle == NULL) 696bffde63dSSheetal Tigadoli return SD_INVALID_HANDLE; 697bffde63dSSheetal Tigadoli 698bffde63dSSheetal Tigadoli handle = (struct sd_dev *) sd_handle; 699bffde63dSSheetal Tigadoli 700bffde63dSSheetal Tigadoli if (length <= handle->cfg.blockSize) { 701bffde63dSSheetal Tigadoli handle->ctrl.blkReg = length | handle->cfg.dmaBoundary; 702bffde63dSSheetal Tigadoli } else { 703bffde63dSSheetal Tigadoli blocks = length / handle->cfg.blockSize; 704bffde63dSSheetal Tigadoli handle->ctrl.blkReg = (blocks << 16) | handle->cfg.blockSize | 705bffde63dSSheetal Tigadoli handle->cfg.dmaBoundary; 706bffde63dSSheetal Tigadoli } 707bffde63dSSheetal Tigadoli 708bffde63dSSheetal Tigadoli if (handle->cfg.dma != SD_DMA_OFF) { 709bffde63dSSheetal Tigadoli /* For DMA target address setting, physical address should be used */ 710bffde63dSSheetal Tigadoli mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_SYSADDR_OFFSET, 711bffde63dSSheetal Tigadoli (uintptr_t)data); 712bffde63dSSheetal Tigadoli } 713bffde63dSSheetal Tigadoli 714bffde63dSSheetal Tigadoli return SD_OK; 715bffde63dSSheetal Tigadoli } 716bffde63dSSheetal Tigadoli 717bffde63dSSheetal Tigadoli #ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE 718bffde63dSSheetal Tigadoli /* 719bffde63dSSheetal Tigadoli * function to write one block data directly to the 720bffde63dSSheetal Tigadoli * host controller's FIFO which is 1K uint8_t or 721bffde63dSSheetal Tigadoli * 2K uint8_t in size. 722bffde63dSSheetal Tigadoli * It is used in Non-DMA mode for data transmission. 723bffde63dSSheetal Tigadoli */ 724bffde63dSSheetal Tigadoli int32_t chal_sd_write_buffer(CHAL_HANDLE *sd_handle, uint32_t length, 725bffde63dSSheetal Tigadoli uint8_t *data) 726bffde63dSSheetal Tigadoli { 727bffde63dSSheetal Tigadoli uint32_t i, leftOver = 0, blockSize, size, value = 0; 728bffde63dSSheetal Tigadoli struct sd_dev *handle; 729bffde63dSSheetal Tigadoli 730bffde63dSSheetal Tigadoli if (sd_handle == NULL) 731bffde63dSSheetal Tigadoli return SD_INVALID_HANDLE; 732bffde63dSSheetal Tigadoli 733bffde63dSSheetal Tigadoli handle = (struct sd_dev *) sd_handle; 734bffde63dSSheetal Tigadoli 735bffde63dSSheetal Tigadoli blockSize = handle->cfg.blockSize; 736bffde63dSSheetal Tigadoli 737bffde63dSSheetal Tigadoli if (length == 0) 738bffde63dSSheetal Tigadoli return SD_OK; 739bffde63dSSheetal Tigadoli 740bffde63dSSheetal Tigadoli /* PIO mode, push into fifo word by word */ 741bffde63dSSheetal Tigadoli if (length >= blockSize) { 742bffde63dSSheetal Tigadoli size = blockSize; 743bffde63dSSheetal Tigadoli } else { 744bffde63dSSheetal Tigadoli size = ((length >> 2) << 2); 745bffde63dSSheetal Tigadoli leftOver = length % 4; 746bffde63dSSheetal Tigadoli } 747bffde63dSSheetal Tigadoli 748bffde63dSSheetal Tigadoli for (i = 0; i < size; i += 4) { 749bffde63dSSheetal Tigadoli value = *(uint32_t *)(data + i); 750bffde63dSSheetal Tigadoli mmio_write_32(handle->ctrl.sdRegBaseAddr + 751bffde63dSSheetal Tigadoli SD4_EMMC_TOP_BUFDAT_OFFSET, value); 752bffde63dSSheetal Tigadoli } 753bffde63dSSheetal Tigadoli /* 754bffde63dSSheetal Tigadoli * BUG ALERT: 755bffde63dSSheetal Tigadoli * This implementation has TWO issues that must be addressed before you 756bffde63dSSheetal Tigadoli * can safely INCLUDE_EMMC_DRIVER_WRITE_CODE. 757bffde63dSSheetal Tigadoli * 758bffde63dSSheetal Tigadoli * (1) For the last leftOver bytes, driver writes full word, which means 759bffde63dSSheetal Tigadoli * some of the eMMC content (i.e. "4 - leftOver" will be erroneously 760bffde63dSSheetal Tigadoli * overwritten). 761bffde63dSSheetal Tigadoli * (2) eMMC is a block device. What happens when less than a full block of 762bffde63dSSheetal Tigadoli * data is submitted??? 763bffde63dSSheetal Tigadoli */ 764bffde63dSSheetal Tigadoli if (leftOver > 0) { 765bffde63dSSheetal Tigadoli value = ((*(uint32_t *)(data + i)) << (4 - leftOver)); 766bffde63dSSheetal Tigadoli mmio_write_32(handle->ctrl.sdRegBaseAddr + 767bffde63dSSheetal Tigadoli SD4_EMMC_TOP_BUFDAT_OFFSET, value); 768bffde63dSSheetal Tigadoli } 769bffde63dSSheetal Tigadoli 770bffde63dSSheetal Tigadoli return SD_OK; 771bffde63dSSheetal Tigadoli } 772bffde63dSSheetal Tigadoli #endif /* INCLUDE_EMMC_DRIVER_WRITE_CODE */ 773bffde63dSSheetal Tigadoli 774bffde63dSSheetal Tigadoli /* 775bffde63dSSheetal Tigadoli * Function to read maximal one block data directly 776bffde63dSSheetal Tigadoli * from the data port of the host controller (FIFO). It is used 777bffde63dSSheetal Tigadoli * in Non-DMA mode for data transmission. 778bffde63dSSheetal Tigadoli */ 779bffde63dSSheetal Tigadoli int32_t chal_sd_read_buffer(CHAL_HANDLE *sd_handle, uint32_t length, 780bffde63dSSheetal Tigadoli uint8_t *data) 781bffde63dSSheetal Tigadoli { 782bffde63dSSheetal Tigadoli uint32_t i, size, leftOver, blockSize, value; 783bffde63dSSheetal Tigadoli struct sd_dev *handle; 784bffde63dSSheetal Tigadoli 785bffde63dSSheetal Tigadoli if (sd_handle == NULL) 786bffde63dSSheetal Tigadoli return SD_INVALID_HANDLE; 787bffde63dSSheetal Tigadoli 788bffde63dSSheetal Tigadoli handle = (struct sd_dev *)sd_handle; 789bffde63dSSheetal Tigadoli 790bffde63dSSheetal Tigadoli value = 0; 791bffde63dSSheetal Tigadoli 792bffde63dSSheetal Tigadoli blockSize = handle->cfg.blockSize; 793bffde63dSSheetal Tigadoli 794bffde63dSSheetal Tigadoli /* PIO mode, extract fifo word by word */ 795bffde63dSSheetal Tigadoli if (length >= blockSize) { 796bffde63dSSheetal Tigadoli size = blockSize; 797bffde63dSSheetal Tigadoli leftOver = 0; 798bffde63dSSheetal Tigadoli } else { 799bffde63dSSheetal Tigadoli leftOver = length % 4; 800bffde63dSSheetal Tigadoli size = ((length >> 2) << 2); 801bffde63dSSheetal Tigadoli } 802bffde63dSSheetal Tigadoli 803bffde63dSSheetal Tigadoli for (i = 0; i < size; i += 4) { 804bffde63dSSheetal Tigadoli value = 805bffde63dSSheetal Tigadoli mmio_read_32(handle->ctrl.sdRegBaseAddr + 806bffde63dSSheetal Tigadoli SD4_EMMC_TOP_BUFDAT_OFFSET); 807bffde63dSSheetal Tigadoli memcpy((void *)(data + i), &value, sizeof(uint32_t)); 808bffde63dSSheetal Tigadoli } 809bffde63dSSheetal Tigadoli 810bffde63dSSheetal Tigadoli if (leftOver > 0) { 811bffde63dSSheetal Tigadoli value = mmio_read_32(handle->ctrl.sdRegBaseAddr + 812bffde63dSSheetal Tigadoli SD4_EMMC_TOP_BUFDAT_OFFSET); 813bffde63dSSheetal Tigadoli 814bffde63dSSheetal Tigadoli /* 815bffde63dSSheetal Tigadoli * Copy remaining non-full word bytes. 816bffde63dSSheetal Tigadoli * (We run ARM as Little Endian) 817bffde63dSSheetal Tigadoli */ 818bffde63dSSheetal Tigadoli uint8_t j = 0; 819bffde63dSSheetal Tigadoli 820bffde63dSSheetal Tigadoli for (j = 0; j < leftOver; j++) { 821bffde63dSSheetal Tigadoli data[i + j] = (value >> (j * 8)) & 0xFF; 822bffde63dSSheetal Tigadoli } 823bffde63dSSheetal Tigadoli } 824bffde63dSSheetal Tigadoli 825bffde63dSSheetal Tigadoli return SD_OK; 826bffde63dSSheetal Tigadoli } 827bffde63dSSheetal Tigadoli 828bffde63dSSheetal Tigadoli /* 829bffde63dSSheetal Tigadoli * Resets both DAT or CMD line. 830bffde63dSSheetal Tigadoli */ 831bffde63dSSheetal Tigadoli int32_t chal_sd_reset_line(CHAL_HANDLE *sd_handle, uint32_t line) 832bffde63dSSheetal Tigadoli { 833bffde63dSSheetal Tigadoli uint32_t control, flag; 834bffde63dSSheetal Tigadoli struct sd_dev *handle; 835bffde63dSSheetal Tigadoli 836bffde63dSSheetal Tigadoli if (sd_handle == NULL) 837bffde63dSSheetal Tigadoli return SD_INVALID_HANDLE; 838bffde63dSSheetal Tigadoli 839bffde63dSSheetal Tigadoli handle = (struct sd_dev *) sd_handle; 840bffde63dSSheetal Tigadoli 841bffde63dSSheetal Tigadoli flag = SD4_EMMC_TOP_CTRL1_CMDRST_MASK | SD4_EMMC_TOP_CTRL1_DATRST_MASK; 842bffde63dSSheetal Tigadoli 843bffde63dSSheetal Tigadoli if (flag != (line | flag)) 844bffde63dSSheetal Tigadoli return SD_FAIL; 845bffde63dSSheetal Tigadoli 846bffde63dSSheetal Tigadoli control = mmio_read_32(handle->ctrl.sdRegBaseAddr + 847bffde63dSSheetal Tigadoli SD4_EMMC_TOP_CTRL1_OFFSET); 848bffde63dSSheetal Tigadoli control |= line; 849bffde63dSSheetal Tigadoli mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_CTRL1_OFFSET, 850bffde63dSSheetal Tigadoli control); 851bffde63dSSheetal Tigadoli 852bffde63dSSheetal Tigadoli /* reset CMD and DATA line should always work, no need to timed out */ 853bffde63dSSheetal Tigadoli do { 854bffde63dSSheetal Tigadoli control = mmio_read_32(handle->ctrl.sdRegBaseAddr + 855bffde63dSSheetal Tigadoli SD4_EMMC_TOP_CTRL1_OFFSET); 856bffde63dSSheetal Tigadoli } while (control & line); 857bffde63dSSheetal Tigadoli 858bffde63dSSheetal Tigadoli return SD_OK; 859bffde63dSSheetal Tigadoli } 860bffde63dSSheetal Tigadoli 861bffde63dSSheetal Tigadoli /* 862bffde63dSSheetal Tigadoli * Function to be called once a SD command is done to read 863bffde63dSSheetal Tigadoli * back it's response data. 864bffde63dSSheetal Tigadoli */ 865bffde63dSSheetal Tigadoli int32_t chal_sd_get_response(CHAL_HANDLE *sd_handle, uint32_t *resp) 866bffde63dSSheetal Tigadoli { 867bffde63dSSheetal Tigadoli struct sd_dev *handle; 868bffde63dSSheetal Tigadoli 869bffde63dSSheetal Tigadoli if (sd_handle == NULL) 870bffde63dSSheetal Tigadoli return SD_INVALID_HANDLE; 871bffde63dSSheetal Tigadoli 872bffde63dSSheetal Tigadoli handle = (struct sd_dev *) sd_handle; 873bffde63dSSheetal Tigadoli resp[0] = mmio_read_32(handle->ctrl.sdRegBaseAddr + 874bffde63dSSheetal Tigadoli SD4_EMMC_TOP_RESP0_OFFSET); 875bffde63dSSheetal Tigadoli resp[1] = mmio_read_32(handle->ctrl.sdRegBaseAddr + 876bffde63dSSheetal Tigadoli SD4_EMMC_TOP_RESP2_OFFSET); 877bffde63dSSheetal Tigadoli resp[2] = mmio_read_32(handle->ctrl.sdRegBaseAddr + 878bffde63dSSheetal Tigadoli SD4_EMMC_TOP_RESP4_OFFSET); 879bffde63dSSheetal Tigadoli resp[3] = mmio_read_32(handle->ctrl.sdRegBaseAddr + 880bffde63dSSheetal Tigadoli SD4_EMMC_TOP_RESP6_OFFSET); 881bffde63dSSheetal Tigadoli 882bffde63dSSheetal Tigadoli return SD_OK; 883bffde63dSSheetal Tigadoli } 884bffde63dSSheetal Tigadoli 885bffde63dSSheetal Tigadoli /* 886bffde63dSSheetal Tigadoli * The function is called to clean all the pending interrupts. 887bffde63dSSheetal Tigadoli */ 888bffde63dSSheetal Tigadoli int32_t chal_sd_clear_pending_irq(CHAL_HANDLE *sd_handle) 889bffde63dSSheetal Tigadoli { 890bffde63dSSheetal Tigadoli uint32_t status = SD_OK; 891bffde63dSSheetal Tigadoli struct sd_dev *handle; 892bffde63dSSheetal Tigadoli 893bffde63dSSheetal Tigadoli if (sd_handle == NULL) 894bffde63dSSheetal Tigadoli return SD_INVALID_HANDLE; 895bffde63dSSheetal Tigadoli 896bffde63dSSheetal Tigadoli handle = (struct sd_dev *)sd_handle; 897bffde63dSSheetal Tigadoli 898bffde63dSSheetal Tigadoli /* Make sure clean all interrupts */ 899bffde63dSSheetal Tigadoli do { 900bffde63dSSheetal Tigadoli mmio_write_32(handle->ctrl.sdRegBaseAddr + 901bffde63dSSheetal Tigadoli SD4_EMMC_TOP_INTR_OFFSET, 0xFFFFFFFF); 902bffde63dSSheetal Tigadoli SD_US_DELAY(10); 903bffde63dSSheetal Tigadoli } while (mmio_read_32(handle->ctrl.sdRegBaseAddr + 904bffde63dSSheetal Tigadoli SD4_EMMC_TOP_INTR_OFFSET)); 905bffde63dSSheetal Tigadoli 906bffde63dSSheetal Tigadoli return status; 907bffde63dSSheetal Tigadoli } 908bffde63dSSheetal Tigadoli 909bffde63dSSheetal Tigadoli /* 910bffde63dSSheetal Tigadoli * The function returns interrupt status register value. 911bffde63dSSheetal Tigadoli */ 912bffde63dSSheetal Tigadoli int32_t chal_sd_get_irq_status(CHAL_HANDLE *sd_handle) 913bffde63dSSheetal Tigadoli { 914bffde63dSSheetal Tigadoli struct sd_dev *handle; 915bffde63dSSheetal Tigadoli 916bffde63dSSheetal Tigadoli if (sd_handle == NULL) 917bffde63dSSheetal Tigadoli return SD_INVALID_HANDLE; 918bffde63dSSheetal Tigadoli 919bffde63dSSheetal Tigadoli handle = (struct sd_dev *) sd_handle; 920bffde63dSSheetal Tigadoli 921bffde63dSSheetal Tigadoli return (mmio_read_32(handle->ctrl.sdRegBaseAddr + 922bffde63dSSheetal Tigadoli SD4_EMMC_TOP_INTR_OFFSET)); 923bffde63dSSheetal Tigadoli } 924bffde63dSSheetal Tigadoli 925bffde63dSSheetal Tigadoli /* 926bffde63dSSheetal Tigadoli * The function clears interrupt(s) specified in the mask. 927bffde63dSSheetal Tigadoli */ 928bffde63dSSheetal Tigadoli int32_t chal_sd_clear_irq(CHAL_HANDLE *sd_handle, uint32_t mask) 929bffde63dSSheetal Tigadoli { 930bffde63dSSheetal Tigadoli struct sd_dev *handle; 931bffde63dSSheetal Tigadoli 932bffde63dSSheetal Tigadoli if (sd_handle == NULL) 933bffde63dSSheetal Tigadoli return SD_INVALID_HANDLE; 934bffde63dSSheetal Tigadoli 935bffde63dSSheetal Tigadoli handle = (struct sd_dev *) sd_handle; 936bffde63dSSheetal Tigadoli 937bffde63dSSheetal Tigadoli /* Make sure clean masked interrupts */ 938bffde63dSSheetal Tigadoli do { 939bffde63dSSheetal Tigadoli mmio_write_32(handle->ctrl.sdRegBaseAddr + 940bffde63dSSheetal Tigadoli SD4_EMMC_TOP_INTR_OFFSET, mask); 941bffde63dSSheetal Tigadoli SD_US_DELAY(10); 942bffde63dSSheetal Tigadoli } while (mask & 943bffde63dSSheetal Tigadoli mmio_read_32(handle->ctrl.sdRegBaseAddr + 944bffde63dSSheetal Tigadoli SD4_EMMC_TOP_INTR_OFFSET)); 945bffde63dSSheetal Tigadoli 946bffde63dSSheetal Tigadoli return SD_OK; 947bffde63dSSheetal Tigadoli } 948bffde63dSSheetal Tigadoli 949bffde63dSSheetal Tigadoli /* 950bffde63dSSheetal Tigadoli * Description: The function configures the SD host controller. 951bffde63dSSheetal Tigadoli */ 952bffde63dSSheetal Tigadoli int32_t chal_sd_config(CHAL_HANDLE *sd_handle, uint32_t speed, uint32_t retry, 953bffde63dSSheetal Tigadoli uint32_t boundary, uint32_t blkSize, uint32_t dma) 954bffde63dSSheetal Tigadoli { 955bffde63dSSheetal Tigadoli struct sd_dev *handle; 956bffde63dSSheetal Tigadoli 957bffde63dSSheetal Tigadoli if (sd_handle == NULL) 958bffde63dSSheetal Tigadoli return SD_INVALID_HANDLE; 959bffde63dSSheetal Tigadoli 960bffde63dSSheetal Tigadoli handle = (struct sd_dev *) sd_handle; 961bffde63dSSheetal Tigadoli 962bffde63dSSheetal Tigadoli handle->cfg.speedMode = speed; 963bffde63dSSheetal Tigadoli handle->cfg.retryLimit = retry; 964bffde63dSSheetal Tigadoli handle->cfg.dmaBoundary = boundary; 965bffde63dSSheetal Tigadoli handle->cfg.blockSize = blkSize; 966bffde63dSSheetal Tigadoli 967bffde63dSSheetal Tigadoli chal_sd_set_dma(sd_handle, dma); 968bffde63dSSheetal Tigadoli SD_US_DELAY(100); 969bffde63dSSheetal Tigadoli chal_sd_set_dma_boundary(handle, boundary); 970bffde63dSSheetal Tigadoli SD_US_DELAY(100); 971bffde63dSSheetal Tigadoli 972bffde63dSSheetal Tigadoli chal_sd_set_speed(sd_handle, speed); 973bffde63dSSheetal Tigadoli 974bffde63dSSheetal Tigadoli SD_US_DELAY(100); 975bffde63dSSheetal Tigadoli return SD_OK; 976bffde63dSSheetal Tigadoli } 977bffde63dSSheetal Tigadoli 978bffde63dSSheetal Tigadoli /* 979bffde63dSSheetal Tigadoli * Cleans up HC FIFO. 980bffde63dSSheetal Tigadoli */ 981bffde63dSSheetal Tigadoli void chal_sd_dump_fifo(CHAL_HANDLE *sd_handle) 982bffde63dSSheetal Tigadoli { 983bffde63dSSheetal Tigadoli struct sd_dev *handle; 984bffde63dSSheetal Tigadoli 985bffde63dSSheetal Tigadoli if (sd_handle == NULL) 986bffde63dSSheetal Tigadoli return; 987bffde63dSSheetal Tigadoli 988bffde63dSSheetal Tigadoli handle = (struct sd_dev *)sd_handle; 989bffde63dSSheetal Tigadoli 990bffde63dSSheetal Tigadoli /* in case there still data in the host buffer */ 991bffde63dSSheetal Tigadoli while (mmio_read_32(handle->ctrl.sdRegBaseAddr + 992bffde63dSSheetal Tigadoli SD4_EMMC_TOP_PSTATE_OFFSET) & 0x800) { 993bffde63dSSheetal Tigadoli mmio_read_32(handle->ctrl.sdRegBaseAddr + 994bffde63dSSheetal Tigadoli SD4_EMMC_TOP_BUFDAT_OFFSET); 995bffde63dSSheetal Tigadoli }; 996bffde63dSSheetal Tigadoli } 997bffde63dSSheetal Tigadoli 998bffde63dSSheetal Tigadoli /* 999bffde63dSSheetal Tigadoli * Enable or disable a SD interrupt signal. 1000bffde63dSSheetal Tigadoli */ 1001bffde63dSSheetal Tigadoli void chal_sd_set_irq_signal(CHAL_HANDLE *sd_handle, uint32_t mask, 1002bffde63dSSheetal Tigadoli uint32_t state) 1003bffde63dSSheetal Tigadoli { 1004bffde63dSSheetal Tigadoli struct sd_dev *handle; 1005bffde63dSSheetal Tigadoli 1006bffde63dSSheetal Tigadoli if (sd_handle == NULL) 1007bffde63dSSheetal Tigadoli return; 1008bffde63dSSheetal Tigadoli 1009bffde63dSSheetal Tigadoli handle = (struct sd_dev *)sd_handle; 1010bffde63dSSheetal Tigadoli 1011bffde63dSSheetal Tigadoli if (state) 1012bffde63dSSheetal Tigadoli mmio_setbits_32(handle->ctrl.sdRegBaseAddr + 1013bffde63dSSheetal Tigadoli SD4_EMMC_TOP_INTREN2_OFFSET, mask); 1014bffde63dSSheetal Tigadoli else 1015bffde63dSSheetal Tigadoli mmio_clrbits_32(handle->ctrl.sdRegBaseAddr + 1016bffde63dSSheetal Tigadoli SD4_EMMC_TOP_INTREN2_OFFSET, mask); 1017bffde63dSSheetal Tigadoli } 1018