Exemple #1
0
/*
 * Function: sdhci set SDR mode
 * Arg     : Host structure
 * Return  : None
 * Flow:   : 1. Disable the clock
 *           2. Enable sdr mode
 *           3. Enable the clock
 * Details : SDR50/SDR104 mode is nothing but HS200
 *			 mode SDCC spec refers to it as SDR mode
 *			 & emmc spec refers as HS200 mode.
 */
void sdhci_set_sdr_mode(struct sdhci_host *host)
{
	uint16_t clk;
	uint16_t ctrl = 0;

	/* Disable the clock */
	clk = REG_READ16(host, SDHCI_CLK_CTRL_REG);
	clk &= ~SDHCI_CLK_EN;
	REG_WRITE16(host, clk, SDHCI_CLK_CTRL_REG);

	/* Enable SDR50 mode:
	 * Right now we support only SDR50 mode which runs at
	 * 100 MHZ sdcc clock, we dont need tuning with SDR50
	 * mode
	 */
	ctrl = REG_READ16(host, SDHCI_HOST_CTRL2_REG);

	/* Enable SDR50/SDR104 mode based on the controller
	 * capabilities.
	 */
	if (host->caps.sdr50_support)
		ctrl |= SDHCI_SDR50_MODE_EN;

	REG_WRITE16(host, ctrl, SDHCI_HOST_CTRL2_REG);

	/* Run the clock back */
	sdhci_clk_supply(host, SDHCI_CLK_100MHZ);
}
Exemple #2
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);
}
Exemple #3
0
/*
 * Function: sdhci error status enable
 * Arg     : Host structure
 * Return  : None
 * Flow:   : Enable command error status
 */
static void sdhci_error_status_enable(struct sdhci_host *host)
{
	/* Enable all interrupt status */
	REG_WRITE16(host, SDHCI_NRML_INT_STS_EN, SDHCI_NRML_INT_STS_EN_REG);
	REG_WRITE16(host, SDHCI_ERR_INT_STS_EN, SDHCI_ERR_INT_STS_EN_REG);
	/* Enable all interrupt signal */
	REG_WRITE16(host, SDHCI_NRML_INT_SIG_EN, SDHCI_NRML_INT_SIG_EN_REG);
	REG_WRITE16(host, SDHCI_ERR_INT_SIG_EN, SDHCI_ERR_INT_SIG_EN_REG);
}
Exemple #4
0
/*
 * Function: sdhci clock supply
 * Arg     : Host structure
 * Return  : 0 on Success, 1 on Failure
 * Flow:   : 1. Calculate the clock divider
 *           2. Set the clock divider
 *           3. Check if clock stable
 *           4. Enable Clock
 */
uint32_t sdhci_clk_supply(struct sdhci_host *host, uint32_t clk)
{
	uint32_t div = 0;
	uint32_t freq = 0;
	uint16_t clk_val = 0;

	if (clk > host->caps.base_clk_rate) {
		dprintf(CRITICAL, "Error: Requested clk freq is more than supported\n");
		return 1;
	}

	if (clk == host->caps.base_clk_rate)
		goto clk_ctrl;

	/* As per the sd spec div should be a multiplier of 2 */
	for (div = 2; div < SDHCI_CLK_MAX_DIV; div += 2) {
		freq = host->caps.base_clk_rate / div;
		if (freq <= clk)
			break;
	}

	div >>= 1;

clk_ctrl:
	/* As per the sdhci spec 3.0, bits 6-7 of the clock
	 * control registers will be mapped to bit 8-9, to
	 * support a 10 bit divider value.
	 * This is needed when the divider value overflows
	 * the 8 bit range.
	 */
	clk_val = ((div & SDHCI_SDCLK_FREQ_MASK) << SDHCI_SDCLK_FREQ_SEL);
	clk_val |= ((div & SDHC_SDCLK_UP_BIT_MASK) >> SDHCI_SDCLK_FREQ_SEL)
				<< SDHCI_SDCLK_UP_BIT_SEL;

	clk_val |= SDHCI_INT_CLK_EN;
	REG_WRITE16(host, clk_val, SDHCI_CLK_CTRL_REG);

	/* Check for clock stable */
	while (!(REG_READ16(host, SDHCI_CLK_CTRL_REG) & SDHCI_CLK_STABLE));

	/* Now clock is stable, enable it */
	clk_val = REG_READ16(host, SDHCI_CLK_CTRL_REG);
	clk_val |= SDHCI_CLK_EN;
	REG_WRITE16(host, clk_val, SDHCI_CLK_CTRL_REG);

	host->cur_clk_rate = freq;

	return 0;
}
Exemple #5
0
/*
 * Function: sdhci set ddr mode
 * Arg     : Host structure
 * Return  : None
 * Flow:   : 1. Disable the clock
 *           2. Enable DDR mode
 *           3. Enable the clock
 */
void sdhci_set_ddr_mode(struct sdhci_host *host)
{
	uint16_t clk;
	uint16_t ctrl = 0;

	/* Disable the clock */
	clk = REG_READ16(host, SDHCI_CLK_CTRL_REG);
	clk &= ~SDHCI_CLK_EN;
	REG_WRITE16(host, clk, SDHCI_CLK_CTRL_REG);

	ctrl = REG_READ16(host, SDHCI_HOST_CTRL2_REG);
	ctrl |= SDHCI_DDR_MODE_EN;

	/* Enalbe DDR mode */
	REG_WRITE16(host, ctrl, SDHCI_HOST_CTRL2_REG);

	/* Run the clock back */
	sdhci_clk_supply(host, host->cur_clk_rate);
}
Exemple #6
0
/*
 * Function: sdhci stop sdcc clock
 * Arg     : Host structure
 * Return  : 0 on Success, 1 on Failure
 * Flow:   : 1. Stop the clock
 */
static uint32_t sdhci_stop_sdcc_clk(struct sdhci_host *host)
{
	uint32_t reg;

	reg = REG_READ32(host, SDHCI_PRESENT_STATE_REG);

	if (reg & (SDHCI_CMD_ACT | SDHCI_DAT_ACT)) {
		dprintf(CRITICAL, "Error: SDCC command & data line are active\n");
		return 1;
	}

	REG_WRITE16(host, SDHCI_CLK_DIS, SDHCI_CLK_CTRL_REG);

	return 0;
}
Exemple #7
0
/*
 * Function: sdhci command complete
 * Arg     : Host & command structure
 * Return  : 0 on Sucess, 1 on Failure
 * Flow:   : 1. Check for command complete
 *           2. Check for transfer complete
 *           3. Get the command response
 *           4. Check for errors
 */
static uint8_t sdhci_cmd_complete(struct sdhci_host *host, struct mmc_command *cmd)
{
	uint8_t i;
	uint32_t retry = 0;
	uint32_t int_status;

	do {
		int_status = REG_READ16(host, SDHCI_NRML_INT_STS_REG);
		int_status &= SDHCI_INT_STS_CMD_COMPLETE;

		if (int_status == SDHCI_INT_STS_CMD_COMPLETE)
			break;

		retry++;
		udelay(500);
		if (retry == SDHCI_MAX_CMD_RETRY) {
			dprintf(CRITICAL, "Error: Command never completed\n");
			goto err;
		}
	} while(1);

	/* Command is complete, clear the interrupt bit */
	REG_WRITE16(host, SDHCI_INT_STS_CMD_COMPLETE, SDHCI_NRML_INT_STS_REG);

	/* Copy the command response,
	 * The valid bits for R2 response are 0-119, & but the actual response
	 * is stored in bits 8-128. We need to move 8 bits of MSB of each
	 * response to register 8 bits of LSB of next response register.
	 * As:
	 * MSB 8 bits of RESP0 --> LSB 8 bits of RESP1
	 * MSB 8 bits of RESP1 --> LSB 8 bits of RESP2
	 * MSB 8 bits of RESP2 --> LSB 8 bits of RESP3
	 */
	if (cmd->resp_type == SDHCI_CMD_RESP_R2) {
		for (i = 0; i < 4; i++) {
			cmd->resp[i] = REG_READ32(host, SDHCI_RESP_REG + (i * 4));
			cmd->resp[i] <<= SDHCI_RESP_LSHIFT;

			if (i != 0)
				cmd->resp[i] |= (REG_READ32(host, SDHCI_RESP_REG + ((i-1) * 4)) >> SDHCI_RESP_RSHIFT);
		}
	} else