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 13a3e2cd7fSThierry Reding #include <linux/err.h> 1462ca8034SShashidhar Hiremath #include <linux/interrupt.h> 1562ca8034SShashidhar Hiremath #include <linux/module.h> 1662ca8034SShashidhar Hiremath #include <linux/io.h> 1762ca8034SShashidhar Hiremath #include <linux/irq.h> 1862ca8034SShashidhar Hiremath #include <linux/platform_device.h> 1962ca8034SShashidhar Hiremath #include <linux/slab.h> 2062ca8034SShashidhar Hiremath #include <linux/mmc/host.h> 2162ca8034SShashidhar Hiremath #include <linux/mmc/mmc.h> 2262ca8034SShashidhar Hiremath #include <linux/mmc/dw_mmc.h> 23c91eab4bSThomas Abraham #include <linux/of.h> 24c91eab4bSThomas Abraham 2562ca8034SShashidhar Hiremath #include "dw_mmc.h" 2662ca8034SShashidhar Hiremath 27800d78bfSThomas Abraham int dw_mci_pltfm_register(struct platform_device *pdev, 288e2b36eaSArnd Bergmann const struct dw_mci_drv_data *drv_data) 2962ca8034SShashidhar Hiremath { 3062ca8034SShashidhar Hiremath struct dw_mci *host; 3162ca8034SShashidhar Hiremath struct resource *regs; 3262ca8034SShashidhar Hiremath int ret; 3362ca8034SShashidhar Hiremath 34bb8bdc77SThomas Abraham host = devm_kzalloc(&pdev->dev, sizeof(struct dw_mci), GFP_KERNEL); 3562ca8034SShashidhar Hiremath if (!host) 3662ca8034SShashidhar Hiremath return -ENOMEM; 3762ca8034SShashidhar Hiremath 3862ca8034SShashidhar Hiremath regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); 39bb8bdc77SThomas Abraham if (!regs) 40bb8bdc77SThomas Abraham return -ENXIO; 4162ca8034SShashidhar Hiremath 4262ca8034SShashidhar Hiremath host->irq = platform_get_irq(pdev, 0); 43bb8bdc77SThomas Abraham if (host->irq < 0) 44bb8bdc77SThomas Abraham return host->irq; 4562ca8034SShashidhar Hiremath 46800d78bfSThomas Abraham host->drv_data = drv_data; 474a90920cSThomas Abraham host->dev = &pdev->dev; 4862ca8034SShashidhar Hiremath host->irq_flags = 0; 4962ca8034SShashidhar Hiremath host->pdata = pdev->dev.platform_data; 50a3e2cd7fSThierry Reding host->regs = devm_ioremap_resource(&pdev->dev, regs); 51a3e2cd7fSThierry Reding if (IS_ERR(host->regs)) 52a3e2cd7fSThierry Reding return PTR_ERR(host->regs); 53bb8bdc77SThomas Abraham 54cb27a843SJames Hogan if (drv_data && drv_data->init) { 55cb27a843SJames Hogan ret = drv_data->init(host); 56800d78bfSThomas Abraham if (ret) 57800d78bfSThomas Abraham return ret; 58800d78bfSThomas Abraham } 59800d78bfSThomas Abraham 6062ca8034SShashidhar Hiremath platform_set_drvdata(pdev, host); 6162ca8034SShashidhar Hiremath ret = dw_mci_probe(host); 6262ca8034SShashidhar Hiremath return ret; 6362ca8034SShashidhar Hiremath } 6417403f23SThomas Abraham EXPORT_SYMBOL_GPL(dw_mci_pltfm_register); 6517403f23SThomas Abraham 66c3be1efdSBill Pemberton static int dw_mci_pltfm_probe(struct platform_device *pdev) 6717403f23SThomas Abraham { 68800d78bfSThomas Abraham return dw_mci_pltfm_register(pdev, NULL); 6917403f23SThomas Abraham } 7062ca8034SShashidhar Hiremath 716e0ee714SBill Pemberton static int dw_mci_pltfm_remove(struct platform_device *pdev) 7262ca8034SShashidhar Hiremath { 7362ca8034SShashidhar Hiremath struct dw_mci *host = platform_get_drvdata(pdev); 7462ca8034SShashidhar Hiremath 7562ca8034SShashidhar Hiremath platform_set_drvdata(pdev, NULL); 7662ca8034SShashidhar Hiremath dw_mci_remove(host); 7762ca8034SShashidhar Hiremath return 0; 7862ca8034SShashidhar Hiremath } 7917403f23SThomas Abraham EXPORT_SYMBOL_GPL(dw_mci_pltfm_remove); 8062ca8034SShashidhar Hiremath 8162ca8034SShashidhar Hiremath #ifdef CONFIG_PM_SLEEP 8262ca8034SShashidhar Hiremath /* 8362ca8034SShashidhar Hiremath * TODO: we should probably disable the clock to the card in the suspend path. 8462ca8034SShashidhar Hiremath */ 8562ca8034SShashidhar Hiremath static int dw_mci_pltfm_suspend(struct device *dev) 8662ca8034SShashidhar Hiremath { 8762ca8034SShashidhar Hiremath int ret; 8862ca8034SShashidhar Hiremath struct dw_mci *host = dev_get_drvdata(dev); 8962ca8034SShashidhar Hiremath 9062ca8034SShashidhar Hiremath ret = dw_mci_suspend(host); 9162ca8034SShashidhar Hiremath if (ret) 9262ca8034SShashidhar Hiremath return ret; 9362ca8034SShashidhar Hiremath 9462ca8034SShashidhar Hiremath return 0; 9562ca8034SShashidhar Hiremath } 9662ca8034SShashidhar Hiremath 9762ca8034SShashidhar Hiremath static int dw_mci_pltfm_resume(struct device *dev) 9862ca8034SShashidhar Hiremath { 9962ca8034SShashidhar Hiremath int ret; 10062ca8034SShashidhar Hiremath struct dw_mci *host = dev_get_drvdata(dev); 10162ca8034SShashidhar Hiremath 10262ca8034SShashidhar Hiremath ret = dw_mci_resume(host); 10362ca8034SShashidhar Hiremath if (ret) 10462ca8034SShashidhar Hiremath return ret; 10562ca8034SShashidhar Hiremath 10662ca8034SShashidhar Hiremath return 0; 10762ca8034SShashidhar Hiremath } 10862ca8034SShashidhar Hiremath #else 10962ca8034SShashidhar Hiremath #define dw_mci_pltfm_suspend NULL 11062ca8034SShashidhar Hiremath #define dw_mci_pltfm_resume NULL 11162ca8034SShashidhar Hiremath #endif /* CONFIG_PM_SLEEP */ 11262ca8034SShashidhar Hiremath 11317403f23SThomas Abraham SIMPLE_DEV_PM_OPS(dw_mci_pltfm_pmops, dw_mci_pltfm_suspend, dw_mci_pltfm_resume); 11417403f23SThomas Abraham EXPORT_SYMBOL_GPL(dw_mci_pltfm_pmops); 11562ca8034SShashidhar Hiremath 116c91eab4bSThomas Abraham static const struct of_device_id dw_mci_pltfm_match[] = { 117c91eab4bSThomas Abraham { .compatible = "snps,dw-mshc", }, 118c91eab4bSThomas Abraham {}, 119c91eab4bSThomas Abraham }; 120c91eab4bSThomas Abraham MODULE_DEVICE_TABLE(of, dw_mci_pltfm_match); 121c91eab4bSThomas Abraham 12262ca8034SShashidhar Hiremath static struct platform_driver dw_mci_pltfm_driver = { 12349480cf2SAndy Shevchenko .probe = dw_mci_pltfm_probe, 1244e608e4eSGreg Kroah-Hartman .remove = dw_mci_pltfm_remove, 12562ca8034SShashidhar Hiremath .driver = { 12662ca8034SShashidhar Hiremath .name = "dw_mmc", 127c91eab4bSThomas Abraham .of_match_table = of_match_ptr(dw_mci_pltfm_match), 12862ca8034SShashidhar Hiremath .pm = &dw_mci_pltfm_pmops, 12962ca8034SShashidhar Hiremath }, 13062ca8034SShashidhar Hiremath }; 13162ca8034SShashidhar Hiremath 13249480cf2SAndy Shevchenko module_platform_driver(dw_mci_pltfm_driver); 13362ca8034SShashidhar Hiremath 13462ca8034SShashidhar Hiremath MODULE_DESCRIPTION("DW Multimedia Card Interface driver"); 13562ca8034SShashidhar Hiremath MODULE_AUTHOR("NXP Semiconductor VietNam"); 13662ca8034SShashidhar Hiremath MODULE_AUTHOR("Imagination Technologies Ltd"); 13762ca8034SShashidhar Hiremath MODULE_LICENSE("GPL v2"); 138