2006-12-31 00:11:32 +01:00
/*
2007-07-11 20:04:50 +02:00
* linux / drivers / mmc / core / mmc . c
2006-12-31 00:11:32 +01:00
*
* Copyright ( C ) 2003 - 2004 Russell King , All Rights Reserved .
* Copyright ( C ) 2005 - 2007 Pierre Ossman , All Rights Reserved .
* MMCv4 support Copyright ( C ) 2006 Philip Langdale , All Rights Reserved .
*
* 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 .
*/
# include <linux/err.h>
# include <linux/mmc/host.h>
# include <linux/mmc/card.h>
# include <linux/mmc/mmc.h>
# include "core.h"
2007-05-19 13:39:01 +02:00
# include "bus.h"
2006-12-31 00:11:32 +01:00
# include "mmc_ops.h"
static const unsigned int tran_exp [ ] = {
10000 , 100000 , 1000000 , 10000000 ,
0 , 0 , 0 , 0
} ;
static const unsigned char tran_mant [ ] = {
0 , 10 , 12 , 13 , 15 , 20 , 25 , 30 ,
35 , 40 , 45 , 50 , 55 , 60 , 70 , 80 ,
} ;
static const unsigned int tacc_exp [ ] = {
1 , 10 , 100 , 1000 , 10000 , 100000 , 1000000 , 10000000 ,
} ;
static const unsigned int tacc_mant [ ] = {
0 , 10 , 12 , 13 , 15 , 20 , 25 , 30 ,
35 , 40 , 45 , 50 , 55 , 60 , 70 , 80 ,
} ;
# define UNSTUFF_BITS(resp,start,size) \
( { \
const int __size = size ; \
const u32 __mask = ( __size < 32 ? 1 < < __size : 0 ) - 1 ; \
const int __off = 3 - ( ( start ) / 32 ) ; \
const int __shft = ( start ) & 31 ; \
u32 __res ; \
\
__res = resp [ __off ] > > __shft ; \
if ( __size + __shft > 32 ) \
__res | = resp [ __off - 1 ] < < ( ( 32 - __shft ) % 32 ) ; \
__res & __mask ; \
} )
/*
* Given the decoded CSD structure , decode the raw CID to our CID structure .
*/
2007-05-01 16:11:57 +02:00
static int mmc_decode_cid ( struct mmc_card * card )
2006-12-31 00:11:32 +01:00
{
u32 * resp = card - > raw_cid ;
/*
* The selection of the format here is based upon published
* specs from sandisk and from what people have reported .
*/
switch ( card - > csd . mmca_vsn ) {
case 0 : /* MMC v1.0 - v1.2 */
case 1 : /* MMC v1.4 */
card - > cid . manfid = UNSTUFF_BITS ( resp , 104 , 24 ) ;
card - > cid . prod_name [ 0 ] = UNSTUFF_BITS ( resp , 96 , 8 ) ;
card - > cid . prod_name [ 1 ] = UNSTUFF_BITS ( resp , 88 , 8 ) ;
card - > cid . prod_name [ 2 ] = UNSTUFF_BITS ( resp , 80 , 8 ) ;
card - > cid . prod_name [ 3 ] = UNSTUFF_BITS ( resp , 72 , 8 ) ;
card - > cid . prod_name [ 4 ] = UNSTUFF_BITS ( resp , 64 , 8 ) ;
card - > cid . prod_name [ 5 ] = UNSTUFF_BITS ( resp , 56 , 8 ) ;
card - > cid . prod_name [ 6 ] = UNSTUFF_BITS ( resp , 48 , 8 ) ;
card - > cid . hwrev = UNSTUFF_BITS ( resp , 44 , 4 ) ;
card - > cid . fwrev = UNSTUFF_BITS ( resp , 40 , 4 ) ;
card - > cid . serial = UNSTUFF_BITS ( resp , 16 , 24 ) ;
card - > cid . month = UNSTUFF_BITS ( resp , 12 , 4 ) ;
card - > cid . year = UNSTUFF_BITS ( resp , 8 , 4 ) + 1997 ;
break ;
case 2 : /* MMC v2.0 - v2.2 */
case 3 : /* MMC v3.1 - v3.3 */
case 4 : /* MMC v4 */
card - > cid . manfid = UNSTUFF_BITS ( resp , 120 , 8 ) ;
card - > cid . oemid = UNSTUFF_BITS ( resp , 104 , 16 ) ;
card - > cid . prod_name [ 0 ] = UNSTUFF_BITS ( resp , 96 , 8 ) ;
card - > cid . prod_name [ 1 ] = UNSTUFF_BITS ( resp , 88 , 8 ) ;
card - > cid . prod_name [ 2 ] = UNSTUFF_BITS ( resp , 80 , 8 ) ;
card - > cid . prod_name [ 3 ] = UNSTUFF_BITS ( resp , 72 , 8 ) ;
card - > cid . prod_name [ 4 ] = UNSTUFF_BITS ( resp , 64 , 8 ) ;
card - > cid . prod_name [ 5 ] = UNSTUFF_BITS ( resp , 56 , 8 ) ;
card - > cid . serial = UNSTUFF_BITS ( resp , 16 , 32 ) ;
card - > cid . month = UNSTUFF_BITS ( resp , 12 , 4 ) ;
card - > cid . year = UNSTUFF_BITS ( resp , 8 , 4 ) + 1997 ;
break ;
default :
2007-07-24 21:53:43 +02:00
printk ( KERN_ERR " %s: card has unknown MMCA version %d \n " ,
2006-12-31 00:11:32 +01:00
mmc_hostname ( card - > host ) , card - > csd . mmca_vsn ) ;
2007-05-01 16:11:57 +02:00
return - EINVAL ;
2006-12-31 00:11:32 +01:00
}
2007-05-01 16:11:57 +02:00
return 0 ;
2006-12-31 00:11:32 +01:00
}
/*
* Given a 128 - bit response , decode to our card CSD structure .
*/
2007-05-01 16:11:57 +02:00
static int mmc_decode_csd ( struct mmc_card * card )
2006-12-31 00:11:32 +01:00
{
struct mmc_csd * csd = & card - > csd ;
unsigned int e , m , csd_struct ;
u32 * resp = card - > raw_csd ;
/*
* We only understand CSD structure v1 .1 and v1 .2 .
* v1 .2 has extra information in bits 15 , 11 and 10.
*/
csd_struct = UNSTUFF_BITS ( resp , 126 , 2 ) ;
if ( csd_struct ! = 1 & & csd_struct ! = 2 ) {
2007-07-24 21:53:43 +02:00
printk ( KERN_ERR " %s: unrecognised CSD structure version %d \n " ,
2006-12-31 00:11:32 +01:00
mmc_hostname ( card - > host ) , csd_struct ) ;
2007-05-01 16:11:57 +02:00
return - EINVAL ;
2006-12-31 00:11:32 +01:00
}
csd - > mmca_vsn = UNSTUFF_BITS ( resp , 122 , 4 ) ;
m = UNSTUFF_BITS ( resp , 115 , 4 ) ;
e = UNSTUFF_BITS ( resp , 112 , 3 ) ;
csd - > tacc_ns = ( tacc_exp [ e ] * tacc_mant [ m ] + 9 ) / 10 ;
csd - > tacc_clks = UNSTUFF_BITS ( resp , 104 , 8 ) * 100 ;
m = UNSTUFF_BITS ( resp , 99 , 4 ) ;
e = UNSTUFF_BITS ( resp , 96 , 3 ) ;
csd - > max_dtr = tran_exp [ e ] * tran_mant [ m ] ;
csd - > cmdclass = UNSTUFF_BITS ( resp , 84 , 12 ) ;
e = UNSTUFF_BITS ( resp , 47 , 3 ) ;
m = UNSTUFF_BITS ( resp , 62 , 12 ) ;
csd - > capacity = ( 1 + m ) < < ( e + 2 ) ;
csd - > read_blkbits = UNSTUFF_BITS ( resp , 80 , 4 ) ;
csd - > read_partial = UNSTUFF_BITS ( resp , 79 , 1 ) ;
csd - > write_misalign = UNSTUFF_BITS ( resp , 78 , 1 ) ;
csd - > read_misalign = UNSTUFF_BITS ( resp , 77 , 1 ) ;
csd - > r2w_factor = UNSTUFF_BITS ( resp , 26 , 3 ) ;
csd - > write_blkbits = UNSTUFF_BITS ( resp , 22 , 4 ) ;
csd - > write_partial = UNSTUFF_BITS ( resp , 21 , 1 ) ;
2007-05-01 16:11:57 +02:00
return 0 ;
2006-12-31 00:11:32 +01:00
}
/*
2007-05-01 15:08:30 +02:00
* Read and decode extended CSD .
2006-12-31 00:11:32 +01:00
*/
2007-05-01 15:08:30 +02:00
static int mmc_read_ext_csd ( struct mmc_card * card )
2006-12-31 00:11:32 +01:00
{
int err ;
u8 * ext_csd ;
BUG_ON ( ! card ) ;
if ( card - > csd . mmca_vsn < CSD_SPEC_VER_4 )
2007-07-22 22:18:46 +02:00
return 0 ;
2006-12-31 00:11:32 +01:00
/*
* As the ext_csd is so large and mostly unused , we don ' t store the
* raw block in mmc_card .
*/
ext_csd = kmalloc ( 512 , GFP_KERNEL ) ;
if ( ! ext_csd ) {
printk ( KERN_ERR " %s: could not allocate a buffer to "
2007-07-22 23:08:30 +02:00
" receive the ext_csd. \n " , mmc_hostname ( card - > host ) ) ;
2007-07-22 22:18:46 +02:00
return - ENOMEM ;
2006-12-31 00:11:32 +01:00
}
err = mmc_send_ext_csd ( card , ext_csd ) ;
2007-07-22 22:18:46 +02:00
if ( err ) {
2009-09-22 16:45:26 -07:00
/* If the host or the card can't do the switch,
* fail more gracefully . */
if ( ( err ! = - EINVAL )
& & ( err ! = - ENOSYS )
& & ( err ! = - EFAULT ) )
2007-07-22 23:08:30 +02:00
goto out ;
2006-12-31 00:11:32 +01:00
/*
* High capacity cards should have this " magic " size
* stored in their CSD .
*/
if ( card - > csd . capacity = = ( 4096 * 512 ) ) {
printk ( KERN_ERR " %s: unable to read EXT_CSD "
" on a possible high capacity card. "
" Card will be ignored. \n " ,
mmc_hostname ( card - > host ) ) ;
} else {
printk ( KERN_WARNING " %s: unable to read "
" EXT_CSD, performance might "
" suffer. \n " ,
mmc_hostname ( card - > host ) ) ;
2007-07-22 22:18:46 +02:00
err = 0 ;
2006-12-31 00:11:32 +01:00
}
2007-07-22 23:08:30 +02:00
2006-12-31 00:11:32 +01:00
goto out ;
}
2009-09-22 16:44:34 -07:00
card - > ext_csd . rev = ext_csd [ EXT_CSD_REV ] ;
2010-01-08 14:43:01 -08:00
if ( card - > ext_csd . rev > 5 ) {
2007-07-24 21:53:43 +02:00
printk ( KERN_ERR " %s: unrecognised EXT_CSD structure "
" version %d \n " , mmc_hostname ( card - > host ) ,
2009-09-22 16:44:34 -07:00
card - > ext_csd . rev ) ;
2007-10-13 12:27:20 -04:00
err = - EINVAL ;
goto out ;
2007-07-23 00:34:07 +02:00
}
2009-09-22 16:44:34 -07:00
if ( card - > ext_csd . rev > = 2 ) {
2007-07-23 00:34:07 +02:00
card - > ext_csd . sectors =
ext_csd [ EXT_CSD_SEC_CNT + 0 ] < < 0 |
ext_csd [ EXT_CSD_SEC_CNT + 1 ] < < 8 |
ext_csd [ EXT_CSD_SEC_CNT + 2 ] < < 16 |
ext_csd [ EXT_CSD_SEC_CNT + 3 ] < < 24 ;
if ( card - > ext_csd . sectors )
mmc_card_set_blockaddr ( card ) ;
}
2006-12-31 00:11:32 +01:00
switch ( ext_csd [ EXT_CSD_CARD_TYPE ] ) {
case EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26 :
card - > ext_csd . hs_max_dtr = 52000000 ;
break ;
case EXT_CSD_CARD_TYPE_26 :
card - > ext_csd . hs_max_dtr = 26000000 ;
break ;
default :
/* MMC v4 spec says this cannot happen */
printk ( KERN_WARNING " %s: card is mmc v4 but doesn't "
" support any high-speed modes. \n " ,
mmc_hostname ( card - > host ) ) ;
goto out ;
}
2009-09-22 16:44:34 -07:00
if ( card - > ext_csd . rev > = 3 ) {
u8 sa_shift = ext_csd [ EXT_CSD_S_A_TIMEOUT ] ;
/* Sleep / awake timeout in 100ns units */
if ( sa_shift > 0 & & sa_shift < = 0x17 )
card - > ext_csd . sa_timeout =
1 < < ext_csd [ EXT_CSD_S_A_TIMEOUT ] ;
}
2006-12-31 00:11:32 +01:00
out :
kfree ( ext_csd ) ;
return err ;
}
2008-03-21 23:54:50 +01:00
MMC_DEV_ATTR ( cid , " %08x%08x%08x%08x \n " , card - > raw_cid [ 0 ] , card - > raw_cid [ 1 ] ,
card - > raw_cid [ 2 ] , card - > raw_cid [ 3 ] ) ;
MMC_DEV_ATTR ( csd , " %08x%08x%08x%08x \n " , card - > raw_csd [ 0 ] , card - > raw_csd [ 1 ] ,
card - > raw_csd [ 2 ] , card - > raw_csd [ 3 ] ) ;
MMC_DEV_ATTR ( date , " %02d/%04d \n " , card - > cid . month , card - > cid . year ) ;
MMC_DEV_ATTR ( fwrev , " 0x%x \n " , card - > cid . fwrev ) ;
MMC_DEV_ATTR ( hwrev , " 0x%x \n " , card - > cid . hwrev ) ;
MMC_DEV_ATTR ( manfid , " 0x%06x \n " , card - > cid . manfid ) ;
MMC_DEV_ATTR ( name , " %s \n " , card - > cid . prod_name ) ;
MMC_DEV_ATTR ( oemid , " 0x%04x \n " , card - > cid . oemid ) ;
MMC_DEV_ATTR ( serial , " 0x%08x \n " , card - > cid . serial ) ;
static struct attribute * mmc_std_attrs [ ] = {
& dev_attr_cid . attr ,
& dev_attr_csd . attr ,
& dev_attr_date . attr ,
& dev_attr_fwrev . attr ,
& dev_attr_hwrev . attr ,
& dev_attr_manfid . attr ,
& dev_attr_name . attr ,
& dev_attr_oemid . attr ,
& dev_attr_serial . attr ,
NULL ,
} ;
static struct attribute_group mmc_std_attr_group = {
. attrs = mmc_std_attrs ,
} ;
2009-06-24 10:06:31 -07:00
static const struct attribute_group * mmc_attr_groups [ ] = {
2008-03-21 23:54:50 +01:00
& mmc_std_attr_group ,
NULL ,
} ;
static struct device_type mmc_type = {
. groups = mmc_attr_groups ,
} ;
2006-12-31 00:11:32 +01:00
/*
2007-05-01 16:00:02 +02:00
* Handle the detection and initialisation of a card .
*
2008-06-16 19:20:57 -07:00
* In the case of a resume , " oldcard " will contain the card
2007-05-01 16:00:02 +02:00
* we ' re trying to reinitialise .
2006-12-31 00:11:32 +01:00
*/
2007-05-19 16:14:43 +02:00
static int mmc_init_card ( struct mmc_host * host , u32 ocr ,
2007-05-01 16:00:02 +02:00
struct mmc_card * oldcard )
2006-12-31 00:11:32 +01:00
{
struct mmc_card * card ;
int err ;
u32 cid [ 4 ] ;
unsigned int max_dtr ;
BUG_ON ( ! host ) ;
2007-08-09 13:23:56 +02:00
WARN_ON ( ! host - > claimed ) ;
2006-12-31 00:11:32 +01:00
/*
* Since we ' re changing the OCR value , we seem to
* need to tell some cards to go back to the idle
* state . We wait 1 ms to give cards time to
* respond .
*/
mmc_go_idle ( host ) ;
/* The extra bit indicates that we support high capacity */
2007-05-01 16:00:02 +02:00
err = mmc_send_op_cond ( host , ocr | ( 1 < < 30 ) , NULL ) ;
2007-07-22 22:18:46 +02:00
if ( err )
2007-05-01 16:00:02 +02:00
goto err ;
2006-12-31 00:11:32 +01:00
MMC core learns about SPI
Teach the MMC/SD/SDIO core about using SPI mode.
- Use mmc_host_is_spi() so enumeration works through SPI signaling
and protocols, not just the native versions.
- Provide the SPI response type flags with each request issued,
including requests from the new lock/unlock code.
- Understand that cmd->resp[0] and mmc_get_status() results for SPI
return different values than for "native" MMC/SD protocol; this
affects resetting, checking card lock status, and some others.
- Understand that some commands act a bit differently ... notably:
* OP_COND command doesn't return the OCR
* APP_CMD status doesn't have an R1_APP_CMD analogue
Those changes required some new and updated primitives:
- Provide utilities to access two SPI-only requests, and one
request that wasn't previously needed:
* mmc_spi_read_ocr() ... SPI only
* mmc_spi_set_crc() ... SPI only (override by module parm)
* mmc_send_cid() ... for use without broadcast mode
- Updated internal routines:
* Previous mmc_send_csd() modified into mmc_send_cxd_native();
it uses native "R2" responses, which include 16 bytes of data.
* Previous mmc_send_ext_csd() becomes new mmc_send_cxd_data()
helper for command-and-data access
* Bugfix to that mmc_send_cxd_data() code: dma-to-stack is
unsafe/nonportable, so kmalloc a bounce buffer instead.
- Modified mmc_send_ext_csd() now uses mmc_send_cxd_data() helper
- Modified mmc_send_csd(), and new mmc_spi_send_cid(), routines use
those helper routines based on whether they're native or SPI
The newest categories of cards supported by the MMC stack aren't expected
to work yet with SPI: MMC or SD cards with over 4GB data, and SDIO.
All those cards support SPI mode, so eventually they should work too.
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
2007-08-08 09:11:32 -07:00
/*
* For SPI , enable CRC as appropriate .
*/
if ( mmc_host_is_spi ( host ) ) {
err = mmc_spi_set_crc ( host , use_spi_crc ) ;
if ( err )
goto err ;
}
2006-12-31 00:11:32 +01:00
/*
* Fetch CID from card .
*/
MMC core learns about SPI
Teach the MMC/SD/SDIO core about using SPI mode.
- Use mmc_host_is_spi() so enumeration works through SPI signaling
and protocols, not just the native versions.
- Provide the SPI response type flags with each request issued,
including requests from the new lock/unlock code.
- Understand that cmd->resp[0] and mmc_get_status() results for SPI
return different values than for "native" MMC/SD protocol; this
affects resetting, checking card lock status, and some others.
- Understand that some commands act a bit differently ... notably:
* OP_COND command doesn't return the OCR
* APP_CMD status doesn't have an R1_APP_CMD analogue
Those changes required some new and updated primitives:
- Provide utilities to access two SPI-only requests, and one
request that wasn't previously needed:
* mmc_spi_read_ocr() ... SPI only
* mmc_spi_set_crc() ... SPI only (override by module parm)
* mmc_send_cid() ... for use without broadcast mode
- Updated internal routines:
* Previous mmc_send_csd() modified into mmc_send_cxd_native();
it uses native "R2" responses, which include 16 bytes of data.
* Previous mmc_send_ext_csd() becomes new mmc_send_cxd_data()
helper for command-and-data access
* Bugfix to that mmc_send_cxd_data() code: dma-to-stack is
unsafe/nonportable, so kmalloc a bounce buffer instead.
- Modified mmc_send_ext_csd() now uses mmc_send_cxd_data() helper
- Modified mmc_send_csd(), and new mmc_spi_send_cid(), routines use
those helper routines based on whether they're native or SPI
The newest categories of cards supported by the MMC stack aren't expected
to work yet with SPI: MMC or SD cards with over 4GB data, and SDIO.
All those cards support SPI mode, so eventually they should work too.
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
2007-08-08 09:11:32 -07:00
if ( mmc_host_is_spi ( host ) )
err = mmc_send_cid ( host , cid ) ;
else
err = mmc_all_send_cid ( host , cid ) ;
2007-07-22 22:18:46 +02:00
if ( err )
2006-12-31 00:11:32 +01:00
goto err ;
2007-05-01 16:00:02 +02:00
if ( oldcard ) {
2007-07-22 23:08:30 +02:00
if ( memcmp ( cid , oldcard - > raw_cid , sizeof ( cid ) ) ! = 0 ) {
err = - ENOENT ;
2007-05-01 16:00:02 +02:00
goto err ;
2007-07-22 23:08:30 +02:00
}
2007-05-01 16:00:02 +02:00
card = oldcard ;
} else {
/*
* Allocate card structure .
*/
2008-03-21 23:54:50 +01:00
card = mmc_alloc_card ( host , & mmc_type ) ;
2007-07-22 23:08:30 +02:00
if ( IS_ERR ( card ) ) {
err = PTR_ERR ( card ) ;
2007-05-01 16:00:02 +02:00
goto err ;
2007-07-22 23:08:30 +02:00
}
2006-12-31 00:11:32 +01:00
2007-05-01 16:00:02 +02:00
card - > type = MMC_TYPE_MMC ;
card - > rca = 1 ;
memcpy ( card - > raw_cid , cid , sizeof ( card - > raw_cid ) ) ;
}
2006-12-31 00:11:32 +01:00
/*
MMC core learns about SPI
Teach the MMC/SD/SDIO core about using SPI mode.
- Use mmc_host_is_spi() so enumeration works through SPI signaling
and protocols, not just the native versions.
- Provide the SPI response type flags with each request issued,
including requests from the new lock/unlock code.
- Understand that cmd->resp[0] and mmc_get_status() results for SPI
return different values than for "native" MMC/SD protocol; this
affects resetting, checking card lock status, and some others.
- Understand that some commands act a bit differently ... notably:
* OP_COND command doesn't return the OCR
* APP_CMD status doesn't have an R1_APP_CMD analogue
Those changes required some new and updated primitives:
- Provide utilities to access two SPI-only requests, and one
request that wasn't previously needed:
* mmc_spi_read_ocr() ... SPI only
* mmc_spi_set_crc() ... SPI only (override by module parm)
* mmc_send_cid() ... for use without broadcast mode
- Updated internal routines:
* Previous mmc_send_csd() modified into mmc_send_cxd_native();
it uses native "R2" responses, which include 16 bytes of data.
* Previous mmc_send_ext_csd() becomes new mmc_send_cxd_data()
helper for command-and-data access
* Bugfix to that mmc_send_cxd_data() code: dma-to-stack is
unsafe/nonportable, so kmalloc a bounce buffer instead.
- Modified mmc_send_ext_csd() now uses mmc_send_cxd_data() helper
- Modified mmc_send_csd(), and new mmc_spi_send_cid(), routines use
those helper routines based on whether they're native or SPI
The newest categories of cards supported by the MMC stack aren't expected
to work yet with SPI: MMC or SD cards with over 4GB data, and SDIO.
All those cards support SPI mode, so eventually they should work too.
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
2007-08-08 09:11:32 -07:00
* For native busses : set card RCA and quit open drain mode .
2006-12-31 00:11:32 +01:00
*/
MMC core learns about SPI
Teach the MMC/SD/SDIO core about using SPI mode.
- Use mmc_host_is_spi() so enumeration works through SPI signaling
and protocols, not just the native versions.
- Provide the SPI response type flags with each request issued,
including requests from the new lock/unlock code.
- Understand that cmd->resp[0] and mmc_get_status() results for SPI
return different values than for "native" MMC/SD protocol; this
affects resetting, checking card lock status, and some others.
- Understand that some commands act a bit differently ... notably:
* OP_COND command doesn't return the OCR
* APP_CMD status doesn't have an R1_APP_CMD analogue
Those changes required some new and updated primitives:
- Provide utilities to access two SPI-only requests, and one
request that wasn't previously needed:
* mmc_spi_read_ocr() ... SPI only
* mmc_spi_set_crc() ... SPI only (override by module parm)
* mmc_send_cid() ... for use without broadcast mode
- Updated internal routines:
* Previous mmc_send_csd() modified into mmc_send_cxd_native();
it uses native "R2" responses, which include 16 bytes of data.
* Previous mmc_send_ext_csd() becomes new mmc_send_cxd_data()
helper for command-and-data access
* Bugfix to that mmc_send_cxd_data() code: dma-to-stack is
unsafe/nonportable, so kmalloc a bounce buffer instead.
- Modified mmc_send_ext_csd() now uses mmc_send_cxd_data() helper
- Modified mmc_send_csd(), and new mmc_spi_send_cid(), routines use
those helper routines based on whether they're native or SPI
The newest categories of cards supported by the MMC stack aren't expected
to work yet with SPI: MMC or SD cards with over 4GB data, and SDIO.
All those cards support SPI mode, so eventually they should work too.
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
2007-08-08 09:11:32 -07:00
if ( ! mmc_host_is_spi ( host ) ) {
err = mmc_set_relative_addr ( card ) ;
if ( err )
goto free_card ;
2006-12-31 00:11:32 +01:00
MMC core learns about SPI
Teach the MMC/SD/SDIO core about using SPI mode.
- Use mmc_host_is_spi() so enumeration works through SPI signaling
and protocols, not just the native versions.
- Provide the SPI response type flags with each request issued,
including requests from the new lock/unlock code.
- Understand that cmd->resp[0] and mmc_get_status() results for SPI
return different values than for "native" MMC/SD protocol; this
affects resetting, checking card lock status, and some others.
- Understand that some commands act a bit differently ... notably:
* OP_COND command doesn't return the OCR
* APP_CMD status doesn't have an R1_APP_CMD analogue
Those changes required some new and updated primitives:
- Provide utilities to access two SPI-only requests, and one
request that wasn't previously needed:
* mmc_spi_read_ocr() ... SPI only
* mmc_spi_set_crc() ... SPI only (override by module parm)
* mmc_send_cid() ... for use without broadcast mode
- Updated internal routines:
* Previous mmc_send_csd() modified into mmc_send_cxd_native();
it uses native "R2" responses, which include 16 bytes of data.
* Previous mmc_send_ext_csd() becomes new mmc_send_cxd_data()
helper for command-and-data access
* Bugfix to that mmc_send_cxd_data() code: dma-to-stack is
unsafe/nonportable, so kmalloc a bounce buffer instead.
- Modified mmc_send_ext_csd() now uses mmc_send_cxd_data() helper
- Modified mmc_send_csd(), and new mmc_spi_send_cid(), routines use
those helper routines based on whether they're native or SPI
The newest categories of cards supported by the MMC stack aren't expected
to work yet with SPI: MMC or SD cards with over 4GB data, and SDIO.
All those cards support SPI mode, so eventually they should work too.
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
2007-08-08 09:11:32 -07:00
mmc_set_bus_mode ( host , MMC_BUSMODE_PUSHPULL ) ;
}
2006-12-31 00:11:32 +01:00
2007-05-01 16:00:02 +02:00
if ( ! oldcard ) {
/*
* Fetch CSD from card .
*/
err = mmc_send_csd ( card , card - > raw_csd ) ;
2007-07-22 22:18:46 +02:00
if ( err )
2007-05-01 16:00:02 +02:00
goto free_card ;
2006-12-31 00:11:32 +01:00
2007-05-01 16:11:57 +02:00
err = mmc_decode_csd ( card ) ;
2007-07-22 23:08:30 +02:00
if ( err )
2007-05-01 16:11:57 +02:00
goto free_card ;
err = mmc_decode_cid ( card ) ;
2007-07-22 23:08:30 +02:00
if ( err )
2007-05-01 16:11:57 +02:00
goto free_card ;
2007-05-01 16:00:02 +02:00
}
2006-12-31 00:11:32 +01:00
/*
2007-05-01 15:08:30 +02:00
* Select card , as all following commands rely on that .
2006-12-31 00:11:32 +01:00
*/
MMC core learns about SPI
Teach the MMC/SD/SDIO core about using SPI mode.
- Use mmc_host_is_spi() so enumeration works through SPI signaling
and protocols, not just the native versions.
- Provide the SPI response type flags with each request issued,
including requests from the new lock/unlock code.
- Understand that cmd->resp[0] and mmc_get_status() results for SPI
return different values than for "native" MMC/SD protocol; this
affects resetting, checking card lock status, and some others.
- Understand that some commands act a bit differently ... notably:
* OP_COND command doesn't return the OCR
* APP_CMD status doesn't have an R1_APP_CMD analogue
Those changes required some new and updated primitives:
- Provide utilities to access two SPI-only requests, and one
request that wasn't previously needed:
* mmc_spi_read_ocr() ... SPI only
* mmc_spi_set_crc() ... SPI only (override by module parm)
* mmc_send_cid() ... for use without broadcast mode
- Updated internal routines:
* Previous mmc_send_csd() modified into mmc_send_cxd_native();
it uses native "R2" responses, which include 16 bytes of data.
* Previous mmc_send_ext_csd() becomes new mmc_send_cxd_data()
helper for command-and-data access
* Bugfix to that mmc_send_cxd_data() code: dma-to-stack is
unsafe/nonportable, so kmalloc a bounce buffer instead.
- Modified mmc_send_ext_csd() now uses mmc_send_cxd_data() helper
- Modified mmc_send_csd(), and new mmc_spi_send_cid(), routines use
those helper routines based on whether they're native or SPI
The newest categories of cards supported by the MMC stack aren't expected
to work yet with SPI: MMC or SD cards with over 4GB data, and SDIO.
All those cards support SPI mode, so eventually they should work too.
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
2007-08-08 09:11:32 -07:00
if ( ! mmc_host_is_spi ( host ) ) {
err = mmc_select_card ( card ) ;
if ( err )
goto free_card ;
}
2006-12-31 00:11:32 +01:00
2007-05-01 16:00:02 +02:00
if ( ! oldcard ) {
/*
MMC core learns about SPI
Teach the MMC/SD/SDIO core about using SPI mode.
- Use mmc_host_is_spi() so enumeration works through SPI signaling
and protocols, not just the native versions.
- Provide the SPI response type flags with each request issued,
including requests from the new lock/unlock code.
- Understand that cmd->resp[0] and mmc_get_status() results for SPI
return different values than for "native" MMC/SD protocol; this
affects resetting, checking card lock status, and some others.
- Understand that some commands act a bit differently ... notably:
* OP_COND command doesn't return the OCR
* APP_CMD status doesn't have an R1_APP_CMD analogue
Those changes required some new and updated primitives:
- Provide utilities to access two SPI-only requests, and one
request that wasn't previously needed:
* mmc_spi_read_ocr() ... SPI only
* mmc_spi_set_crc() ... SPI only (override by module parm)
* mmc_send_cid() ... for use without broadcast mode
- Updated internal routines:
* Previous mmc_send_csd() modified into mmc_send_cxd_native();
it uses native "R2" responses, which include 16 bytes of data.
* Previous mmc_send_ext_csd() becomes new mmc_send_cxd_data()
helper for command-and-data access
* Bugfix to that mmc_send_cxd_data() code: dma-to-stack is
unsafe/nonportable, so kmalloc a bounce buffer instead.
- Modified mmc_send_ext_csd() now uses mmc_send_cxd_data() helper
- Modified mmc_send_csd(), and new mmc_spi_send_cid(), routines use
those helper routines based on whether they're native or SPI
The newest categories of cards supported by the MMC stack aren't expected
to work yet with SPI: MMC or SD cards with over 4GB data, and SDIO.
All those cards support SPI mode, so eventually they should work too.
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
2007-08-08 09:11:32 -07:00
* Fetch and process extended CSD .
2007-05-01 16:00:02 +02:00
*/
err = mmc_read_ext_csd ( card ) ;
2007-07-22 22:18:46 +02:00
if ( err )
2007-05-01 16:00:02 +02:00
goto free_card ;
}
2006-12-31 00:11:32 +01:00
2007-05-01 15:08:30 +02:00
/*
* Activate high speed ( if supported )
*/
if ( ( card - > ext_csd . hs_max_dtr ! = 0 ) & &
( host - > caps & MMC_CAP_MMC_HIGHSPEED ) ) {
err = mmc_switch ( card , EXT_CSD_CMD_SET_NORMAL ,
EXT_CSD_HS_TIMING , 1 ) ;
2009-09-22 16:44:37 -07:00
if ( err & & err ! = - EBADMSG )
2007-05-01 15:08:30 +02:00
goto free_card ;
2009-09-22 16:44:37 -07:00
if ( err ) {
printk ( KERN_WARNING " %s: switch to highspeed failed \n " ,
mmc_hostname ( card - > host ) ) ;
err = 0 ;
} else {
mmc_card_set_highspeed ( card ) ;
mmc_set_timing ( card - > host , MMC_TIMING_MMC_HS ) ;
}
2007-05-01 15:08:30 +02:00
}
2006-12-31 00:11:32 +01:00
/*
* Compute bus speed .
*/
max_dtr = ( unsigned int ) - 1 ;
if ( mmc_card_highspeed ( card ) ) {
if ( max_dtr > card - > ext_csd . hs_max_dtr )
max_dtr = card - > ext_csd . hs_max_dtr ;
} else if ( max_dtr > card - > csd . max_dtr ) {
max_dtr = card - > csd . max_dtr ;
}
mmc_set_clock ( host , max_dtr ) ;
2007-05-01 15:08:30 +02:00
/*
* Activate wide bus ( if supported ) .
*/
if ( ( card - > csd . mmca_vsn > = CSD_SPEC_VER_4 ) & &
2008-11-17 14:35:21 +02:00
( host - > caps & ( MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA ) ) ) {
unsigned ext_csd_bit , bus_width ;
if ( host - > caps & MMC_CAP_8_BIT_DATA ) {
ext_csd_bit = EXT_CSD_BUS_WIDTH_8 ;
bus_width = MMC_BUS_WIDTH_8 ;
} else {
ext_csd_bit = EXT_CSD_BUS_WIDTH_4 ;
bus_width = MMC_BUS_WIDTH_4 ;
}
2007-05-01 15:08:30 +02:00
err = mmc_switch ( card , EXT_CSD_CMD_SET_NORMAL ,
2008-11-17 14:35:21 +02:00
EXT_CSD_BUS_WIDTH , ext_csd_bit ) ;
2009-09-22 16:44:37 -07:00
if ( err & & err ! = - EBADMSG )
2007-05-01 15:08:30 +02:00
goto free_card ;
2009-09-22 16:44:37 -07:00
if ( err ) {
printk ( KERN_WARNING " %s: switch to bus width %d "
" failed \n " , mmc_hostname ( card - > host ) ,
1 < < bus_width ) ;
err = 0 ;
} else {
mmc_set_bus_width ( card - > host , bus_width ) ;
}
2007-05-01 15:08:30 +02:00
}
2007-05-01 16:00:02 +02:00
if ( ! oldcard )
host - > card = card ;
2007-07-22 22:18:46 +02:00
return 0 ;
2007-05-01 16:00:02 +02:00
free_card :
if ( ! oldcard )
mmc_remove_card ( card ) ;
err :
2007-07-22 23:08:30 +02:00
return err ;
2007-05-01 16:00:02 +02:00
}
/*
* Host is being removed . Free up the current card .
*/
static void mmc_remove ( struct mmc_host * host )
{
BUG_ON ( ! host ) ;
BUG_ON ( ! host - > card ) ;
mmc_remove_card ( host - > card ) ;
host - > card = NULL ;
}
/*
* Card detection callback from host .
*/
static void mmc_detect ( struct mmc_host * host )
{
int err ;
BUG_ON ( ! host ) ;
BUG_ON ( ! host - > card ) ;
mmc_claim_host ( host ) ;
/*
* Just check if our card has been removed .
*/
err = mmc_send_status ( host - > card , NULL ) ;
mmc_release_host ( host ) ;
2007-07-22 22:18:46 +02:00
if ( err ) {
2007-05-19 13:39:01 +02:00
mmc_remove ( host ) ;
2007-05-01 16:00:02 +02:00
mmc_claim_host ( host ) ;
mmc_detach_bus ( host ) ;
mmc_release_host ( host ) ;
}
}
/*
* Suspend callback from host .
*/
2009-09-22 16:45:29 -07:00
static int mmc_suspend ( struct mmc_host * host )
2007-05-01 16:00:02 +02:00
{
BUG_ON ( ! host ) ;
BUG_ON ( ! host - > card ) ;
2006-12-31 00:11:32 +01:00
2007-05-01 16:00:02 +02:00
mmc_claim_host ( host ) ;
MMC core learns about SPI
Teach the MMC/SD/SDIO core about using SPI mode.
- Use mmc_host_is_spi() so enumeration works through SPI signaling
and protocols, not just the native versions.
- Provide the SPI response type flags with each request issued,
including requests from the new lock/unlock code.
- Understand that cmd->resp[0] and mmc_get_status() results for SPI
return different values than for "native" MMC/SD protocol; this
affects resetting, checking card lock status, and some others.
- Understand that some commands act a bit differently ... notably:
* OP_COND command doesn't return the OCR
* APP_CMD status doesn't have an R1_APP_CMD analogue
Those changes required some new and updated primitives:
- Provide utilities to access two SPI-only requests, and one
request that wasn't previously needed:
* mmc_spi_read_ocr() ... SPI only
* mmc_spi_set_crc() ... SPI only (override by module parm)
* mmc_send_cid() ... for use without broadcast mode
- Updated internal routines:
* Previous mmc_send_csd() modified into mmc_send_cxd_native();
it uses native "R2" responses, which include 16 bytes of data.
* Previous mmc_send_ext_csd() becomes new mmc_send_cxd_data()
helper for command-and-data access
* Bugfix to that mmc_send_cxd_data() code: dma-to-stack is
unsafe/nonportable, so kmalloc a bounce buffer instead.
- Modified mmc_send_ext_csd() now uses mmc_send_cxd_data() helper
- Modified mmc_send_csd(), and new mmc_spi_send_cid(), routines use
those helper routines based on whether they're native or SPI
The newest categories of cards supported by the MMC stack aren't expected
to work yet with SPI: MMC or SD cards with over 4GB data, and SDIO.
All those cards support SPI mode, so eventually they should work too.
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
2007-08-08 09:11:32 -07:00
if ( ! mmc_host_is_spi ( host ) )
mmc_deselect_cards ( host ) ;
2007-05-01 16:00:02 +02:00
host - > card - > state & = ~ MMC_STATE_HIGHSPEED ;
2006-12-31 00:11:32 +01:00
mmc_release_host ( host ) ;
2009-09-22 16:45:29 -07:00
return 0 ;
2007-05-01 16:00:02 +02:00
}
2006-12-31 00:11:32 +01:00
2007-05-01 16:00:02 +02:00
/*
* Resume callback from host .
*
* This function tries to determine if the same card is still present
* and , if so , restore all state to it .
*/
2009-09-22 16:45:29 -07:00
static int mmc_resume ( struct mmc_host * host )
2007-05-01 16:00:02 +02:00
{
int err ;
BUG_ON ( ! host ) ;
BUG_ON ( ! host - > card ) ;
mmc_claim_host ( host ) ;
2007-05-19 16:14:43 +02:00
err = mmc_init_card ( host , host - > ocr , host - > card ) ;
2007-07-22 17:52:06 +02:00
mmc_release_host ( host ) ;
2009-09-22 16:45:29 -07:00
return err ;
2007-05-01 16:00:02 +02:00
}
2009-09-22 16:44:33 -07:00
static void mmc_power_restore ( struct mmc_host * host )
{
host - > card - > state & = ~ MMC_STATE_HIGHSPEED ;
mmc_claim_host ( host ) ;
mmc_init_card ( host , host - > ocr , host - > card ) ;
mmc_release_host ( host ) ;
}
2009-09-22 16:44:34 -07:00
static int mmc_sleep ( struct mmc_host * host )
{
struct mmc_card * card = host - > card ;
int err = - ENOSYS ;
if ( card & & card - > ext_csd . rev > = 3 ) {
err = mmc_card_sleepawake ( host , 1 ) ;
if ( err < 0 )
pr_debug ( " %s: Error %d while putting card into sleep " ,
mmc_hostname ( host ) , err ) ;
}
return err ;
}
static int mmc_awake ( struct mmc_host * host )
{
struct mmc_card * card = host - > card ;
int err = - ENOSYS ;
if ( card & & card - > ext_csd . rev > = 3 ) {
err = mmc_card_sleepawake ( host , 0 ) ;
if ( err < 0 )
pr_debug ( " %s: Error %d while awaking sleeping card " ,
mmc_hostname ( host ) , err ) ;
}
return err ;
}
2007-05-01 16:00:02 +02:00
static const struct mmc_bus_ops mmc_ops = {
2009-09-22 16:44:34 -07:00
. awake = mmc_awake ,
. sleep = mmc_sleep ,
2009-09-22 16:44:32 -07:00
. remove = mmc_remove ,
. detect = mmc_detect ,
. suspend = NULL ,
. resume = NULL ,
2009-09-22 16:44:33 -07:00
. power_restore = mmc_power_restore ,
2009-09-22 16:44:32 -07:00
} ;
static const struct mmc_bus_ops mmc_ops_unsafe = {
2009-09-22 16:44:34 -07:00
. awake = mmc_awake ,
. sleep = mmc_sleep ,
2007-05-01 16:00:02 +02:00
. remove = mmc_remove ,
. detect = mmc_detect ,
. suspend = mmc_suspend ,
. resume = mmc_resume ,
2009-09-22 16:44:33 -07:00
. power_restore = mmc_power_restore ,
2007-05-01 16:00:02 +02:00
} ;
2009-09-22 16:44:32 -07:00
static void mmc_attach_bus_ops ( struct mmc_host * host )
{
const struct mmc_bus_ops * bus_ops ;
2009-12-14 18:01:29 -08:00
if ( host - > caps & MMC_CAP_NONREMOVABLE | | ! mmc_assume_removable )
2009-09-22 16:44:32 -07:00
bus_ops = & mmc_ops_unsafe ;
else
bus_ops = & mmc_ops ;
mmc_attach_bus ( host , bus_ops ) ;
}
2007-05-01 16:00:02 +02:00
/*
* Starting point for MMC card init .
*/
int mmc_attach_mmc ( struct mmc_host * host , u32 ocr )
{
int err ;
BUG_ON ( ! host ) ;
2007-08-09 13:23:56 +02:00
WARN_ON ( ! host - > claimed ) ;
2007-05-01 16:00:02 +02:00
2009-09-22 16:44:32 -07:00
mmc_attach_bus_ops ( host ) ;
2007-05-01 16:00:02 +02:00
MMC core learns about SPI
Teach the MMC/SD/SDIO core about using SPI mode.
- Use mmc_host_is_spi() so enumeration works through SPI signaling
and protocols, not just the native versions.
- Provide the SPI response type flags with each request issued,
including requests from the new lock/unlock code.
- Understand that cmd->resp[0] and mmc_get_status() results for SPI
return different values than for "native" MMC/SD protocol; this
affects resetting, checking card lock status, and some others.
- Understand that some commands act a bit differently ... notably:
* OP_COND command doesn't return the OCR
* APP_CMD status doesn't have an R1_APP_CMD analogue
Those changes required some new and updated primitives:
- Provide utilities to access two SPI-only requests, and one
request that wasn't previously needed:
* mmc_spi_read_ocr() ... SPI only
* mmc_spi_set_crc() ... SPI only (override by module parm)
* mmc_send_cid() ... for use without broadcast mode
- Updated internal routines:
* Previous mmc_send_csd() modified into mmc_send_cxd_native();
it uses native "R2" responses, which include 16 bytes of data.
* Previous mmc_send_ext_csd() becomes new mmc_send_cxd_data()
helper for command-and-data access
* Bugfix to that mmc_send_cxd_data() code: dma-to-stack is
unsafe/nonportable, so kmalloc a bounce buffer instead.
- Modified mmc_send_ext_csd() now uses mmc_send_cxd_data() helper
- Modified mmc_send_csd(), and new mmc_spi_send_cid(), routines use
those helper routines based on whether they're native or SPI
The newest categories of cards supported by the MMC stack aren't expected
to work yet with SPI: MMC or SD cards with over 4GB data, and SDIO.
All those cards support SPI mode, so eventually they should work too.
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
2007-08-08 09:11:32 -07:00
/*
* We need to get OCR a different way for SPI .
*/
if ( mmc_host_is_spi ( host ) ) {
err = mmc_spi_read_ocr ( host , 1 , & ocr ) ;
if ( err )
goto err ;
}
2007-05-01 16:00:02 +02:00
/*
* Sanity check the voltages that the card claims to
* support .
*/
if ( ocr & 0x7F ) {
printk ( KERN_WARNING " %s: card claims to support voltages "
" below the defined range. These will be ignored. \n " ,
mmc_hostname ( host ) ) ;
ocr & = ~ 0x7F ;
}
host - > ocr = mmc_select_voltage ( host , ocr ) ;
/*
* Can we support the voltage of the card ?
*/
2007-07-23 00:12:10 +02:00
if ( ! host - > ocr ) {
err = - EINVAL ;
2007-05-01 16:00:02 +02:00
goto err ;
2007-07-23 00:12:10 +02:00
}
2007-05-01 16:00:02 +02:00
/*
* Detect and init the card .
*/
2007-05-19 16:14:43 +02:00
err = mmc_init_card ( host , host - > ocr , NULL ) ;
2007-07-22 22:18:46 +02:00
if ( err )
2007-05-01 16:00:02 +02:00
goto err ;
mmc_release_host ( host ) ;
2007-05-19 13:39:01 +02:00
err = mmc_add_card ( host - > card ) ;
2006-12-31 00:11:32 +01:00
if ( err )
2007-07-22 17:52:06 +02:00
goto remove_card ;
2006-12-31 00:11:32 +01:00
return 0 ;
2007-07-22 17:52:06 +02:00
remove_card :
2007-05-01 16:00:02 +02:00
mmc_remove_card ( host - > card ) ;
2006-12-31 00:11:32 +01:00
host - > card = NULL ;
2007-07-22 17:52:06 +02:00
mmc_claim_host ( host ) ;
2006-12-31 00:11:32 +01:00
err :
mmc_detach_bus ( host ) ;
mmc_release_host ( host ) ;
2007-07-23 00:12:10 +02:00
printk ( KERN_ERR " %s: error %d whilst initialising MMC card \n " ,
mmc_hostname ( host ) , err ) ;
2007-07-22 23:08:30 +02:00
return err ;
2006-12-31 00:11:32 +01:00
}