2009-12-18 02:27:20 +03:00
/*
* Freescale eSDHC controller driver .
*
2011-09-09 16:05:46 +04:00
* Copyright ( c ) 2007 , 2010 Freescale Semiconductor , Inc .
2009-12-18 02:27:20 +03:00
* Copyright ( c ) 2009 MontaVista Software , Inc .
*
* Authors : Xiaobo Xie < X . Xie @ freescale . com >
* Anton Vorontsov < avorontsov @ ru . mvista . com >
*
* 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 .
*/
# include <linux/io.h>
# include <linux/delay.h>
2011-07-03 23:15:51 +04:00
# include <linux/module.h>
2009-12-18 02:27:20 +03:00
# include <linux/mmc/host.h>
2011-05-27 19:48:14 +04:00
# include "sdhci-pltfm.h"
2010-10-15 14:21:03 +04:00
# include "sdhci-esdhc.h"
2009-12-18 02:27:20 +03:00
static u16 esdhc_readw ( struct sdhci_host * host , int reg )
{
u16 ret ;
2011-09-09 16:05:46 +04:00
int base = reg & ~ 0x3 ;
int shift = ( reg & 0x2 ) * 8 ;
2009-12-18 02:27:20 +03:00
if ( unlikely ( reg = = SDHCI_HOST_VERSION ) )
2011-09-09 16:05:46 +04:00
ret = in_be32 ( host - > ioaddr + base ) & 0xffff ;
2009-12-18 02:27:20 +03:00
else
2011-09-09 16:05:46 +04:00
ret = ( in_be32 ( host - > ioaddr + base ) > > shift ) & 0xffff ;
return ret ;
}
static u8 esdhc_readb ( struct sdhci_host * host , int reg )
{
int base = reg & ~ 0x3 ;
int shift = ( reg & 0x3 ) * 8 ;
u8 ret = ( in_be32 ( host - > ioaddr + base ) > > shift ) & 0xff ;
2009-12-18 02:27:20 +03:00
return ret ;
}
static void esdhc_writew ( struct sdhci_host * host , u16 val , int reg )
{
if ( reg = = SDHCI_BLOCK_SIZE ) {
/*
* Two last DMA bits are reserved , and first one is used for
* non - standard blksz of 4096 bytes that we don ' t support
* yet . So clear the DMA boundary bits .
*/
val & = ~ SDHCI_MAKE_BLKSZ ( 0x7 , 0 ) ;
}
sdhci_be32bs_writew ( host , val , reg ) ;
}
static void esdhc_writeb ( struct sdhci_host * host , u8 val , int reg )
{
/* Prevent SDHCI core from writing reserved bits (e.g. HISPD). */
if ( reg = = SDHCI_HOST_CONTROL )
val & = ~ ESDHC_HOST_CONTROL_RES ;
sdhci_be32bs_writeb ( host , val , reg ) ;
}
2010-10-15 14:21:03 +04:00
static int esdhc_of_enable_dma ( struct sdhci_host * host )
2009-12-18 02:27:20 +03:00
{
setbits32 ( host - > ioaddr + ESDHC_DMA_SYSCTL , ESDHC_DMA_SNOOP ) ;
return 0 ;
}
2010-10-15 14:21:03 +04:00
static unsigned int esdhc_of_get_max_clock ( struct sdhci_host * host )
2009-12-18 02:27:20 +03:00
{
2011-07-21 01:13:36 +04:00
struct sdhci_pltfm_host * pltfm_host = sdhci_priv ( host ) ;
2009-12-18 02:27:20 +03:00
2011-07-21 01:13:36 +04:00
return pltfm_host - > clock ;
2009-12-18 02:27:20 +03:00
}
2010-10-15 14:21:03 +04:00
static unsigned int esdhc_of_get_min_clock ( struct sdhci_host * host )
2009-12-18 02:27:20 +03:00
{
2011-07-21 01:13:36 +04:00
struct sdhci_pltfm_host * pltfm_host = sdhci_priv ( host ) ;
2009-12-18 02:27:20 +03:00
2011-07-21 01:13:36 +04:00
return pltfm_host - > clock / 256 / 16 ;
2009-12-18 02:27:20 +03:00
}
2011-07-21 01:13:36 +04:00
static struct sdhci_ops sdhci_esdhc_ops = {
. read_l = sdhci_be32bs_readl ,
. read_w = esdhc_readw ,
2011-09-09 16:05:46 +04:00
. read_b = esdhc_readb ,
2011-07-21 01:13:36 +04:00
. write_l = sdhci_be32bs_writel ,
. write_w = esdhc_writew ,
. write_b = esdhc_writeb ,
. set_clock = esdhc_set_clock ,
. enable_dma = esdhc_of_enable_dma ,
. get_max_clock = esdhc_of_get_max_clock ,
. get_min_clock = esdhc_of_get_min_clock ,
} ;
2011-05-27 19:48:14 +04:00
static struct sdhci_pltfm_data sdhci_esdhc_pdata = {
2011-02-26 16:44:40 +03:00
/* card detection could be handled via GPIO */
2011-03-21 08:22:13 +03:00
. quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_CARD_DETECTION
| SDHCI_QUIRK_NO_CARD_NO_RESET ,
2011-07-21 01:13:36 +04:00
. ops = & sdhci_esdhc_ops ,
2009-12-18 02:27:20 +03:00
} ;
2011-05-27 19:48:14 +04:00
static int __devinit sdhci_esdhc_probe ( struct platform_device * pdev )
{
return sdhci_pltfm_register ( pdev , & sdhci_esdhc_pdata ) ;
}
static int __devexit sdhci_esdhc_remove ( struct platform_device * pdev )
{
return sdhci_pltfm_unregister ( pdev ) ;
}
static const struct of_device_id sdhci_esdhc_of_match [ ] = {
{ . compatible = " fsl,mpc8379-esdhc " } ,
{ . compatible = " fsl,mpc8536-esdhc " } ,
{ . compatible = " fsl,esdhc " } ,
{ }
} ;
MODULE_DEVICE_TABLE ( of , sdhci_esdhc_of_match ) ;
static struct platform_driver sdhci_esdhc_driver = {
. driver = {
. name = " sdhci-esdhc " ,
. owner = THIS_MODULE ,
. of_match_table = sdhci_esdhc_of_match ,
2011-11-03 14:09:45 +04:00
. pm = SDHCI_PLTFM_PMOPS ,
2011-05-27 19:48:14 +04:00
} ,
. probe = sdhci_esdhc_probe ,
. remove = __devexit_p ( sdhci_esdhc_remove ) ,
} ;
2011-11-26 08:55:43 +04:00
module_platform_driver ( sdhci_esdhc_driver ) ;
2011-05-27 19:48:14 +04:00
MODULE_DESCRIPTION ( " SDHCI OF driver for Freescale MPC eSDHC " ) ;
MODULE_AUTHOR ( " Xiaobo Xie <X.Xie@freescale.com>, "
" Anton Vorontsov <avorontsov@ru.mvista.com> " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;