Esempio n. 1
0
File: sdhci.c Progetto: wuxx/sos
int sdhci_init(struct mmc *mmc)
{
	struct sdhci_host *host = (struct sdhci_host *)mmc->priv;

	if ((host->quirks & SDHCI_QUIRK_32BIT_DMA_ADDR) && !aligned_buffer) {
		aligned_buffer = NULL; /* memalign(8, 512*1024); */ /* FIXME: */
		if (!aligned_buffer) {
			PRINT_ERR("Aligned buffer alloc failed!!!");
			return -1;
		}
	}
	sdhci_set_power(host, fls(mmc->voltages) - 1);

	if (host->quirks & SDHCI_QUIRK_NO_CD) {
		unsigned int status;

		sdhci_writel(host, SDHCI_CTRL_CD_TEST_INS | SDHCI_CTRL_CD_TEST,
			SDHCI_HOST_CONTROL);

		status = sdhci_readl(host, SDHCI_PRESENT_STATE);
		while ((!(status & SDHCI_CARD_PRESENT)) ||
		    (!(status & SDHCI_CARD_STATE_STABLE)) ||
		    (!(status & SDHCI_CARD_DETECT_PIN_LEVEL)))
			status = sdhci_readl(host, SDHCI_PRESENT_STATE);
	}

	/* Eable all state */
	sdhci_writel(host, SDHCI_INT_ALL_MASK, SDHCI_INT_ENABLE);
	sdhci_writel(host, SDHCI_INT_ALL_MASK, SDHCI_SIGNAL_ENABLE);

	return 0;
}
Esempio n. 2
0
static void sdhci_f_sdh30_soft_voltage_switch(struct sdhci_host *host)
{
    struct f_sdhost_priv *priv = sdhci_priv(host);
    u32 ctrl = 0;

    usleep_range(2500, 3000);
    ctrl = sdhci_readl(host, F_SDH30_IO_CONTROL2);
    ctrl |= F_SDH30_CRES_O_DN;
    sdhci_writel(host, ctrl, F_SDH30_IO_CONTROL2);
    ctrl |= F_SDH30_MSEL_O_1_8;
    sdhci_writel(host, ctrl, F_SDH30_IO_CONTROL2);

    ctrl &= ~F_SDH30_CRES_O_DN;
    sdhci_writel(host, ctrl, F_SDH30_IO_CONTROL2);
    usleep_range(2500, 3000);

    if (priv->vendor_hs200) {
        dev_info(priv->dev, "%s: setting hs200\n", __func__);
        ctrl = sdhci_readl(host, F_SDH30_ESD_CONTROL);
        ctrl |= priv->vendor_hs200;
        sdhci_writel(host, ctrl, F_SDH30_ESD_CONTROL);
    }

    ctrl = sdhci_readl(host, F_SDH30_TUNING_SETTING);
    ctrl |= F_SDH30_CMD_CHK_DIS;
    sdhci_writel(host, ctrl, F_SDH30_TUNING_SETTING);
}
static int bcm_kona_sd_init(struct sdio_dev *dev)
{
	struct sdhci_host *host = dev->host;
	unsigned int val;

	/* enable the interrupt from the IP core */
	val = sdhci_readl(host, KONA_SDHOST_COREIMR);
	val |= KONA_SDHOST_IP;
	sdhci_writel(host, val, KONA_SDHOST_COREIMR);

	/*
	 * Enable DAT3 logic for card detection and enable the AHB clock to the
	 * host
	 */
	val = sdhci_readl(host, KONA_SDHOST_CORECTRL);
	val |= /*KONA_SDHOST_CD_PINCTRL | */ KONA_SDHOST_EN;

	/* Back-to-Back register write needs a delay of 1ms
	 * at bootup (min 10uS)
	 */
	udelay(1000);
	sdhci_writel(host, val, KONA_SDHOST_CORECTRL);

	return 0;
}
Esempio n. 4
0
File: sdhci.c Progetto: DFE/u-boot
int sdhci_init(struct mmc *mmc)
{
	struct sdhci_host *host = (struct sdhci_host *)mmc->priv;

	if ((host->quirks & SDHCI_QUIRK_32BIT_DMA_ADDR) && !aligned_buffer) {
		aligned_buffer = memalign(8, 512*1024);
		if (!aligned_buffer) {
			printf("Aligned buffer alloc failed!!!");
			return -1;
		}
	}

	sdhci_set_power(host, fls(mmc->voltages) - 1);

	if (host->quirks & SDHCI_QUIRK_NO_CD) {
		unsigned int status;

		sdhci_writel(host, SDHCI_CTRL_CD_TEST_INS | SDHCI_CTRL_CD_TEST,
			SDHCI_HOST_CONTROL);

		status = sdhci_readl(host, SDHCI_PRESENT_STATE);
		while ((!(status & SDHCI_CARD_PRESENT)) ||
		    (!(status & SDHCI_CARD_STATE_STABLE)) ||
		    (!(status & SDHCI_CARD_DETECT_PIN_LEVEL)))
			status = sdhci_readl(host, SDHCI_PRESENT_STATE);
	}

	/* Enable only interrupts served by the SD controller */
	sdhci_writel(host, SDHCI_INT_DATA_MASK | SDHCI_INT_CMD_MASK
		     , SDHCI_INT_ENABLE);
	/* Mask all sdhci interrupt sources */
	sdhci_writel(host, 0x0, SDHCI_SIGNAL_ENABLE);

	return 0;
}
Esempio n. 5
0
static void tegra_sdhci_reset(struct sdhci_host *host, u8 mask)
{
	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
	struct sdhci_tegra *tegra_host = pltfm_host->priv;
	const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data;
	u32 misc_ctrl, clk_ctrl;

	sdhci_reset(host, mask);

	if (!(mask & SDHCI_RESET_ALL))
		return;

	misc_ctrl = sdhci_readl(host, SDHCI_TEGRA_VENDOR_MISC_CTRL);
	/* Erratum: Enable SDHCI spec v3.00 support */
	if (soc_data->nvquirks & NVQUIRK_ENABLE_SDHCI_SPEC_300)
		misc_ctrl |= SDHCI_MISC_CTRL_ENABLE_SDHCI_SPEC_300;
	/* Advertise UHS modes as supported by host */
	if (soc_data->nvquirks & NVQUIRK_ENABLE_SDR50)
		misc_ctrl |= SDHCI_MISC_CTRL_ENABLE_SDR50;
	if (soc_data->nvquirks & NVQUIRK_ENABLE_DDR50)
		misc_ctrl |= SDHCI_MISC_CTRL_ENABLE_DDR50;
	if (soc_data->nvquirks & NVQUIRK_ENABLE_SDR104)
		misc_ctrl |= SDHCI_MISC_CTRL_ENABLE_SDR104;
	sdhci_writel(host, misc_ctrl, SDHCI_TEGRA_VENDOR_MISC_CTRL);

	clk_ctrl = sdhci_readl(host, SDHCI_TEGRA_VENDOR_CLOCK_CTRL);
	clk_ctrl &= ~SDHCI_CLOCK_CTRL_SPI_MODE_CLKEN_OVERRIDE;
	if (soc_data->nvquirks & SDHCI_MISC_CTRL_ENABLE_SDR50)
		clk_ctrl |= SDHCI_CLOCK_CTRL_SDR50_TUNING_OVERRIDE;
	sdhci_writel(host, clk_ctrl, SDHCI_TEGRA_VENDOR_CLOCK_CTRL);

	tegra_host->ddr_signaling = false;
}
Esempio n. 6
0
static int armada_38x_quirks(struct platform_device *pdev,
			     struct sdhci_host *host)
{
	struct device_node *np = pdev->dev.of_node;

	host->quirks |= SDHCI_QUIRK_MISSING_CAPS;
	/*
	 * According to erratum 'FE-2946959' both SDR50 and DDR50
	 * modes require specific clock adjustments in SDIO3
	 * Configuration register, if the adjustment is not done,
	 * remove them from the capabilities.
	 */
	host->caps1 = sdhci_readl(host, SDHCI_CAPABILITIES_1);
	host->caps1 &= ~(SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_DDR50);

	/*
	 * According to erratum 'ERR-7878951' Armada 38x SDHCI
	 * controller has different capabilities than the ones shown
	 * in its registers
	 */
	host->caps = sdhci_readl(host, SDHCI_CAPABILITIES);
	if (of_property_read_bool(np, "no-1-8-v")) {
		host->caps &= ~SDHCI_CAN_VDD_180;
		host->mmc->caps &= ~MMC_CAP_1_8V_DDR;
	} else {
		host->caps &= ~SDHCI_CAN_VDD_330;
	}
	host->caps1 &= ~(SDHCI_SUPPORT_SDR104 | SDHCI_USE_SDR50_TUNING);

	return 0;
}
Esempio n. 7
0
static int sdhci_bcm_kona_sd_reset(struct sdhci_host *host)
{
	unsigned int val;
	unsigned long timeout;

	/* This timeout should be sufficent for core to reset */
	timeout = jiffies + msecs_to_jiffies(100);

	/* reset the host using the top level reset */
	val = sdhci_readl(host, KONA_SDHOST_CORECTRL);
	val |= KONA_SDHOST_RESET;
	sdhci_writel(host, val, KONA_SDHOST_CORECTRL);

	while (!(sdhci_readl(host, KONA_SDHOST_CORECTRL) & KONA_SDHOST_RESET)) {
		if (time_is_before_jiffies(timeout)) {
			pr_err("Error: sd host is stuck in reset!!!\n");
			return -EFAULT;
		}
	}

	/* bring the host out of reset */
	val = sdhci_readl(host, KONA_SDHOST_CORECTRL);
	val &= ~KONA_SDHOST_RESET;

	/*
	 * Back-to-Back register write needs a delay of 1ms at bootup (min 10uS)
	 * Back-to-Back writes to same register needs delay when SD bus clock
	 * is very low w.r.t AHB clock, mainly during boot-time and during card
	 * insert-removal.
	 */
	usleep_range(1000, 5000);
	sdhci_writel(host, val, KONA_SDHOST_CORECTRL);

	return 0;
}
Esempio n. 8
0
static int sdhci_transfer_data(struct sdhci_host *host, 
				struct mmc_data *data,
				u32 start_addr)
{
	u32 ctrl, stat, rdy, mask, timeout, block = 0;

	if (host->sdhci_caps & SDHCI_CAN_DO_SDMA) {
		ctrl = sdhci_readl(host, SDHCI_HOST_CONTROL);
		ctrl &= ~SDHCI_CTRL_DMA_MASK;
		ctrl |= SDHCI_CTRL_SDMA;
		sdhci_writel(host, ctrl, SDHCI_HOST_CONTROL);
	}

	timeout = 1000000;
	rdy = SDHCI_INT_SPACE_AVAIL | SDHCI_INT_DATA_AVAIL;
	mask = SDHCI_DATA_AVAILABLE | SDHCI_SPACE_AVAILABLE;
	do {
		stat = sdhci_readl(host, SDHCI_INT_STATUS);
		if (stat & SDHCI_INT_ERROR) {
			vmm_printf("%s: Error detected in status(0x%X)!\n", 
				   __func__, stat);
			return VMM_EFAIL;
		}

		if (stat & rdy) {
			if (!(sdhci_readl(host, SDHCI_PRESENT_STATE) & mask)) {
				continue;
			}
			sdhci_writel(host, rdy, SDHCI_INT_STATUS);
			sdhci_transfer_pio(host, data);
			data->dest += data->blocksize;
			if (++block >= data->blocks) {
				break;
			}
		}

		if (host->sdhci_caps & SDHCI_CAN_DO_SDMA) {
			if (stat & SDHCI_INT_DMA_END) {
				sdhci_writel(host, SDHCI_INT_DMA_END, 
							SDHCI_INT_STATUS);
				start_addr &= 
					~(SDHCI_DEFAULT_BOUNDARY_SIZE - 1);
				start_addr += SDHCI_DEFAULT_BOUNDARY_SIZE;
				sdhci_writel(host, start_addr, 
							SDHCI_DMA_ADDRESS);
			}
		}

		if (timeout-- > 0) {
			vmm_udelay(10);
		} else {
			vmm_printf("%s: Transfer data timeout\n", __func__);
			return VMM_ETIMEDOUT;
		}
	} while (!(stat & SDHCI_INT_DATA_END));

	return VMM_OK;
}
Esempio n. 9
0
static void tegra_sdhci_reset(struct sdhci_host *host, u8 mask)
{
	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
	struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
	const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data;
	u32 misc_ctrl, clk_ctrl, pad_ctrl;

	sdhci_reset(host, mask);

	if (!(mask & SDHCI_RESET_ALL))
		return;

	tegra_sdhci_set_tap(host, tegra_host->default_tap);

	misc_ctrl = sdhci_readl(host, SDHCI_TEGRA_VENDOR_MISC_CTRL);
	clk_ctrl = sdhci_readl(host, SDHCI_TEGRA_VENDOR_CLOCK_CTRL);

	misc_ctrl &= ~(SDHCI_MISC_CTRL_ENABLE_SDHCI_SPEC_300 |
		       SDHCI_MISC_CTRL_ENABLE_SDR50 |
		       SDHCI_MISC_CTRL_ENABLE_DDR50 |
		       SDHCI_MISC_CTRL_ENABLE_SDR104);

	clk_ctrl &= ~(SDHCI_CLOCK_CTRL_TRIM_MASK |
		      SDHCI_CLOCK_CTRL_SPI_MODE_CLKEN_OVERRIDE);

	if (tegra_sdhci_is_pad_and_regulator_valid(host)) {
		/* Erratum: Enable SDHCI spec v3.00 support */
		if (soc_data->nvquirks & NVQUIRK_ENABLE_SDHCI_SPEC_300)
			misc_ctrl |= SDHCI_MISC_CTRL_ENABLE_SDHCI_SPEC_300;
		/* Advertise UHS modes as supported by host */
		if (soc_data->nvquirks & NVQUIRK_ENABLE_SDR50)
			misc_ctrl |= SDHCI_MISC_CTRL_ENABLE_SDR50;
		if (soc_data->nvquirks & NVQUIRK_ENABLE_DDR50)
			misc_ctrl |= SDHCI_MISC_CTRL_ENABLE_DDR50;
		if (soc_data->nvquirks & NVQUIRK_ENABLE_SDR104)
			misc_ctrl |= SDHCI_MISC_CTRL_ENABLE_SDR104;
		if (soc_data->nvquirks & SDHCI_MISC_CTRL_ENABLE_SDR50)
			clk_ctrl |= SDHCI_CLOCK_CTRL_SDR50_TUNING_OVERRIDE;
	}

	clk_ctrl |= tegra_host->default_trim << SDHCI_CLOCK_CTRL_TRIM_SHIFT;

	sdhci_writel(host, misc_ctrl, SDHCI_TEGRA_VENDOR_MISC_CTRL);
	sdhci_writel(host, clk_ctrl, SDHCI_TEGRA_VENDOR_CLOCK_CTRL);

	if (soc_data->nvquirks & NVQUIRK_HAS_PADCALIB) {
		pad_ctrl = sdhci_readl(host, SDHCI_TEGRA_SDMEM_COMP_PADCTRL);
		pad_ctrl &= ~SDHCI_TEGRA_SDMEM_COMP_PADCTRL_VREF_SEL_MASK;
		pad_ctrl |= SDHCI_TEGRA_SDMEM_COMP_PADCTRL_VREF_SEL_VAL;
		sdhci_writel(host, pad_ctrl, SDHCI_TEGRA_SDMEM_COMP_PADCTRL);

		tegra_host->pad_calib_required = true;
	}

	tegra_host->ddr_signaling = false;
}
Esempio n. 10
0
static int sdhci_transfer_data(struct sdhci_host *host, struct mmc_data *data,
				unsigned int start_addr)
{
	unsigned int stat, rdy, mask, timeout, block = 0;
	bool transfer_done = false;
#ifdef CONFIG_MMC_SDHCI_SDMA
	unsigned char ctrl;
	ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
	ctrl &= ~SDHCI_CTRL_DMA_MASK;
	sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
#endif

	timeout = 1000000;
	rdy = SDHCI_INT_SPACE_AVAIL | SDHCI_INT_DATA_AVAIL;
	mask = SDHCI_DATA_AVAILABLE | SDHCI_SPACE_AVAILABLE;
	do {
		stat = sdhci_readl(host, SDHCI_INT_STATUS);
		if (stat & SDHCI_INT_ERROR) {
			pr_debug("%s: Error detected in status(0x%X)!\n",
				 __func__, stat);
			return -EIO;
		}
		if (!transfer_done && (stat & rdy)) {
			if (!(sdhci_readl(host, SDHCI_PRESENT_STATE) & mask))
				continue;
			sdhci_writel(host, rdy, SDHCI_INT_STATUS);
			sdhci_transfer_pio(host, data);
			data->dest += data->blocksize;
			if (++block >= data->blocks) {
				/* Keep looping until the SDHCI_INT_DATA_END is
				 * cleared, even if we finished sending all the
				 * blocks.
				 */
				transfer_done = true;
				continue;
			}
		}
#ifdef CONFIG_MMC_SDHCI_SDMA
		if (!transfer_done && (stat & SDHCI_INT_DMA_END)) {
			sdhci_writel(host, SDHCI_INT_DMA_END, SDHCI_INT_STATUS);
			start_addr &= ~(SDHCI_DEFAULT_BOUNDARY_SIZE - 1);
			start_addr += SDHCI_DEFAULT_BOUNDARY_SIZE;
			sdhci_writel(host, start_addr, SDHCI_DMA_ADDRESS);
		}
#endif
		if (timeout-- > 0)
			udelay(10);
		else {
			printf("%s: Transfer data timeout\n", __func__);
			return -ETIMEDOUT;
		}
	} while (!(stat & SDHCI_INT_DATA_END));
	return 0;
}
Esempio n. 11
0
static int init_kona_mmc_core(struct sdhci_host *host)
{
	unsigned int mask;
	unsigned int timeout;

	if (sdhci_readb(host, SDHCI_SOFTWARE_RESET) & SDHCI_RESET_ALL) {
		printf("%s: sd host controller reset error\n", __func__);
		return -EBUSY;
	}

	/* For kona a hardware reset before anything else. */
	mask = sdhci_readl(host, SDHCI_CORECTRL_OFFSET) | SDHCI_CORECTRL_RESET;
	sdhci_writel(host, mask, SDHCI_CORECTRL_OFFSET);

	/* Wait max 100 ms */
	timeout = 1000;
	do {
		if (timeout == 0) {
			printf("%s: reset timeout error\n", __func__);
			return -ETIMEDOUT;
		}
		timeout--;
		udelay(100);
	} while (0 ==
		 (sdhci_readl(host, SDHCI_CORECTRL_OFFSET) &
		  SDHCI_CORECTRL_RESET));

	/* Clear the reset bit. */
	mask = mask & ~SDHCI_CORECTRL_RESET;
	sdhci_writel(host, mask, SDHCI_CORECTRL_OFFSET);

	/* Enable AHB clock */
	mask = sdhci_readl(host, SDHCI_CORECTRL_OFFSET);
	sdhci_writel(host, mask | SDHCI_CORECTRL_EN, SDHCI_CORECTRL_OFFSET);

	/* Enable interrupts */
	sdhci_writel(host, SDHCI_COREIMR_IP, SDHCI_COREIMR_OFFSET);

	/* Make sure Card is detected in controller */
	mask = sdhci_readl(host, SDHCI_CORESTAT_OFFSET);
	sdhci_writel(host, mask | SDHCI_CORESTAT_CD_SW, SDHCI_CORESTAT_OFFSET);

	/* Wait max 100 ms */
	timeout = 1000;
	while (!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT)) {
		if (timeout == 0) {
			printf("%s: CARD DETECT timeout error\n", __func__);
			return -ETIMEDOUT;
		}
		timeout--;
		udelay(100);
	}
	return 0;
}
Esempio n. 12
0
static void sdhci_save_regs(struct sdhci_host *host)
{
	struct sprd_host_platdata *host_pdata = sdhci_get_platdata(host);
	if (!host_pdata->regs.is_valid) return;
	host_pdata->regs.addr = sdhci_readl(host, SDHCI_DMA_ADDRESS);
	host_pdata->regs.blk_size = sdhci_readw(host, SDHCI_BLOCK_SIZE);
	host_pdata->regs.blk_cnt = sdhci_readw(host, SDHCI_BLOCK_COUNT);
	host_pdata->regs.arg = sdhci_readl(host, SDHCI_ARGUMENT);
	host_pdata->regs.tran_mode = sdhci_readw(host, SDHCI_TRANSFER_MODE);
	host_pdata->regs.ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
	host_pdata->regs.power = sdhci_readb(host, SDHCI_POWER_CONTROL);
	host_pdata->regs.clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
}
static void sdhci_save_regs(struct sdhci_host *host)
{
	if (!strcmp("Spread SDIO host1", host->hw_name)){
		host_addr = sdhci_readl(host, SDHCI_DMA_ADDRESS);
		host_blk_size = sdhci_readw(host, SDHCI_BLOCK_SIZE);
		host_blk_cnt = sdhci_readw(host, SDHCI_BLOCK_COUNT);
		host_arg = sdhci_readl(host, SDHCI_ARGUMENT);
		host_tran_mode = sdhci_readw(host, SDHCI_TRANSFER_MODE);
		host_ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
		host_power = sdhci_readb(host, SDHCI_POWER_CONTROL);
		host_clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
	}
}
Esempio n. 14
0
int sdhci_complete_adma(struct sdhci_ctrlr *sdhci_ctrlr,
	struct mmc_command *cmd)
{
	int retry;
	u32 stat = 0, mask;

	mask = SDHCI_INT_RESPONSE | SDHCI_INT_ERROR;

	retry = 10000; /* Command should be done in way less than 10 ms. */
	while (--retry) {
		stat = sdhci_readl(sdhci_ctrlr, SDHCI_INT_STATUS);
		if (stat & mask)
			break;
		udelay(1);
	}

	sdhci_writel(sdhci_ctrlr, SDHCI_INT_RESPONSE, SDHCI_INT_STATUS);

	if (retry && !(stat & SDHCI_INT_ERROR)) {
		/* Command OK, let's wait for data transfer completion. */
		mask = SDHCI_INT_DATA_END |
			SDHCI_INT_ERROR | SDHCI_INT_ADMA_ERROR;

		/* Transfer should take 10 seconds tops. */
		retry = 10 * 1000 * 1000;
		while (--retry) {
			stat = sdhci_readl(sdhci_ctrlr, SDHCI_INT_STATUS);
			if (stat & mask)
				break;
			udelay(1);
		}

		sdhci_writel(sdhci_ctrlr, stat, SDHCI_INT_STATUS);
		if (retry && !(stat & SDHCI_INT_ERROR)) {
			sdhci_cmd_done(sdhci_ctrlr, cmd);
			return 0;
		}
	}

	sdhc_error("%s: transfer error, stat %#x, adma error %#x, retry %d\n",
	       __func__, stat, sdhci_readl(sdhci_ctrlr, SDHCI_ADMA_ERROR),
		retry);

	sdhci_reset(sdhci_ctrlr, SDHCI_RESET_CMD);
	sdhci_reset(sdhci_ctrlr, SDHCI_RESET_DATA);

	if (stat & SDHCI_INT_TIMEOUT)
		return CARD_TIMEOUT;
	return CARD_COMM_ERR;
}
Esempio n. 15
0
static void xenon_mmc_disable_tuning(struct sdhci_host *host, u8 slot)
{
	u32 var;

	/* Clear the Re-Tuning Request functionality */
	var = sdhci_readl(host, SDHC_SLOT_RETUNING_REQ_CTRL);
	var &= ~RETUNING_COMPATIBLE;
	sdhci_writel(host, var, SDHC_SLOT_RETUNING_REQ_CTRL);

	/* Clear the Re-tuning Event Signal Enable */
	var = sdhci_readl(host, SDHCI_SIGNAL_ENABLE);
	var &= ~SDHCI_RETUNE_EVT_INTSIG;
	sdhci_writel(host, var, SDHCI_SIGNAL_ENABLE);
}
Esempio n. 16
0
static void sdhci_clear_set_irqs(struct sdhci_host *host, u32 clear, u32 set)
{
	u32 ier;

	ier = sdhci_readl(host, SDHCI_INT_ENABLE);
	ier &= ~clear;
	ier |= set;
	sdhci_writel(host, ier, SDHCI_INT_ENABLE);

	ier = sdhci_readl(host, SDHCI_SIGNAL_ENABLE);
	ier &= ~clear;
	ier |= set;
	sdhci_writel(host, ier, SDHCI_SIGNAL_ENABLE);
}
Esempio n. 17
0
static int bxt_get_cd(struct mmc_host *mmc)
{
	int gpio_cd = mmc_gpio_get_cd(mmc);
	struct sdhci_host *host = mmc_priv(mmc);
	unsigned long flags;
	int ret = 0;

	if (!gpio_cd)
		return 0;

	pm_runtime_get_sync(mmc->parent);

	spin_lock_irqsave(&host->lock, flags);

	if (host->flags & SDHCI_DEVICE_DEAD)
		goto out;

	ret = !!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT);
out:
	spin_unlock_irqrestore(&host->lock, flags);

	pm_runtime_mark_last_busy(mmc->parent);
	pm_runtime_put_autosuspend(mmc->parent);

	return ret;
}
Esempio n. 18
0
File: sdhci.c Progetto: DFE/u-boot
static void sdhci_cmd_done(struct sdhci_host *host, struct mmc_cmd *cmd)
{
	int i;
	if (cmd->resp_type & MMC_RSP_136) {
		/* CRC is stripped so we need to do some shifting. */
		for (i = 0; i < 4; i++) {
			cmd->response[i] = sdhci_readl(host,
					SDHCI_RESPONSE + (3-i)*4) << 8;
			if (i != 3)
				cmd->response[i] |= sdhci_readb(host,
						SDHCI_RESPONSE + (3-i)*4-1);
		}
	} else {
		cmd->response[0] = sdhci_readl(host, SDHCI_RESPONSE);
	}
}
Esempio n. 19
0
int sdhci_query_command_backstage(struct mmc *mmc, struct mmc_data *data)
{
	struct sdhci_host *host = (struct sdhci_host *)mmc->priv;
	unsigned int start_addr = 0;
	int ret = 0;
	unsigned int stat = 0;

	start_addr = (unsigned int)data->src;

	if (NULL != data)
		ret = sdhci_transfer_data(host, data, start_addr);

	stat = sdhci_readl(host, SDHCI_INT_STATUS);
	sdhci_writel(host, SDHCI_INT_ALL_MASK, SDHCI_INT_STATUS);
	if (!ret)
		return 0;

	if (stat & SDHCI_INT_TIMEOUT) {
		//sdio_dump(host->ioaddr);
		sdhci_reset(host, SDHCI_RESET_CMD);
		sdhci_reset(host, SDHCI_RESET_DATA);
		return TIMEOUT;
	} else {
		//sdio_dump(host->ioaddr);
		sdhci_reset(host, SDHCI_RESET_CMD);
		sdhci_reset(host, SDHCI_RESET_DATA);
		return COMM_ERR;
	}
}
Esempio n. 20
0
static int sdhci_s3c_resume(struct platform_device *dev)
{
	struct sdhci_host *host = platform_get_drvdata(dev);

#if defined(CONFIG_WIMAX_CMC)/* && defined(CONFIG_TARGET_LOCALE_NA)*/

	struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
	u32 ier;
#endif
#ifdef CONFIG_MACH_MIDAS_01_BD
	/* turn vdd_tflash off if a card exists*/
	if (sdhci_s3c_get_card_exist(host))
		sdhci_s3c_vtf_on_off(1);
	else
		sdhci_s3c_vtf_on_off(0);

#endif
	sdhci_resume_host(host);
#if defined(CONFIG_WIMAX_CMC)/* && defined(CONFIG_TARGET_LOCALE_NA)*/

	if (pdata->enable_intr_on_resume) {
		ier = sdhci_readl(host, SDHCI_INT_ENABLE);
		ier |= SDHCI_INT_CARD_INT;
		sdhci_writel(host, ier, SDHCI_INT_ENABLE);
		sdhci_writel(host, ier, SDHCI_SIGNAL_ENABLE);
	}
#endif
	return 0;
}
Esempio n. 21
0
static int arasan_sdhci_probe(struct udevice *dev)
{
	struct arasan_sdhci_plat *plat = dev_get_platdata(dev);
	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
	struct sdhci_host *host = dev_get_priv(dev);
	u32 caps;
	int ret;

	host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD |
		       SDHCI_QUIRK_BROKEN_R1B;

#ifdef CONFIG_ZYNQ_HISPD_BROKEN
	host->quirks |= SDHCI_QUIRK_NO_HISPD_BIT;
#endif

	host->version = sdhci_readw(host, SDHCI_HOST_VERSION);

	caps = sdhci_readl(host, SDHCI_CAPABILITIES);
	ret = sdhci_setup_cfg(&plat->cfg, dev->name, host->bus_width,
			      caps, CONFIG_ZYNQ_SDHCI_MAX_FREQ,
			      CONFIG_ZYNQ_SDHCI_MIN_FREQ, host->version,
			      host->quirks, 0);
	host->mmc = &plat->mmc;
	if (ret)
		return ret;
	host->mmc->priv = host;
	host->mmc->dev = dev;
	upriv->mmc = host->mmc;

	return sdhci_probe(dev);
}
Esempio n. 22
0
/*
 * Software emulation of the SD card insertion/removal. Set insert=1 for insert
 * and insert=0 for removal. The card detection is done by GPIO. For Broadcom
 * IP to function properly the bit 0 of CORESTAT register needs to be set/reset
 * to generate the CD IRQ handled in sdhci.c which schedules card_tasklet.
 */
static int sdhci_bcm_kona_sd_card_emulate(struct sdhci_host *host, int insert)
{
	struct sdhci_pltfm_host *pltfm_priv = sdhci_priv(host);
	struct sdhci_bcm_kona_dev *kona_dev = sdhci_pltfm_priv(pltfm_priv);
	u32 val;

	/*
	 * Back-to-Back register write needs a delay of min 10uS.
	 * Back-to-Back writes to same register needs delay when SD bus clock
	 * is very low w.r.t AHB clock, mainly during boot-time and during card
	 * insert-removal.
	 * We keep 20uS
	 */
	mutex_lock(&kona_dev->write_lock);
	udelay(20);
	val = sdhci_readl(host, KONA_SDHOST_CORESTAT);

	if (insert) {
		int ret;

		ret = mmc_gpio_get_ro(host->mmc);
		if (ret >= 0)
			val = (val & ~KONA_SDHOST_WP) |
				((ret) ? KONA_SDHOST_WP : 0);

		val |= KONA_SDHOST_CD_SW;
		sdhci_writel(host, val, KONA_SDHOST_CORESTAT);
	} else {
		val &= ~KONA_SDHOST_CD_SW;
		sdhci_writel(host, val, KONA_SDHOST_CORESTAT);
	}
	mutex_unlock(&kona_dev->write_lock);

	return 0;
}
Esempio n. 23
0
int add_sdhci(struct sdhci_host *host, u32 max_clk, u32 min_clk)
{
    unsigned int caps;

    host->cfg.name = host->name;
    host->cfg.ops = &sdhci_ops;

    caps = sdhci_readl(host, SDHCI_CAPABILITIES);
#ifdef CONFIG_MMC_SDMA
    if (!(caps & SDHCI_CAN_DO_SDMA)) {
        printf("%s: Your controller doesn't support SDMA!!\n",
               __func__);
        return -1;
    }
#endif

    if (max_clk)
        host->cfg.f_max = max_clk;
    else {
        if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300)
            host->cfg.f_max = (caps & SDHCI_CLOCK_V3_BASE_MASK)
                              >> SDHCI_CLOCK_BASE_SHIFT;
        else
            host->cfg.f_max = (caps & SDHCI_CLOCK_BASE_MASK)
                              >> SDHCI_CLOCK_BASE_SHIFT;
        host->cfg.f_max *= 1000000;
    }
Esempio n. 24
0
static void tegra_sdhci_set_tap(struct sdhci_host *host, unsigned int tap)
{
	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
	struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
	const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data;
	bool card_clk_enabled = false;
	u32 reg;

	/*
	 * Touching the tap values is a bit tricky on some SoC generations.
	 * The quirk enables a workaround for a glitch that sometimes occurs if
	 * the tap values are changed.
	 */

	if (soc_data->nvquirks & NVQUIRK_DIS_CARD_CLK_CONFIG_TAP)
		card_clk_enabled = tegra_sdhci_configure_card_clk(host, false);

	reg = sdhci_readl(host, SDHCI_TEGRA_VENDOR_CLOCK_CTRL);
	reg &= ~SDHCI_CLOCK_CTRL_TAP_MASK;
	reg |= tap << SDHCI_CLOCK_CTRL_TAP_SHIFT;
	sdhci_writel(host, reg, SDHCI_TEGRA_VENDOR_CLOCK_CTRL);

	if (soc_data->nvquirks & NVQUIRK_DIS_CARD_CLK_CONFIG_TAP &&
	    card_clk_enabled) {
		udelay(1);
		sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
		tegra_sdhci_configure_card_clk(host, card_clk_enabled);
	}
}
Esempio n. 25
0
static int armada_38x_quirks(struct platform_device *pdev,
			     struct sdhci_host *host)
{
	struct device_node *np = pdev->dev.of_node;
	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
	struct sdhci_pxa *pxa = sdhci_pltfm_priv(pltfm_host);
	struct resource *res;

	host->quirks &= ~SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN;
	host->quirks |= SDHCI_QUIRK_MISSING_CAPS;

	host->caps = sdhci_readl(host, SDHCI_CAPABILITIES);
	host->caps1 = sdhci_readl(host, SDHCI_CAPABILITIES_1);

	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
					   "conf-sdio3");
	if (res) {
		pxa->sdio3_conf_reg = devm_ioremap_resource(&pdev->dev, res);
		if (IS_ERR(pxa->sdio3_conf_reg))
			return PTR_ERR(pxa->sdio3_conf_reg);
	} else {
		/*
		 * According to erratum 'FE-2946959' both SDR50 and DDR50
		 * modes require specific clock adjustments in SDIO3
		 * Configuration register, if the adjustment is not done,
		 * remove them from the capabilities.
		 */
		host->caps1 &= ~(SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_DDR50);

		dev_warn(&pdev->dev, "conf-sdio3 register not found: disabling SDR50 and DDR50 modes.\nConsider updating your dtb\n");
	}

	/*
	 * According to erratum 'ERR-7878951' Armada 38x SDHCI
	 * controller has different capabilities than the ones shown
	 * in its registers
	 */
	if (of_property_read_bool(np, "no-1-8-v")) {
		host->caps &= ~SDHCI_CAN_VDD_180;
		host->mmc->caps &= ~MMC_CAP_1_8V_DDR;
	} else {
		host->caps &= ~SDHCI_CAN_VDD_330;
	}
	host->caps1 &= ~(SDHCI_SUPPORT_SDR104 | SDHCI_USE_SDR50_TUNING);

	return 0;
}
Esempio n. 26
0
File: sdhci.c Progetto: DFE/u-boot
static int sdhci_transfer_data(struct sdhci_host *host, struct mmc_data *data,
				unsigned int start_addr)
{
	unsigned int stat, rdy, mask, timeout, block = 0;
#ifdef CONFIG_MMC_SDMA
	unsigned char ctrl;
	ctrl = sdhci_readl(host, SDHCI_HOST_CONTROL);
	ctrl &= ~SDHCI_CTRL_DMA_MASK;
	ctrl |= SDHCI_CTRL_SDMA;
	sdhci_writel(host, ctrl, SDHCI_HOST_CONTROL);
#endif

	timeout = 1000000;
	rdy = SDHCI_INT_SPACE_AVAIL | SDHCI_INT_DATA_AVAIL;
	mask = SDHCI_DATA_AVAILABLE | SDHCI_SPACE_AVAILABLE;
	do {
		stat = sdhci_readl(host, SDHCI_INT_STATUS);
		if (stat & SDHCI_INT_ERROR) {
			printf("Error detected in status(0x%X)!\n", stat);
			return -1;
		}
		if (stat & rdy) {
			if (!(sdhci_readl(host, SDHCI_PRESENT_STATE) & mask))
				continue;
			sdhci_writel(host, rdy, SDHCI_INT_STATUS);
			sdhci_transfer_pio(host, data);
			data->dest += data->blocksize;
			if (++block >= data->blocks)
				break;
		}
#ifdef CONFIG_MMC_SDMA
		if (stat & SDHCI_INT_DMA_END) {
			sdhci_writel(host, SDHCI_INT_DMA_END, SDHCI_INT_STATUS);
			start_addr &= ~(SDHCI_DEFAULT_BOUNDARY_SIZE - 1);
			start_addr += SDHCI_DEFAULT_BOUNDARY_SIZE;
			sdhci_writel(host, start_addr, SDHCI_DMA_ADDRESS);
		}
#endif
		if (timeout-- > 0)
			udelay(10);
		else {
			printf("Transfer data timeout\n");
			return -1;
		}
	} while (!(stat & SDHCI_INT_DATA_END));
	return 0;
}
Esempio n. 27
0
static int bcm_kona_sd_reset(struct sdio_dev *dev)
{
	struct sdhci_host *host = dev->host;
	unsigned int val;
#ifdef CONFIG_ARCH_CAPRI
	unsigned int tries = 10000;
#endif
	unsigned long timeout;

	/* Reset host controller by setting 'Software Reset for All' */
	sdhci_writeb(host, SDHCI_RESET_ALL, SDHCI_SOFTWARE_RESET);

	/* Wait for 100 ms max (100ms timeout is taken from sdhci.c) */
	timeout = jiffies + msecs_to_jiffies(100);

	while (sdhci_readb(host, SDHCI_SOFTWARE_RESET) & SDHCI_RESET_ALL) {
		if (time_is_before_jiffies(timeout)) {
			dev_err(dev->dev, "Error: sd host is in reset!!!\n");
			return -EFAULT;
		}
	}

	/* reset the host using the top level reset */
	val = sdhci_readl(host, KONA_SDHOST_CORECTRL);
	val |= KONA_SDHOST_RESET;
	sdhci_writel(host, val, KONA_SDHOST_CORECTRL);
	do {
		val = sdhci_readl(host, KONA_SDHOST_CORECTRL);
#ifdef CONFIG_ARCH_CAPRI
		if (--tries <= 0)
			break;
#endif
	} while (0 == (val & KONA_SDHOST_RESET));

	/* bring the host out of reset */
	val = sdhci_readl(host, KONA_SDHOST_CORECTRL);
	val &= ~KONA_SDHOST_RESET;

	/* Back-to-Back register write needs a delay of 1ms
	 * at bootup (min 10uS)
	 */
	udelay(1000);
	sdhci_writel(host, val, KONA_SDHOST_CORECTRL);

	return 0;
}
Esempio n. 28
0
/* Enable Parallel Transfer Mode */
static void xenon_mmc_enable_parallel_tran(struct sdhci_host *host, u8 slot)
{
	u32 var;

	var = sdhci_readl(host, SDHC_SYS_EXT_OP_CTRL);
	var |= SLOT_MASK(slot);
	sdhci_writel(host, var, SDHC_SYS_EXT_OP_CTRL);
}
Esempio n. 29
0
/* Enable specific slot */
static void xenon_mmc_enable_slot(struct sdhci_host *host, u8 slot)
{
	u32 var;

	var = sdhci_readl(host, SDHC_SYS_OP_CTRL);
	var |= SLOT_MASK(slot) << SLOT_ENABLE_SHIFT;
	sdhci_writel(host, var, SDHC_SYS_OP_CTRL);
}
Esempio n. 30
0
/* Mask command conflict error */
static void xenon_mask_cmd_conflict_err(struct sdhci_host *host)
{
	u32  reg;

	reg = sdhci_readl(host, SDHC_SYS_EXT_OP_CTRL);
	reg |= MASK_CMD_CONFLICT_ERROR;
	sdhci_writel(host, reg, SDHC_SYS_EXT_OP_CTRL);
}