2011-02-06 19:03:46 +01:00
/*
2011-04-11 17:02:15 -05:00
* This file contains work - arounds for many known SD / MMC
* and SDIO hardware bugs .
2011-02-06 19:03:46 +01:00
*
2011-04-11 17:02:15 -05:00
* Copyright ( c ) 2011 Andrei Warkentin < andreiw @ motorola . com >
2011-02-06 19:03:46 +01:00
* Copyright ( c ) 2011 Pierre Tardy < tardyp @ gmail . com >
* Inspired from pci fixup code :
* Copyright ( c ) 1999 Martin Mares < mj @ ucw . cz >
*
*/
# include <linux/types.h>
# include <linux/kernel.h>
2011-07-10 12:42:00 -04:00
# include <linux/export.h>
2011-02-06 19:03:46 +01:00
# include <linux/mmc/card.h>
2011-04-11 17:02:15 -05:00
# ifndef SDIO_VENDOR_ID_TI
# define SDIO_VENDOR_ID_TI 0x0097
# endif
2011-02-06 19:03:46 +01:00
2011-04-11 17:02:15 -05:00
# ifndef SDIO_DEVICE_ID_TI_WL1271
# define SDIO_DEVICE_ID_TI_WL1271 0x4076
# endif
2011-02-06 19:03:46 +01:00
2011-09-15 17:43:04 +02:00
# ifndef SDIO_VENDOR_ID_STE
# define SDIO_VENDOR_ID_STE 0x0020
# endif
# ifndef SDIO_DEVICE_ID_STE_CW1200
# define SDIO_DEVICE_ID_STE_CW1200 0x2280
# endif
2011-02-06 19:03:47 +01:00
/*
* This hook just adds a quirk for all sdio devices
*/
static void add_quirk_for_sdio_devices ( struct mmc_card * card , int data )
{
if ( mmc_card_sdio ( card ) )
card - > quirks | = data ;
}
2011-02-06 19:03:46 +01:00
static const struct mmc_fixup mmc_fixup_methods [ ] = {
2011-02-06 19:03:47 +01:00
/* by default sdio devices are considered CLK_GATING broken */
/* good cards will be whitelisted as they are tested */
2011-04-11 17:02:15 -05:00
SDIO_FIXUP ( SDIO_ANY_ID , SDIO_ANY_ID ,
add_quirk_for_sdio_devices ,
MMC_QUIRK_BROKEN_CLK_GATING ) ,
SDIO_FIXUP ( SDIO_VENDOR_ID_TI , SDIO_DEVICE_ID_TI_WL1271 ,
remove_quirk , MMC_QUIRK_BROKEN_CLK_GATING ) ,
SDIO_FIXUP ( SDIO_VENDOR_ID_TI , SDIO_DEVICE_ID_TI_WL1271 ,
add_quirk , MMC_QUIRK_NONSTD_FUNC_IF ) ,
SDIO_FIXUP ( SDIO_VENDOR_ID_TI , SDIO_DEVICE_ID_TI_WL1271 ,
add_quirk , MMC_QUIRK_DISABLE_CD ) ,
2011-09-15 17:43:04 +02:00
SDIO_FIXUP ( SDIO_VENDOR_ID_STE , SDIO_DEVICE_ID_STE_CW1200 ,
add_quirk , MMC_QUIRK_BROKEN_BYTE_MODE_512 ) ,
2011-04-11 17:02:15 -05:00
END_FIXUP
2011-02-06 19:03:46 +01:00
} ;
2011-04-11 17:02:15 -05:00
void mmc_fixup_device ( struct mmc_card * card , const struct mmc_fixup * table )
2011-02-06 19:03:46 +01:00
{
const struct mmc_fixup * f ;
2011-04-11 17:02:15 -05:00
u64 rev = cid_rev_card ( card ) ;
/* Non-core specific workarounds. */
if ( ! table )
table = mmc_fixup_methods ;
2011-02-06 19:03:46 +01:00
2011-04-11 17:02:15 -05:00
for ( f = table ; f - > vendor_fixup ; f + + ) {
if ( ( f - > manfid = = CID_MANFID_ANY | |
f - > manfid = = card - > cid . manfid ) & &
( f - > oemid = = CID_OEMID_ANY | |
f - > oemid = = card - > cid . oemid ) & &
( f - > name = = CID_NAME_ANY | |
! strncmp ( f - > name , card - > cid . prod_name ,
sizeof ( card - > cid . prod_name ) ) ) & &
( f - > cis_vendor = = card - > cis . vendor | |
f - > cis_vendor = = ( u16 ) SDIO_ANY_ID ) & &
( f - > cis_device = = card - > cis . device | |
f - > cis_device = = ( u16 ) SDIO_ANY_ID ) & &
rev > = f - > rev_start & & rev < = f - > rev_end ) {
2011-02-06 19:03:46 +01:00
dev_dbg ( & card - > dev , " calling %pF \n " , f - > vendor_fixup ) ;
f - > vendor_fixup ( card , f - > data ) ;
}
}
}
EXPORT_SYMBOL ( mmc_fixup_device ) ;