2012-01-13 14:34:57 +04:00
/*
* Synopsys DesignWare Multimedia Card Interface driver
*
* Copyright ( C ) 2009 NXP Semiconductors
* Copyright ( C ) 2009 , 2010 Imagination Technologies Ltd .
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*/
2013-01-21 14:09:11 +04:00
# include <linux/err.h>
2012-01-13 14:34:57 +04:00
# include <linux/interrupt.h>
# include <linux/module.h>
# include <linux/io.h>
# include <linux/irq.h>
# include <linux/platform_device.h>
# include <linux/slab.h>
# include <linux/mmc/host.h>
# include <linux/mmc/mmc.h>
# include <linux/mmc/dw_mmc.h>
2012-09-17 22:16:40 +04:00
# include <linux/of.h>
2014-07-31 10:01:38 +04:00
# include <linux/clk.h>
2012-09-17 22:16:40 +04:00
2012-01-13 14:34:57 +04:00
# include "dw_mmc.h"
2013-08-06 05:54:07 +04:00
# include "dw_mmc-pltfm.h"
2012-01-13 14:34:57 +04:00
2014-02-18 06:31:01 +04:00
static void dw_mci_pltfm_prepare_command ( struct dw_mci * host , u32 * cmdr )
2013-06-27 19:55:35 +04:00
{
* cmdr | = SDMMC_CMD_USE_HOLD_REG ;
}
2014-02-18 06:31:01 +04:00
static const struct dw_mci_drv_data socfpga_drv_data = {
. prepare_command = dw_mci_pltfm_prepare_command ,
2013-06-27 19:55:35 +04:00
} ;
2012-09-17 22:16:42 +04:00
int dw_mci_pltfm_register ( struct platform_device * pdev ,
2013-06-05 13:24:10 +04:00
const struct dw_mci_drv_data * drv_data )
2012-01-13 14:34:57 +04:00
{
struct dw_mci * host ;
struct resource * regs ;
2012-09-17 22:16:36 +04:00
host = devm_kzalloc ( & pdev - > dev , sizeof ( struct dw_mci ) , GFP_KERNEL ) ;
2012-01-13 14:34:57 +04:00
if ( ! host )
return - ENOMEM ;
host - > irq = platform_get_irq ( pdev , 0 ) ;
2012-09-17 22:16:36 +04:00
if ( host - > irq < 0 )
return host - > irq ;
2012-01-13 14:34:57 +04:00
2012-09-17 22:16:42 +04:00
host - > drv_data = drv_data ;
2012-09-17 22:16:35 +04:00
host - > dev = & pdev - > dev ;
2012-01-13 14:34:57 +04:00
host - > irq_flags = 0 ;
host - > pdata = pdev - > dev . platform_data ;
2013-06-05 13:24:10 +04:00
regs = platform_get_resource ( pdev , IORESOURCE_MEM , 0 ) ;
2013-01-21 14:09:11 +04:00
host - > regs = devm_ioremap_resource ( & pdev - > dev , regs ) ;
if ( IS_ERR ( host - > regs ) )
return PTR_ERR ( host - > regs ) ;
2012-09-17 22:16:36 +04:00
2012-01-13 14:34:57 +04:00
platform_set_drvdata ( pdev , host ) ;
2013-06-05 13:24:11 +04:00
return dw_mci_probe ( host ) ;
2012-01-13 14:34:57 +04:00
}
2012-09-17 22:16:41 +04:00
EXPORT_SYMBOL_GPL ( dw_mci_pltfm_register ) ;
2012-01-13 14:34:57 +04:00
# ifdef CONFIG_PM_SLEEP
/*
* TODO : we should probably disable the clock to the card in the suspend path .
*/
static int dw_mci_pltfm_suspend ( struct device * dev )
{
struct dw_mci * host = dev_get_drvdata ( dev ) ;
2013-06-05 13:24:11 +04:00
return dw_mci_suspend ( host ) ;
2012-01-13 14:34:57 +04:00
}
static int dw_mci_pltfm_resume ( struct device * dev )
{
struct dw_mci * host = dev_get_drvdata ( dev ) ;
2013-06-05 13:24:11 +04:00
return dw_mci_resume ( host ) ;
2012-01-13 14:34:57 +04:00
}
# endif /* CONFIG_PM_SLEEP */
2012-09-17 22:16:41 +04:00
SIMPLE_DEV_PM_OPS ( dw_mci_pltfm_pmops , dw_mci_pltfm_suspend , dw_mci_pltfm_resume ) ;
EXPORT_SYMBOL_GPL ( dw_mci_pltfm_pmops ) ;
2012-01-13 14:34:57 +04:00
2012-09-17 22:16:40 +04:00
static const struct of_device_id dw_mci_pltfm_match [ ] = {
{ . compatible = " snps,dw-mshc " , } ,
2014-02-18 06:31:01 +04:00
{ . compatible = " altr,socfpga-dw-mshc " ,
. data = & socfpga_drv_data } ,
2012-09-17 22:16:40 +04:00
{ } ,
} ;
MODULE_DEVICE_TABLE ( of , dw_mci_pltfm_match ) ;
2013-06-13 12:57:01 +04:00
static int dw_mci_pltfm_probe ( struct platform_device * pdev )
{
2013-06-27 19:55:35 +04:00
const struct dw_mci_drv_data * drv_data = NULL ;
const struct of_device_id * match ;
if ( pdev - > dev . of_node ) {
match = of_match_node ( dw_mci_pltfm_match , pdev - > dev . of_node ) ;
drv_data = match - > data ;
}
return dw_mci_pltfm_register ( pdev , drv_data ) ;
2013-06-13 12:57:01 +04:00
}
int dw_mci_pltfm_remove ( struct platform_device * pdev )
{
struct dw_mci * host = platform_get_drvdata ( pdev ) ;
dw_mci_remove ( host ) ;
return 0 ;
}
EXPORT_SYMBOL_GPL ( dw_mci_pltfm_remove ) ;
2012-01-13 14:34:57 +04:00
static struct platform_driver dw_mci_pltfm_driver = {
2012-10-03 17:26:37 +04:00
. probe = dw_mci_pltfm_probe ,
2012-12-22 03:05:47 +04:00
. remove = dw_mci_pltfm_remove ,
2012-01-13 14:34:57 +04:00
. driver = {
. name = " dw_mmc " ,
2014-02-25 13:48:23 +04:00
. of_match_table = dw_mci_pltfm_match ,
2012-01-13 14:34:57 +04:00
. pm = & dw_mci_pltfm_pmops ,
} ,
} ;
2012-10-03 17:26:37 +04:00
module_platform_driver ( dw_mci_pltfm_driver ) ;
2012-01-13 14:34:57 +04:00
MODULE_DESCRIPTION ( " DW Multimedia Card Interface driver " ) ;
MODULE_AUTHOR ( " NXP Semiconductor VietNam " ) ;
MODULE_AUTHOR ( " Imagination Technologies Ltd " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;