162ca8034SShashidhar Hiremath /* 262ca8034SShashidhar Hiremath * Synopsys DesignWare Multimedia Card Interface driver 362ca8034SShashidhar Hiremath * 462ca8034SShashidhar Hiremath * Copyright (C) 2009 NXP Semiconductors 562ca8034SShashidhar Hiremath * Copyright (C) 2009, 2010 Imagination Technologies Ltd. 662ca8034SShashidhar Hiremath * 762ca8034SShashidhar Hiremath * This program is free software; you can redistribute it and/or modify 862ca8034SShashidhar Hiremath * it under the terms of the GNU General Public License as published by 962ca8034SShashidhar Hiremath * the Free Software Foundation; either version 2 of the License, or 1062ca8034SShashidhar Hiremath * (at your option) any later version. 1162ca8034SShashidhar Hiremath */ 1262ca8034SShashidhar Hiremath 1362ca8034SShashidhar Hiremath #include <linux/interrupt.h> 1462ca8034SShashidhar Hiremath #include <linux/module.h> 1562ca8034SShashidhar Hiremath #include <linux/io.h> 1662ca8034SShashidhar Hiremath #include <linux/irq.h> 1762ca8034SShashidhar Hiremath #include <linux/platform_device.h> 1862ca8034SShashidhar Hiremath #include <linux/slab.h> 1962ca8034SShashidhar Hiremath #include <linux/mmc/host.h> 2062ca8034SShashidhar Hiremath #include <linux/mmc/mmc.h> 2162ca8034SShashidhar Hiremath #include <linux/mmc/dw_mmc.h> 2262ca8034SShashidhar Hiremath #include "dw_mmc.h" 2362ca8034SShashidhar Hiremath 2436c179a9SJaehoon Chung static int __devinit dw_mci_pltfm_probe(struct platform_device *pdev) 2562ca8034SShashidhar Hiremath { 2662ca8034SShashidhar Hiremath struct dw_mci *host; 2762ca8034SShashidhar Hiremath struct resource *regs; 2862ca8034SShashidhar Hiremath int ret; 2962ca8034SShashidhar Hiremath 3062ca8034SShashidhar Hiremath host = kzalloc(sizeof(struct dw_mci), GFP_KERNEL); 3162ca8034SShashidhar Hiremath if (!host) 3262ca8034SShashidhar Hiremath return -ENOMEM; 3362ca8034SShashidhar Hiremath 3462ca8034SShashidhar Hiremath regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); 3562ca8034SShashidhar Hiremath if (!regs) { 3662ca8034SShashidhar Hiremath ret = -ENXIO; 3762ca8034SShashidhar Hiremath goto err_free; 3862ca8034SShashidhar Hiremath } 3962ca8034SShashidhar Hiremath 4062ca8034SShashidhar Hiremath host->irq = platform_get_irq(pdev, 0); 4162ca8034SShashidhar Hiremath if (host->irq < 0) { 4262ca8034SShashidhar Hiremath ret = host->irq; 4362ca8034SShashidhar Hiremath goto err_free; 4462ca8034SShashidhar Hiremath } 4562ca8034SShashidhar Hiremath 464a90920cSThomas Abraham host->dev = &pdev->dev; 4762ca8034SShashidhar Hiremath host->irq_flags = 0; 4862ca8034SShashidhar Hiremath host->pdata = pdev->dev.platform_data; 4962ca8034SShashidhar Hiremath ret = -ENOMEM; 5062ca8034SShashidhar Hiremath host->regs = ioremap(regs->start, resource_size(regs)); 5162ca8034SShashidhar Hiremath if (!host->regs) 5262ca8034SShashidhar Hiremath goto err_free; 5362ca8034SShashidhar Hiremath platform_set_drvdata(pdev, host); 5462ca8034SShashidhar Hiremath ret = dw_mci_probe(host); 5562ca8034SShashidhar Hiremath if (ret) 5662ca8034SShashidhar Hiremath goto err_out; 5762ca8034SShashidhar Hiremath return ret; 5862ca8034SShashidhar Hiremath err_out: 5962ca8034SShashidhar Hiremath iounmap(host->regs); 6062ca8034SShashidhar Hiremath err_free: 6162ca8034SShashidhar Hiremath kfree(host); 6262ca8034SShashidhar Hiremath return ret; 6362ca8034SShashidhar Hiremath } 6462ca8034SShashidhar Hiremath 6536c179a9SJaehoon Chung static int __devexit dw_mci_pltfm_remove(struct platform_device *pdev) 6662ca8034SShashidhar Hiremath { 6762ca8034SShashidhar Hiremath struct dw_mci *host = platform_get_drvdata(pdev); 6862ca8034SShashidhar Hiremath 6962ca8034SShashidhar Hiremath platform_set_drvdata(pdev, NULL); 7062ca8034SShashidhar Hiremath dw_mci_remove(host); 7162ca8034SShashidhar Hiremath iounmap(host->regs); 7262ca8034SShashidhar Hiremath kfree(host); 7362ca8034SShashidhar Hiremath return 0; 7462ca8034SShashidhar Hiremath } 7562ca8034SShashidhar Hiremath 7662ca8034SShashidhar Hiremath #ifdef CONFIG_PM_SLEEP 7762ca8034SShashidhar Hiremath /* 7862ca8034SShashidhar Hiremath * TODO: we should probably disable the clock to the card in the suspend path. 7962ca8034SShashidhar Hiremath */ 8062ca8034SShashidhar Hiremath static int dw_mci_pltfm_suspend(struct device *dev) 8162ca8034SShashidhar Hiremath { 8262ca8034SShashidhar Hiremath int ret; 8362ca8034SShashidhar Hiremath struct dw_mci *host = dev_get_drvdata(dev); 8462ca8034SShashidhar Hiremath 8562ca8034SShashidhar Hiremath ret = dw_mci_suspend(host); 8662ca8034SShashidhar Hiremath if (ret) 8762ca8034SShashidhar Hiremath return ret; 8862ca8034SShashidhar Hiremath 8962ca8034SShashidhar Hiremath return 0; 9062ca8034SShashidhar Hiremath } 9162ca8034SShashidhar Hiremath 9262ca8034SShashidhar Hiremath static int dw_mci_pltfm_resume(struct device *dev) 9362ca8034SShashidhar Hiremath { 9462ca8034SShashidhar Hiremath int ret; 9562ca8034SShashidhar Hiremath struct dw_mci *host = dev_get_drvdata(dev); 9662ca8034SShashidhar Hiremath 9762ca8034SShashidhar Hiremath ret = dw_mci_resume(host); 9862ca8034SShashidhar Hiremath if (ret) 9962ca8034SShashidhar Hiremath return ret; 10062ca8034SShashidhar Hiremath 10162ca8034SShashidhar Hiremath return 0; 10262ca8034SShashidhar Hiremath } 10362ca8034SShashidhar Hiremath #else 10462ca8034SShashidhar Hiremath #define dw_mci_pltfm_suspend NULL 10562ca8034SShashidhar Hiremath #define dw_mci_pltfm_resume NULL 10662ca8034SShashidhar Hiremath #endif /* CONFIG_PM_SLEEP */ 10762ca8034SShashidhar Hiremath 10862ca8034SShashidhar Hiremath static SIMPLE_DEV_PM_OPS(dw_mci_pltfm_pmops, dw_mci_pltfm_suspend, dw_mci_pltfm_resume); 10962ca8034SShashidhar Hiremath 11062ca8034SShashidhar Hiremath static struct platform_driver dw_mci_pltfm_driver = { 11162ca8034SShashidhar Hiremath .remove = __exit_p(dw_mci_pltfm_remove), 11262ca8034SShashidhar Hiremath .driver = { 11362ca8034SShashidhar Hiremath .name = "dw_mmc", 11462ca8034SShashidhar Hiremath .pm = &dw_mci_pltfm_pmops, 11562ca8034SShashidhar Hiremath }, 11662ca8034SShashidhar Hiremath }; 11762ca8034SShashidhar Hiremath 11862ca8034SShashidhar Hiremath static int __init dw_mci_init(void) 11962ca8034SShashidhar Hiremath { 12062ca8034SShashidhar Hiremath return platform_driver_probe(&dw_mci_pltfm_driver, dw_mci_pltfm_probe); 12162ca8034SShashidhar Hiremath } 12262ca8034SShashidhar Hiremath 12362ca8034SShashidhar Hiremath static void __exit dw_mci_exit(void) 12462ca8034SShashidhar Hiremath { 12562ca8034SShashidhar Hiremath platform_driver_unregister(&dw_mci_pltfm_driver); 12662ca8034SShashidhar Hiremath } 12762ca8034SShashidhar Hiremath 12862ca8034SShashidhar Hiremath module_init(dw_mci_init); 12962ca8034SShashidhar Hiremath module_exit(dw_mci_exit); 13062ca8034SShashidhar Hiremath 13162ca8034SShashidhar Hiremath MODULE_DESCRIPTION("DW Multimedia Card Interface driver"); 13262ca8034SShashidhar Hiremath MODULE_AUTHOR("NXP Semiconductor VietNam"); 13362ca8034SShashidhar Hiremath MODULE_AUTHOR("Imagination Technologies Ltd"); 13462ca8034SShashidhar Hiremath MODULE_LICENSE("GPL v2"); 135