Example #1
0
static int tegra_sdhci_remove(struct platform_device *pdev)
{
	struct tegra_sdhci_host *host = platform_get_drvdata(pdev);
	if (host) {
		struct tegra_sdhci_platform_data *plat;
		plat = pdev->dev.platform_data;
		if (plat && plat->board_probe)
			plat->board_probe(pdev->id, host->sdhci->mmc);

		if (host->cd_gpio != -1)
			gpio_free(host->cd_gpio);

		if (host->irq_cd != -1)
			free_irq(host->irq_cd, host->sdhci);

		if (host->wp_gpio != -1)
			gpio_free(host->wp_gpio);

		if (host->power_gpio != -1)
			gpio_free(host->power_gpio);

		sdhci_remove_host(host->sdhci, 0);
		sdhci_free_host(host->sdhci);
	}
	return 0;
}
Example #2
0
static int __devexit sdhci_s3c_remove(struct platform_device *pdev)
{
	struct sdhci_host *host =  platform_get_drvdata(pdev);
	struct sdhci_s3c *sc = sdhci_priv(host);
	int ptr, dead = 0;
	u32 scratch;

	scratch = readl(host->ioaddr + SDHCI_INT_STATUS);
	if (scratch == (u32)-1)
		dead = 1;

	if(sc->pdata && sc->pdata->cfg_ext_cd)
		free_irq(sc->pdata->ext_cd, sc);

	sdhci_remove_host(host, dead);

	for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) {
		if (sc->clk_bus[ptr]) {
			clk_disable(sc->clk_bus[ptr]);
			clk_put(sc->clk_bus[ptr]);
		}
	}
	clk_disable(sc->clk_io);
	clk_put(sc->clk_io);

	iounmap(host->ioaddr);
	release_resource(sc->ioarea);
	kfree(sc->ioarea);

	sdhci_free_host(host);
	platform_set_drvdata(pdev, NULL);

	return 0;
}
static int __devexit sdhci_pltfm_remove(struct platform_device *pdev)
{
	const struct platform_device_id *platid = platform_get_device_id(pdev);
	const struct of_device_id *dtid = sdhci_get_of_device_id(pdev);
	struct sdhci_pltfm_data *pdata;
	struct sdhci_host *host = platform_get_drvdata(pdev);
	struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	int dead;
	u32 scratch;

	if (platid && platid->driver_data)
		pdata = (void *)platid->driver_data;
	else if (dtid && dtid->data)
		pdata = dtid->data;
	else
		pdata = pdev->dev.platform_data;

	dead = 0;
	scratch = readl(host->ioaddr + SDHCI_INT_STATUS);
	if (scratch == (u32)-1)
		dead = 1;

	sdhci_remove_host(host, dead);
	if (pdata && pdata->exit)
		pdata->exit(host);
	iounmap(host->ioaddr);
	release_mem_region(iomem->start, resource_size(iomem));
	sdhci_free_host(host);
	platform_set_drvdata(pdev, NULL);

	return 0;
}
Example #4
0
static int __devexit sdhci_s3c_remove(struct platform_device *pdev)
{
	struct s3c_sdhci_platdata *pdata = pdev->dev.platform_data;
	struct sdhci_host *host =  platform_get_drvdata(pdev);
	struct sdhci_s3c *sc = sdhci_priv(host);
	int ptr;

	if (pdata->cd_type == S3C_SDHCI_CD_EXTERNAL && pdata->ext_cd_cleanup)
		pdata->ext_cd_cleanup(&sdhci_s3c_notify_change);

	if (sc->ext_cd_irq)
		free_irq(sc->ext_cd_irq, sc);

	if (gpio_is_valid(sc->ext_cd_gpio))
		gpio_free(sc->ext_cd_gpio);

	sdhci_remove_host(host, 1);

	for (ptr = 0; ptr < 3; ptr++) {
		clk_disable(sc->clk_bus[ptr]);
		clk_put(sc->clk_bus[ptr]);
	}
	clk_disable(sc->clk_io);
	clk_put(sc->clk_io);

	iounmap(host->ioaddr);
	release_resource(sc->ioarea);
	kfree(sc->ioarea);

	sdhci_free_host(host);
	platform_set_drvdata(pdev, NULL);

	return 0;
}
static int __devexit sdhci_tegra_remove(struct platform_device *pdev)
{
	struct sdhci_host *host = platform_get_drvdata(pdev);
	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
	struct sdhci_tegra *tegra_host = pltfm_host->priv;
	const struct tegra_sdhci_platform_data *plat = tegra_host->plat;
	int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff);

	sdhci_remove_host(host, dead);

	if (gpio_is_valid(plat->wp_gpio)) {
		tegra_gpio_disable(plat->wp_gpio);
		gpio_free(plat->wp_gpio);
	}

	if (gpio_is_valid(plat->cd_gpio)) {
		free_irq(gpio_to_irq(plat->cd_gpio), host);
		tegra_gpio_disable(plat->cd_gpio);
		gpio_free(plat->cd_gpio);
	}

	if (gpio_is_valid(plat->power_gpio)) {
		tegra_gpio_disable(plat->power_gpio);
		gpio_free(plat->power_gpio);
	}

	clk_disable(pltfm_host->clk);
	clk_put(pltfm_host->clk);

	sdhci_pltfm_free(pdev);

	return 0;
}
static int sdhci_s3c_remove(struct platform_device *pdev)
{
	struct sdhci_host *host =  platform_get_drvdata(pdev);
	struct sdhci_s3c *sc = sdhci_priv(host);
	struct s3c_sdhci_platdata *pdata = sc->pdata;

	if (pdata->cd_type == S3C_SDHCI_CD_EXTERNAL && pdata->ext_cd_cleanup)
		pdata->ext_cd_cleanup(&sdhci_s3c_notify_change);

	if (sc->ext_cd_irq)
		free_irq(sc->ext_cd_irq, sc);

#ifdef CONFIG_PM_RUNTIME
	if (pdata->cd_type != S3C_SDHCI_CD_INTERNAL)
		clk_prepare_enable(sc->clk_io);
#endif
	sdhci_remove_host(host, 1);

	pm_runtime_dont_use_autosuspend(&pdev->dev);
	pm_runtime_disable(&pdev->dev);

#ifndef CONFIG_PM_RUNTIME
	clk_disable_unprepare(sc->clk_bus[sc->cur_clk]);
#endif
	clk_disable_unprepare(sc->clk_io);

	sdhci_free_host(host);
	platform_set_drvdata(pdev, NULL);

	return 0;
}
Example #7
0
static int __devexit sdhci_s3c_remove(struct platform_device *pdev)
{
	struct sdhci_host *host =  platform_get_drvdata(pdev);
	struct sdhci_s3c *sc = sdhci_priv(host);
	int ptr;

	sdhci_remove_host(host, 1);

	for (ptr = 0; ptr < 3; ptr++) {
		if (sc->clk_bus[ptr]) {
		clk_disable(sc->clk_bus[ptr]);
		clk_put(sc->clk_bus[ptr]);
	}
	}
	clk_disable(sc->clk_io);
	clk_put(sc->clk_io);

	iounmap(host->ioaddr);
	release_resource(sc->ioarea);
	kfree(sc->ioarea);

	sdhci_free_host(host);
	platform_set_drvdata(pdev, NULL);

	return 0;
}
Example #8
0
static int __devexit sdhci_remove(struct platform_device *pdev)
{
	struct sdhci_host *host = platform_get_drvdata(pdev);
	struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	struct spear_sdhci *sdhci = dev_get_platdata(&pdev->dev);
	int dead;
	u32 scratch;

	if (sdhci->data) {
		if (sdhci->data->card_int_gpio >= 0) {
			free_irq(gpio_to_irq(sdhci->data->card_int_gpio), pdev);
			gpio_free(sdhci->data->card_int_gpio);
		}

		if (sdhci->data->card_power_gpio >= 0)
			gpio_free(sdhci->data->card_power_gpio);
	}

	platform_set_drvdata(pdev, NULL);
	dead = 0;
	scratch = readl(host->ioaddr + SDHCI_INT_STATUS);
	if (scratch == (u32)-1)
		dead = 1;

	sdhci_remove_host(host, dead);
	iounmap(host->ioaddr);
	sdhci_free_host(host);
	clk_disable(sdhci->clk);
	clk_put(sdhci->clk);
	kfree(sdhci);
	if (iomem)
		release_mem_region(iomem->start, resource_size(iomem));

	return 0;
}
static int __devexit sdhci_pxav3_remove(struct platform_device *pdev)
{
	struct sdhci_host *host = platform_get_drvdata(pdev);
	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
	struct sdhci_pxa *pxa = pltfm_host->priv;
	struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;

	sdhci_remove_host(host, 1);
	if (pdata && pdata->flags & PXA_FLAG_EN_PM_RUNTIME)
		pm_runtime_disable(&pdev->dev);

	if (pdata)
		pm_qos_remove_request(&pdata->qos_idle);

	clk_disable_unprepare(pltfm_host->clk);
	clk_put(pltfm_host->clk);

	if (pdata && pdata->cd_type == PXA_SDHCI_CD_GPIO &&
			gpio_is_valid(pdata->ext_cd_gpio))
		mmc_gpio_free_cd(host->mmc);

	sdhci_pltfm_free(pdev);
	kfree(pxa);

	platform_set_drvdata(pdev, NULL);

	return 0;
}
int sdhci_pltfm_unregister(struct platform_device *pdev)
{
	struct sdhci_host *host = platform_get_drvdata(pdev);
	int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff);

	sdhci_remove_host(host, dead);
	sdhci_pltfm_free(pdev);

	return 0;
}
Example #11
0
static int __devexit sdhci_of_remove(struct of_device *ofdev)
{
	struct sdhci_host *host = dev_get_drvdata(&ofdev->dev);

	sdhci_remove_host(host, 0);
	sdhci_free_host(host);
	irq_dispose_mapping(host->irq);
	iounmap(host->ioaddr);
	return 0;
}
static int sdhci_pxav2_remove(struct platform_device *pdev)
{
	struct sdhci_host *host = platform_get_drvdata(pdev);
	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);

	sdhci_remove_host(host, 1);

	clk_disable_unprepare(pltfm_host->clk);
	clk_put(pltfm_host->clk);
	sdhci_pltfm_free(pdev);

	return 0;
}
static int tegra_sdhci_remove(struct platform_device *pdev)
{
	struct tegra_sdhci_host *host = platform_get_drvdata(pdev);
	if (host) {
		struct tegra_sdhci_platform_data *plat;
		plat = pdev->dev.platform_data;
		if (plat && plat->board_probe)
			plat->board_probe(pdev->id, host->sdhci->mmc);

		sdhci_remove_host(host->sdhci, 0);
		sdhci_free_host(host->sdhci);
	}
	return 0;
}
Example #14
0
static int __exit sdhci_bcm_kona_remove(struct platform_device *pdev)
{
	struct sdhci_host *host = platform_get_drvdata(pdev);
	struct sdhci_pltfm_host *pltfm_priv = sdhci_priv(host);
	struct sdhci_bcm_kona_dev *kona_dev = sdhci_pltfm_priv(pltfm_priv);
	int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff);

	sdhci_remove_host(host, dead);

	clk_disable_unprepare(kona_dev->external_clk);

	sdhci_pltfm_free(pdev);

	return 0;
}
Example #15
0
static int sdhci_msm_remove(struct platform_device *pdev)
{
	struct sdhci_host *host = platform_get_drvdata(pdev);
	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
	struct sdhci_msm_host *msm_host = pltfm_host->priv;
	int dead = (readl_relaxed(host->ioaddr + SDHCI_INT_STATUS) ==
		    0xffffffff);

	sdhci_remove_host(host, dead);
	sdhci_pltfm_free(pdev);
	clk_disable_unprepare(msm_host->clk);
	clk_disable_unprepare(msm_host->pclk);
	if (!IS_ERR(msm_host->bus_clk))
		clk_disable_unprepare(msm_host->bus_clk);
	return 0;
}
Example #16
0
static int sdhci_tegra_remove(struct platform_device *pdev)
{
	struct sdhci_host *host = platform_get_drvdata(pdev);
	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
	struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);

	sdhci_remove_host(host, 0);

	reset_control_assert(tegra_host->rst);
	usleep_range(2000, 4000);
	clk_disable_unprepare(pltfm_host->clk);

	sdhci_pltfm_free(pdev);

	return 0;
}
Example #17
0
static int __exit sdhci_bcm_kona_remove(struct platform_device *pdev)
{
	struct sdhci_host *host = platform_get_drvdata(pdev);
	int dead;
	u32 scratch;

	dead = 0;
	scratch = readl(host->ioaddr + SDHCI_INT_STATUS);
	if (scratch == (u32)-1)
		dead = 1;
	sdhci_remove_host(host, dead);

	sdhci_free_host(host);

	return 0;
}
Example #18
0
static int sdhci_f_sdh30_remove(struct platform_device *pdev)
{
    struct sdhci_host *host = platform_get_drvdata(pdev);
    struct f_sdhost_priv *priv = sdhci_priv(host);

    sdhci_remove_host(host, readl(host->ioaddr + SDHCI_INT_STATUS) ==
                      0xffffffff);

    clk_disable_unprepare(priv->clk_iface);
    clk_disable_unprepare(priv->clk);

    sdhci_free_host(host);
    platform_set_drvdata(pdev, NULL);

    return 0;
}
Example #19
0
static int __devexit sdhci_s3c_remove(struct platform_device *pdev)
{
	struct sdhci_host *host =  platform_get_drvdata(pdev);
	struct sdhci_s3c *sc = sdhci_priv(host);
	struct s3c_sdhci_platdata *pdata = sc->pdata;
	int ptr;

	if (pdata->cd_type == S3C_SDHCI_CD_EXTERNAL && pdata->ext_cd_cleanup)
		pdata->ext_cd_cleanup(&sdhci_s3c_notify_change);

	if (sc->ext_cd_irq)
		free_irq(sc->ext_cd_irq, sc);

	if (gpio_is_valid(sc->ext_cd_gpio))
		gpio_free(sc->ext_cd_gpio);

#ifdef CONFIG_PM_RUNTIME
	if (pdata->cd_type != S3C_SDHCI_CD_INTERNAL)
		clk_prepare_enable(sc->clk_io);
#endif
	sdhci_remove_host(host, 1);

	pm_runtime_dont_use_autosuspend(&pdev->dev);
	pm_runtime_disable(&pdev->dev);

#ifndef CONFIG_PM_RUNTIME
	clk_disable_unprepare(sc->clk_bus[sc->cur_clk]);
#endif
	for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) {
		if (sc->clk_bus[ptr]) {
			clk_put(sc->clk_bus[ptr]);
		}
	}
	clk_disable_unprepare(sc->clk_io);
	clk_put(sc->clk_io);

	if (pdev->dev.of_node) {
		for (ptr = 0; ptr < NUM_GPIOS(sc->pdata->max_width); ptr++)
			gpio_free(sc->gpios[ptr]);
	}

	sdhci_free_host(host);
	platform_set_drvdata(pdev, NULL);

	return 0;
}
static int __devexit sdhci_pxav2_remove(struct platform_device *pdev)
{
	struct sdhci_host *host = platform_get_drvdata(pdev);
	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
	struct sdhci_pxa *pxa = pltfm_host->priv;

	sdhci_remove_host(host, 1);

	clk_disable(pltfm_host->clk);
	clk_put(pltfm_host->clk);
	sdhci_pltfm_free(pdev);
	kfree(pxa);

	platform_set_drvdata(pdev, NULL);

	return 0;
}
Example #21
0
static int sdhci_acpi_remove(struct platform_device *pdev)
{
	struct sdhci_acpi_host *c = platform_get_drvdata(pdev);
	struct device *dev = &pdev->dev;
	int dead;

	if (c->use_runtime_pm) {
		pm_runtime_get_sync(dev);
		pm_runtime_disable(dev);
		pm_runtime_put_noidle(dev);
	}

	dead = (sdhci_readl(c->host, SDHCI_INT_STATUS) == ~0);
	sdhci_remove_host(c->host, dead);
	sdhci_free_host(c->host);

	return 0;
}
static int sdhci_pxav3_remove(struct platform_device *pdev)
{
	struct sdhci_host *host = platform_get_drvdata(pdev);
	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
	struct sdhci_pxa *pxa = pltfm_host->priv;

	pm_runtime_get_sync(&pdev->dev);
	sdhci_remove_host(host, 1);
	pm_runtime_disable(&pdev->dev);

	clk_disable_unprepare(pltfm_host->clk);
	clk_put(pltfm_host->clk);

	sdhci_pltfm_free(pdev);
	kfree(pxa);

	return 0;
}
static int sdhci_remove(struct platform_device *pdev)
{
    struct sdhci_host *host = platform_get_drvdata(pdev);
    struct spear_sdhci *sdhci = dev_get_platdata(&pdev->dev);
    int dead = 0;
    u32 scratch;

    platform_set_drvdata(pdev, NULL);
    scratch = readl(host->ioaddr + SDHCI_INT_STATUS);
    if (scratch == (u32)-1)
        dead = 1;

    sdhci_remove_host(host, dead);
    sdhci_free_host(host);
    clk_disable_unprepare(sdhci->clk);
    clk_put(sdhci->clk);

    return 0;
}
Example #24
0
static int sdhci_tegra_remove(struct platform_device *pdev)
{
	struct sdhci_host *host = platform_get_drvdata(pdev);
	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
	struct sdhci_tegra *tegra_host = pltfm_host->priv;
	int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff);

	sdhci_remove_host(host, dead);

	if (gpio_is_valid(tegra_host->power_gpio))
		gpio_free(tegra_host->power_gpio);

	clk_disable_unprepare(pltfm_host->clk);
	clk_put(pltfm_host->clk);

	sdhci_pltfm_free(pdev);

	return 0;
}
Example #25
0
static int __devexit sdhci_brcm_remove(struct platform_device *pdev)
{
	struct sdhci_host *host = dev_get_drvdata(&pdev->dev);
	struct resource *mres;
	int mres_size;

	if (host) {
		sdhci_remove_host(host, 0);
		HIF_DISABLE_IRQ(SDIO);

		mres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
		mres_size = mres->end - mres->start + 1;
		iounmap(host->ioaddr);
		release_mem_region(mres->start, mres_size);

		sdhci_free_host(host);
	}
	return 0;
}
Example #26
0
static int __devexit sdhci_pltfm_remove(struct platform_device *pdev)
{
    struct sdhci_host *host = platform_get_drvdata(pdev);
    struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    int dead;
    u32 scratch;

    dead = 0;
    scratch = readl(host->ioaddr + SDHCI_INT_STATUS);
    if (scratch == (u32)-1)
        dead = 1;

    sdhci_remove_host(host, dead);
    iounmap(host->ioaddr);
    release_mem_region(iomem->start, resource_size(iomem));
    sdhci_free_host(host);
    platform_set_drvdata(pdev, NULL);

    return 0;
}
Example #27
0
static int sdhci_msm_remove(struct platform_device *pdev)
{
	struct sdhci_host *host = platform_get_drvdata(pdev);
	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
	struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
	int dead = (readl_relaxed(host->ioaddr + SDHCI_INT_STATUS) ==
		    0xffffffff);

	sdhci_remove_host(host, dead);

	pm_runtime_get_sync(&pdev->dev);
	pm_runtime_disable(&pdev->dev);
	pm_runtime_put_noidle(&pdev->dev);

	clk_bulk_disable_unprepare(ARRAY_SIZE(msm_host->bulk_clks),
				   msm_host->bulk_clks);
	if (!IS_ERR(msm_host->bus_clk))
		clk_disable_unprepare(msm_host->bus_clk);
	sdhci_pltfm_free(pdev);
	return 0;
}
Example #28
0
static int __devexit sdhci_pxav3_remove(struct platform_device *pdev)
{
	struct sdhci_host *host = platform_get_drvdata(pdev);
	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
	struct sdhci_pxa *pxa = pltfm_host->priv;
	struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;

	sdhci_remove_host(host, 1);

	clk_disable_unprepare(pltfm_host->clk);
	clk_put(pltfm_host->clk);

	if (gpio_is_valid(pdata->ext_cd_gpio))
		mmc_gpio_free_cd(host->mmc);

	sdhci_pltfm_free(pdev);
	kfree(pxa);

	platform_set_drvdata(pdev, NULL);

	return 0;
}
Example #29
0
static int __devexit sdhci_sprd_remove(struct platform_device *pdev)
{
	struct sdhci_host *host = platform_get_drvdata(pdev);
	struct sprd_host_data *host_data = sdhci_priv(host);

#ifdef CONFIG_PM_RUNTIME
	if (pm_runtime_suspended(&(pdev)->dev))
		pm_runtime_resume(&(pdev)->dev);
#endif
	sdhci_remove_host(host, 1);
	sdhci_free_host(host);

	if (host_data->clk_enable) {
		clk_disable(host->clk);
		host_data->clk_enable = 0;
	}

#ifdef CONFIG_PM_RUNTIME
	pm_runtime_disable(&(pdev)->dev);
	pm_runtime_set_suspended(&(pdev)->dev);
#endif
	return 0;
}
static int __devinit sdhci_probe(struct platform_device *pdev)
{
	struct sdhci_host *host;
	struct resource *iomem;
	struct spear_sdhci *sdhci;
	int ret;

	BUG_ON(pdev == NULL);

	iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!iomem) {
		ret = -ENOMEM;
		dev_dbg(&pdev->dev, "memory resource not defined\n");
		goto err;
	}

	if (!request_mem_region(iomem->start, resource_size(iomem),
				"spear-sdhci")) {
		ret = -EBUSY;
		dev_dbg(&pdev->dev, "cannot request region\n");
		goto err;
	}

	sdhci = kzalloc(sizeof(*sdhci), GFP_KERNEL);
	if (!sdhci) {
		ret = -ENOMEM;
		dev_dbg(&pdev->dev, "cannot allocate memory for sdhci\n");
		goto err_kzalloc;
	}

	/* clk enable */
	sdhci->clk = clk_get(&pdev->dev, NULL);
	if (IS_ERR(sdhci->clk)) {
		ret = PTR_ERR(sdhci->clk);
		dev_dbg(&pdev->dev, "Error getting clock\n");
		goto err_clk_get;
	}

	ret = clk_enable(sdhci->clk);
	if (ret) {
		dev_dbg(&pdev->dev, "Error enabling clock\n");
		goto err_clk_enb;
	}

	/* overwrite platform_data */
	sdhci->data = dev_get_platdata(&pdev->dev);
	pdev->dev.platform_data = sdhci;

	if (pdev->dev.parent)
		host = sdhci_alloc_host(pdev->dev.parent, 0);
	else
		host = sdhci_alloc_host(&pdev->dev, 0);

	if (IS_ERR(host)) {
		ret = PTR_ERR(host);
		dev_dbg(&pdev->dev, "error allocating host\n");
		goto err_alloc_host;
	}

	host->hw_name = "sdhci";
	host->ops = &sdhci_pltfm_ops;
	host->irq = platform_get_irq(pdev, 0);
	host->quirks = SDHCI_QUIRK_BROKEN_ADMA;

	host->ioaddr = ioremap(iomem->start, resource_size(iomem));
	if (!host->ioaddr) {
		ret = -ENOMEM;
		dev_dbg(&pdev->dev, "failed to remap registers\n");
		goto err_ioremap;
	}

	ret = sdhci_add_host(host);
	if (ret) {
		dev_dbg(&pdev->dev, "error adding host\n");
		goto err_add_host;
	}

	platform_set_drvdata(pdev, host);

	/*
	 * It is optional to use GPIOs for sdhci Power control & sdhci card
	 * interrupt detection. If sdhci->data is NULL, then use original sdhci
	 * lines otherwise GPIO lines.
	 * If GPIO is selected for power control, then power should be disabled
	 * after card removal and should be enabled when card insertion
	 * interrupt occurs
	 */
	if (!sdhci->data)
		return 0;

	if (sdhci->data->card_power_gpio >= 0) {
		int val = 0;

		ret = gpio_request(sdhci->data->card_power_gpio, "sdhci");
		if (ret < 0) {
			dev_dbg(&pdev->dev, "gpio request fail: %d\n",
					sdhci->data->card_power_gpio);
			goto err_pgpio_request;
		}

		if (sdhci->data->power_always_enb)
			val = sdhci->data->power_active_high;
		else
			val = !sdhci->data->power_active_high;

		ret = gpio_direction_output(sdhci->data->card_power_gpio, val);
		if (ret) {
			dev_dbg(&pdev->dev, "gpio set direction fail: %d\n",
					sdhci->data->card_power_gpio);
			goto err_pgpio_direction;
		}

		gpio_set_value(sdhci->data->card_power_gpio, 1);
	}

	if (sdhci->data->card_int_gpio >= 0) {
		ret = gpio_request(sdhci->data->card_int_gpio, "sdhci");
		if (ret < 0) {
			dev_dbg(&pdev->dev, "gpio request fail: %d\n",
					sdhci->data->card_int_gpio);
			goto err_igpio_request;
		}

		ret = gpio_direction_input(sdhci->data->card_int_gpio);
		if (ret) {
			dev_dbg(&pdev->dev, "gpio set direction fail: %d\n",
					sdhci->data->card_int_gpio);
			goto err_igpio_direction;
		}
		ret = request_irq(gpio_to_irq(sdhci->data->card_int_gpio),
				sdhci_gpio_irq, IRQF_TRIGGER_LOW,
				mmc_hostname(host->mmc), pdev);
		if (ret) {
			dev_dbg(&pdev->dev, "gpio request irq fail: %d\n",
					sdhci->data->card_int_gpio);
			goto err_igpio_request_irq;
		}

	}

	return 0;

err_igpio_request_irq:
err_igpio_direction:
	if (sdhci->data->card_int_gpio >= 0)
		gpio_free(sdhci->data->card_int_gpio);
err_igpio_request:
err_pgpio_direction:
	if (sdhci->data->card_power_gpio >= 0)
		gpio_free(sdhci->data->card_power_gpio);
err_pgpio_request:
	platform_set_drvdata(pdev, NULL);
	sdhci_remove_host(host, 1);
err_add_host:
	iounmap(host->ioaddr);
err_ioremap:
	sdhci_free_host(host);
err_alloc_host:
	clk_disable(sdhci->clk);
err_clk_enb:
	clk_put(sdhci->clk);
err_clk_get:
	kfree(sdhci);
err_kzalloc:
	release_mem_region(iomem->start, resource_size(iomem));
err:
	dev_err(&pdev->dev, "spear-sdhci probe failed: %d\n", ret);
	return ret;
}