Пример #1
0
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;
}
Пример #2
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);
	}
}
Пример #3
0
/* 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;
}
Пример #4
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);
}
Пример #5
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;

	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;
}
Пример #6
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);
}
Пример #7
0
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);
}
Пример #8
0
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;
}
Пример #9
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;
}
Пример #10
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;
}
Пример #11
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;
}