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