1 /* 2 * Synopsys DesignWare Multimedia Card Interface driver 3 * 4 * Copyright (C) 2009 NXP Semiconductors 5 * Copyright (C) 2009, 2010 Imagination Technologies Ltd. 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 */ 12 13 #include <linux/interrupt.h> 14 #include <linux/module.h> 15 #include <linux/io.h> 16 #include <linux/irq.h> 17 #include <linux/platform_device.h> 18 #include <linux/slab.h> 19 #include <linux/mmc/host.h> 20 #include <linux/mmc/mmc.h> 21 #include <linux/mmc/dw_mmc.h> 22 #include "dw_mmc.h" 23 24 static int dw_mci_pltfm_probe(struct platform_device *pdev) 25 { 26 struct dw_mci *host; 27 struct resource *regs; 28 int ret; 29 30 host = kzalloc(sizeof(struct dw_mci), GFP_KERNEL); 31 if (!host) 32 return -ENOMEM; 33 34 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); 35 if (!regs) { 36 ret = -ENXIO; 37 goto err_free; 38 } 39 40 host->irq = platform_get_irq(pdev, 0); 41 if (host->irq < 0) { 42 ret = host->irq; 43 goto err_free; 44 } 45 46 host->dev = pdev->dev; 47 host->irq_flags = 0; 48 host->pdata = pdev->dev.platform_data; 49 ret = -ENOMEM; 50 host->regs = ioremap(regs->start, resource_size(regs)); 51 if (!host->regs) 52 goto err_free; 53 platform_set_drvdata(pdev, host); 54 ret = dw_mci_probe(host); 55 if (ret) 56 goto err_out; 57 return ret; 58 err_out: 59 iounmap(host->regs); 60 err_free: 61 kfree(host); 62 return ret; 63 } 64 65 static int __exit dw_mci_pltfm_remove(struct platform_device *pdev) 66 { 67 struct dw_mci *host = platform_get_drvdata(pdev); 68 69 platform_set_drvdata(pdev, NULL); 70 dw_mci_remove(host); 71 iounmap(host->regs); 72 kfree(host); 73 return 0; 74 } 75 76 #ifdef CONFIG_PM_SLEEP 77 /* 78 * TODO: we should probably disable the clock to the card in the suspend path. 79 */ 80 static int dw_mci_pltfm_suspend(struct device *dev) 81 { 82 int ret; 83 struct dw_mci *host = dev_get_drvdata(dev); 84 85 ret = dw_mci_suspend(host); 86 if (ret) 87 return ret; 88 89 return 0; 90 } 91 92 static int dw_mci_pltfm_resume(struct device *dev) 93 { 94 int ret; 95 struct dw_mci *host = dev_get_drvdata(dev); 96 97 ret = dw_mci_resume(host); 98 if (ret) 99 return ret; 100 101 return 0; 102 } 103 #else 104 #define dw_mci_pltfm_suspend NULL 105 #define dw_mci_pltfm_resume NULL 106 #endif /* CONFIG_PM_SLEEP */ 107 108 static SIMPLE_DEV_PM_OPS(dw_mci_pltfm_pmops, dw_mci_pltfm_suspend, dw_mci_pltfm_resume); 109 110 static struct platform_driver dw_mci_pltfm_driver = { 111 .remove = __exit_p(dw_mci_pltfm_remove), 112 .driver = { 113 .name = "dw_mmc", 114 .pm = &dw_mci_pltfm_pmops, 115 }, 116 }; 117 118 static int __init dw_mci_init(void) 119 { 120 return platform_driver_probe(&dw_mci_pltfm_driver, dw_mci_pltfm_probe); 121 } 122 123 static void __exit dw_mci_exit(void) 124 { 125 platform_driver_unregister(&dw_mci_pltfm_driver); 126 } 127 128 module_init(dw_mci_init); 129 module_exit(dw_mci_exit); 130 131 MODULE_DESCRIPTION("DW Multimedia Card Interface driver"); 132 MODULE_AUTHOR("NXP Semiconductor VietNam"); 133 MODULE_AUTHOR("Imagination Technologies Ltd"); 134 MODULE_LICENSE("GPL v2"); 135