Exemplo n.º 1
0
static int sunximmc_resource_release(struct sunxi_mmc_host *smc_host)
{
    //close clock resource
    clk_disable(smc_host->hclk);
    clk_put(smc_host->hclk);

    clk_disable(smc_host->mclk);
    clk_put(smc_host->mclk);

    //free memory region
    iounmap(smc_host->smc_base);
    release_mem_region(smc_host->smc_base_res->start, RESSIZE(smc_host->smc_base_res));

    gpio_release(smc_host->pio_hdle, 1);
    return 0;
}
Exemplo n.º 2
0
static int s3cmci_remove(struct platform_device *pdev)
{
	struct mmc_host 	*mmc  = platform_get_drvdata(pdev);
	struct s3cmci_host 	*host = mmc_priv(mmc);

	mmc_remove_host(mmc);
	clk_disable(host->clk);
	clk_put(host->clk);
 	free_irq(host->irq_cd, host);
 	free_irq(host->irq, host);
	iounmap(host->base);
	release_mem_region(host->mem->start, RESSIZE(host->mem));
	mmc_free_host(mmc);

	return 0;
}
Exemplo n.º 3
0
static int __devexit s3cmci_remove(struct platform_device *pdev)
{
	struct mmc_host		*mmc  = platform_get_drvdata(pdev);
	struct s3cmci_host	*host = mmc_priv(mmc);

	s3cmci_shutdown(pdev);

	clk_put(host->clk);

	tasklet_disable(&host->pio_tasklet);
	s3c2410_dma_free(S3CMCI_DMA, &s3cmci_dma_client);

	free_irq(host->irq, host);

	iounmap(host->base);
	release_mem_region(host->mem->start, RESSIZE(host->mem));

	mmc_free_host(mmc);
	return 0;
}
Exemplo n.º 4
0
static int s3c_hsmmc_probe (struct platform_device *pdev)
{
	struct mmc_host *mmc;
	struct s3c_hsmmc_host *host;
	struct s3c_hsmmc_cfg *plat_data;
	uint i;
	int ret;

	mmc = mmc_alloc_host(sizeof(struct s3c_hsmmc_host), &pdev->dev);

	if (mmc==NULL) {
		ret = -ENOMEM;
		printk("Failed to get mmc_alloc_host.\n");
		return ret;
	}

	plat_data = s3c_hsmmc_get_platdata(&pdev->dev);

	host = mmc_priv(mmc);

	host->mmc = mmc;

	host->plat_data = plat_data;

	host->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!host->mem) {
		printk("Failed to get io memory region resouce.\n");
		ret = -ENOENT;
		goto probe_free_host;
	}

	host->mem = request_mem_region(host->mem->start,
		RESSIZE(host->mem), pdev->name);
	if (!host->mem) {
		printk("Failed to request io memory region.\n");
		ret = -ENOENT;
		goto probe_free_host;
	}

	host->base = ioremap(host->mem->start, (host->mem->end - host->mem->start)+1);
	if (host->base == NULL) {
		printk(KERN_ERR "Failed to remap register block\n");
		return -ENOMEM;
	}

	host->irq = platform_get_irq(pdev, 0);
	if (host->irq == 0) {
		printk("Failed to get interrupt resouce.\n");
		ret = -EINVAL;
		goto untasklet;
	}

#if defined(CONFIG_CPU_S3C6410)
        /* To detect a card inserted on channel 0,  an external interrupt is used. */
        if ((plat_data->enabled == 1) && (plat_data->hwport == 0)) {
                host->irq_cd = platform_get_irq(pdev, 1);
                if (host->irq_cd == 0) {
                        printk("Failed to get interrupt resouce.\n");
                        ret = -EINVAL;
                        goto untasklet;
                }
               set_irq_type(host->irq_cd, IRQ_TYPE_LEVEL_LOW);
        }
#endif

	host->flags |= S3C_HSMMC_USE_DMA;

	s3c_hsmmc_reset(host, S3C_HSMMC_RESET_ALL);

	clk_enable(clk_get(&pdev->dev, "hsmmc"));

	/* register some clock sources if exist */
	for (i=0; i<NUM_OF_HSMMC_CLKSOURCES; i++) {
		host->clk[i] = clk_get(&pdev->dev, plat_data->clocks[i].name);
		if (IS_ERR(host->clk[i])) {
			ret = PTR_ERR(host->clk[i]);
			host->clk[i] = ERR_PTR(-ENOENT);
		}

		if (clk_enable(host->clk[i])) {
			host->clk[i] = ERR_PTR(-ENOENT);
		}

		if (!IS_ERR(host->clk[i])) {
			DBG("MMC clock source[%d], %s is %ld Hz\n",i, plat_data->clocks[i].name, clk_get_rate(host->clk[i]));
		}
	}

	mmc->ops = &s3c_hsmmc_ops;
	mmc->ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34;
	mmc->f_min = 400 * 1000; /* at least 400kHz */

	/* you must make sure that our hsmmc block can support
	 * up to 52MHz.
	 */
	mmc->f_max = 100 * MHZ;
	mmc->caps = plat_data->host_caps;
	DBG("mmc->caps: %08x\n", mmc->caps);

	spin_lock_init(&host->lock);

	/*
	 * Maximum number of segments. Hardware cannot do scatter lists.
	 * XXX: must modify later.
	 */
#ifdef CONFIG_HSMMC_SCATTERGATHER
	mmc->max_hw_segs = CONFIG_S3C_HSMMC_MAX_HW_SEGS;
	mmc->max_phys_segs = CONFIG_S3C_HSMMC_MAX_HW_SEGS;
#else
	mmc->max_hw_segs = 1;
#endif

	/*
	 * Maximum segment size. Could be one segment with the maximum number
	 * of sectors.
	 */
	mmc->max_blk_size = 512;
	mmc->max_seg_size = 128 * mmc->max_blk_size;

	mmc->max_blk_count = 128;
	mmc->max_req_size = mmc->max_seg_size;


	init_timer(&host->timer);
        host->timer.data = (unsigned long)host;
        host->timer.function = s3c_hsmmc_check_status;
        host->timer.expires = jiffies + HZ;

	/*
	 * Init tasklets.
	 */
	tasklet_init(&host->card_tasklet,
		s3c_hsmmc_tasklet_card, (unsigned long)host);
	tasklet_init(&host->finish_tasklet,
		s3c_hsmmc_tasklet_finish, (unsigned long)host);

	ret = request_irq(host->irq, s3c_hsmmc_irq, 0, DRIVER_NAME, host);
	if (ret)
		goto untasklet;

#if defined(CONFIG_CPU_S3C6410)
        if ((plat_data->enabled == 1) && (plat_data->hwport == 0)) {
                ret = request_irq(host->irq_cd, s3c_hsmmc_irq_cd, 0, DRIVER_NAME, host);
                if (ret)
                        goto untasklet;
        }
#endif

	s3c_hsmmc_ios_init(host);

	mmc_add_host(mmc);

#if defined(CONFIG_PM)
	global_host[plat_data->hwport] = host;
#endif

	printk(KERN_INFO "[s3c_hsmmc_probe]: %s.%d: at 0x%p with irq %d. clk src:",
			pdev->name, pdev->id, host->base, host->irq);

	for (i=0; i<NUM_OF_HSMMC_CLKSOURCES; i++) {
		if (!IS_ERR(host->clk[i]))
			printk(" %s", host->clk[i]->name);
	}
	printk("\n");

	return 0;

untasklet:
	tasklet_kill(&host->card_tasklet);
	tasklet_kill(&host->finish_tasklet);

	for (i=0; i<NUM_OF_HSMMC_CLKSOURCES; i++) {
		if (host->clk[i] != ERR_PTR(-ENOENT)) {
			clk_disable(host->clk[i]);
			clk_put(host->clk[i]);
		}
	}

probe_free_host:
	mmc_free_host(mmc);

	return ret;
}
Exemplo n.º 5
0
static int sunximmc_resource_request(struct sunxi_mmc_host *smc_host)
{
    struct platform_device *pdev = smc_host->pdev;
    u32 smc_no = pdev->id;
    char hclk_name[16] = {0};
    char mclk_name[8] = {0};
    char pio_para[16] = {0};
    u32 pio_hdle = 0;
    s32 ret = 0;

    sprintf(pio_para, "mmc%d_para", smc_no);
    pio_hdle = gpio_request_ex(pio_para, NULL);
    if (!pio_hdle)
    {
        SMC_ERR("sdc %d request pio parameter failed\n", smc_no);
        goto out;
    }
    smc_host->pio_hdle = pio_hdle;

    //iomap
    smc_host->smc_base_res  = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    if (!smc_host->smc_base_res)
    {
    	SMC_ERR("Failed to get io memory region resouce.\n");

    	ret = -ENOENT;
    	goto release_pin;
    }
    /* smc address remap */
    smc_host->smc_base_res = request_mem_region(smc_host->smc_base_res->start, RESSIZE(smc_host->smc_base_res), pdev->name);
    if (!smc_host->smc_base_res)
    {
    	SMC_ERR("Failed to request io memory region.\n");
    	ret = -ENOENT;
    	goto release_pin;
    }
    smc_host->smc_base = ioremap(smc_host->smc_base_res->start, RESSIZE(smc_host->smc_base_res));
    if (!smc_host->smc_base)
    {
    	SMC_ERR("Failed to ioremap() io memory region.\n");
    	ret = -EINVAL;
    	goto free_mem_region;
    }

    //get hclock
    sprintf(hclk_name, "ahb_sdc%d", smc_no);
    smc_host->hclk = clk_get(&pdev->dev, hclk_name);
    if (IS_ERR(smc_host->hclk))
    {
    	ret = PTR_ERR(smc_host->hclk);
    	SMC_ERR("Error to get ahb clk for %s\n", hclk_name);
    	goto iounmap;
    }

    sprintf(mclk_name, "sdc%d", smc_no);
    smc_host->mclk = clk_get(&pdev->dev, mclk_name);
    if (IS_ERR(smc_host->mclk))
    {
    	ret = PTR_ERR(smc_host->mclk);
    	SMC_ERR("Error to get clk for mux_mmc\n");
    	goto free_hclk;
    }

    goto out;

free_hclk:
    clk_put(smc_host->hclk);

iounmap:
    iounmap(smc_host->smc_base);

free_mem_region:
    release_mem_region(smc_host->smc_base_res->start, RESSIZE(smc_host->smc_base_res));

release_pin:
    gpio_release(smc_host->pio_hdle, 1);

out:
    return ret;
}
Exemplo n.º 6
0
static int s3cmci_probe(struct platform_device *pdev, int is2440)
{
	struct mmc_host 	*mmc;
	struct s3cmci_host 	*host;

	int ret;

	mmc = mmc_alloc_host(sizeof(struct s3cmci_host), &pdev->dev);
	if (!mmc) {
		ret = -ENOMEM;
		goto probe_out;
	}

	host = mmc_priv(mmc);
	host->mmc 	= mmc;
	host->pdev	= pdev;

	host->pdata = pdev->dev.platform_data;
	if (!host->pdata) {
		pdev->dev.platform_data = &s3cmci_def_pdata;
		host->pdata = &s3cmci_def_pdata;
	}

	spin_lock_init(&host->complete_lock);
	tasklet_init(&host->pio_tasklet, pio_tasklet, (unsigned long) host);
	if (is2440) {
		host->is2440	= 1;
		host->sdiimsk	= S3C2440_SDIIMSK;
		host->sdidata	= S3C2440_SDIDATA;
		host->clk_div	= 1;
	} else {
		host->is2440	= 0;
		host->sdiimsk	= S3C2410_SDIIMSK;
		host->sdidata	= S3C2410_SDIDATA;
		host->clk_div	= 2;
	}

	host->dodma		= 0;
	host->complete_what 	= COMPLETION_NONE;
	host->pio_active 		= XFER_NONE;

	host->dma		= S3CMCI_DMA;

	host->irq_cd 	= s3c2410_gpio_getirq(host->pdata->gpio_detect);

	s3c2410_gpio_cfgpin(host->pdata->gpio_detect, S3C2410_GPIO_IRQ);

	host->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!host->mem) {
		dev_err(&pdev->dev, "failed to get io memory region resouce.\n");

		ret = -ENOENT;
		goto probe_free_host;
	}

	host->mem = request_mem_region(host->mem->start,
		RESSIZE(host->mem), pdev->name);

	if (!host->mem) {
		dev_err(&pdev->dev, "failed to request io memory region.\n");
		ret = -ENOENT;
		goto probe_free_host;
	}

	host->base = ioremap(host->mem->start, RESSIZE(host->mem));
	if (host->base == 0) {
		dev_err(&pdev->dev, "failed to ioremap() io memory region.\n");
		ret = -EINVAL;
		goto probe_free_mem_region;
	}

	host->irq = platform_get_irq(pdev, 0);
	if (host->irq == 0) {
		dev_err(&pdev->dev, "failed to get interrupt resouce.\n");
		ret = -EINVAL;
		goto probe_iounmap;
	}

	if (request_irq(host->irq, s3cmci_irq, 0, DRIVER_NAME, host)) {
		dev_err(&pdev->dev, "failed to request mci interrupt.\n");
		ret = -ENOENT;
		goto probe_iounmap;
	}

	disable_irq(host->irq);

printk("======>>>> card detect [ %d ]\n", host->pdata->gpio_detect);

	s3c2410_gpio_cfgpin(host->pdata->gpio_detect, S3C2410_GPIO_IRQ);
	set_irq_type(host->irq_cd, IRQT_BOTHEDGE);
//	set_irq_type(host->irq_cd, IRQT_LOW);

	if (request_irq(host->irq_cd, s3cmci_irq_cd, 0, DRIVER_NAME, host)) {
		dev_err(&pdev->dev,
			"failed to request card detect interrupt.\n");

		ret = -ENOENT;
		goto probe_free_irq;
	}

	if (host->pdata->gpio_wprotect)
		s3c2410_gpio_cfgpin(host->pdata->gpio_wprotect,
				    S3C2410_GPIO_INPUT);

	if (s3c2410_dma_request(S3CMCI_DMA, &s3cmci_dma_client, NULL)) {
		dev_err(&pdev->dev, "unable to get DMA channel.\n");
		ret = -EBUSY;
		goto probe_free_irq_cd;
	}

	host->clk = clk_get(&pdev->dev, "sdi");
	if (IS_ERR(host->clk)) {
		dev_err(&pdev->dev, "failed to find clock source.\n");
		ret = PTR_ERR(host->clk);
		host->clk = NULL;
		goto probe_free_host;
	}

	if ((ret = clk_enable(host->clk))) {
		dev_err(&pdev->dev, "failed to enable clock source.\n");
		goto clk_free;
	}

	host->clk_rate = clk_get_rate(host->clk);

	mmc->ops 	= &s3cmci_ops;
	mmc->ocr_avail	= host->pdata->ocr_avail;
	mmc->caps	= MMC_CAP_4_BIT_DATA;
	mmc->f_min 	= host->clk_rate / (host->clk_div * 256);
	mmc->f_max 	= host->clk_rate / host->clk_div;

	mmc->max_blk_count	= 4095;
	mmc->max_blk_size	= 4095;
	mmc->max_req_size	= 4095 * 512;
	mmc->max_seg_size	= mmc->max_req_size;

	mmc->max_phys_segs	= 128;
	mmc->max_hw_segs	= 128;

	dbg(host, dbg_debug, "probe: mode:%s mapped mci_base:%p irq:%u irq_cd:%u dma:%u.\n",
		(host->is2440?"2440":""),
		host->base, host->irq, host->irq_cd, host->dma);

	if ((ret = mmc_add_host(mmc))) {
		dev_err(&pdev->dev, "failed to add mmc host.\n");
		goto free_dmabuf;
	}

	platform_set_drvdata(pdev, mmc);

	dev_info(&pdev->dev,"initialisation done.\n");

	return 0;

 free_dmabuf:
	clk_disable(host->clk);

 clk_free:
	clk_put(host->clk);

 probe_free_irq_cd:
 	free_irq(host->irq_cd, host);

 probe_free_irq:
 	free_irq(host->irq, host);

 probe_iounmap:
	iounmap(host->base);

 probe_free_mem_region:
	release_mem_region(host->mem->start, RESSIZE(host->mem));

 probe_free_host:
	mmc_free_host(mmc);
 probe_out:
	return ret;
}
Exemplo n.º 7
0
static int __devinit s3cmci_probe(struct platform_device *pdev, int is2440)
{
	struct s3cmci_host *host;
	struct mmc_host	*mmc;
	int ret;

	mmc = mmc_alloc_host(sizeof(struct s3cmci_host), &pdev->dev);
	if (!mmc) {
		ret = -ENOMEM;
		goto probe_out;
	}

	host = mmc_priv(mmc);
	host->mmc 	= mmc;
	host->pdev	= pdev;
	host->is2440	= is2440;

	host->pdata = pdev->dev.platform_data;
	if (!host->pdata) {
		pdev->dev.platform_data = &s3cmci_def_pdata;
		host->pdata = &s3cmci_def_pdata;
	}

	spin_lock_init(&host->complete_lock);
	tasklet_init(&host->pio_tasklet, pio_tasklet, (unsigned long) host);

	if (is2440) {
		host->sdiimsk	= S3C2440_SDIIMSK;
		host->sdidata	= S3C2440_SDIDATA;
		host->clk_div	= 1;
	} else {
		host->sdiimsk	= S3C2410_SDIIMSK;
		host->sdidata	= S3C2410_SDIDATA;
		host->clk_div	= 2;
	}

	host->dodma		= 0;
	host->complete_what 	= COMPLETION_NONE;
	host->pio_active 	= XFER_NONE;

	host->dma		= S3CMCI_DMA;

	host->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!host->mem) {
		dev_err(&pdev->dev,
			"failed to get io memory region resouce.\n");

		ret = -ENOENT;
		goto probe_free_host;
	}

	host->mem = request_mem_region(host->mem->start,
				       RESSIZE(host->mem), pdev->name);

	if (!host->mem) {
		dev_err(&pdev->dev, "failed to request io memory region.\n");
		ret = -ENOENT;
		goto probe_free_host;
	}

	host->base = ioremap(host->mem->start, RESSIZE(host->mem));
	if (host->base == 0) {
		dev_err(&pdev->dev, "failed to ioremap() io memory region.\n");
		ret = -EINVAL;
		goto probe_free_mem_region;
	}

	host->irq = platform_get_irq(pdev, 0);
	if (host->irq == 0) {
		dev_err(&pdev->dev, "failed to get interrupt resouce.\n");
		ret = -EINVAL;
		goto probe_iounmap;
	}

	if (request_irq(host->irq, s3cmci_irq, 0, DRIVER_NAME, host)) {
		dev_err(&pdev->dev, "failed to request mci interrupt.\n");
		ret = -ENOENT;
		goto probe_iounmap;
	}

	/* We get spurious interrupts even when we have set the IMSK
	 * register to ignore everything, so use disable_irq() to make
	 * ensure we don't lock the system with un-serviceable requests. */

	disable_irq(host->irq);

	host->irq_cd = s3c2410_gpio_getirq(host->pdata->gpio_detect);

	if (host->irq_cd >= 0) {
		if (request_irq(host->irq_cd, s3cmci_irq_cd,
				IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
				DRIVER_NAME, host)) {
			dev_err(&pdev->dev, "can't get card detect irq.\n");
			ret = -ENOENT;
			goto probe_free_irq;
		}
	} else {
		dev_warn(&pdev->dev, "host detect has no irq available\n");
		s3c2410_gpio_cfgpin(host->pdata->gpio_detect,
				    S3C2410_GPIO_INPUT);
	}

	if (host->pdata->gpio_wprotect)
		s3c2410_gpio_cfgpin(host->pdata->gpio_wprotect,
				    S3C2410_GPIO_INPUT);

	if (s3c2410_dma_request(S3CMCI_DMA, &s3cmci_dma_client, NULL) < 0) {
		dev_err(&pdev->dev, "unable to get DMA channel.\n");
		ret = -EBUSY;
		goto probe_free_irq_cd;
	}

	host->clk = clk_get(&pdev->dev, "sdi");
	if (IS_ERR(host->clk)) {
		dev_err(&pdev->dev, "failed to find clock source.\n");
		ret = PTR_ERR(host->clk);
		host->clk = NULL;
		goto probe_free_host;
	}

	ret = clk_enable(host->clk);
	if (ret) {
		dev_err(&pdev->dev, "failed to enable clock source.\n");
		goto clk_free;
	}

	host->clk_rate = clk_get_rate(host->clk);

	mmc->ops 	= &s3cmci_ops;
	mmc->ocr_avail	= MMC_VDD_32_33 | MMC_VDD_33_34;
	mmc->caps	= MMC_CAP_4_BIT_DATA;
	mmc->f_min 	= host->clk_rate / (host->clk_div * 256);
	mmc->f_max 	= host->clk_rate / host->clk_div;

	if (host->pdata->ocr_avail)
		mmc->ocr_avail = host->pdata->ocr_avail;

	mmc->max_blk_count	= 4095;
	mmc->max_blk_size	= 4095;
	mmc->max_req_size	= 4095 * 512;
	mmc->max_seg_size	= mmc->max_req_size;

	mmc->max_phys_segs	= 128;
	mmc->max_hw_segs	= 128;

	dbg(host, dbg_debug,
	    "probe: mode:%s mapped mci_base:%p irq:%u irq_cd:%u dma:%u.\n",
	    (host->is2440?"2440":""),
	    host->base, host->irq, host->irq_cd, host->dma);

	ret = mmc_add_host(mmc);
	if (ret) {
		dev_err(&pdev->dev, "failed to add mmc host.\n");
		goto free_dmabuf;
	}

	platform_set_drvdata(pdev, mmc);
	dev_info(&pdev->dev, "initialisation done.\n");

	return 0;

 free_dmabuf:
	clk_disable(host->clk);

 clk_free:
	clk_put(host->clk);

 probe_free_irq_cd:
	if (host->irq_cd >= 0)
		free_irq(host->irq_cd, host);

 probe_free_irq:
	free_irq(host->irq, host);

 probe_iounmap:
	iounmap(host->base);

 probe_free_mem_region:
	release_mem_region(host->mem->start, RESSIZE(host->mem));

 probe_free_host:
	mmc_free_host(mmc);
 probe_out:
	return ret;
}
Exemplo n.º 8
0
static int s3c_sdi_probe(struct device *dev)
{
    struct platform_device* pdev = to_platform_device(dev);
    struct mmc_host *mmc;
    struct s3c_sdi_host *host;

    int ret;
#ifdef CONFIG_S3C2443_EVT1
    /* EXTINT0 S3C2443 EVT1 workaround */
    u32 tmp;
#endif

    mmc = mmc_alloc_host(sizeof(struct s3c_sdi_host), &pdev->dev);
    if (!mmc) {
        ret = -ENOMEM;
        goto probe_out;
    }

    host = mmc_priv(mmc);
    spin_lock_init(&host->complete_lock);
    host->complete_what 	= COMPLETION_NONE;
    host->mmc 		= mmc;
#if CONFIG_MACH_TOMTOMGO
    host->irq_cd		= IO_GetInterruptNumber(CD_SD);
    mmc->removable		= 1;
#elif CONFIG_ARCH_S3C2460
    host->irq_cd		= IRQ_EINT3;
#elif defined(CONFIG_MACH_SMDK2443)
    host->irq_cd		= IRQ_EINT1;
#elif defined(CONFIG_ARCH_MDIRAC3)
    host->subchannel	=S3C_DMA3_SDMMC;
//	host->irq_cd		= IRQ_EINT7;
#elif defined CONFIG_ARCH_S3C2412
    host->irq_cd		= IRQ_EINT18;
#endif
    host->dma		= S3C_SDI_DMA;

    host->mem = platform_get_resource(pdev, IORESOURCE_MEM ,0);
    if (!host->mem) {
        printk("failed to get io memory region resource.\n");
        ret = -ENOENT;
        goto probe_free_host;
    }

    host->mem = request_mem_region(host->mem->start,
                                   RESSIZE(host->mem), pdev->name);

    if (!host->mem) {
        printk("failed to request io memory region.\n");
        ret = -ENOENT;
        goto probe_free_host;
    }

    /* if there is an error here, check your SoC dependent code.
     * You must have iotable that contains SDI in it.
     * by scsuh.
     */
    host->base = S3C24XX_VA_SDI;
    host->irq = platform_get_irq(pdev, 0);

    if (host->irq == 0) {
        printk("failed to get interrupt resouce.\n");
        ret = -EINVAL;
        goto release_memory;
    }

    if (request_irq(host->irq, s3c_sdi_irq, 0, DRIVER_NAME, host)) {
        printk("failed to request sdi interrupt.\n");
        ret = -ENOENT;
        goto release_memory;
    }

#if defined(CONFIG_MACH_SMDK2443)
#ifdef CONFIG_S3C2443_EVT1
    /* EXTINT0 S3C2443 EVT1 workaround */
    tmp = __raw_readl(S3C_EXTINT0);
    s3c_swap_4bit(tmp);
    __raw_writel(tmp | (1<<7), S3C_EXTINT0);
#endif
    s3c_gpio_cfgpin(S3C_GPF1, S3C_GPF1_EINT1);
#elif defined(CONFIG_ARCH_S3C2460)
    s3c_gpio_cfgpin(S3C_GPJ3, S3C_GPJ3_EXT_INT3);
#elif defined CONFIG_ARCH_S3C2412
    s3c_gpio_cfgpin(S3C_GPG10, S3C_GPG10_EINT18);
#elif defined CONFIG_ARCH_MDIRAC3
    ;
#endif

#ifdef CONFIG_ARCH_MDIRAC3
    if (s3c_dma_request(host->dma,host->subchannel, &s3c_sdi_dma_client,NULL)) {
        printk("unable to get DMA channel.\n" );
        ret = -EBUSY;
        goto probe_free_irq_cd;
    }
#else
    INIT_WORK( &host->irq_cd_wq, s3c24xx_irq_cd_handler, mmc );
    set_irq_type(host->irq_cd, IRQT_BOTHEDGE);

    if (host->irq_cd > 0) {
        if (request_irq(host->irq_cd, s3c_sdi_irq_cd, SA_INTERRUPT, DRIVER_NAME, host)) {
            printk("failed to request card detect interrupt.\n" );
            ret = -ENOENT;
            goto probe_free_irq;
        }
    }
    if (s3c_dma_request(S3C_SDI_DMA, &s3c_sdi_dma_client, NULL)) {
        printk("unable to get DMA channel.\n" );
        ret = -EBUSY;
        goto probe_free_irq_cd;
    }

#endif
    host->clk = clk_get(&pdev->dev, "sdi");
    if (IS_ERR(host->clk)) {
        printk("failed to find clock source.\n");
        ret = PTR_ERR(host->clk);
        host->clk = NULL;
        goto probe_free_host;
    }

    if ((ret = clk_enable(host->clk))) {
        printk("failed to enable clock source.\n");
        goto clk_free;
    }

    mmc->ops = &s3c_sdi_ops;
    mmc->ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34;
    mmc->f_min = clk_get_rate(host->clk) / 512;
    /* you must make sure that our sdmmc block can support
     * up to 25MHz. by scsuh
     */
    mmc->f_max = 25 * MHZ;
    mmc->caps = MMC_CAP_4_BIT_DATA;

    /*
     * Since we only have a 16-bit data length register, we must
     * ensure that we don't exceed 2^16-1 bytes in a single request.
     */
    mmc->max_req_size = 65535;

    /*
     * Set the maximum segment size.  Since we aren't doing DMA
     * (yet) we are only limited by the data length register.
     */

    mmc->max_seg_size = mmc->max_req_size;

    /*
     * Both block size and block count use 12 bit registers.
     */
    mmc->max_blk_size = 4095;
    mmc->max_blk_count = 4095;

    printk(KERN_INFO PFX "probe: mapped sdi_base=%p irq=%u irq_cd=%u dma=%u.\n",
           host->base, host->irq, host->irq_cd, host->dma);
    platform_set_drvdata(pdev, mmc);

    init_timer(&host->timer);
    host->timer.data = (unsigned long)host;
    host->timer.function = s3c_sdi_check_status;
    host->timer.expires = jiffies + HZ;
    host->ena_2410_workaround=(IO_GetCpuType( ) == GOCPU_S3C2410);

    if ((ret = mmc_add_host(mmc))) {
        printk(KERN_INFO PFX "failed to add mmc host.\n");
        goto free_dmabuf;
    }

    /* Do CPUFREQ registration. */
#if defined CONFIG_CPU_FREQ && defined CONFIG_S3C24XX_DFS_CPUFREQ
    host->freq_transition.notifier_call = s3c24xxsdi_freq_transition;
    host->freq_transition.priority = CPUFREQ_ORDER_S3C24XX_SDCARD_PRIO;
    host->freq_policy.notifier_call = s3c24xxsdi_freq_policy;
    cpufreq_register_notifier(&host->freq_transition, CPUFREQ_TRANSITION_NOTIFIER);
    cpufreq_register_notifier(&host->freq_policy, CPUFREQ_POLICY_NOTIFIER);
#endif

    printk(KERN_INFO PFX "initialization done.\n");
    return 0;

free_dmabuf:
    clk_disable(host->clk);

clk_free:
    clk_put(host->clk);

probe_free_irq_cd:
#ifndef CONFIG_ARCH_MDIRAC3
    free_irq(host->irq_cd, host);
#endif
probe_free_irq:
    free_irq(host->irq, host);

release_memory:
    release_mem_region(host->mem->start, RESSIZE(host->mem));

probe_free_host:
    mmc_free_host(mmc);

probe_out:
    return ret;
}