2006-12-31 02:11:32 +03:00
/*
2007-07-11 22:04:50 +04:00
* linux / drivers / mmc / core / mmc . c
2006-12-31 02:11:32 +03: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 15:39:01 +04:00
# include "bus.h"
2006-12-31 02:11:32 +03: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 18:11:57 +04:00
static int mmc_decode_cid ( struct mmc_card * card )
2006-12-31 02:11:32 +03: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 23:53:43 +04:00
printk ( KERN_ERR " %s: card has unknown MMCA version %d \n " ,
2006-12-31 02:11:32 +03:00
mmc_hostname ( card - > host ) , card - > csd . mmca_vsn ) ;
2007-05-01 18:11:57 +04:00
return - EINVAL ;
2006-12-31 02:11:32 +03:00
}
2007-05-01 18:11:57 +04:00
return 0 ;
2006-12-31 02:11:32 +03:00
}
/*
* Given a 128 - bit response , decode to our card CSD structure .
*/
2007-05-01 18:11:57 +04:00
static int mmc_decode_csd ( struct mmc_card * card )
2006-12-31 02:11:32 +03: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 23:53:43 +04:00
printk ( KERN_ERR " %s: unrecognised CSD structure version %d \n " ,
2006-12-31 02:11:32 +03:00
mmc_hostname ( card - > host ) , csd_struct ) ;
2007-05-01 18:11:57 +04:00
return - EINVAL ;
2006-12-31 02:11:32 +03: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 18:11:57 +04:00
return 0 ;
2006-12-31 02:11:32 +03:00
}
/*
2007-05-01 17:08:30 +04:00
* Read and decode extended CSD .
2006-12-31 02:11:32 +03:00
*/
2007-05-01 17:08:30 +04:00
static int mmc_read_ext_csd ( struct mmc_card * card )
2006-12-31 02:11:32 +03:00
{
int err ;
u8 * ext_csd ;
2007-07-23 02:34:07 +04:00
unsigned int ext_csd_struct ;
2006-12-31 02:11:32 +03:00
BUG_ON ( ! card ) ;
if ( card - > csd . mmca_vsn < CSD_SPEC_VER_4 )
2007-07-23 00:18:46 +04:00
return 0 ;
2006-12-31 02:11:32 +03: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-23 01:08:30 +04:00
" receive the ext_csd. \n " , mmc_hostname ( card - > host ) ) ;
2007-07-23 00:18:46 +04:00
return - ENOMEM ;
2006-12-31 02:11:32 +03:00
}
err = mmc_send_ext_csd ( card , ext_csd ) ;
2007-07-23 00:18:46 +04:00
if ( err ) {
2007-07-23 01:08:30 +04:00
/*
* We all hosts that cannot perform the command
* to fail more gracefully
*/
if ( err ! = - EINVAL )
goto out ;
2006-12-31 02:11:32 +03: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-23 00:18:46 +04:00
err = 0 ;
2006-12-31 02:11:32 +03:00
}
2007-07-23 01:08:30 +04:00
2006-12-31 02:11:32 +03:00
goto out ;
}
2007-07-23 02:34:07 +04:00
ext_csd_struct = ext_csd [ EXT_CSD_REV ] ;
2008-11-27 15:30:32 +03:00
if ( ext_csd_struct > 3 ) {
2007-07-24 23:53:43 +04:00
printk ( KERN_ERR " %s: unrecognised EXT_CSD structure "
" version %d \n " , mmc_hostname ( card - > host ) ,
ext_csd_struct ) ;
2007-10-13 20:27:20 +04:00
err = - EINVAL ;
goto out ;
2007-07-23 02:34:07 +04:00
}
if ( ext_csd_struct > = 2 ) {
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 02:11:32 +03: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 ;
}
out :
kfree ( ext_csd ) ;
return err ;
}
2008-03-22 01:54:50 +03: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 21:06:31 +04:00
static const struct attribute_group * mmc_attr_groups [ ] = {
2008-03-22 01:54:50 +03:00
& mmc_std_attr_group ,
NULL ,
} ;
static struct device_type mmc_type = {
. groups = mmc_attr_groups ,
} ;
2006-12-31 02:11:32 +03:00
/*
2007-05-01 18:00:02 +04:00
* Handle the detection and initialisation of a card .
*
2008-06-17 06:20:57 +04:00
* In the case of a resume , " oldcard " will contain the card
2007-05-01 18:00:02 +04:00
* we ' re trying to reinitialise .
2006-12-31 02:11:32 +03:00
*/
2007-05-19 18:14:43 +04:00
static int mmc_init_card ( struct mmc_host * host , u32 ocr ,
2007-05-01 18:00:02 +04:00
struct mmc_card * oldcard )
2006-12-31 02:11:32 +03:00
{
struct mmc_card * card ;
int err ;
u32 cid [ 4 ] ;
unsigned int max_dtr ;
BUG_ON ( ! host ) ;
2007-08-09 15:23:56 +04:00
WARN_ON ( ! host - > claimed ) ;
2006-12-31 02:11:32 +03: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 18:00:02 +04:00
err = mmc_send_op_cond ( host , ocr | ( 1 < < 30 ) , NULL ) ;
2007-07-23 00:18:46 +04:00
if ( err )
2007-05-01 18:00:02 +04:00
goto err ;
2006-12-31 02:11:32 +03: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 20:11:32 +04: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 02:11:32 +03: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 20:11:32 +04:00
if ( mmc_host_is_spi ( host ) )
err = mmc_send_cid ( host , cid ) ;
else
err = mmc_all_send_cid ( host , cid ) ;
2007-07-23 00:18:46 +04:00
if ( err )
2006-12-31 02:11:32 +03:00
goto err ;
2007-05-01 18:00:02 +04:00
if ( oldcard ) {
2007-07-23 01:08:30 +04:00
if ( memcmp ( cid , oldcard - > raw_cid , sizeof ( cid ) ) ! = 0 ) {
err = - ENOENT ;
2007-05-01 18:00:02 +04:00
goto err ;
2007-07-23 01:08:30 +04:00
}
2007-05-01 18:00:02 +04:00
card = oldcard ;
} else {
/*
* Allocate card structure .
*/
2008-03-22 01:54:50 +03:00
card = mmc_alloc_card ( host , & mmc_type ) ;
2007-07-23 01:08:30 +04:00
if ( IS_ERR ( card ) ) {
err = PTR_ERR ( card ) ;
2007-05-01 18:00:02 +04:00
goto err ;
2007-07-23 01:08:30 +04:00
}
2006-12-31 02:11:32 +03:00
2007-05-01 18:00:02 +04:00
card - > type = MMC_TYPE_MMC ;
card - > rca = 1 ;
memcpy ( card - > raw_cid , cid , sizeof ( card - > raw_cid ) ) ;
}
2006-12-31 02:11:32 +03: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 20:11:32 +04:00
* For native busses : set card RCA and quit open drain mode .
2006-12-31 02:11:32 +03: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 20:11:32 +04:00
if ( ! mmc_host_is_spi ( host ) ) {
err = mmc_set_relative_addr ( card ) ;
if ( err )
goto free_card ;
2006-12-31 02:11:32 +03: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 20:11:32 +04:00
mmc_set_bus_mode ( host , MMC_BUSMODE_PUSHPULL ) ;
}
2006-12-31 02:11:32 +03:00
2007-05-01 18:00:02 +04:00
if ( ! oldcard ) {
/*
* Fetch CSD from card .
*/
err = mmc_send_csd ( card , card - > raw_csd ) ;
2007-07-23 00:18:46 +04:00
if ( err )
2007-05-01 18:00:02 +04:00
goto free_card ;
2006-12-31 02:11:32 +03:00
2007-05-01 18:11:57 +04:00
err = mmc_decode_csd ( card ) ;
2007-07-23 01:08:30 +04:00
if ( err )
2007-05-01 18:11:57 +04:00
goto free_card ;
err = mmc_decode_cid ( card ) ;
2007-07-23 01:08:30 +04:00
if ( err )
2007-05-01 18:11:57 +04:00
goto free_card ;
2007-05-01 18:00:02 +04:00
}
2006-12-31 02:11:32 +03:00
/*
2007-05-01 17:08:30 +04:00
* Select card , as all following commands rely on that .
2006-12-31 02:11:32 +03: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 20:11:32 +04:00
if ( ! mmc_host_is_spi ( host ) ) {
err = mmc_select_card ( card ) ;
if ( err )
goto free_card ;
}
2006-12-31 02:11:32 +03:00
2007-05-01 18:00:02 +04: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 20:11:32 +04:00
* Fetch and process extended CSD .
2007-05-01 18:00:02 +04:00
*/
err = mmc_read_ext_csd ( card ) ;
2007-07-23 00:18:46 +04:00
if ( err )
2007-05-01 18:00:02 +04:00
goto free_card ;
}
2006-12-31 02:11:32 +03:00
2007-05-01 17:08:30 +04: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 ) ;
2007-07-23 00:18:46 +04:00
if ( err )
2007-05-01 17:08:30 +04:00
goto free_card ;
mmc_card_set_highspeed ( card ) ;
mmc_set_timing ( card - > host , MMC_TIMING_MMC_HS ) ;
}
2006-12-31 02:11:32 +03: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 17:08:30 +04:00
/*
* Activate wide bus ( if supported ) .
*/
if ( ( card - > csd . mmca_vsn > = CSD_SPEC_VER_4 ) & &
2008-11-17 15:35:21 +03: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 17:08:30 +04:00
err = mmc_switch ( card , EXT_CSD_CMD_SET_NORMAL ,
2008-11-17 15:35:21 +03:00
EXT_CSD_BUS_WIDTH , ext_csd_bit ) ;
2007-07-23 00:18:46 +04:00
if ( err )
2007-05-01 17:08:30 +04:00
goto free_card ;
2008-11-17 15:35:21 +03:00
mmc_set_bus_width ( card - > host , bus_width ) ;
2007-05-01 17:08:30 +04:00
}
2007-05-01 18:00:02 +04:00
if ( ! oldcard )
host - > card = card ;
2007-07-23 00:18:46 +04:00
return 0 ;
2007-05-01 18:00:02 +04:00
free_card :
if ( ! oldcard )
mmc_remove_card ( card ) ;
err :
2007-07-23 01:08:30 +04:00
return err ;
2007-05-01 18:00:02 +04: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-23 00:18:46 +04:00
if ( err ) {
2007-05-19 15:39:01 +04:00
mmc_remove ( host ) ;
2007-05-01 18:00:02 +04:00
mmc_claim_host ( host ) ;
mmc_detach_bus ( host ) ;
mmc_release_host ( host ) ;
}
}
# ifdef CONFIG_MMC_UNSAFE_RESUME
/*
* Suspend callback from host .
*/
static void mmc_suspend ( struct mmc_host * host )
{
BUG_ON ( ! host ) ;
BUG_ON ( ! host - > card ) ;
2006-12-31 02:11:32 +03:00
2007-05-01 18:00:02 +04: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 20:11:32 +04:00
if ( ! mmc_host_is_spi ( host ) )
mmc_deselect_cards ( host ) ;
2007-05-01 18:00:02 +04:00
host - > card - > state & = ~ MMC_STATE_HIGHSPEED ;
2006-12-31 02:11:32 +03:00
mmc_release_host ( host ) ;
2007-05-01 18:00:02 +04:00
}
2006-12-31 02:11:32 +03:00
2007-05-01 18:00:02 +04: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 .
*/
static void mmc_resume ( struct mmc_host * host )
{
int err ;
BUG_ON ( ! host ) ;
BUG_ON ( ! host - > card ) ;
mmc_claim_host ( host ) ;
2007-05-19 18:14:43 +04:00
err = mmc_init_card ( host , host - > ocr , host - > card ) ;
2007-07-22 19:52:06 +04:00
mmc_release_host ( host ) ;
2007-07-23 00:18:46 +04:00
if ( err ) {
2007-05-19 15:39:01 +04:00
mmc_remove ( host ) ;
2007-07-22 19:52:06 +04:00
mmc_claim_host ( host ) ;
2007-05-01 18:00:02 +04:00
mmc_detach_bus ( host ) ;
2007-07-22 19:52:06 +04:00
mmc_release_host ( host ) ;
2007-05-01 18:00:02 +04:00
}
}
# else
# define mmc_suspend NULL
# define mmc_resume NULL
# endif
static const struct mmc_bus_ops mmc_ops = {
. remove = mmc_remove ,
. detect = mmc_detect ,
. suspend = mmc_suspend ,
. resume = mmc_resume ,
} ;
/*
* Starting point for MMC card init .
*/
int mmc_attach_mmc ( struct mmc_host * host , u32 ocr )
{
int err ;
BUG_ON ( ! host ) ;
2007-08-09 15:23:56 +04:00
WARN_ON ( ! host - > claimed ) ;
2007-05-01 18:00:02 +04:00
mmc_attach_bus ( host , & mmc_ops ) ;
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 20:11:32 +04: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 18:00:02 +04: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 02:12:10 +04:00
if ( ! host - > ocr ) {
err = - EINVAL ;
2007-05-01 18:00:02 +04:00
goto err ;
2007-07-23 02:12:10 +04:00
}
2007-05-01 18:00:02 +04:00
/*
* Detect and init the card .
*/
2007-05-19 18:14:43 +04:00
err = mmc_init_card ( host , host - > ocr , NULL ) ;
2007-07-23 00:18:46 +04:00
if ( err )
2007-05-01 18:00:02 +04:00
goto err ;
mmc_release_host ( host ) ;
2007-05-19 15:39:01 +04:00
err = mmc_add_card ( host - > card ) ;
2006-12-31 02:11:32 +03:00
if ( err )
2007-07-22 19:52:06 +04:00
goto remove_card ;
2006-12-31 02:11:32 +03:00
return 0 ;
2007-07-22 19:52:06 +04:00
remove_card :
2007-05-01 18:00:02 +04:00
mmc_remove_card ( host - > card ) ;
2006-12-31 02:11:32 +03:00
host - > card = NULL ;
2007-07-22 19:52:06 +04:00
mmc_claim_host ( host ) ;
2006-12-31 02:11:32 +03:00
err :
mmc_detach_bus ( host ) ;
mmc_release_host ( host ) ;
2007-07-23 02:12:10 +04:00
printk ( KERN_ERR " %s: error %d whilst initialising MMC card \n " ,
mmc_hostname ( host ) , err ) ;
2007-07-23 01:08:30 +04:00
return err ;
2006-12-31 02:11:32 +03:00
}