2010-11-08 00:57:12 +03:00
/*
* sdhci - dove . c Support for SDHCI on Marvell ' s Dove SoC
*
* Author : Saeed Bishara < saeed @ marvell . com >
* Mike Rapoport < mike @ compulab . co . il >
* Based on sdhci - cns3xxx . c
*
* 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 .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
2012-10-30 01:43:07 +04:00
# include <linux/err.h>
2010-11-08 00:57:12 +03:00
# include <linux/io.h>
2012-07-05 14:14:01 +04:00
# include <linux/clk.h>
# include <linux/err.h>
2012-04-04 20:27:09 +04:00
# include <linux/module.h>
2010-11-08 00:57:12 +03:00
# include <linux/mmc/host.h>
2012-07-31 12:12:59 +04:00
# include <linux/of.h>
2010-11-08 00:57:12 +03:00
# include "sdhci-pltfm.h"
2012-07-05 14:14:01 +04:00
struct sdhci_dove_priv {
struct clk * clk ;
} ;
2010-11-08 00:57:12 +03:00
static u16 sdhci_dove_readw ( struct sdhci_host * host , int reg )
{
u16 ret ;
switch ( reg ) {
case SDHCI_HOST_VERSION :
case SDHCI_SLOT_INT_STATUS :
/* those registers don't exist */
return 0 ;
default :
ret = readw ( host - > ioaddr + reg ) ;
}
return ret ;
}
static u32 sdhci_dove_readl ( struct sdhci_host * host , int reg )
{
u32 ret ;
switch ( reg ) {
case SDHCI_CAPABILITIES :
ret = readl ( host - > ioaddr + reg ) ;
/* Mask the support for 3.0V */
ret & = ~ SDHCI_CAN_VDD_300 ;
break ;
default :
ret = readl ( host - > ioaddr + reg ) ;
}
return ret ;
}
static struct sdhci_ops sdhci_dove_ops = {
. read_w = sdhci_dove_readw ,
. read_l = sdhci_dove_readl ,
} ;
2011-05-27 19:48:12 +04:00
static struct sdhci_pltfm_data sdhci_dove_pdata = {
2010-11-08 00:57:12 +03:00
. ops = & sdhci_dove_ops ,
. quirks = SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER |
SDHCI_QUIRK_NO_BUSY_IRQ |
SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
2012-07-22 03:26:19 +04:00
SDHCI_QUIRK_FORCE_DMA |
SDHCI_QUIRK_NO_HISPD_BIT ,
2010-11-08 00:57:12 +03:00
} ;
2011-05-27 19:48:12 +04:00
2012-11-19 22:23:06 +04:00
static int sdhci_dove_probe ( struct platform_device * pdev )
2011-05-27 19:48:12 +04:00
{
2012-07-05 14:14:01 +04:00
struct sdhci_host * host ;
struct sdhci_pltfm_host * pltfm_host ;
struct sdhci_dove_priv * priv ;
int ret ;
priv = devm_kzalloc ( & pdev - > dev , sizeof ( struct sdhci_dove_priv ) ,
GFP_KERNEL ) ;
if ( ! priv ) {
dev_err ( & pdev - > dev , " unable to allocate private data " ) ;
2012-10-30 01:43:07 +04:00
return - ENOMEM ;
2012-07-05 14:14:01 +04:00
}
2012-10-30 01:43:07 +04:00
priv - > clk = clk_get ( & pdev - > dev , NULL ) ;
if ( ! IS_ERR ( priv - > clk ) )
clk_prepare_enable ( priv - > clk ) ;
ret = sdhci_pltfm_register ( pdev , & sdhci_dove_pdata ) ;
if ( ret )
goto sdhci_dove_register_fail ;
2012-07-05 14:14:01 +04:00
host = platform_get_drvdata ( pdev ) ;
pltfm_host = sdhci_priv ( host ) ;
pltfm_host - > priv = priv ;
return 0 ;
sdhci_dove_register_fail :
2012-10-30 01:43:07 +04:00
if ( ! IS_ERR ( priv - > clk ) ) {
clk_disable_unprepare ( priv - > clk ) ;
clk_put ( priv - > clk ) ;
}
2012-07-05 14:14:01 +04:00
return ret ;
2011-05-27 19:48:12 +04:00
}
static int __devexit sdhci_dove_remove ( struct platform_device * pdev )
{
2012-07-05 14:14:01 +04:00
struct sdhci_host * host = platform_get_drvdata ( pdev ) ;
struct sdhci_pltfm_host * pltfm_host = sdhci_priv ( host ) ;
struct sdhci_dove_priv * priv = pltfm_host - > priv ;
2012-10-30 01:43:07 +04:00
sdhci_pltfm_unregister ( pdev ) ;
if ( ! IS_ERR ( priv - > clk ) ) {
clk_disable_unprepare ( priv - > clk ) ;
clk_put ( priv - > clk ) ;
2012-07-05 14:14:01 +04:00
}
2012-10-30 01:43:07 +04:00
return 0 ;
2011-05-27 19:48:12 +04:00
}
2012-11-19 22:24:22 +04:00
static const struct of_device_id sdhci_dove_of_match_table [ ] = {
2012-07-31 12:12:59 +04:00
{ . compatible = " marvell,dove-sdhci " , } ,
{ }
} ;
MODULE_DEVICE_TABLE ( of , sdhci_dove_of_match_table ) ;
2011-05-27 19:48:12 +04:00
static struct platform_driver sdhci_dove_driver = {
. driver = {
. name = " sdhci-dove " ,
. owner = THIS_MODULE ,
2011-11-03 14:09:45 +04:00
. pm = SDHCI_PLTFM_PMOPS ,
2012-07-31 12:12:59 +04:00
. of_match_table = of_match_ptr ( sdhci_dove_of_match_table ) ,
2011-05-27 19:48:12 +04:00
} ,
. probe = sdhci_dove_probe ,
2012-11-19 22:20:26 +04:00
. remove = sdhci_dove_remove ,
2011-05-27 19:48:12 +04:00
} ;
2011-11-26 08:55:43 +04:00
module_platform_driver ( sdhci_dove_driver ) ;
2011-05-27 19:48:12 +04:00
MODULE_DESCRIPTION ( " SDHCI driver for Dove " ) ;
MODULE_AUTHOR ( " Saeed Bishara <saeed@marvell.com>, "
" Mike Rapoport <mike@compulab.co.il> " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;