static uint32_t sdhci_msm_cm_dll_sdc4_calibration(struct sdhci_host *host) { uint32_t timeout = 0; DBG("\n CM_DLL_SDC4 Calibration Start\n"); /*1.Write the DDR config value to SDCC_HC_REG_DDR_CONFIG register*/ REG_WRITE32(host, target_ddr_cfg_val(), SDCC_HC_REG_DDR_CONFIG); /*2. Write DDR_CAL_EN to '1' */ REG_WRITE32(host, (REG_READ32(host, SDCC_HC_REG_DLL_CONFIG_2) | DDR_CAL_EN), SDCC_HC_REG_DLL_CONFIG_2); /*3. Wait for DLL_LOCK for hs400 to be set */ timeout = DDR_CAL_TIMEOUT_MAX; while (!(REG_READ32(host, SDCC_REG_DLL_STATUS) & DDR_DLL_LOCK_JDR)) { timeout--; mdelay(1); if (!timeout) { dprintf(CRITICAL, "Error: DLL lock for hs400 operation is not set\n"); return 1; } } /*4. Set powersave dll */ REG_WRITE32(host, (REG_READ32(host, SDCC_HC_VENDOR_SPECIFIC_FUNC3) | PWRSAVE_DLL), SDCC_HC_VENDOR_SPECIFIC_FUNC3); DBG("\n CM_DLL_SDC4 Calibration Done\n"); return 0; }
static void sdhci_dll_clk_enable(struct sdhci_host *host, int enable) { if (enable) { REG_WRITE32(host, (REG_READ32(host, SDCC_HC_REG_DLL_CONFIG_2) & ~SDCC_DLL_CLOCK_DISABLE), SDCC_HC_REG_DLL_CONFIG_2); } else { REG_WRITE32(host, (REG_READ32(host, SDCC_DLL_CONFIG_REG) & ~SDCC_DLL_CLK_OUT_EN), SDCC_DLL_CONFIG_REG); REG_WRITE32(host, (REG_READ32(host, SDCC_HC_REG_DLL_CONFIG_2) | SDCC_DLL_CLOCK_DISABLE), SDCC_HC_REG_DLL_CONFIG_2); } }
/* Configure DLL with delay value based on 'phase' */ static uint32_t sdhci_msm_config_dll(struct sdhci_host *host, uint32_t phase) { uint32_t core_cfg = 0; uint32_t timeout = SDHCI_DLL_TIMEOUT; /* Gray code values from SWI */ uint32_t gray_code [] = { 0x0, 0x1, 0x3, 0x2, 0x6, 0x7, 0x5, 0x4, 0xC, 0xD, 0xF, 0xE, 0xA, 0xB, 0x9, 0x8 }; /* set CDR_EN & CLK_OUT_EN to 0 and * CDR_EXT_EN & DLL_EN to 1*/ core_cfg = REG_READ32(host, SDCC_DLL_CONFIG_REG); core_cfg &= ~(SDCC_DLL_CDR_EN | SDCC_DLL_CLK_OUT_EN); core_cfg |= (SDCC_DLL_CDR_EXT_EN | SDCC_DLL_EN); REG_WRITE32(host, core_cfg, SDCC_DLL_CONFIG_REG); /* Wait until CLK_OUT_EN is 0 */ while(REG_READ32(host, SDCC_DLL_CONFIG_REG) & SDCC_DLL_CLK_OUT_EN); REG_RMW32(host, SDCC_DLL_CONFIG_REG, SDCC_DLL_GRAY_CODE_START, SDCC_DLL_GRAY_CODE_WIDTH, gray_code[phase]); REG_WRITE32(host, (REG_READ32(host, SDCC_DLL_CONFIG_REG) | SDCC_DLL_CLK_OUT_EN), SDCC_DLL_CONFIG_REG); /* Wait until CLK_OUT_EN is 1, wait time 50us */ while(!(REG_READ32(host, SDCC_DLL_CONFIG_REG) & SDCC_DLL_CLK_OUT_EN)) { timeout--; udelay(1); if (!timeout) { dprintf(CRITICAL, "%s: clk_out_en timed out: %08x\n", __func__, REG_READ32(host, SDCC_DLL_CONFIG_REG)); return 1; } } core_cfg = REG_READ32(host, SDCC_DLL_CONFIG_REG); core_cfg |= SDCC_DLL_CDR_EN; core_cfg &= ~SDCC_DLL_CDR_EXT_EN; REG_WRITE32(host, core_cfg, SDCC_DLL_CONFIG_REG); return 0; }
/** * usb_hub_init - initialises and resets the external USB hub * * The USB hub needs to be held in reset while the power is being applied * and the reference clock is enabled at 19.2MHz. The following is the * layout of the USB hub taken from the Pandaboard reference manual. * * * .-------------. .--------------. .----------------. * | OMAP4430 | | USB3320C | | LAN9514 | * | | | | | USB Hub / Eth | * | CLK | <------ | CLKOUT | | | * | STP | ------> | STP | | | * | DIR | <------ | DIR | | | * | NXT | <------ | NXT | | | * | DAT0 | <-----> | DAT0 | | | * | DAT1 | <-----> | DAT1 DP | <-----> | DP | * | DAT2 | <-----> | DAT2 DM | <-----> | DM | * | DAT3 | <-----> | DAT3 | | | * | DAT4 | <-----> | DAT4 | | | * | DAT5 | <-----> | DAT5 | +----> | N_RESET | * | DAT6 | <-----> | DAT6 | | | | * | DAT7 | <-----> | DAT7 | | | | * | | | | | +-> | VDD33IO | * | AUX_CLK3 | ------> | REFCLK | | +-> | VDD33A | * | | | | | | | | * | GPIO_62 | --+---> | RESET | | | | | * | | | | | | | | | * | | | '--------------' | | '----------------' * | | | .--------------. | | * | | '---->| VOLT CONVERT |--' | * | | '--------------' | * | | | * | | .--------------. | * | GPIO_1 | ------> | TPS73633 |-----' * | | '--------------' * '-------------' * * * RETURNS: * nothing. */ static void usb_hub_init(void) { bus_space_handle_t scrm_addr, gpio1_addr, gpio2_addr, scm_addr; if (bus_space_map(fdtbus_bs_tag, OMAP44XX_SCRM_HWBASE, OMAP44XX_SCRM_SIZE, 0, &scrm_addr) != 0) panic("Couldn't map SCRM registers"); if (bus_space_map(fdtbus_bs_tag, OMAP44XX_GPIO1_HWBASE, OMAP44XX_GPIO1_SIZE, 0, &gpio1_addr) != 0) panic("Couldn't map GPIO1 registers"); if (bus_space_map(fdtbus_bs_tag, OMAP44XX_GPIO2_HWBASE, OMAP44XX_GPIO2_SIZE, 0, &gpio2_addr) != 0) panic("Couldn't map GPIO2 registers"); if (bus_space_map(fdtbus_bs_tag, OMAP44XX_SCM_PADCONF_HWBASE, OMAP44XX_SCM_PADCONF_SIZE, 0, &scm_addr) != 0) panic("Couldn't map SCM Padconf registers"); /* Need to set FREF_CLK3_OUT to 19.2 MHz and pump it out on pin GPIO_WK31. * We know the SYS_CLK is 38.4Mhz and therefore to get the needed 19.2Mhz, * just use a 2x divider and ensure the SYS_CLK is used as the source. */ REG_WRITE32(scrm_addr + SCRM_AUXCLK3, (1 << 16) | /* Divider of 2 */ (0 << 1) | /* Use the SYS_CLK as the source */ (1 << 8)); /* Enable the clock */ /* Enable the clock out to the pin (GPIO_WK31). * muxmode=fref_clk3_out, pullup/down=disabled, input buffer=disabled, * wakeup=disabled. */ REG_WRITE16(scm_addr + CONTROL_WKUP_PAD0_FREF_CLK3_OUT, 0x0000); /* Disable the power to the USB hub, drive GPIO1 low */ REG_WRITE32(gpio1_addr + GPIO1_OE, REG_READ32(gpio1_addr + GPIO1_OE) & ~(1UL << 1)); REG_WRITE32(gpio1_addr + GPIO1_CLEARDATAOUT, (1UL << 1)); REG_WRITE16(scm_addr + CONTROL_CORE_PAD1_KPD_COL2, 0x0003); /* Reset the USB PHY and Hub using GPIO_62 */ REG_WRITE32(gpio2_addr + GPIO2_OE, REG_READ32(gpio2_addr + GPIO2_OE) & ~(1UL << 30)); REG_WRITE32(gpio2_addr + GPIO2_CLEARDATAOUT, (1UL << 30)); REG_WRITE16(scm_addr + CONTROL_CORE_PAD0_GPMC_WAIT1, 0x0003); DELAY(10); REG_WRITE32(gpio2_addr + GPIO2_SETDATAOUT, (1UL << 30)); /* Enable power to the hub (GPIO_1) */ REG_WRITE32(gpio1_addr + GPIO1_SETDATAOUT, (1UL << 1)); bus_space_unmap(fdtbus_bs_tag, scrm_addr, OMAP44XX_SCRM_SIZE); bus_space_unmap(fdtbus_bs_tag, gpio1_addr, OMAP44XX_GPIO1_SIZE); bus_space_unmap(fdtbus_bs_tag, gpio2_addr, OMAP44XX_GPIO2_SIZE); bus_space_unmap(fdtbus_bs_tag, scm_addr, OMAP44XX_SCM_PADCONF_SIZE); }
/* Initialize DLL (Programmable Delay Line) */ static uint32_t sdhci_msm_init_dll(struct sdhci_host *host) { uint32_t pwr_save = 0; uint32_t timeout = SDHCI_DLL_TIMEOUT; pwr_save = REG_READ32(host, SDCC_VENDOR_SPECIFIC_FUNC) & SDCC_DLL_PWR_SAVE_EN; /* PWR SAVE to 0 */ if (pwr_save) REG_WRITE32(host, (REG_READ32(host, SDCC_VENDOR_SPECIFIC_FUNC) & ~SDCC_DLL_PWR_SAVE_EN), SDCC_VENDOR_SPECIFIC_FUNC); /* Set DLL_RST to 1 */ REG_WRITE32(host, (REG_READ32(host, SDCC_DLL_CONFIG_REG) | SDCC_DLL_RESET_EN), SDCC_DLL_CONFIG_REG); /* Set DLL_PDN to 1 */ REG_WRITE32(host, (REG_READ32(host, SDCC_DLL_CONFIG_REG) | SDCC_DLL_PDN_EN), SDCC_DLL_CONFIG_REG); /* Set frequency field in DLL_CONFIG */ msm_set_dll_freq(host); /* Write 0 to DLL_RST */ REG_WRITE32(host, (REG_READ32(host, SDCC_DLL_CONFIG_REG) & ~SDCC_DLL_RESET_EN), SDCC_DLL_CONFIG_REG); /* Write 0 to DLL_PDN */ REG_WRITE32(host, (REG_READ32(host, SDCC_DLL_CONFIG_REG) & ~SDCC_DLL_PDN_EN), SDCC_DLL_CONFIG_REG); /* Write 1 to DLL_EN */ REG_WRITE32(host, (REG_READ32(host, SDCC_DLL_CONFIG_REG) | SDCC_DLL_EN), SDCC_DLL_CONFIG_REG); /* Write 1 to CLK_OUT_EN */ REG_WRITE32(host, (REG_READ32(host, SDCC_DLL_CONFIG_REG) | SDCC_DLL_CLK_OUT_EN), SDCC_DLL_CONFIG_REG); /* Wait for DLL_LOCK in DLL_STATUS register, wait time 50us */ while(!((REG_READ32(host, SDCC_REG_DLL_STATUS)) & SDCC_DLL_LOCK_STAT)); { udelay(1); timeout--; if (!timeout) { dprintf(CRITICAL, "%s: Failed to get DLL lock: 0x%08x\n", __func__, REG_READ32(host, SDCC_REG_DLL_STATUS)); return 1; } } /* Set the powersave back on */ if (pwr_save) REG_WRITE32(host, (REG_READ32(host, SDCC_VENDOR_SPECIFIC_FUNC) | SDCC_DLL_PWR_SAVE_EN), SDCC_VENDOR_SPECIFIC_FUNC); return 0; }
void sdhci_msm_toggle_cdr(struct sdhci_host *host, bool enable) { uint32_t core_cfg; core_cfg = REG_READ32(host, SDCC_DLL_CONFIG_REG); if (enable) { core_cfg |= SDCC_DLL_CDR_EN; } else { core_cfg &= ~SDCC_DLL_CDR_EN; } REG_WRITE32(host, core_cfg, SDCC_DLL_CONFIG_REG); }
void octeon_pcibus_pci_conf_write(void *v, pcitag_t tag, int offset, pcireg_t data) { uint64_t cfgoff; if (tag == 0){ if (offset & 0x4){ cfgoff = OCTEON_PCI_CFG1 + (offset & 0xfff8); } else { cfgoff = OCTEON_PCI_CFG0 + (offset & 0xfff8); } } else { cfgoff = tag + offset; if (offset & 0x4){ cfgoff = OCTEON_PCI_CONFIG_BASE1 + (cfgoff & 0xfffffff8); } else { cfgoff = OCTEON_PCI_CONFIG_BASE0 + (cfgoff & 0xfffffff8); } } REG_WRITE32(cfgoff, data); }
static uint32_t sdhci_msm_hs400_calibration(struct sdhci_host *host) { DBG("\n HS400 Calibration Start\n"); /* Reset & Initialize the DLL block */ if (sdhci_msm_init_dll(host)) return 1; /* Write the save phase */ if (sdhci_msm_config_dll(host, host->msm_host->saved_phase)) return 1; /* Write 1 to CMD_DAT_TRACK_SEL field in DLL_CONFIG */ REG_WRITE32(host, (REG_READ32(host, SDCC_DLL_CONFIG_REG) | CMD_DAT_TRACK_SEL), SDCC_DLL_CONFIG_REG); if (host->use_cdclp533) return sdhci_msm_cdclp533_calibration(host); else return sdhci_msm_cm_dll_sdc4_calibration(host); DBG("\n HS400 Calibration Done\n"); return 0; }
static uint32_t sdhci_msm_cdclp533_calibration(struct sdhci_host *host) { uint32_t timeout; uint32_t cdc_err; DBG("\n CDCLP533 Calibration Start\n"); /* Write 0 to CDC_T4_DLY_SEL field in VENDOR_SPEC_DDR200_CFG */ REG_WRITE32(host, (REG_READ32(host, SDCC_CDC_DDR200_CFG) & ~CDC_T4_DLY_SEL), SDCC_CDC_DDR200_CFG); /* Write 0 to START_CDC_TRAFFIC field in CORE_DDR200_CFG */ REG_WRITE32(host, (REG_READ32(host, SDCC_CDC_DDR200_CFG) & ~START_CDC_TRAFFIC), SDCC_CDC_DDR200_CFG); /* Write 0 to CDC_SWITCH_BYPASS_OFF field in CSR_CDC_GEN_CFG */ REG_WRITE32(host, (REG_READ32(host, SDCC_VENDOR_SPEC_CSR_CDC_CFG) & ~CDC_SWITCH_BYPASS_OFF), SDCC_VENDOR_SPEC_CSR_CDC_CFG); /* Write 1 to CDC_SWITCH_RC_EN field in CSR_CDC_GEN_CFG */ REG_WRITE32(host, (REG_READ32(host, SDCC_VENDOR_SPEC_CSR_CDC_CFG) | CDC_SWITCH_RC_EN), SDCC_VENDOR_SPEC_CSR_CDC_CFG); /* Write 0 to START_CDC_TRAFFIC field in CORE_DDR200_CFG */ REG_WRITE32(host, (REG_READ32(host, SDCC_CDC_DDR200_CFG) & ~START_CDC_TRAFFIC), SDCC_CDC_DDR200_CFG); /* Perform CDCLP533 initialization sequence * SDCC_CSR_CDC_CTRL_CFG0 --> 0x11800EC * SDCC_CSR_CDC_CTRL_CFG1 --> 0x3011111 * SDCC_CSR_CDC_CAL_TIMER_CFG0 --> 0x1201000 * SDCC_CSR_CDC_CAL_TIMER_CFG1 --> 0x4 * SDCC_CSR_CDC_REFCOUNT_CFG --> 0xCB732020 * SDCC_CSR_CDC_COARSE_CAL_CFG --> 0xB19 * SDCC_CSR_CDC_DELAY_CFG --> 0x4E2 * SDCC_CDC_OFFSET_CFG --> 0x0 * SDCC_CDC_SLAVE_DDA_CFG --> 0x16334 */ REG_WRITE32(host, 0x11800EC, SDCC_CSR_CDC_CTRL_CFG0); REG_WRITE32(host, 0x3011111, SDCC_CSR_CDC_CTRL_CFG1); REG_WRITE32(host, 0x1201000, SDCC_CSR_CDC_CAL_TIMER_CFG0); REG_WRITE32(host, 0x4, SDCC_CSR_CDC_CAL_TIMER_CFG1); REG_WRITE32(host, 0xCB732020, SDCC_CSR_CDC_REFCOUNT_CFG); REG_WRITE32(host, 0xB19, SDCC_CSR_CDC_COARSE_CAL_CFG); REG_WRITE32(host, 0x4E2, SDCC_CSR_CDC_DELAY_CFG); REG_WRITE32(host, 0x0, SDCC_CDC_OFFSET_CFG); REG_WRITE32(host, 0x16334, SDCC_CDC_SLAVE_DDA_CFG); /* Write 1 to SW_TRIGGER_FULL_CALIB */ REG_WRITE32(host, (REG_READ32(host, SDCC_CSR_CDC_CTRL_CFG0) | CDC_SW_TRIGGER_FULL_CALIB), SDCC_CSR_CDC_CTRL_CFG0); /* Write 0 to SW_TRIGGER_FULL_CALIB */ REG_WRITE32(host, (REG_READ32(host, SDCC_CSR_CDC_CTRL_CFG0) & ~CDC_SW_TRIGGER_FULL_CALIB), SDCC_CSR_CDC_CTRL_CFG0); /* Write 1 to HW_AUTO_CAL_EN */ REG_WRITE32(host, (REG_READ32(host, SDCC_CSR_CDC_CTRL_CFG0) | CDC_HW_AUTO_CAL_EN), SDCC_CSR_CDC_CTRL_CFG0); /* Write 1 to TIMER_ENA */ REG_WRITE32(host, (REG_READ32(host, SDCC_CSR_CDC_CAL_TIMER_CFG0) | CDC_TIMER_EN), SDCC_CSR_CDC_CAL_TIMER_CFG0); /* Wait for CALIBRATION_DONE in CDC_STATUS */ timeout = CDC_STATUS_TIMEOUT; while (!(REG_READ32(host, SDCC_CSR_CDC_STATUS0) & BIT(0))) { timeout--; mdelay(1); if (!timeout) { dprintf(CRITICAL, "Error: Calibration done in CDC status not set\n"); return 1; } } cdc_err = REG_READ32(host, SDCC_CSR_CDC_STATUS0) & CSR_CDC_ERROR_MASK; if (cdc_err) { dprintf(CRITICAL, "CDC error set during calibration: %x\n", cdc_err); return 1; } /* Write 1 to START_CDC_TRAFFIC field in CORE_DDR200_CFG */ REG_WRITE32(host, (REG_READ32(host, SDCC_CDC_DDR200_CFG) | START_CDC_TRAFFIC), SDCC_CDC_DDR200_CFG); DBG("\n CDCLP533 Calibration Done\n"); return 0; }
/* Initialize DLL (Programmable Delay Line) */ static uint32_t sdhci_msm_init_dll(struct sdhci_host *host) { uint32_t pwr_save = 0; uint32_t timeout = SDHCI_DLL_TIMEOUT; uint32_t dll_cfg2; uint32_t mclk_clk_freq = 0; pwr_save = REG_READ32(host, SDCC_VENDOR_SPECIFIC_FUNC) & SDCC_DLL_PWR_SAVE_EN; /* Dll sequence needs additional steps for sdcc core version 42 */ if (host->major == 1 && host->minor >= 0x42) { /* Disable DLL clock before configuring */ sdhci_dll_clk_enable(host, 0); } /* PWR SAVE to 0 */ if (pwr_save) REG_WRITE32(host, (REG_READ32(host, SDCC_VENDOR_SPECIFIC_FUNC) & ~SDCC_DLL_PWR_SAVE_EN), SDCC_VENDOR_SPECIFIC_FUNC); /* Set DLL_RST to 1 */ REG_WRITE32(host, (REG_READ32(host, SDCC_DLL_CONFIG_REG) | SDCC_DLL_RESET_EN), SDCC_DLL_CONFIG_REG); /* Set DLL_PDN to 1 */ REG_WRITE32(host, (REG_READ32(host, SDCC_DLL_CONFIG_REG) | SDCC_DLL_PDN_EN), SDCC_DLL_CONFIG_REG); /* Set frequency field in DLL_CONFIG */ msm_set_dll_freq(host); /* Configure the mclk freq based on the current clock rate * and fll cycle count */ if (host->major == 1 && host->minor >= 0x42) { dll_cfg2 = REG_READ32(host, SDCC_HC_REG_DLL_CONFIG_2); if (dll_cfg2 & SDCC_FLL_CYCLE_CNT) mclk_clk_freq = (host->cur_clk_rate / TCXO_FREQ) * 8; else mclk_clk_freq = (host->cur_clk_rate / TCXO_FREQ) * 4; REG_WRITE32(host, ((REG_READ32(host, SDCC_HC_REG_DLL_CONFIG_2) & ~(0xFF << 10)) | (mclk_clk_freq << 10)), SDCC_HC_REG_DLL_CONFIG_2); udelay(5); } /* Write 0 to DLL_RST */ REG_WRITE32(host, (REG_READ32(host, SDCC_DLL_CONFIG_REG) & ~SDCC_DLL_RESET_EN), SDCC_DLL_CONFIG_REG); /* Write 0 to DLL_PDN */ REG_WRITE32(host, (REG_READ32(host, SDCC_DLL_CONFIG_REG) & ~SDCC_DLL_PDN_EN), SDCC_DLL_CONFIG_REG); /* Set the mclk clock and enable the dll clock */ if (host->major == 1 && host->minor >= 0x42) { msm_set_dll_freq(host); sdhci_dll_clk_enable(host, 1); } /* Write 1 to DLL_EN */ REG_WRITE32(host, (REG_READ32(host, SDCC_DLL_CONFIG_REG) | SDCC_DLL_EN), SDCC_DLL_CONFIG_REG); /* Write 1 to CLK_OUT_EN */ REG_WRITE32(host, (REG_READ32(host, SDCC_DLL_CONFIG_REG) | SDCC_DLL_CLK_OUT_EN), SDCC_DLL_CONFIG_REG); /* Wait for DLL_LOCK in DLL_STATUS register, wait time 50us */ while(!((REG_READ32(host, SDCC_REG_DLL_STATUS)) & SDCC_DLL_LOCK_STAT)) { udelay(1); timeout--; if (!timeout) { dprintf(CRITICAL, "%s: Failed to get DLL lock: 0x%08x\n", __func__, REG_READ32(host, SDCC_REG_DLL_STATUS)); return 1; } } /* Set the powersave back on */ if (pwr_save) REG_WRITE32(host, (REG_READ32(host, SDCC_VENDOR_SPECIFIC_FUNC) | SDCC_DLL_PWR_SAVE_EN), SDCC_VENDOR_SPECIFIC_FUNC); return 0; }
/* * Function: sdhci msm init * Arg : MSM specific config data for sdhci * Return : None * Flow: : Enable sdhci mode & do msm specific init */ void sdhci_msm_init(struct sdhci_host *host, struct sdhci_msm_data *config) { uint32_t io_switch; uint32_t caps = 0; uint32_t version; /* Disable HC mode */ RMWREG32((config->pwrctl_base + SDCC_MCI_HC_MODE), SDHCI_HC_START_BIT, SDHCI_HC_WIDTH, 0); /* Core power reset */ RMWREG32((config->pwrctl_base + SDCC_MCI_POWER), CORE_SW_RST_START, CORE_SW_RST_WIDTH, 1); /* Wait for the core power reset to complete*/ mdelay(1); /* Enable sdhc mode */ RMWREG32((config->pwrctl_base + SDCC_MCI_HC_MODE), SDHCI_HC_START_BIT, SDHCI_HC_WIDTH, SDHCI_HC_MODE_EN); /* Set the FF_CLK_SW_RST_DIS to 1 */ RMWREG32((config->pwrctl_base + SDCC_MCI_HC_MODE), FF_CLK_SW_RST_DIS_START, FF_CLK_SW_RST_DIS_WIDTH, 1); /* * Reset the controller */ sdhci_reset(host, SDHCI_SOFT_RESET); /* * Some platforms have same SDC instance shared between emmc & sd card. * For such platforms the emmc IO voltage has to be switched from 3.3 to * 1.8 for the contoller to work with emmc. */ if(config->use_io_switch) { io_switch = REG_READ32(host, SDCC_VENDOR_SPECIFIC_FUNC); io_switch |= HC_IO_PAD_PWR_SWITCH | HC_IO_PAD_PWR_SWITCH_EN; REG_WRITE32(host, io_switch, SDCC_VENDOR_SPECIFIC_FUNC); } /* * CORE_SW_RST may trigger power irq if previous status of PWRCTL * was either BUS_ON or IO_HIGH. So before we enable the power irq * interrupt in GIC (by registering the interrupt handler), we need to * ensure that any pending power irq interrupt status is acknowledged * otherwise power irq interrupt handler would be fired prematurely. */ sdhci_clear_power_ctrl_irq(config); /* * Register the interrupt handler for pwr irq */ register_int_handler(config->pwr_irq, (int_handler)sdhci_int_handler, (void *)config); unmask_interrupt(config->pwr_irq); /* Enable pwr control interrupt */ writel(SDCC_HC_PWR_CTRL_INT, (config->pwrctl_base + SDCC_HC_PWRCTL_MASK_REG)); version = readl(host->msm_host->pwrctl_base + MCI_VERSION); host->major = (version & CORE_VERSION_MAJOR_MASK) >> CORE_VERSION_MAJOR_SHIFT; host->minor = (version & CORE_VERSION_MINOR_MASK); /* * For SDCC5 the capabilities registers does not have voltage advertised * Override the values using SDCC_HC_VENDOR_SPECIFIC_CAPABILITIES0 */ if (host->major >= 1 && host->minor != 0x11 && host->minor != 0x12) { caps = REG_READ32(host, SDHCI_CAPS_REG1); if (config->slot == 0x1) REG_WRITE32(host, (caps | SDHCI_1_8_VOL_MASK), SDCC_HC_VENDOR_SPECIFIC_CAPABILITIES0); else REG_WRITE32(host, (caps | SDHCI_3_0_VOL_MASK), SDCC_HC_VENDOR_SPECIFIC_CAPABILITIES0); } config->tuning_done = false; config->calibration_done = false; host->tuning_in_progress = false; }