2008-07-15 16:02:21 +01:00
/*
2011-03-23 12:42:44 +01:00
* linux / drivers / mmc / host / tmio_mmc . c
2008-07-15 16:02:21 +01:00
*
2011-03-23 12:42:44 +01:00
* Copyright ( C ) 2007 Ian Molton
* Copyright ( C ) 2004 Ian Molton
2008-07-15 16:02:21 +01:00
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*
* Driver for the MMC / SD / SDIO cell found in :
*
2009-06-04 20:12:37 +02:00
* TC6393XB TC6391XB TC6387XB T7L66XB ASIC3
2008-07-15 16:02:21 +01:00
*/
2010-11-23 17:24:11 +01:00
# include <linux/device.h>
2008-07-15 16:02:21 +01:00
# include <linux/mfd/core.h>
# include <linux/mfd/tmio.h>
2010-11-23 17:24:11 +01:00
# include <linux/mmc/host.h>
# include <linux/module.h>
# include <linux/pagemap.h>
# include <linux/scatterlist.h>
2011-01-05 17:36:14 -05:00
2011-03-23 12:42:44 +01:00
# include "tmio_mmc.h"
2008-07-15 16:02:21 +01:00
# ifdef CONFIG_PM
static int tmio_mmc_suspend ( struct platform_device * dev , pm_message_t state )
{
2011-03-01 12:32:20 -08:00
const struct mfd_cell * cell = mfd_get_cell ( dev ) ;
2008-07-15 16:02:21 +01:00
struct mmc_host * mmc = platform_get_drvdata ( dev ) ;
int ret ;
2010-05-26 14:42:08 -07:00
ret = mmc_suspend_host ( mmc ) ;
2008-07-15 16:02:21 +01:00
/* Tell MFD core it can disable us now.*/
if ( ! ret & & cell - > disable )
cell - > disable ( dev ) ;
return ret ;
}
static int tmio_mmc_resume ( struct platform_device * dev )
{
2011-03-01 12:32:20 -08:00
const struct mfd_cell * cell = mfd_get_cell ( dev ) ;
2008-07-15 16:02:21 +01:00
struct mmc_host * mmc = platform_get_drvdata ( dev ) ;
int ret = 0 ;
/* Tell the MFD core we are ready to be enabled */
2010-01-06 13:51:48 +01:00
if ( cell - > resume ) {
ret = cell - > resume ( dev ) ;
2008-07-15 16:02:21 +01:00
if ( ret )
goto out ;
}
mmc_resume_host ( mmc ) ;
out :
return ret ;
}
# else
# define tmio_mmc_suspend NULL
# define tmio_mmc_resume NULL
# endif
2011-03-23 12:42:44 +01:00
static int __devinit tmio_mmc_probe ( struct platform_device * pdev )
2008-07-15 16:02:21 +01:00
{
2011-03-23 12:42:44 +01:00
const struct mfd_cell * cell = mfd_get_cell ( pdev ) ;
2009-06-04 20:12:31 +02:00
struct tmio_mmc_data * pdata ;
2008-07-15 16:02:21 +01:00
struct tmio_mmc_host * host ;
2009-06-04 20:12:34 +02:00
int ret = - EINVAL ;
2008-07-15 16:02:21 +01:00
2011-03-23 12:42:44 +01:00
if ( pdev - > num_resources ! = 2 )
2008-07-15 16:02:21 +01:00
goto out ;
2011-03-23 12:42:44 +01:00
pdata = mfd_get_data ( pdev ) ;
2009-06-04 20:12:34 +02:00
if ( ! pdata | | ! pdata - > hclk )
2009-06-04 20:12:31 +02:00
goto out ;
2009-06-04 20:12:34 +02:00
2008-07-15 16:02:21 +01:00
/* Tell the MFD core we are ready to be enabled */
if ( cell - > enable ) {
2011-03-23 12:42:44 +01:00
ret = cell - > enable ( pdev ) ;
2008-07-15 16:02:21 +01:00
if ( ret )
2011-03-23 12:42:44 +01:00
goto out ;
2008-07-15 16:02:21 +01:00
}
2011-03-23 12:42:44 +01:00
ret = tmio_mmc_host_probe ( & host , pdev , pdata ) ;
2008-07-15 16:02:21 +01:00
if ( ret )
2010-02-17 16:38:23 +09:00
goto cell_disable ;
2008-07-15 16:02:21 +01:00
2010-05-19 18:34:22 +00:00
pr_info ( " %s at 0x%08lx irq %d \n " , mmc_hostname ( host - > mmc ) ,
( unsigned long ) host - > ctl , host - > irq ) ;
2008-07-15 16:02:21 +01:00
return 0 ;
2010-02-17 16:38:23 +09:00
cell_disable :
if ( cell - > disable )
2011-03-23 12:42:44 +01:00
cell - > disable ( pdev ) ;
2008-07-15 16:02:21 +01:00
out :
return ret ;
}
2011-03-23 12:42:44 +01:00
static int __devexit tmio_mmc_remove ( struct platform_device * pdev )
2008-07-15 16:02:21 +01:00
{
2011-03-23 12:42:44 +01:00
const struct mfd_cell * cell = mfd_get_cell ( pdev ) ;
struct mmc_host * mmc = platform_get_drvdata ( pdev ) ;
2008-07-15 16:02:21 +01:00
2011-03-23 12:42:44 +01:00
platform_set_drvdata ( pdev , NULL ) ;
2008-07-15 16:02:21 +01:00
if ( mmc ) {
2011-03-23 12:42:44 +01:00
tmio_mmc_host_remove ( mmc_priv ( mmc ) ) ;
2010-02-17 16:38:23 +09:00
if ( cell - > disable )
2011-03-23 12:42:44 +01:00
cell - > disable ( pdev ) ;
2008-07-15 16:02:21 +01:00
}
return 0 ;
}
/* ------------------- device registration ----------------------- */
static struct platform_driver tmio_mmc_driver = {
. driver = {
. name = " tmio-mmc " ,
. owner = THIS_MODULE ,
} ,
. probe = tmio_mmc_probe ,
. remove = __devexit_p ( tmio_mmc_remove ) ,
. suspend = tmio_mmc_suspend ,
. resume = tmio_mmc_resume ,
} ;
static int __init tmio_mmc_init ( void )
{
return platform_driver_register ( & tmio_mmc_driver ) ;
}
static void __exit tmio_mmc_exit ( void )
{
platform_driver_unregister ( & tmio_mmc_driver ) ;
}
module_init ( tmio_mmc_init ) ;
module_exit ( tmio_mmc_exit ) ;
MODULE_DESCRIPTION ( " Toshiba TMIO SD/MMC driver " ) ;
MODULE_AUTHOR ( " Ian Molton <spyro@f2s.com> " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;
MODULE_ALIAS ( " platform:tmio-mmc " ) ;