2007-05-21 22:23:20 +04:00
/*
* linux / drivers / mmc / sdio . c
*
* Copyright 2006 - 2007 Pierre Ossman
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or ( at
* your option ) any later version .
*/
# include <linux/err.h>
2010-10-02 15:54:10 +04:00
# include <linux/pm_runtime.h>
2007-05-21 22:23:20 +04:00
# include <linux/mmc/host.h>
# include <linux/mmc/card.h>
2012-01-11 23:04:52 +04:00
# include <linux/mmc/mmc.h>
2007-06-11 22:25:43 +04:00
# include <linux/mmc/sdio.h>
2007-05-26 15:48:18 +04:00
# include <linux/mmc/sdio_func.h>
2011-04-05 18:50:14 +04:00
# include <linux/mmc/sdio_ids.h>
2007-05-21 22:23:20 +04:00
# include "core.h"
# include "bus.h"
2010-08-11 05:01:40 +04:00
# include "sd.h"
2007-05-26 15:48:18 +04:00
# include "sdio_bus.h"
2007-05-21 22:23:20 +04:00
# include "mmc_ops.h"
# include "sd_ops.h"
# include "sdio_ops.h"
2007-06-16 10:04:16 +04:00
# include "sdio_cis.h"
2007-05-21 22:23:20 +04:00
2007-06-11 23:01:00 +04:00
static int sdio_read_fbr ( struct sdio_func * func )
{
int ret ;
unsigned char data ;
2011-04-05 18:50:14 +04:00
if ( mmc_card_nonstd_func_interface ( func - > card ) ) {
func - > class = SDIO_CLASS_NONE ;
return 0 ;
}
2007-06-11 23:01:00 +04:00
ret = mmc_io_rw_direct ( func - > card , 0 , 0 ,
2007-08-08 17:23:05 +04:00
SDIO_FBR_BASE ( func - > num ) + SDIO_FBR_STD_IF , 0 , & data ) ;
2007-06-11 23:01:00 +04:00
if ( ret )
goto out ;
data & = 0x0f ;
if ( data = = 0x0f ) {
ret = mmc_io_rw_direct ( func - > card , 0 , 0 ,
2007-08-08 17:23:05 +04:00
SDIO_FBR_BASE ( func - > num ) + SDIO_FBR_STD_IF_EXT , 0 , & data ) ;
2007-06-11 23:01:00 +04:00
if ( ret )
goto out ;
}
func - > class = data ;
out :
return ret ;
}
2007-05-26 15:48:18 +04:00
static int sdio_init_func ( struct mmc_card * card , unsigned int fn )
{
2007-06-11 23:01:00 +04:00
int ret ;
2007-05-26 15:48:18 +04:00
struct sdio_func * func ;
BUG_ON ( fn > SDIO_MAX_FUNCS ) ;
func = sdio_alloc_func ( card ) ;
if ( IS_ERR ( func ) )
return PTR_ERR ( func ) ;
func - > num = fn ;
2010-08-11 05:01:50 +04:00
if ( ! ( card - > quirks & MMC_QUIRK_NONSTD_SDIO ) ) {
ret = sdio_read_fbr ( func ) ;
if ( ret )
goto fail ;
2007-06-11 23:01:00 +04:00
2010-08-11 05:01:50 +04:00
ret = sdio_read_func_cis ( func ) ;
if ( ret )
goto fail ;
} else {
func - > vendor = func - > card - > cis . vendor ;
func - > device = func - > card - > cis . device ;
func - > max_blksize = func - > card - > cis . blksize ;
}
2007-06-16 10:04:16 +04:00
2007-05-26 15:48:18 +04:00
card - > sdio_func [ fn - 1 ] = func ;
return 0 ;
2007-06-11 23:01:00 +04:00
fail :
/*
* It is okay to remove the function here even though we hold
* the host lock as we haven ' t registered the device yet .
*/
sdio_remove_func ( func ) ;
return ret ;
2007-05-26 15:48:18 +04:00
}
2012-01-26 18:57:10 +04:00
static int sdio_read_cccr ( struct mmc_card * card , u32 ocr )
2007-06-11 22:25:43 +04:00
{
int ret ;
int cccr_vsn ;
2012-01-26 18:57:10 +04:00
int uhs = ocr & R4_18V_PRESENT ;
2007-06-11 22:25:43 +04:00
unsigned char data ;
2011-11-15 07:14:38 +04:00
unsigned char speed ;
2007-06-11 22:25:43 +04:00
ret = mmc_io_rw_direct ( card , 0 , 0 , SDIO_CCCR_CCCR , 0 , & data ) ;
if ( ret )
goto out ;
cccr_vsn = data & 0x0f ;
2011-10-21 06:16:32 +04:00
if ( cccr_vsn > SDIO_CCCR_REV_3_00 ) {
2011-10-11 10:14:09 +04:00
pr_err ( " %s: unrecognised CCCR structure version %d \n " ,
2007-06-11 22:25:43 +04:00
mmc_hostname ( card - > host ) , cccr_vsn ) ;
return - EINVAL ;
}
card - > cccr . sdio_vsn = ( data & 0xf0 ) > > 4 ;
ret = mmc_io_rw_direct ( card , 0 , 0 , SDIO_CCCR_CAPS , 0 , & data ) ;
if ( ret )
goto out ;
if ( data & SDIO_CCCR_CAP_SMB )
card - > cccr . multi_block = 1 ;
if ( data & SDIO_CCCR_CAP_LSC )
card - > cccr . low_speed = 1 ;
if ( data & SDIO_CCCR_CAP_4BLS )
card - > cccr . wide_bus = 1 ;
if ( cccr_vsn > = SDIO_CCCR_REV_1_10 ) {
ret = mmc_io_rw_direct ( card , 0 , 0 , SDIO_CCCR_POWER , 0 , & data ) ;
if ( ret )
goto out ;
if ( data & SDIO_POWER_SMPC )
card - > cccr . high_power = 1 ;
}
if ( cccr_vsn > = SDIO_CCCR_REV_1_20 ) {
2011-11-15 07:14:38 +04:00
ret = mmc_io_rw_direct ( card , 0 , 0 , SDIO_CCCR_SPEED , 0 , & speed ) ;
2007-06-11 22:25:43 +04:00
if ( ret )
goto out ;
2011-11-15 07:14:38 +04:00
card - > scr . sda_spec3 = 0 ;
card - > sw_caps . sd3_bus_mode = 0 ;
card - > sw_caps . sd3_drv_type = 0 ;
2012-01-26 18:57:10 +04:00
if ( cccr_vsn > = SDIO_CCCR_REV_3_00 & & uhs ) {
2011-11-15 07:14:38 +04:00
card - > scr . sda_spec3 = 1 ;
ret = mmc_io_rw_direct ( card , 0 , 0 ,
SDIO_CCCR_UHS , 0 , & data ) ;
if ( ret )
goto out ;
2012-12-04 15:36:19 +04:00
if ( mmc_host_uhs ( card - > host ) ) {
2011-11-15 07:14:38 +04:00
if ( data & SDIO_UHS_DDR50 )
card - > sw_caps . sd3_bus_mode
| = SD_MODE_UHS_DDR50 ;
if ( data & SDIO_UHS_SDR50 )
card - > sw_caps . sd3_bus_mode
| = SD_MODE_UHS_SDR50 ;
if ( data & SDIO_UHS_SDR104 )
card - > sw_caps . sd3_bus_mode
| = SD_MODE_UHS_SDR104 ;
}
ret = mmc_io_rw_direct ( card , 0 , 0 ,
SDIO_CCCR_DRIVE_STRENGTH , 0 , & data ) ;
if ( ret )
goto out ;
if ( data & SDIO_DRIVE_SDTA )
card - > sw_caps . sd3_drv_type | = SD_DRIVER_TYPE_A ;
if ( data & SDIO_DRIVE_SDTC )
card - > sw_caps . sd3_drv_type | = SD_DRIVER_TYPE_C ;
if ( data & SDIO_DRIVE_SDTD )
card - > sw_caps . sd3_drv_type | = SD_DRIVER_TYPE_D ;
}
/* if no uhs mode ensure we check for high speed */
if ( ! card - > sw_caps . sd3_bus_mode ) {
if ( speed & SDIO_SPEED_SHS ) {
card - > cccr . high_speed = 1 ;
card - > sw_caps . hs_max_dtr = 50000000 ;
} else {
card - > cccr . high_speed = 0 ;
card - > sw_caps . hs_max_dtr = 25000000 ;
}
}
2007-06-11 22:25:43 +04:00
}
out :
return ret ;
}
2007-07-30 20:23:53 +04:00
static int sdio_enable_wide ( struct mmc_card * card )
{
int ret ;
u8 ctrl ;
if ( ! ( card - > host - > caps & MMC_CAP_4_BIT_DATA ) )
return 0 ;
if ( card - > cccr . low_speed & & ! card - > cccr . wide_bus )
return 0 ;
ret = mmc_io_rw_direct ( card , 0 , 0 , SDIO_CCCR_IF , 0 , & ctrl ) ;
if ( ret )
return ret ;
2012-05-15 09:09:43 +04:00
if ( ( ctrl & SDIO_BUS_WIDTH_MASK ) = = SDIO_BUS_WIDTH_RESERVED )
2014-09-13 01:56:56 +04:00
pr_warn ( " %s: SDIO_CCCR_IF is invalid: 0x%02x \n " ,
mmc_hostname ( card - > host ) , ctrl ) ;
2012-05-15 09:09:43 +04:00
/* set as 4-bit bus width */
ctrl & = ~ SDIO_BUS_WIDTH_MASK ;
2007-07-30 20:23:53 +04:00
ctrl | = SDIO_BUS_WIDTH_4BIT ;
ret = mmc_io_rw_direct ( card , 1 , 0 , SDIO_CCCR_IF , ctrl , NULL ) ;
if ( ret )
return ret ;
2010-08-11 05:01:40 +04:00
return 1 ;
2007-07-30 20:23:53 +04:00
}
2009-09-23 03:45:07 +04:00
/*
* If desired , disconnect the pull - up resistor on CD / DAT [ 3 ] ( pin 1 )
* of the card . This may be required on certain setups of boards ,
* controllers and embedded sdio device which do not need the card ' s
* pull - up . As a result , card detection is disabled and power is saved .
*/
static int sdio_disable_cd ( struct mmc_card * card )
{
int ret ;
u8 ctrl ;
2011-04-05 19:02:25 +04:00
if ( ! mmc_card_disable_cd ( card ) )
2009-09-23 03:45:07 +04:00
return 0 ;
ret = mmc_io_rw_direct ( card , 0 , 0 , SDIO_CCCR_IF , 0 , & ctrl ) ;
if ( ret )
return ret ;
ctrl | = SDIO_BUS_CD_DISABLE ;
return mmc_io_rw_direct ( card , 1 , 0 , SDIO_CCCR_IF , ctrl , NULL ) ;
}
2010-03-06 00:43:34 +03:00
/*
* Devices that remain active during a system suspend are
* put back into 1 - bit mode .
*/
static int sdio_disable_wide ( struct mmc_card * card )
{
int ret ;
u8 ctrl ;
if ( ! ( card - > host - > caps & MMC_CAP_4_BIT_DATA ) )
return 0 ;
if ( card - > cccr . low_speed & & ! card - > cccr . wide_bus )
return 0 ;
ret = mmc_io_rw_direct ( card , 0 , 0 , SDIO_CCCR_IF , 0 , & ctrl ) ;
if ( ret )
return ret ;
if ( ! ( ctrl & SDIO_BUS_WIDTH_4BIT ) )
return 0 ;
ctrl & = ~ SDIO_BUS_WIDTH_4BIT ;
ctrl | = SDIO_BUS_ASYNC_INT ;
ret = mmc_io_rw_direct ( card , 1 , 0 , SDIO_CCCR_IF , ctrl , NULL ) ;
if ( ret )
return ret ;
mmc_set_bus_width ( card - > host , MMC_BUS_WIDTH_1 ) ;
return 0 ;
}
2010-08-11 05:01:40 +04:00
static int sdio_enable_4bit_bus ( struct mmc_card * card )
{
int err ;
if ( card - > type = = MMC_TYPE_SDIO )
2015-02-24 05:42:23 +03:00
err = sdio_enable_wide ( card ) ;
else if ( ( card - > host - > caps & MMC_CAP_4_BIT_DATA ) & &
( card - > scr . bus_widths & SD_SCR_BUS_WIDTH_4 ) ) {
2010-08-11 05:01:40 +04:00
err = mmc_app_set_bus_width ( card , MMC_BUS_WIDTH_4 ) ;
if ( err )
return err ;
2015-02-24 05:42:23 +03:00
err = sdio_enable_wide ( card ) ;
if ( err < = 0 )
mmc_app_set_bus_width ( card , MMC_BUS_WIDTH_1 ) ;
2010-08-11 05:01:40 +04:00
} else
return 0 ;
2015-02-24 05:42:23 +03:00
if ( err > 0 ) {
mmc_set_bus_width ( card - > host , MMC_BUS_WIDTH_4 ) ;
err = 0 ;
}
2010-08-11 05:01:40 +04:00
return err ;
}
2008-08-31 19:22:46 +04:00
/*
* Test if the card supports high - speed mode and , if so , switch to it .
*/
2010-08-11 05:01:40 +04:00
static int mmc_sdio_switch_hs ( struct mmc_card * card , int enable )
2008-08-31 19:22:46 +04:00
{
int ret ;
u8 speed ;
if ( ! ( card - > host - > caps & MMC_CAP_SD_HIGHSPEED ) )
return 0 ;
if ( ! card - > cccr . high_speed )
return 0 ;
ret = mmc_io_rw_direct ( card , 0 , 0 , SDIO_CCCR_SPEED , 0 , & speed ) ;
if ( ret )
return ret ;
2010-08-11 05:01:40 +04:00
if ( enable )
speed | = SDIO_SPEED_EHS ;
else
speed & = ~ SDIO_SPEED_EHS ;
2008-08-31 19:22:46 +04:00
ret = mmc_io_rw_direct ( card , 1 , 0 , SDIO_CCCR_SPEED , speed , NULL ) ;
if ( ret )
return ret ;
2010-08-11 05:01:40 +04:00
return 1 ;
}
2008-08-31 19:22:46 +04:00
2010-08-11 05:01:40 +04:00
/*
* Enable SDIO / combo card ' s high - speed mode . Return 0 / 1 if [ not ] supported .
*/
static int sdio_enable_hs ( struct mmc_card * card )
{
int ret ;
ret = mmc_sdio_switch_hs ( card , true ) ;
if ( ret < = 0 | | card - > type = = MMC_TYPE_SDIO )
return ret ;
ret = mmc_sd_switch_hs ( card ) ;
if ( ret < = 0 )
mmc_sdio_switch_hs ( card , false ) ;
return ret ;
}
2010-08-11 05:01:40 +04:00
static unsigned mmc_sdio_get_max_clock ( struct mmc_card * card )
{
unsigned max_dtr ;
2014-04-23 12:07:35 +04:00
if ( mmc_card_hs ( card ) ) {
2010-08-11 05:01:40 +04:00
/*
* The SDIO specification doesn ' t mention how
* the CIS transfer speed register relates to
* high - speed , but it seems that 50 MHz is
* mandatory .
*/
max_dtr = 50000000 ;
} else {
max_dtr = card - > cis . max_dtr ;
}
2010-08-11 05:01:40 +04:00
if ( card - > type = = MMC_TYPE_SD_COMBO )
max_dtr = min ( max_dtr , mmc_sd_get_max_clock ( card ) ) ;
2010-08-11 05:01:40 +04:00
return max_dtr ;
2008-08-31 19:22:46 +04:00
}
2011-11-15 07:14:38 +04:00
static unsigned char host_drive_to_sdio_drive ( int host_strength )
{
switch ( host_strength ) {
case MMC_SET_DRIVER_TYPE_A :
return SDIO_DTSx_SET_TYPE_A ;
case MMC_SET_DRIVER_TYPE_B :
return SDIO_DTSx_SET_TYPE_B ;
case MMC_SET_DRIVER_TYPE_C :
return SDIO_DTSx_SET_TYPE_C ;
case MMC_SET_DRIVER_TYPE_D :
return SDIO_DTSx_SET_TYPE_D ;
default :
return SDIO_DTSx_SET_TYPE_B ;
}
}
static void sdio_select_driver_type ( struct mmc_card * card )
{
2015-02-06 15:12:53 +03:00
int card_drv_type , drive_strength , drv_type ;
2011-11-15 07:14:38 +04:00
unsigned char card_strength ;
int err ;
2015-02-06 15:12:56 +03:00
card - > drive_strength = 0 ;
2015-02-06 15:12:53 +03:00
card_drv_type = card - > sw_caps . sd3_drv_type | SD_DRIVER_TYPE_B ;
2011-11-15 07:14:38 +04:00
2015-02-06 15:12:55 +03:00
drive_strength = mmc_select_drive_strength ( card ,
card - > sw_caps . uhs_max_dtr ,
card_drv_type , & drv_type ) ;
2011-11-15 07:14:38 +04:00
2015-02-06 15:12:52 +03:00
if ( drive_strength ) {
/* if error just use default for drive strength B */
err = mmc_io_rw_direct ( card , 0 , 0 , SDIO_CCCR_DRIVE_STRENGTH , 0 ,
& card_strength ) ;
if ( err )
return ;
2011-11-15 07:14:38 +04:00
2015-02-06 15:12:52 +03:00
card_strength & = ~ ( SDIO_DRIVE_DTSx_MASK < < SDIO_DRIVE_DTSx_SHIFT ) ;
card_strength | = host_drive_to_sdio_drive ( drive_strength ) ;
2011-11-15 07:14:38 +04:00
2015-02-06 15:12:52 +03:00
/* if error default to drive strength B */
err = mmc_io_rw_direct ( card , 1 , 0 , SDIO_CCCR_DRIVE_STRENGTH ,
card_strength , NULL ) ;
if ( err )
return ;
2015-02-06 15:12:56 +03:00
card - > drive_strength = drive_strength ;
2015-02-06 15:12:52 +03:00
}
2011-11-15 07:14:38 +04:00
2015-02-06 15:12:52 +03:00
if ( drv_type )
mmc_set_driver_type ( card - > host , drv_type ) ;
2011-11-15 07:14:38 +04:00
}
static int sdio_set_bus_speed_mode ( struct mmc_card * card )
{
unsigned int bus_speed , timing ;
int err ;
unsigned char speed ;
/*
* If the host doesn ' t support any of the UHS - I modes , fallback on
* default speed .
*/
2012-12-04 15:36:19 +04:00
if ( ! mmc_host_uhs ( card - > host ) )
2011-11-15 07:14:38 +04:00
return 0 ;
bus_speed = SDIO_SPEED_SDR12 ;
timing = MMC_TIMING_UHS_SDR12 ;
if ( ( card - > host - > caps & MMC_CAP_UHS_SDR104 ) & &
( card - > sw_caps . sd3_bus_mode & SD_MODE_UHS_SDR104 ) ) {
bus_speed = SDIO_SPEED_SDR104 ;
timing = MMC_TIMING_UHS_SDR104 ;
card - > sw_caps . uhs_max_dtr = UHS_SDR104_MAX_DTR ;
2012-12-04 15:36:20 +04:00
card - > sd_bus_speed = UHS_SDR104_BUS_SPEED ;
2011-11-15 07:14:38 +04:00
} else if ( ( card - > host - > caps & MMC_CAP_UHS_DDR50 ) & &
( card - > sw_caps . sd3_bus_mode & SD_MODE_UHS_DDR50 ) ) {
bus_speed = SDIO_SPEED_DDR50 ;
timing = MMC_TIMING_UHS_DDR50 ;
card - > sw_caps . uhs_max_dtr = UHS_DDR50_MAX_DTR ;
2012-12-04 15:36:20 +04:00
card - > sd_bus_speed = UHS_DDR50_BUS_SPEED ;
2011-11-15 07:14:38 +04:00
} else if ( ( card - > host - > caps & ( MMC_CAP_UHS_SDR104 |
MMC_CAP_UHS_SDR50 ) ) & & ( card - > sw_caps . sd3_bus_mode &
SD_MODE_UHS_SDR50 ) ) {
bus_speed = SDIO_SPEED_SDR50 ;
timing = MMC_TIMING_UHS_SDR50 ;
card - > sw_caps . uhs_max_dtr = UHS_SDR50_MAX_DTR ;
2012-12-04 15:36:20 +04:00
card - > sd_bus_speed = UHS_SDR50_BUS_SPEED ;
2011-11-15 07:14:38 +04:00
} else if ( ( card - > host - > caps & ( MMC_CAP_UHS_SDR104 |
MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR25 ) ) & &
( card - > sw_caps . sd3_bus_mode & SD_MODE_UHS_SDR25 ) ) {
bus_speed = SDIO_SPEED_SDR25 ;
timing = MMC_TIMING_UHS_SDR25 ;
card - > sw_caps . uhs_max_dtr = UHS_SDR25_MAX_DTR ;
2012-12-04 15:36:20 +04:00
card - > sd_bus_speed = UHS_SDR25_BUS_SPEED ;
2011-11-15 07:14:38 +04:00
} else if ( ( card - > host - > caps & ( MMC_CAP_UHS_SDR104 |
MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR25 |
MMC_CAP_UHS_SDR12 ) ) & & ( card - > sw_caps . sd3_bus_mode &
SD_MODE_UHS_SDR12 ) ) {
bus_speed = SDIO_SPEED_SDR12 ;
timing = MMC_TIMING_UHS_SDR12 ;
card - > sw_caps . uhs_max_dtr = UHS_SDR12_MAX_DTR ;
2012-12-04 15:36:20 +04:00
card - > sd_bus_speed = UHS_SDR12_BUS_SPEED ;
2011-11-15 07:14:38 +04:00
}
err = mmc_io_rw_direct ( card , 0 , 0 , SDIO_CCCR_SPEED , 0 , & speed ) ;
if ( err )
return err ;
speed & = ~ SDIO_SPEED_BSS_MASK ;
speed | = bus_speed ;
err = mmc_io_rw_direct ( card , 1 , 0 , SDIO_CCCR_SPEED , speed , NULL ) ;
if ( err )
return err ;
if ( bus_speed ) {
mmc_set_timing ( card - > host , timing ) ;
mmc_set_clock ( card - > host , card - > sw_caps . uhs_max_dtr ) ;
}
return 0 ;
}
/*
* UHS - I specific initialization procedure
*/
static int mmc_sdio_init_uhs_card ( struct mmc_card * card )
{
int err ;
if ( ! card - > scr . sda_spec3 )
return 0 ;
/*
* Switch to wider bus ( if supported ) .
*/
2015-02-24 05:42:23 +03:00
if ( card - > host - > caps & MMC_CAP_4_BIT_DATA )
2011-11-15 07:14:38 +04:00
err = sdio_enable_4bit_bus ( card ) ;
/* Set the driver strength for the card */
sdio_select_driver_type ( card ) ;
/* Set bus speed mode of the card */
err = sdio_set_bus_speed_mode ( card ) ;
if ( err )
goto out ;
2013-04-17 15:50:53 +04:00
/*
* SPI mode doesn ' t define CMD19 and tuning is only valid for SDR50 and
* SDR104 mode SD - cards . Note that tuning is mandatory for SDR104 .
*/
2014-12-05 20:40:59 +03:00
if ( ! mmc_host_is_spi ( card - > host ) & &
2016-01-13 11:36:55 +03:00
( ( card - > host - > ios . timing = = MMC_TIMING_UHS_SDR50 ) | |
( card - > host - > ios . timing = = MMC_TIMING_UHS_SDR104 ) ) )
2014-12-05 20:40:59 +03:00
err = mmc_execute_tuning ( card ) ;
2011-11-15 07:14:38 +04:00
out :
return err ;
}
2009-09-23 03:45:28 +04:00
/*
* Handle the detection and initialisation of a card .
*
* In the case of a resume , " oldcard " will contain the card
* we ' re trying to reinitialise .
*/
static int mmc_sdio_init_card ( struct mmc_host * host , u32 ocr ,
2010-03-06 00:43:33 +03:00
struct mmc_card * oldcard , int powered_resume )
2009-09-23 03:45:28 +04:00
{
struct mmc_card * card ;
int err ;
2013-01-28 18:08:28 +04:00
int retries = 10 ;
2013-09-13 12:49:34 +04:00
u32 rocr = 0 ;
2013-09-13 13:31:33 +04:00
u32 ocr_card = ocr ;
2009-09-23 03:45:28 +04:00
BUG_ON ( ! host ) ;
WARN_ON ( ! host - > claimed ) ;
2013-09-13 12:49:34 +04:00
/* to query card if 1.8V signalling is supported */
if ( mmc_host_uhs ( host ) )
ocr | = R4_18V_PRESENT ;
2013-01-28 18:08:28 +04:00
try_again :
if ( ! retries ) {
2014-09-13 01:56:56 +04:00
pr_warn ( " %s: Skipping voltage switch \n " , mmc_hostname ( host ) ) ;
2013-01-28 18:08:28 +04:00
ocr & = ~ R4_18V_PRESENT ;
}
2009-09-23 03:45:28 +04:00
/*
* Inform the card of the voltage
*/
2010-03-06 00:43:33 +03:00
if ( ! powered_resume ) {
2013-09-13 12:49:34 +04:00
err = mmc_send_io_op_cond ( host , ocr , & rocr ) ;
2010-03-06 00:43:33 +03:00
if ( err )
goto err ;
}
2009-09-23 03:45:28 +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 ;
}
/*
* Allocate card structure .
*/
card = mmc_alloc_card ( host , NULL ) ;
if ( IS_ERR ( card ) ) {
err = PTR_ERR ( card ) ;
goto err ;
}
2013-09-13 12:49:34 +04:00
if ( ( rocr & R4_MEMORY_PRESENT ) & &
mmc_sd_get_cid ( host , ocr & rocr , card - > raw_cid , NULL ) = = 0 ) {
2010-08-11 05:01:40 +04:00
card - > type = MMC_TYPE_SD_COMBO ;
if ( oldcard & & ( oldcard - > type ! = MMC_TYPE_SD_COMBO | |
memcmp ( card - > raw_cid , oldcard - > raw_cid , sizeof ( card - > raw_cid ) ) ! = 0 ) ) {
mmc_remove_card ( card ) ;
return - ENOENT ;
}
} else {
card - > type = MMC_TYPE_SDIO ;
if ( oldcard & & oldcard - > type ! = MMC_TYPE_SDIO ) {
mmc_remove_card ( card ) ;
return - ENOENT ;
}
}
2009-09-23 03:45:28 +04:00
2010-04-01 12:03:25 +04:00
/*
* Call the optional HC ' s init_card function to handle quirks .
*/
if ( host - > ops - > init_card )
host - > ops - > init_card ( host , card ) ;
2011-11-15 07:14:38 +04:00
/*
* If the host and card support UHS - I mode request the card
* to switch to 1.8 V signaling level . No 1.8 v signalling if
2012-08-05 18:25:40 +04:00
* UHS mode is not enabled to maintain compatibility and some
2011-11-15 07:14:38 +04:00
* systems that claim 1.8 v signalling in fact do not support
* it .
*/
2013-09-13 12:49:34 +04:00
if ( ! powered_resume & & ( rocr & ocr & R4_18V_PRESENT ) ) {
2013-09-12 17:36:34 +04:00
err = mmc_set_signal_voltage ( host , MMC_SIGNAL_VOLTAGE_180 ,
2015-11-26 15:00:47 +03:00
ocr_card ) ;
2013-01-28 18:08:28 +04:00
if ( err = = - EAGAIN ) {
sdio_reset ( host ) ;
mmc_go_idle ( host ) ;
mmc_send_if_cond ( host , host - > ocr_avail ) ;
mmc_remove_card ( card ) ;
retries - - ;
goto try_again ;
} else if ( err ) {
2011-11-15 07:14:38 +04:00
ocr & = ~ R4_18V_PRESENT ;
}
err = 0 ;
} else {
ocr & = ~ R4_18V_PRESENT ;
}
2009-09-23 03:45:28 +04:00
/*
* For native busses : set card RCA and quit open drain mode .
*/
2010-03-06 00:43:33 +03:00
if ( ! powered_resume & & ! mmc_host_is_spi ( host ) ) {
2009-09-23 03:45:28 +04:00
err = mmc_send_relative_addr ( host , & card - > rca ) ;
if ( err )
goto remove ;
2011-03-01 16:41:04 +03:00
/*
* Update oldcard with the new RCA received from the SDIO
* device - - we ' re doing this so that it ' s updated in the
* " card " struct when oldcard overwrites that later .
*/
if ( oldcard )
oldcard - > rca = card - > rca ;
2009-09-23 03:45:28 +04:00
}
2010-08-11 05:01:40 +04:00
/*
* Read CSD , before selecting the card
*/
if ( ! oldcard & & card - > type = = MMC_TYPE_SD_COMBO ) {
err = mmc_sd_get_csd ( host , card ) ;
if ( err )
return err ;
mmc_decode_cid ( card ) ;
}
2009-09-23 03:45:28 +04:00
/*
* Select card , as all following commands rely on that .
*/
2010-03-06 00:43:33 +03:00
if ( ! powered_resume & & ! mmc_host_is_spi ( host ) ) {
2009-09-23 03:45:28 +04:00
err = mmc_select_card ( card ) ;
if ( err )
goto remove ;
}
2010-08-11 05:01:50 +04:00
if ( card - > quirks & MMC_QUIRK_NONSTD_SDIO ) {
/*
* This is non - standard SDIO device , meaning it doesn ' t
* have any CIA ( Common I / O area ) registers present .
* It ' s host ' s responsibility to fill cccr and cis
* structures in init_card ( ) .
*/
mmc_set_clock ( host , card - > cis . max_dtr ) ;
if ( card - > cccr . high_speed ) {
mmc_set_timing ( card - > host , MMC_TIMING_SD_HS ) ;
}
goto finish ;
}
2009-09-23 03:45:28 +04:00
/*
* Read the common registers .
*/
2012-01-26 18:57:10 +04:00
err = sdio_read_cccr ( card , ocr ) ;
2009-09-23 03:45:28 +04:00
if ( err )
goto remove ;
/*
* Read the common CIS tuples .
*/
err = sdio_read_common_cis ( card ) ;
if ( err )
goto remove ;
if ( oldcard ) {
int same = ( card - > cis . vendor = = oldcard - > cis . vendor & &
card - > cis . device = = oldcard - > cis . device ) ;
mmc_remove_card ( card ) ;
2010-08-11 05:01:40 +04:00
if ( ! same )
return - ENOENT ;
2009-09-23 03:45:28 +04:00
card = oldcard ;
}
2013-09-13 13:31:33 +04:00
card - > ocr = ocr_card ;
2011-04-12 02:02:15 +04:00
mmc_fixup_device ( card , NULL ) ;
2009-09-23 03:45:28 +04:00
2010-08-11 05:01:40 +04:00
if ( card - > type = = MMC_TYPE_SD_COMBO ) {
err = mmc_sd_setup_card ( host , card , oldcard ! = NULL ) ;
/* handle as SDIO-only card if memory init failed */
if ( err ) {
mmc_go_idle ( host ) ;
if ( mmc_host_is_spi ( host ) )
/* should not fail, as it worked previously */
mmc_spi_set_crc ( host , use_spi_crc ) ;
card - > type = MMC_TYPE_SDIO ;
} else
card - > dev . type = & sd_type ;
}
/*
* If needed , disconnect card detection pull - up resistor .
*/
err = sdio_disable_cd ( card ) ;
if ( err )
goto remove ;
2011-11-15 07:14:38 +04:00
/* Initialization sequence for UHS-I cards */
/* Only if card supports 1.8v and UHS signaling */
if ( ( ocr & R4_18V_PRESENT ) & & card - > sw_caps . sd3_bus_mode ) {
err = mmc_sdio_init_uhs_card ( card ) ;
if ( err )
goto remove ;
} else {
/*
* Switch to high - speed ( if supported ) .
*/
err = sdio_enable_hs ( card ) ;
if ( err > 0 )
2014-04-23 12:07:35 +04:00
mmc_set_timing ( card - > host , MMC_TIMING_SD_HS ) ;
2011-11-15 07:14:38 +04:00
else if ( err )
goto remove ;
2009-09-23 03:45:28 +04:00
2011-11-15 07:14:38 +04:00
/*
* Change to the card ' s maximum speed .
*/
mmc_set_clock ( host , mmc_sdio_get_max_clock ( card ) ) ;
2009-09-23 03:45:28 +04:00
2011-11-15 07:14:38 +04:00
/*
* Switch to wider bus ( if supported ) .
*/
err = sdio_enable_4bit_bus ( card ) ;
2015-02-24 05:42:23 +03:00
if ( err )
2011-11-15 07:14:38 +04:00
goto remove ;
}
2010-08-11 05:01:50 +04:00
finish :
2009-09-23 03:45:28 +04:00
if ( ! oldcard )
host - > card = card ;
return 0 ;
remove :
if ( ! oldcard )
mmc_remove_card ( card ) ;
err :
return err ;
}
2007-05-21 22:23:20 +04:00
/*
* Host is being removed . Free up the current card .
*/
static void mmc_sdio_remove ( struct mmc_host * host )
{
2007-05-26 15:48:18 +04:00
int i ;
2007-05-21 22:23:20 +04:00
BUG_ON ( ! host ) ;
BUG_ON ( ! host - > card ) ;
2007-05-26 15:48:18 +04:00
for ( i = 0 ; i < host - > card - > sdio_funcs ; i + + ) {
if ( host - > card - > sdio_func [ i ] ) {
sdio_remove_func ( host - > card - > sdio_func [ i ] ) ;
host - > card - > sdio_func [ i ] = NULL ;
}
}
2007-05-21 22:23:20 +04:00
mmc_remove_card ( host - > card ) ;
host - > card = NULL ;
}
2011-11-28 18:22:00 +04:00
/*
* Card detection - card is alive .
*/
static int mmc_sdio_alive ( struct mmc_host * host )
{
return mmc_select_card ( host - > card ) ;
}
2007-05-21 22:23:20 +04:00
/*
* Card detection callback from host .
*/
static void mmc_sdio_detect ( struct mmc_host * host )
{
int err ;
BUG_ON ( ! host ) ;
BUG_ON ( ! host - > card ) ;
2010-10-02 15:54:12 +04:00
/* Make sure card is powered before detecting it */
2010-11-19 10:29:09 +03:00
if ( host - > caps & MMC_CAP_POWER_OFF_CARD ) {
err = pm_runtime_get_sync ( & host - > card - > dev ) ;
2013-04-08 05:36:39 +04:00
if ( err < 0 ) {
pm_runtime_put_noidle ( & host - > card - > dev ) ;
2010-11-19 10:29:09 +03:00
goto out ;
2013-04-08 05:36:39 +04:00
}
2010-11-19 10:29:09 +03:00
}
2010-10-02 15:54:12 +04:00
2007-05-21 22:23:20 +04:00
mmc_claim_host ( host ) ;
/*
* Just check if our card has been removed .
*/
2011-11-28 18:22:00 +04:00
err = _mmc_detect_card_removed ( host ) ;
2007-05-21 22:23:20 +04:00
mmc_release_host ( host ) ;
2010-11-14 13:40:33 +03:00
/*
* Tell PM core it ' s OK to power off the card now .
*
* The _sync variant is used in order to ensure that the card
* is left powered off in case an error occurred , and the card
* is going to be removed .
*
* Since there is no specific reason to believe a new user
* is about to show up at this point , the _sync variant is
* desirable anyway .
*/
2010-11-19 10:29:09 +03:00
if ( host - > caps & MMC_CAP_POWER_OFF_CARD )
pm_runtime_put_sync ( & host - > card - > dev ) ;
2010-11-14 13:40:33 +03:00
2010-10-02 15:54:12 +04:00
out :
2007-05-21 22:23:20 +04:00
if ( err ) {
mmc_sdio_remove ( host ) ;
mmc_claim_host ( host ) ;
mmc_detach_bus ( host ) ;
2011-09-21 22:08:13 +04:00
mmc_power_off ( host ) ;
2007-05-21 22:23:20 +04:00
mmc_release_host ( host ) ;
}
}
2009-09-23 03:45:28 +04:00
/*
2013-06-10 19:03:37 +04:00
* SDIO pre_suspend . We need to suspend all functions separately .
2009-09-23 03:45:28 +04:00
* Therefore all registered functions must have drivers with suspend
* and resume methods . Failing that we simply remove the whole card .
*/
2013-06-10 19:03:37 +04:00
static int mmc_sdio_pre_suspend ( struct mmc_host * host )
2009-09-23 03:45:28 +04:00
{
2009-09-23 03:45:29 +04:00
int i , err = 0 ;
2009-09-23 03:45:28 +04:00
for ( i = 0 ; i < host - > card - > sdio_funcs ; i + + ) {
struct sdio_func * func = host - > card - > sdio_func [ i ] ;
if ( func & & sdio_func_present ( func ) & & func - > dev . driver ) {
const struct dev_pm_ops * pmops = func - > dev . driver - > pm ;
if ( ! pmops | | ! pmops - > suspend | | ! pmops - > resume ) {
2009-09-23 03:45:29 +04:00
/* force removal of entire card in that case */
err = - ENOSYS ;
2013-06-10 19:03:37 +04:00
break ;
}
}
}
return err ;
}
/*
* SDIO suspend . Suspend all functions separately .
*/
static int mmc_sdio_suspend ( struct mmc_host * host )
{
2015-09-11 15:41:55 +03:00
mmc_claim_host ( host ) ;
if ( mmc_card_keep_power ( host ) & & mmc_card_wake_sdio_irq ( host ) )
2010-03-06 00:43:34 +03:00
sdio_disable_wide ( host - > card ) ;
2015-05-07 13:10:13 +03:00
if ( ! mmc_card_keep_power ( host ) ) {
2013-06-10 19:03:38 +04:00
mmc_power_off ( host ) ;
2015-05-07 13:10:13 +03:00
} else if ( host - > retune_period ) {
mmc_retune_timer_stop ( host ) ;
mmc_retune_needed ( host ) ;
}
2013-06-10 19:03:38 +04:00
2015-09-11 15:41:55 +03:00
mmc_release_host ( host ) ;
2014-02-28 15:49:00 +04:00
return 0 ;
2009-09-23 03:45:28 +04:00
}
2009-09-23 03:45:29 +04:00
static int mmc_sdio_resume ( struct mmc_host * host )
2009-09-23 03:45:28 +04:00
{
2014-02-28 15:49:00 +04:00
int err = 0 ;
2009-09-23 03:45:28 +04:00
BUG_ON ( ! host ) ;
BUG_ON ( ! host - > card ) ;
2009-09-23 03:45:29 +04:00
/* Basic card reinitialization. */
2009-09-23 03:45:28 +04:00
mmc_claim_host ( host ) ;
2010-11-28 08:21:29 +03:00
2013-06-10 19:03:38 +04:00
/* Restore power if needed */
if ( ! mmc_card_keep_power ( host ) ) {
2013-09-13 13:31:33 +04:00
mmc_power_up ( host , host - > card - > ocr ) ;
2013-06-10 19:03:38 +04:00
/*
* Tell runtime PM core we just powered up the card ,
* since it still believes the card is powered off .
* Note that currently runtime PM is only enabled
* for SDIO cards that are MMC_CAP_POWER_OFF_CARD
*/
if ( host - > caps & MMC_CAP_POWER_OFF_CARD ) {
pm_runtime_disable ( & host - > card - > dev ) ;
pm_runtime_set_active ( & host - > card - > dev ) ;
pm_runtime_enable ( & host - > card - > dev ) ;
}
}
2010-11-28 08:21:29 +03:00
/* No need to reinitialize powered-resumed nonremovable cards */
2012-12-04 15:36:18 +04:00
if ( mmc_card_is_removable ( host ) | | ! mmc_card_keep_power ( host ) ) {
sdio_reset ( host ) ;
mmc_go_idle ( host ) ;
2014-11-12 06:55:19 +03:00
mmc_send_if_cond ( host , host - > card - > ocr ) ;
err = mmc_send_io_op_cond ( host , 0 , NULL ) ;
if ( ! err )
err = mmc_sdio_init_card ( host , host - > card - > ocr ,
host - > card ,
mmc_card_keep_power ( host ) ) ;
2012-12-04 15:36:18 +04:00
} else if ( mmc_card_keep_power ( host ) & & mmc_card_wake_sdio_irq ( host ) ) {
2010-11-28 08:21:29 +03:00
/* We may have switched to 1-bit mode during suspend */
err = sdio_enable_4bit_bus ( host - > card ) ;
}
2014-08-18 06:48:14 +04:00
if ( ! err & & host - > sdio_irqs ) {
2015-10-02 11:56:11 +03:00
if ( ! ( host - > caps2 & MMC_CAP2_SDIO_IRQ_NOTHREAD ) )
2014-08-18 06:48:14 +04:00
wake_up_process ( host - > sdio_irq_thread ) ;
2015-10-02 11:56:11 +03:00
else if ( host - > caps & MMC_CAP_SDIO_IRQ )
2014-08-18 06:48:14 +04:00
host - > ops - > enable_sdio_irq ( host , 1 ) ;
}
2009-09-23 03:45:28 +04:00
mmc_release_host ( host ) ;
2013-06-10 19:03:38 +04:00
host - > pm_flags & = ~ MMC_PM_KEEP_POWER ;
2009-09-23 03:45:29 +04:00
return err ;
2009-09-23 03:45:28 +04:00
}
2007-05-21 22:23:20 +04:00
2010-10-02 15:54:07 +04:00
static int mmc_sdio_power_restore ( struct mmc_host * host )
{
int ret ;
BUG_ON ( ! host ) ;
BUG_ON ( ! host - > card ) ;
mmc_claim_host ( host ) ;
2011-06-25 22:20:11 +04:00
/*
* Reset the card by performing the same steps that are taken by
* mmc_rescan_try_freq ( ) and mmc_attach_sdio ( ) during a " normal " probe .
*
* sdio_reset ( ) is technically not needed . Having just powered up the
* hardware , it should already be in reset state . However , some
* platforms ( such as SD8686 on OLPC ) do not instantly cut power ,
* meaning that a reset is required when restoring power soon after
* powering off . It is harmless in other cases .
*
* The CMD5 reset ( mmc_send_io_op_cond ( ) ) , according to the SDIO spec ,
* is not necessary for non - removable cards . However , it is required
* for OLPC SD8686 ( which expects a [ CMD5 , 5 , 3 , 7 ] init sequence ) , and
* harmless in other situations .
*
*/
2012-03-01 16:18:05 +04:00
2011-06-25 22:20:11 +04:00
sdio_reset ( host ) ;
mmc_go_idle ( host ) ;
2014-11-12 06:55:19 +03:00
mmc_send_if_cond ( host , host - > card - > ocr ) ;
2011-06-25 22:20:11 +04:00
2013-09-16 13:28:42 +04:00
ret = mmc_send_io_op_cond ( host , 0 , NULL ) ;
2011-06-25 22:20:11 +04:00
if ( ret )
goto out ;
2013-09-16 13:28:42 +04:00
ret = mmc_sdio_init_card ( host , host - > card - > ocr , host - > card ,
2011-04-05 18:43:20 +04:00
mmc_card_keep_power ( host ) ) ;
2010-10-02 15:54:07 +04:00
if ( ! ret & & host - > sdio_irqs )
mmc_signal_sdio_irq ( host ) ;
2011-06-25 22:20:11 +04:00
out :
2010-10-02 15:54:07 +04:00
mmc_release_host ( host ) ;
return ret ;
}
2013-05-02 16:02:37 +04:00
static int mmc_sdio_runtime_suspend ( struct mmc_host * host )
{
/* No references to the card, cut the power to it. */
2015-09-11 15:41:55 +03:00
mmc_claim_host ( host ) ;
2013-05-02 16:02:37 +04:00
mmc_power_off ( host ) ;
2015-09-11 15:41:55 +03:00
mmc_release_host ( host ) ;
2013-05-02 16:02:37 +04:00
return 0 ;
}
static int mmc_sdio_runtime_resume ( struct mmc_host * host )
{
2015-09-11 15:41:55 +03:00
int ret ;
2013-05-02 16:02:37 +04:00
/* Restore power and re-initialize. */
2015-09-11 15:41:55 +03:00
mmc_claim_host ( host ) ;
2013-09-13 13:31:33 +04:00
mmc_power_up ( host , host - > card - > ocr ) ;
2015-09-11 15:41:55 +03:00
ret = mmc_sdio_power_restore ( host ) ;
mmc_release_host ( host ) ;
return ret ;
2013-05-02 16:02:37 +04:00
}
2015-04-23 14:15:42 +03:00
static int mmc_sdio_reset ( struct mmc_host * host )
{
mmc_power_cycle ( host , host - > card - > ocr ) ;
return mmc_sdio_power_restore ( host ) ;
}
2007-05-21 22:23:20 +04:00
static const struct mmc_bus_ops mmc_sdio_ops = {
. remove = mmc_sdio_remove ,
. detect = mmc_sdio_detect ,
2013-06-10 19:03:37 +04:00
. pre_suspend = mmc_sdio_pre_suspend ,
2009-09-23 03:45:28 +04:00
. suspend = mmc_sdio_suspend ,
. resume = mmc_sdio_resume ,
2013-05-02 16:02:37 +04:00
. runtime_suspend = mmc_sdio_runtime_suspend ,
. runtime_resume = mmc_sdio_runtime_resume ,
2010-10-02 15:54:07 +04:00
. power_restore = mmc_sdio_power_restore ,
2011-11-28 18:22:00 +04:00
. alive = mmc_sdio_alive ,
2015-04-23 14:15:42 +03:00
. reset = mmc_sdio_reset ,
2007-05-21 22:23:20 +04:00
} ;
/*
* Starting point for SDIO card init .
*/
2011-01-03 21:36:56 +03:00
int mmc_attach_sdio ( struct mmc_host * host )
2007-05-21 22:23:20 +04:00
{
2011-01-03 21:36:56 +03:00
int err , i , funcs ;
2013-09-13 13:31:33 +04:00
u32 ocr , rocr ;
2007-05-21 22:23:20 +04:00
struct mmc_card * card ;
BUG_ON ( ! host ) ;
2007-08-09 15:23:56 +04:00
WARN_ON ( ! host - > claimed ) ;
2007-05-21 22:23:20 +04:00
2011-01-03 21:36:56 +03:00
err = mmc_send_io_op_cond ( host , 0 , & ocr ) ;
if ( err )
return err ;
2007-05-21 22:23:20 +04:00
mmc_attach_bus ( host , & mmc_sdio_ops ) ;
2010-12-08 12:04:30 +03:00
if ( host - > ocr_avail_sdio )
host - > ocr_avail = host - > ocr_avail_sdio ;
2007-05-21 22:23:20 +04:00
2013-09-13 13:31:33 +04:00
rocr = mmc_select_voltage ( host , ocr ) ;
2007-05-21 22:23:20 +04:00
/*
* Can we support the voltage ( s ) of the card ( s ) ?
*/
2013-09-13 13:31:33 +04:00
if ( ! rocr ) {
2007-05-21 22:23:20 +04:00
err = - EINVAL ;
goto err ;
}
/*
2009-09-23 03:45:28 +04:00
* Detect and init the card .
2007-05-21 22:23:20 +04:00
*/
2013-09-13 13:31:33 +04:00
err = mmc_sdio_init_card ( host , rocr , NULL , 0 ) ;
2013-09-12 18:38:56 +04:00
if ( err )
goto err ;
2009-09-23 03:45:28 +04:00
card = host - > 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
2010-10-02 15:54:10 +04:00
/*
2010-11-19 10:29:09 +03:00
* Enable runtime PM only if supported by host + card + board
2010-10-02 15:54:10 +04:00
*/
2010-11-19 10:29:09 +03:00
if ( host - > caps & MMC_CAP_POWER_OFF_CARD ) {
/*
* Let runtime PM core know our card is active
*/
err = pm_runtime_set_active ( & card - > dev ) ;
if ( err )
goto remove ;
2010-10-02 15:54:10 +04:00
2010-11-19 10:29:09 +03:00
/*
* Enable runtime PM for this card
*/
pm_runtime_enable ( & card - > dev ) ;
}
2010-10-02 15:54:10 +04:00
2007-05-21 22:23:20 +04:00
/*
* The number of functions on the card is encoded inside
* the ocr .
*/
2009-12-18 02:27:18 +03:00
funcs = ( ocr & 0x70000000 ) > > 28 ;
card - > sdio_funcs = 0 ;
2007-07-30 20:23:53 +04:00
2007-05-26 15:48:18 +04:00
/*
* Initialize ( but don ' t add ) all present functions .
*/
2009-12-18 02:27:18 +03:00
for ( i = 0 ; i < funcs ; i + + , card - > sdio_funcs + + ) {
2007-05-26 15:48:18 +04:00
err = sdio_init_func ( host - > card , i + 1 ) ;
if ( err )
goto remove ;
2010-10-02 15:54:11 +04:00
/*
2010-11-19 10:29:09 +03:00
* Enable Runtime PM for this func ( if supported )
2010-10-02 15:54:11 +04:00
*/
2010-11-19 10:29:09 +03:00
if ( host - > caps & MMC_CAP_POWER_OFF_CARD )
pm_runtime_enable ( & card - > sdio_func [ i ] - > dev ) ;
2007-05-26 15:48:18 +04:00
}
2007-05-21 22:23:20 +04:00
2007-05-26 15:48:18 +04:00
/*
* First add the card to the driver model . . .
*/
2011-01-03 21:36:56 +03:00
mmc_release_host ( host ) ;
2007-05-21 22:23:20 +04:00
err = mmc_add_card ( host - > card ) ;
if ( err )
2007-05-26 15:48:18 +04:00
goto remove_added ;
/*
* . . . then the SDIO functions .
*/
for ( i = 0 ; i < funcs ; i + + ) {
err = sdio_add_func ( host - > card - > sdio_func [ i ] ) ;
if ( err )
goto remove_added ;
}
2007-05-21 22:23:20 +04:00
2011-03-04 01:40:10 +03:00
mmc_claim_host ( host ) ;
2007-05-21 22:23:20 +04:00
return 0 ;
2007-05-26 15:48:18 +04:00
remove_added :
/* Remove without lock if the device has been added. */
mmc_sdio_remove ( host ) ;
2007-05-21 22:23:20 +04:00
mmc_claim_host ( host ) ;
2007-05-26 15:48:18 +04:00
remove :
/* And with lock if it hasn't been added. */
2011-01-03 21:36:56 +03:00
mmc_release_host ( host ) ;
2007-05-26 15:48:18 +04:00
if ( host - > card )
mmc_sdio_remove ( host ) ;
2011-01-03 21:36:56 +03:00
mmc_claim_host ( host ) ;
2007-05-21 22:23:20 +04:00
err :
mmc_detach_bus ( host ) ;
2011-10-11 10:14:09 +04:00
pr_err ( " %s: error %d whilst initialising SDIO card \n " ,
2007-05-21 22:23:20 +04:00
mmc_hostname ( host ) , err ) ;
return err ;
}