s3cmci_probe

 

static int __devinit s3cmci_probe(struct platform_device *pdev)
{
 struct s3cmci_host *host;
 struct mmc_host *mmc;
 int ret;
 int is2440;
 int i;

 is2440 = platform_get_device_id(pdev)->driver_data;

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

 for (i = S3C2410_GPE(5); i <= S3C2410_GPE(10); i++) {
  ret = gpio_request(i, dev_name(&pdev->dev));
  if (ret) {
   dev_err(&pdev->dev, "failed to get gpio %d\n", i);

   for (i--; i >= S3C2410_GPE(5); i--)
    gpio_free(i);

   goto probe_free_host;
  }
 }

 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->complete_what  = COMPLETION_NONE;
 host->pio_active  = XFER_NONE;

#ifdef CONFIG_MMC_S3C_PIODMA
 host->dodma  = host->pdata->dma;
#endif

 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_gpio;
 }

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

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

 host->base = ioremap(host->mem->start, resource_size(host->mem));
 if (!host->base) {
  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);
 host->irq_state = false;

 if (!host->pdata->no_detect) {
  ret = gpio_request(host->pdata->gpio_detect, "s3cmci detect");
  if (ret) {
   dev_err(&pdev->dev, "failed to get detect gpio\n");
   goto probe_free_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_gpio_cd;
   }
  } else {
   dev_warn(&pdev->dev,
     "host detect has no irq available\n");
   gpio_direction_input(host->pdata->gpio_detect);
  }
 } else
  host->irq_cd = -1;

 if (!host->pdata->no_wprotect) {
  ret = gpio_request(host->pdata->gpio_wprotect, "s3cmci wp");
  if (ret) {
   dev_err(&pdev->dev, "failed to get writeprotect\n");
   goto probe_free_irq_cd;
  }

  gpio_direction_input(host->pdata->gpio_wprotect);
 }

 

 if (s3cmci_host_usedma(host)) {
  host->dma = s3c2410_dma_request(DMACH_SDI, &s3cmci_dma_client,
      host);
  if (host->dma < 0) {
   dev_err(&pdev->dev, "cannot get DMA channel.\n");
   if (!s3cmci_host_canpio()) {
    ret = -EBUSY;
    goto probe_free_gpio_wp;
   } else {
    dev_warn(&pdev->dev, "falling back to PIO.\n");
    host->dodma = 0;
   }
  }
 }

 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_dma;
 }

 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;
#ifdef CONFIG_MMC_S3C_HW_SDIO_IRQ
 mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ;
#else
 mmc->caps = MMC_CAP_4_BIT_DATA;
#endif
 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 = s3cmci_cpufreq_register(host);
 if (ret) {
  dev_err(&pdev->dev, "failed to register cpufreq\n");
  goto free_dmabuf;
 }

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

 s3cmci_debugfs_attach(host);

 platform_set_drvdata(pdev, mmc);
 dev_info(&pdev->dev, "%s - using %s, %s SDIO IRQ\n", mmc_hostname(mmc),
   s3cmci_host_usedma(host) ? "dma" : "pio",
   mmc->caps & MMC_CAP_SDIO_IRQ ? "hw" : "sw");

 return 0;

 free_cpufreq:
 s3cmci_cpufreq_deregister(host);

 free_dmabuf:
 clk_disable(host->clk);

 clk_free:
 clk_put(host->clk);

 probe_free_dma:
 if (s3cmci_host_usedma(host))
  s3c2410_dma_free(host->dma, &s3cmci_dma_client);

 probe_free_gpio_wp:
 if (!host->pdata->no_wprotect)
  gpio_free(host->pdata->gpio_wprotect);

 probe_free_gpio_cd:
 if (!host->pdata->no_detect)
  gpio_free(host->pdata->gpio_detect);

 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, resource_size(host->mem));

 probe_free_gpio:
 for (i = S3C2410_GPE(5); i <= S3C2410_GPE(10); i++)
  gpio_free(i);

 probe_free_host:
 mmc_free_host(mmc);

 probe_out:
 return ret;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值