2006-12-31 02:11:32 +03:00
/*
2007-07-11 22:04:50 +04:00
* linux / drivers / mmc / core / sd . c
2006-12-31 02:11:32 +03:00
*
* Copyright ( C ) 2003 - 2004 Russell King , All Rights Reserved .
* SD support Copyright ( C ) 2004 Ian Molton , All Rights Reserved .
* Copyright ( C ) 2005 - 2007 Pierre Ossman , 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>
2007-06-01 00:25:11 +04:00
# include <linux/mmc/sd.h>
2006-12-31 02:11:32 +03:00
# 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"
# include "sd_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 .
*/
static void mmc_decode_cid ( struct mmc_card * card )
{
u32 * resp = card - > raw_cid ;
memset ( & card - > cid , 0 , sizeof ( struct mmc_cid ) ) ;
/*
* SD doesn ' t currently have a version field so we will
* have to assume we can parse this .
*/
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 . hwrev = UNSTUFF_BITS ( resp , 60 , 4 ) ;
card - > cid . fwrev = UNSTUFF_BITS ( resp , 56 , 4 ) ;
card - > cid . serial = UNSTUFF_BITS ( resp , 24 , 32 ) ;
card - > cid . year = UNSTUFF_BITS ( resp , 12 , 8 ) ;
card - > cid . month = UNSTUFF_BITS ( resp , 8 , 4 ) ;
card - > cid . year + = 2000 ; /* SD cards year offset */
}
/*
* 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 ;
csd_struct = UNSTUFF_BITS ( resp , 126 , 2 ) ;
switch ( csd_struct ) {
case 0 :
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 ) ;
break ;
case 1 :
/*
* This is a block - addressed SDHC card . Most
* interesting fields are unused and have fixed
* values . To avoid getting tripped by buggy cards ,
* we assume those fixed values ourselves .
*/
mmc_card_set_blockaddr ( card ) ;
csd - > tacc_ns = 0 ; /* Unused */
csd - > tacc_clks = 0 ; /* Unused */
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 ) ;
m = UNSTUFF_BITS ( resp , 48 , 22 ) ;
csd - > capacity = ( 1 + m ) < < 10 ;
csd - > read_blkbits = 9 ;
csd - > read_partial = 0 ;
csd - > write_misalign = 0 ;
csd - > read_misalign = 0 ;
csd - > r2w_factor = 4 ; /* Unused */
csd - > write_blkbits = 9 ;
csd - > write_partial = 0 ;
break ;
default :
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
}
2007-05-01 18:11:57 +04:00
return 0 ;
2006-12-31 02:11:32 +03:00
}
/*
* Given a 64 - bit response , decode to our card SCR structure .
*/
2007-05-01 18:11:57 +04:00
static int mmc_decode_scr ( struct mmc_card * card )
2006-12-31 02:11:32 +03:00
{
struct sd_scr * scr = & card - > scr ;
unsigned int scr_struct ;
u32 resp [ 4 ] ;
resp [ 3 ] = card - > raw_scr [ 1 ] ;
resp [ 2 ] = card - > raw_scr [ 0 ] ;
scr_struct = UNSTUFF_BITS ( resp , 60 , 4 ) ;
if ( scr_struct ! = 0 ) {
2007-07-24 23:53:43 +04:00
printk ( KERN_ERR " %s: unrecognised SCR structure version %d \n " ,
2006-12-31 02:11:32 +03:00
mmc_hostname ( card - > host ) , scr_struct ) ;
2007-05-01 18:11:57 +04:00
return - EINVAL ;
2006-12-31 02:11:32 +03:00
}
scr - > sda_vsn = UNSTUFF_BITS ( resp , 56 , 4 ) ;
scr - > bus_widths = UNSTUFF_BITS ( resp , 48 , 4 ) ;
2007-05-01 18:11:57 +04:00
return 0 ;
2006-12-31 02:11:32 +03:00
}
/*
2007-05-01 16:46:08 +04:00
* Fetches and decodes switch information
2006-12-31 02:11:32 +03:00
*/
2007-05-01 16:46:08 +04:00
static int mmc_read_switch ( struct mmc_card * card )
2006-12-31 02:11:32 +03:00
{
int err ;
u8 * status ;
2007-06-01 00:25:11 +04:00
if ( card - > scr . sda_vsn < SCR_SPEC_VER_1 )
2007-07-23 00:18:46 +04:00
return 0 ;
2007-06-01 00:25:11 +04:00
if ( ! ( card - > csd . cmdclass & CCC_SWITCH ) ) {
printk ( KERN_WARNING " %s: card lacks mandatory switch "
" function, performance might suffer. \n " ,
mmc_hostname ( card - > host ) ) ;
2007-07-23 00:18:46 +04:00
return 0 ;
2007-06-01 00:25:11 +04:00
}
2007-07-23 00:18:46 +04:00
err = - EIO ;
2006-12-31 02:11:32 +03:00
status = kmalloc ( 64 , GFP_KERNEL ) ;
if ( ! status ) {
2007-07-24 23:53:43 +04:00
printk ( KERN_ERR " %s: could not allocate a buffer for "
" switch capabilities. \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_sd_switch ( card , 0 , 0 , 1 , status ) ;
2007-07-23 00:18:46 +04:00
if ( err ) {
2009-09-23 03:45:26 +04:00
/* If the host or the card can't do the switch,
* fail more gracefully . */
if ( ( err ! = - EINVAL )
& & ( err ! = - ENOSYS )
& & ( err ! = - EFAULT ) )
2007-07-23 01:08:30 +04:00
goto out ;
2007-06-01 00:25:11 +04:00
printk ( KERN_WARNING " %s: problem reading switch "
" capabilities, performance might suffer. \n " ,
mmc_hostname ( card - > host ) ) ;
2007-07-23 00:18:46 +04:00
err = 0 ;
2007-07-23 01:08:30 +04:00
2006-12-31 02:11:32 +03:00
goto out ;
}
if ( status [ 13 ] & 0x02 )
card - > sw_caps . hs_max_dtr = 50000000 ;
2007-05-01 16:46:08 +04:00
out :
kfree ( status ) ;
return err ;
}
/*
* Test if the card supports high - speed mode and , if so , switch to it .
*/
static int mmc_switch_hs ( struct mmc_card * card )
{
int err ;
u8 * status ;
2007-06-01 00:25:11 +04:00
if ( card - > scr . sda_vsn < SCR_SPEC_VER_1 )
2007-07-23 00:18:46 +04:00
return 0 ;
2007-06-01 00:25:11 +04:00
if ( ! ( card - > csd . cmdclass & CCC_SWITCH ) )
2007-07-23 00:18:46 +04:00
return 0 ;
2007-06-01 00:25:11 +04:00
2007-05-01 16:46:08 +04:00
if ( ! ( card - > host - > caps & MMC_CAP_SD_HIGHSPEED ) )
2007-07-23 00:18:46 +04:00
return 0 ;
2007-05-01 16:46:08 +04:00
if ( card - > sw_caps . hs_max_dtr = = 0 )
2007-07-23 00:18:46 +04:00
return 0 ;
2007-05-01 16:46:08 +04:00
2007-07-23 00:18:46 +04:00
err = - EIO ;
2007-05-01 16:46:08 +04:00
status = kmalloc ( 64 , GFP_KERNEL ) ;
if ( ! status ) {
2007-07-24 23:53:43 +04:00
printk ( KERN_ERR " %s: could not allocate a buffer for "
" switch capabilities. \n " , mmc_hostname ( card - > host ) ) ;
2007-07-23 00:18:46 +04:00
return - ENOMEM ;
2007-05-01 16:46:08 +04:00
}
2006-12-31 02:11:32 +03:00
err = mmc_sd_switch ( card , 1 , 0 , 1 , status ) ;
2007-07-23 00:18:46 +04:00
if ( err )
2006-12-31 02:11:32 +03:00
goto out ;
if ( ( status [ 16 ] & 0xF ) ! = 1 ) {
printk ( KERN_WARNING " %s: Problem switching card "
" into high-speed mode! \n " ,
mmc_hostname ( card - > host ) ) ;
} else {
mmc_card_set_highspeed ( card ) ;
mmc_set_timing ( card - > host , MMC_TIMING_SD_HS ) ;
}
out :
kfree ( status ) ;
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 ( scr , " %08x%08x \n " , card - > raw_scr [ 0 ] , card - > raw_scr [ 1 ] ) ;
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 * sd_std_attrs [ ] = {
& dev_attr_cid . attr ,
& dev_attr_csd . attr ,
& dev_attr_scr . 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 sd_std_attr_group = {
. attrs = sd_std_attrs ,
} ;
2009-06-24 21:06:31 +04:00
static const struct attribute_group * sd_attr_groups [ ] = {
2008-03-22 01:54:50 +03:00
& sd_std_attr_group ,
NULL ,
} ;
static struct device_type sd_type = {
. groups = sd_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-01 18:00:02 +04:00
static int mmc_sd_init_card ( struct mmc_host * host , u32 ocr ,
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 ) ;
/*
* If SD_SEND_IF_COND indicates an SD 2.0
* compliant card and we should set bit 30
* of the ocr to indicate that we can handle
* block - addressed SDHC cards .
*/
2007-05-01 18:00:02 +04:00
err = mmc_send_if_cond ( host , ocr ) ;
2007-07-23 00:18:46 +04:00
if ( ! err )
2007-05-01 18:00:02 +04:00
ocr | = 1 < < 30 ;
2006-12-31 02:11:32 +03:00
2007-05-01 18:00:02 +04:00
err = mmc_send_app_op_cond ( host , ocr , 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
/*
* 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
}
2006-12-31 02:11:32 +03: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 , & sd_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
}
2007-05-01 18:00:02 +04:00
card - > type = MMC_TYPE_SD ;
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 : get 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_send_relative_addr ( host , & card - > rca ) ;
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 ;
2007-05-01 18:00:02 +04:00
mmc_decode_cid ( card ) ;
}
2006-12-31 02:11:32 +03:00
/*
2007-05-01 18:00:02 +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 ) {
/*
* Fetch SCR from card .
*/
err = mmc_app_send_scr ( card , card - > raw_scr ) ;
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_scr ( card ) ;
if ( err < 0 )
goto free_card ;
2006-12-31 02:11:32 +03:00
2007-05-01 18:00:02 +04:00
/*
* Fetch switch information from card .
*/
err = mmc_read_switch ( card ) ;
2007-07-23 00:18:46 +04:00
if ( err )
2007-05-01 18:00:02 +04:00
goto free_card ;
}
2007-05-01 16:46:08 +04:00
2009-04-07 17:48:16 +04:00
/*
* For SPI , enable CRC as appropriate .
* This CRC enable is located AFTER the reading of the
* card registers because some SDHC cards are not able
* to provide valid CRCs for non - 512 - byte blocks .
*/
if ( mmc_host_is_spi ( host ) ) {
err = mmc_spi_set_crc ( host , use_spi_crc ) ;
if ( err )
goto free_card ;
}
2007-05-01 16:46:08 +04:00
/*
* Attempt to change to high - speed ( if supported )
2006-12-31 02:11:32 +03:00
*/
err = mmc_switch_hs ( card ) ;
2007-07-23 00:18:46 +04:00
if ( err )
2006-12-31 02:11:32 +03:00
goto free_card ;
/*
* Compute bus speed .
*/
max_dtr = ( unsigned int ) - 1 ;
if ( mmc_card_highspeed ( card ) ) {
if ( max_dtr > card - > sw_caps . hs_max_dtr )
max_dtr = card - > sw_caps . hs_max_dtr ;
} else if ( max_dtr > card - > csd . max_dtr ) {
max_dtr = card - > csd . max_dtr ;
}
mmc_set_clock ( host , max_dtr ) ;
/*
* Switch to wider bus ( if supported ) .
*/
2007-06-06 22:23:25 +04:00
if ( ( host - > caps & MMC_CAP_4_BIT_DATA ) & &
2006-12-31 02:11:32 +03:00
( card - > scr . bus_widths & SD_SCR_BUS_WIDTH_4 ) ) {
err = mmc_app_set_bus_width ( card , MMC_BUS_WIDTH_4 ) ;
2007-07-23 00:18:46 +04:00
if ( err )
2006-12-31 02:11:32 +03:00
goto free_card ;
mmc_set_bus_width ( host , MMC_BUS_WIDTH_4 ) ;
}
2007-06-13 21:06:03 +04:00
/*
* Check if read - only switch is active .
*/
if ( ! oldcard ) {
2008-06-17 18:17:39 +04:00
if ( ! host - > ops - > get_ro | | host - > ops - > get_ro ( host ) < 0 ) {
2007-06-13 21:06:03 +04:00
printk ( KERN_WARNING " %s: host does not "
" support reading read-only "
" switch. assuming write-enable. \n " ,
mmc_hostname ( host ) ) ;
} else {
2008-06-17 18:17:39 +04:00
if ( host - > ops - > get_ro ( host ) > 0 )
2007-06-13 21:06:03 +04:00
mmc_card_set_readonly ( card ) ;
}
}
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_sd_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_sd_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 ) ;
2006-12-31 02:11:32 +03:00
mmc_release_host ( host ) ;
2007-07-23 00:18:46 +04:00
if ( err ) {
2007-05-19 15:39:01 +04:00
mmc_sd_remove ( host ) ;
2007-05-01 18:00:02 +04:00
mmc_claim_host ( host ) ;
mmc_detach_bus ( host ) ;
mmc_release_host ( host ) ;
}
}
/*
* Suspend callback from host .
*/
2009-09-23 03:45:29 +04:00
static int mmc_sd_suspend ( struct mmc_host * host )
2007-05-01 18:00:02 +04:00
{
BUG_ON ( ! host ) ;
BUG_ON ( ! host - > card ) ;
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 ;
mmc_release_host ( host ) ;
2009-09-23 03:45:29 +04:00
return 0 ;
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 .
*/
2009-09-23 03:45:29 +04:00
static int mmc_sd_resume ( struct mmc_host * host )
2007-05-01 18:00:02 +04:00
{
int err ;
BUG_ON ( ! host ) ;
BUG_ON ( ! host - > card ) ;
mmc_claim_host ( host ) ;
err = mmc_sd_init_card ( host , host - > ocr , host - > card ) ;
2007-07-22 19:52:06 +04:00
mmc_release_host ( host ) ;
2009-09-23 03:45:29 +04:00
return err ;
2007-05-01 18:00:02 +04:00
}
2009-09-23 03:44:33 +04:00
static void mmc_sd_power_restore ( struct mmc_host * host )
{
host - > card - > state & = ~ MMC_STATE_HIGHSPEED ;
mmc_claim_host ( host ) ;
mmc_sd_init_card ( host , host - > ocr , host - > card ) ;
mmc_release_host ( host ) ;
}
2007-05-01 18:00:02 +04:00
static const struct mmc_bus_ops mmc_sd_ops = {
2009-09-23 03:44:32 +04:00
. remove = mmc_sd_remove ,
. detect = mmc_sd_detect ,
. suspend = NULL ,
. resume = NULL ,
2009-09-23 03:44:33 +04:00
. power_restore = mmc_sd_power_restore ,
2009-09-23 03:44:32 +04:00
} ;
static const struct mmc_bus_ops mmc_sd_ops_unsafe = {
2007-05-01 18:00:02 +04:00
. remove = mmc_sd_remove ,
. detect = mmc_sd_detect ,
. suspend = mmc_sd_suspend ,
. resume = mmc_sd_resume ,
2009-09-23 03:44:33 +04:00
. power_restore = mmc_sd_power_restore ,
2007-05-01 18:00:02 +04:00
} ;
2009-09-23 03:44:32 +04:00
static void mmc_sd_attach_bus_ops ( struct mmc_host * host )
{
const struct mmc_bus_ops * bus_ops ;
2009-12-15 05:01:29 +03:00
if ( host - > caps & MMC_CAP_NONREMOVABLE | | ! mmc_assume_removable )
2009-09-23 03:44:32 +04:00
bus_ops = & mmc_sd_ops_unsafe ;
else
bus_ops = & mmc_sd_ops ;
mmc_attach_bus ( host , bus_ops ) ;
}
2007-05-01 18:00:02 +04:00
/*
* Starting point for SD card init .
*/
int mmc_attach_sd ( 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
2009-09-23 03:44:32 +04:00
mmc_sd_attach_bus_ops ( host ) ;
2007-05-01 18:00:02 +04: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
/*
* We need to get OCR a different way for SPI .
*/
if ( mmc_host_is_spi ( host ) ) {
mmc_go_idle ( host ) ;
err = mmc_spi_read_ocr ( host , 0 , & 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 ;
}
if ( ocr & MMC_VDD_165_195 ) {
printk ( KERN_WARNING " %s: SD card claims to support the "
" incompletely defined 'low voltage range'. This "
" will be ignored. \n " , mmc_hostname ( host ) ) ;
ocr & = ~ MMC_VDD_165_195 ;
}
host - > ocr = mmc_select_voltage ( host , ocr ) ;
/*
* Can we support the voltage ( s ) of the card ( s ) ?
*/
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 .
*/
err = mmc_sd_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 SD card \n " ,
mmc_hostname ( host ) , err ) ;
2007-07-23 01:08:30 +04:00
return err ;
2006-12-31 02:11:32 +03:00
}