Пример #1
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)
{
	/* 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);

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

	config->tuning_done = false;
	config->calibration_done = false;
	host->tuning_in_progress = false;
}
Пример #2
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;
}