in host/au1xmmc.c [932:1114]
static int au1xmmc_probe(struct platform_device *pdev)
{
struct mmc_host *mmc;
struct au1xmmc_host *host;
struct resource *r;
int ret, iflag;
mmc = mmc_alloc_host(sizeof(struct au1xmmc_host), &pdev->dev);
if (!mmc) {
dev_err(&pdev->dev, "no memory for mmc_host\n");
ret = -ENOMEM;
goto out0;
}
host = mmc_priv(mmc);
host->mmc = mmc;
host->platdata = pdev->dev.platform_data;
host->pdev = pdev;
ret = -ENODEV;
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!r) {
dev_err(&pdev->dev, "no mmio defined\n");
goto out1;
}
host->ioarea = request_mem_region(r->start, resource_size(r),
pdev->name);
if (!host->ioarea) {
dev_err(&pdev->dev, "mmio already in use\n");
goto out1;
}
host->iobase = ioremap(r->start, 0x3c);
if (!host->iobase) {
dev_err(&pdev->dev, "cannot remap mmio\n");
goto out2;
}
host->irq = platform_get_irq(pdev, 0);
if (host->irq < 0) {
ret = host->irq;
goto out3;
}
mmc->ops = &au1xmmc_ops;
mmc->f_min = 450000;
mmc->f_max = 24000000;
mmc->max_blk_size = 2048;
mmc->max_blk_count = 512;
mmc->ocr_avail = AU1XMMC_OCR;
mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ;
mmc->max_segs = AU1XMMC_DESCRIPTOR_COUNT;
iflag = IRQF_SHARED; /* Au1100/Au1200: one int for both ctrls */
switch (alchemy_get_cputype()) {
case ALCHEMY_CPU_AU1100:
mmc->max_seg_size = AU1100_MMC_DESCRIPTOR_SIZE;
break;
case ALCHEMY_CPU_AU1200:
mmc->max_seg_size = AU1200_MMC_DESCRIPTOR_SIZE;
break;
case ALCHEMY_CPU_AU1300:
iflag = 0; /* nothing is shared */
mmc->max_seg_size = AU1200_MMC_DESCRIPTOR_SIZE;
mmc->f_max = 52000000;
if (host->ioarea->start == AU1100_SD0_PHYS_ADDR)
mmc->caps |= MMC_CAP_8_BIT_DATA;
break;
}
ret = request_irq(host->irq, au1xmmc_irq, iflag, DRIVER_NAME, host);
if (ret) {
dev_err(&pdev->dev, "cannot grab IRQ\n");
goto out3;
}
host->clk = clk_get(&pdev->dev, ALCHEMY_PERIPH_CLK);
if (IS_ERR(host->clk)) {
dev_err(&pdev->dev, "cannot find clock\n");
ret = PTR_ERR(host->clk);
goto out_irq;
}
ret = clk_prepare_enable(host->clk);
if (ret) {
dev_err(&pdev->dev, "cannot enable clock\n");
goto out_clk;
}
host->status = HOST_S_IDLE;
/* board-specific carddetect setup, if any */
if (host->platdata && host->platdata->cd_setup) {
ret = host->platdata->cd_setup(mmc, 1);
if (ret) {
dev_warn(&pdev->dev, "board CD setup failed\n");
mmc->caps |= MMC_CAP_NEEDS_POLL;
}
} else
mmc->caps |= MMC_CAP_NEEDS_POLL;
/* platform may not be able to use all advertised caps */
if (host->platdata)
mmc->caps &= ~(host->platdata->mask_host_caps);
tasklet_setup(&host->data_task, au1xmmc_tasklet_data);
tasklet_setup(&host->finish_task, au1xmmc_tasklet_finish);
if (has_dbdma()) {
ret = au1xmmc_dbdma_init(host);
if (ret)
pr_info(DRIVER_NAME ": DBDMA init failed; using PIO\n");
}
#ifdef CONFIG_LEDS_CLASS
if (host->platdata && host->platdata->led) {
struct led_classdev *led = host->platdata->led;
led->name = mmc_hostname(mmc);
led->brightness = LED_OFF;
led->default_trigger = mmc_hostname(mmc);
ret = led_classdev_register(mmc_dev(mmc), led);
if (ret)
goto out5;
}
#endif
au1xmmc_reset_controller(host);
ret = mmc_add_host(mmc);
if (ret) {
dev_err(&pdev->dev, "cannot add mmc host\n");
goto out6;
}
platform_set_drvdata(pdev, host);
pr_info(DRIVER_NAME ": MMC Controller %d set up at %p"
" (mode=%s)\n", pdev->id, host->iobase,
host->flags & HOST_F_DMA ? "dma" : "pio");
return 0; /* all ok */
out6:
#ifdef CONFIG_LEDS_CLASS
if (host->platdata && host->platdata->led)
led_classdev_unregister(host->platdata->led);
out5:
#endif
__raw_writel(0, HOST_ENABLE(host));
__raw_writel(0, HOST_CONFIG(host));
__raw_writel(0, HOST_CONFIG2(host));
wmb(); /* drain writebuffer */
if (host->flags & HOST_F_DBDMA)
au1xmmc_dbdma_shutdown(host);
tasklet_kill(&host->data_task);
tasklet_kill(&host->finish_task);
if (host->platdata && host->platdata->cd_setup &&
!(mmc->caps & MMC_CAP_NEEDS_POLL))
host->platdata->cd_setup(mmc, 0);
out_clk:
clk_disable_unprepare(host->clk);
clk_put(host->clk);
out_irq:
free_irq(host->irq, host);
out3:
iounmap((void *)host->iobase);
out2:
release_resource(host->ioarea);
kfree(host->ioarea);
out1:
mmc_free_host(mmc);
out0:
return ret;
}