Merge tag 'mmc-updates-for-3.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc
Pull MMC updates from Chris Ball:
"MMC highlights for 3.13:
Core:
- Improve runtime PM support, remove mmc_{suspend,resume}_host().
- Add MMC_CAP_RUNTIME_RESUME, for delaying MMC resume until we're
outside of the resume sequence (in runtime_resume) to decrease
system resume time.
Drivers:
- dw_mmc: Support HS200 mode.
- sdhci-eshdc-imx: Support SD3.0 SDR clock tuning, DDR on IMX6.
- sdhci-pci: Add support for Intel Clovertrail and Merrifield"
* tag 'mmc-updates-for-3.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc: (108 commits)
mmc: wbsd: Silence compiler warning
mmc: core: Silence compiler warning in __mmc_switch
mmc: sh_mmcif: Convert to clk_prepare|unprepare
mmc: sh_mmcif: Convert to PM macros when defining dev_pm_ops
mmc: dw_mmc: exynos: Revert the sdr_timing assignment
mmc: sdhci: Avoid needless loop while handling SDIO interrupts in sdhci_irq
mmc: core: Add MMC_CAP_RUNTIME_RESUME to resume at runtime_resume
mmc: core: Improve runtime PM support during suspend/resume for sd/mmc
mmc: core: Remove redundant mmc_power_up|off at runtime callbacks
mmc: Don't force card to active state when entering suspend/shutdown
MIPS: db1235: Don't use MMC_CLKGATE
mmc: core: Remove deprecated mmc_suspend|resume_host APIs
mmc: mmci: Move away from using deprecated APIs
mmc: via-sdmmc: Move away from using deprecated APIs
mmc: tmio: Move away from using deprecated APIs
mmc: sh_mmcif: Move away from using deprecated APIs
mmc: sdricoh_cs: Move away from using deprecated APIs
mmc: rtsx: Remove redundant suspend and resume callbacks
mmc: wbsd: Move away from using deprecated APIs
mmc: pxamci: Remove redundant suspend and resume callbacks
...
This commit is contained in:
@@ -342,7 +342,7 @@ int mmc_add_card(struct mmc_card *card)
|
||||
break;
|
||||
}
|
||||
|
||||
if (mmc_sd_card_uhs(card) &&
|
||||
if (mmc_card_uhs(card) &&
|
||||
(card->sd_bus_speed < ARRAY_SIZE(uhs_speeds)))
|
||||
uhs_bus_speed_mode = uhs_speeds[card->sd_bus_speed];
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <linux/log2.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/pm_wakeup.h>
|
||||
#include <linux/suspend.h>
|
||||
#include <linux/fault-inject.h>
|
||||
#include <linux/random.h>
|
||||
@@ -301,7 +302,7 @@ void mmc_start_bkops(struct mmc_card *card, bool from_exception)
|
||||
}
|
||||
|
||||
err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
|
||||
EXT_CSD_BKOPS_START, 1, timeout, use_busy_signal);
|
||||
EXT_CSD_BKOPS_START, 1, timeout, use_busy_signal, true);
|
||||
if (err) {
|
||||
pr_warn("%s: Error %d starting bkops\n",
|
||||
mmc_hostname(card->host), err);
|
||||
@@ -917,31 +918,6 @@ int __mmc_claim_host(struct mmc_host *host, atomic_t *abort)
|
||||
|
||||
EXPORT_SYMBOL(__mmc_claim_host);
|
||||
|
||||
/**
|
||||
* mmc_try_claim_host - try exclusively to claim a host
|
||||
* @host: mmc host to claim
|
||||
*
|
||||
* Returns %1 if the host is claimed, %0 otherwise.
|
||||
*/
|
||||
int mmc_try_claim_host(struct mmc_host *host)
|
||||
{
|
||||
int claimed_host = 0;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&host->lock, flags);
|
||||
if (!host->claimed || host->claimer == current) {
|
||||
host->claimed = 1;
|
||||
host->claimer = current;
|
||||
host->claim_cnt += 1;
|
||||
claimed_host = 1;
|
||||
}
|
||||
spin_unlock_irqrestore(&host->lock, flags);
|
||||
if (host->ops->enable && claimed_host && host->claim_cnt == 1)
|
||||
host->ops->enable(host);
|
||||
return claimed_host;
|
||||
}
|
||||
EXPORT_SYMBOL(mmc_try_claim_host);
|
||||
|
||||
/**
|
||||
* mmc_release_host - release a host
|
||||
* @host: mmc host to release
|
||||
@@ -1382,22 +1358,31 @@ u32 mmc_select_voltage(struct mmc_host *host, u32 ocr)
|
||||
{
|
||||
int bit;
|
||||
|
||||
/*
|
||||
* Sanity check the voltages that the card claims to
|
||||
* support.
|
||||
*/
|
||||
if (ocr & 0x7F) {
|
||||
dev_warn(mmc_dev(host),
|
||||
"card claims to support voltages below defined range\n");
|
||||
ocr &= ~0x7F;
|
||||
}
|
||||
|
||||
ocr &= host->ocr_avail;
|
||||
if (!ocr) {
|
||||
dev_warn(mmc_dev(host), "no support for card's volts\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
bit = ffs(ocr);
|
||||
if (bit) {
|
||||
bit -= 1;
|
||||
|
||||
if (host->caps2 & MMC_CAP2_FULL_PWR_CYCLE) {
|
||||
bit = ffs(ocr) - 1;
|
||||
ocr &= 3 << bit;
|
||||
|
||||
mmc_host_clk_hold(host);
|
||||
host->ios.vdd = bit;
|
||||
mmc_set_ios(host);
|
||||
mmc_host_clk_release(host);
|
||||
mmc_power_cycle(host, ocr);
|
||||
} else {
|
||||
pr_warning("%s: host doesn't support card's voltages\n",
|
||||
mmc_hostname(host));
|
||||
ocr = 0;
|
||||
bit = fls(ocr) - 1;
|
||||
ocr &= 3 << bit;
|
||||
if (bit != host->ios.vdd)
|
||||
dev_warn(mmc_dev(host), "exceeding card's volts\n");
|
||||
}
|
||||
|
||||
return ocr;
|
||||
@@ -1422,7 +1407,7 @@ int __mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage)
|
||||
|
||||
}
|
||||
|
||||
int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage)
|
||||
int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, u32 ocr)
|
||||
{
|
||||
struct mmc_command cmd = {0};
|
||||
int err = 0;
|
||||
@@ -1504,7 +1489,7 @@ power_cycle:
|
||||
if (err) {
|
||||
pr_debug("%s: Signal voltage switch failed, "
|
||||
"power cycling card\n", mmc_hostname(host));
|
||||
mmc_power_cycle(host);
|
||||
mmc_power_cycle(host, ocr);
|
||||
}
|
||||
|
||||
mmc_host_clk_release(host);
|
||||
@@ -1545,22 +1530,14 @@ void mmc_set_driver_type(struct mmc_host *host, unsigned int drv_type)
|
||||
* If a host does all the power sequencing itself, ignore the
|
||||
* initial MMC_POWER_UP stage.
|
||||
*/
|
||||
void mmc_power_up(struct mmc_host *host)
|
||||
void mmc_power_up(struct mmc_host *host, u32 ocr)
|
||||
{
|
||||
int bit;
|
||||
|
||||
if (host->ios.power_mode == MMC_POWER_ON)
|
||||
return;
|
||||
|
||||
mmc_host_clk_hold(host);
|
||||
|
||||
/* If ocr is set, we use it */
|
||||
if (host->ocr)
|
||||
bit = ffs(host->ocr) - 1;
|
||||
else
|
||||
bit = fls(host->ocr_avail) - 1;
|
||||
|
||||
host->ios.vdd = bit;
|
||||
host->ios.vdd = fls(ocr) - 1;
|
||||
if (mmc_host_is_spi(host))
|
||||
host->ios.chip_select = MMC_CS_HIGH;
|
||||
else
|
||||
@@ -1604,13 +1581,6 @@ void mmc_power_off(struct mmc_host *host)
|
||||
host->ios.clock = 0;
|
||||
host->ios.vdd = 0;
|
||||
|
||||
|
||||
/*
|
||||
* Reset ocr mask to be the highest possible voltage supported for
|
||||
* this mmc host. This value will be used at next power up.
|
||||
*/
|
||||
host->ocr = 1 << (fls(host->ocr_avail) - 1);
|
||||
|
||||
if (!mmc_host_is_spi(host)) {
|
||||
host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
|
||||
host->ios.chip_select = MMC_CS_DONTCARE;
|
||||
@@ -1630,12 +1600,12 @@ void mmc_power_off(struct mmc_host *host)
|
||||
mmc_host_clk_release(host);
|
||||
}
|
||||
|
||||
void mmc_power_cycle(struct mmc_host *host)
|
||||
void mmc_power_cycle(struct mmc_host *host, u32 ocr)
|
||||
{
|
||||
mmc_power_off(host);
|
||||
/* Wait at least 1 ms according to SD spec */
|
||||
mmc_delay(1);
|
||||
mmc_power_up(host);
|
||||
mmc_power_up(host, ocr);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1723,6 +1693,28 @@ void mmc_detach_bus(struct mmc_host *host)
|
||||
mmc_bus_put(host);
|
||||
}
|
||||
|
||||
static void _mmc_detect_change(struct mmc_host *host, unsigned long delay,
|
||||
bool cd_irq)
|
||||
{
|
||||
#ifdef CONFIG_MMC_DEBUG
|
||||
unsigned long flags;
|
||||
spin_lock_irqsave(&host->lock, flags);
|
||||
WARN_ON(host->removed);
|
||||
spin_unlock_irqrestore(&host->lock, flags);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If the device is configured as wakeup, we prevent a new sleep for
|
||||
* 5 s to give provision for user space to consume the event.
|
||||
*/
|
||||
if (cd_irq && !(host->caps & MMC_CAP_NEEDS_POLL) &&
|
||||
device_can_wakeup(mmc_dev(host)))
|
||||
pm_wakeup_event(mmc_dev(host), 5000);
|
||||
|
||||
host->detect_change = 1;
|
||||
mmc_schedule_delayed_work(&host->detect, delay);
|
||||
}
|
||||
|
||||
/**
|
||||
* mmc_detect_change - process change of state on a MMC socket
|
||||
* @host: host which changed state.
|
||||
@@ -1735,16 +1727,8 @@ void mmc_detach_bus(struct mmc_host *host)
|
||||
*/
|
||||
void mmc_detect_change(struct mmc_host *host, unsigned long delay)
|
||||
{
|
||||
#ifdef CONFIG_MMC_DEBUG
|
||||
unsigned long flags;
|
||||
spin_lock_irqsave(&host->lock, flags);
|
||||
WARN_ON(host->removed);
|
||||
spin_unlock_irqrestore(&host->lock, flags);
|
||||
#endif
|
||||
host->detect_change = 1;
|
||||
mmc_schedule_delayed_work(&host->detect, delay);
|
||||
_mmc_detect_change(host, delay, true);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(mmc_detect_change);
|
||||
|
||||
void mmc_init_erase(struct mmc_card *card)
|
||||
@@ -2334,7 +2318,7 @@ static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq)
|
||||
pr_info("%s: %s: trying to init card at %u Hz\n",
|
||||
mmc_hostname(host), __func__, host->f_init);
|
||||
#endif
|
||||
mmc_power_up(host);
|
||||
mmc_power_up(host, host->ocr_avail);
|
||||
|
||||
/*
|
||||
* Some eMMCs (with VCCQ always on) may not be reset after power up, so
|
||||
@@ -2423,7 +2407,7 @@ int mmc_detect_card_removed(struct mmc_host *host)
|
||||
* rescan handle the card removal.
|
||||
*/
|
||||
cancel_delayed_work(&host->detect);
|
||||
mmc_detect_change(host, 0);
|
||||
_mmc_detect_change(host, 0, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2504,8 +2488,8 @@ void mmc_start_host(struct mmc_host *host)
|
||||
if (host->caps2 & MMC_CAP2_NO_PRESCAN_POWERUP)
|
||||
mmc_power_off(host);
|
||||
else
|
||||
mmc_power_up(host);
|
||||
mmc_detect_change(host, 0);
|
||||
mmc_power_up(host, host->ocr_avail);
|
||||
_mmc_detect_change(host, 0, false);
|
||||
}
|
||||
|
||||
void mmc_stop_host(struct mmc_host *host)
|
||||
@@ -2583,7 +2567,7 @@ int mmc_power_restore_host(struct mmc_host *host)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mmc_power_up(host);
|
||||
mmc_power_up(host, host->card->ocr);
|
||||
ret = host->bus_ops->power_restore(host);
|
||||
|
||||
mmc_bus_put(host);
|
||||
@@ -2657,28 +2641,6 @@ EXPORT_SYMBOL(mmc_cache_ctrl);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
/**
|
||||
* mmc_suspend_host - suspend a host
|
||||
* @host: mmc host
|
||||
*/
|
||||
int mmc_suspend_host(struct mmc_host *host)
|
||||
{
|
||||
/* This function is deprecated */
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(mmc_suspend_host);
|
||||
|
||||
/**
|
||||
* mmc_resume_host - resume a previously suspended host
|
||||
* @host: mmc host
|
||||
*/
|
||||
int mmc_resume_host(struct mmc_host *host)
|
||||
{
|
||||
/* This function is deprecated */
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(mmc_resume_host);
|
||||
|
||||
/* Do the card removal on suspend if card is assumed removeable
|
||||
* Do that in pm notifier while userspace isn't yet frozen, so we will be able
|
||||
to sync the card.
|
||||
@@ -2724,7 +2686,7 @@ int mmc_pm_notify(struct notifier_block *notify_block,
|
||||
spin_lock_irqsave(&host->lock, flags);
|
||||
host->rescan_disable = 0;
|
||||
spin_unlock_irqrestore(&host->lock, flags);
|
||||
mmc_detect_change(host, 0);
|
||||
_mmc_detect_change(host, 0, false);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -42,13 +42,13 @@ void mmc_set_ungated(struct mmc_host *host);
|
||||
void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode);
|
||||
void mmc_set_bus_width(struct mmc_host *host, unsigned int width);
|
||||
u32 mmc_select_voltage(struct mmc_host *host, u32 ocr);
|
||||
int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage);
|
||||
int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, u32 ocr);
|
||||
int __mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage);
|
||||
void mmc_set_timing(struct mmc_host *host, unsigned int timing);
|
||||
void mmc_set_driver_type(struct mmc_host *host, unsigned int drv_type);
|
||||
void mmc_power_up(struct mmc_host *host);
|
||||
void mmc_power_up(struct mmc_host *host, u32 ocr);
|
||||
void mmc_power_off(struct mmc_host *host);
|
||||
void mmc_power_cycle(struct mmc_host *host);
|
||||
void mmc_power_cycle(struct mmc_host *host, u32 ocr);
|
||||
|
||||
static inline void mmc_delay(unsigned int ms)
|
||||
{
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <linux/err.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/stat.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
#include <linux/mmc/host.h>
|
||||
#include <linux/mmc/card.h>
|
||||
@@ -934,6 +935,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
|
||||
goto err;
|
||||
}
|
||||
|
||||
card->ocr = ocr;
|
||||
card->type = MMC_TYPE_MMC;
|
||||
card->rca = 1;
|
||||
memcpy(card->raw_cid, cid, sizeof(card->raw_cid));
|
||||
@@ -1404,9 +1406,9 @@ static int mmc_poweroff_notify(struct mmc_card *card, unsigned int notify_type)
|
||||
if (notify_type == EXT_CSD_POWER_OFF_LONG)
|
||||
timeout = card->ext_csd.power_off_longtime;
|
||||
|
||||
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
|
||||
EXT_CSD_POWER_OFF_NOTIFICATION,
|
||||
notify_type, timeout);
|
||||
err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
|
||||
EXT_CSD_POWER_OFF_NOTIFICATION,
|
||||
notify_type, timeout, true, false);
|
||||
if (err)
|
||||
pr_err("%s: Power Off Notification timed out, %u\n",
|
||||
mmc_hostname(card->host), timeout);
|
||||
@@ -1477,6 +1479,9 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend)
|
||||
|
||||
mmc_claim_host(host);
|
||||
|
||||
if (mmc_card_suspended(host->card))
|
||||
goto out;
|
||||
|
||||
if (mmc_card_doing_bkops(host->card)) {
|
||||
err = mmc_stop_bkops(host->card);
|
||||
if (err)
|
||||
@@ -1496,19 +1501,54 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend)
|
||||
err = mmc_deselect_cards(host);
|
||||
host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200);
|
||||
|
||||
if (!err)
|
||||
if (!err) {
|
||||
mmc_power_off(host);
|
||||
mmc_card_set_suspended(host->card);
|
||||
}
|
||||
out:
|
||||
mmc_release_host(host);
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Suspend callback from host.
|
||||
* Suspend callback
|
||||
*/
|
||||
static int mmc_suspend(struct mmc_host *host)
|
||||
{
|
||||
return _mmc_suspend(host, true);
|
||||
int err;
|
||||
|
||||
err = _mmc_suspend(host, true);
|
||||
if (!err) {
|
||||
pm_runtime_disable(&host->card->dev);
|
||||
pm_runtime_set_suspended(&host->card->dev);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function tries to determine if the same card is still present
|
||||
* and, if so, restore all state to it.
|
||||
*/
|
||||
static int _mmc_resume(struct mmc_host *host)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
BUG_ON(!host);
|
||||
BUG_ON(!host->card);
|
||||
|
||||
mmc_claim_host(host);
|
||||
|
||||
if (!mmc_card_suspended(host->card))
|
||||
goto out;
|
||||
|
||||
mmc_power_up(host, host->card->ocr);
|
||||
err = mmc_init_card(host, host->card->ocr, host->card);
|
||||
mmc_card_clr_suspended(host->card);
|
||||
|
||||
out:
|
||||
mmc_release_host(host);
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1516,31 +1556,38 @@ static int mmc_suspend(struct mmc_host *host)
|
||||
*/
|
||||
static int mmc_shutdown(struct mmc_host *host)
|
||||
{
|
||||
return _mmc_suspend(host, false);
|
||||
}
|
||||
int err = 0;
|
||||
|
||||
/*
|
||||
* 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 int mmc_resume(struct mmc_host *host)
|
||||
{
|
||||
int err;
|
||||
/*
|
||||
* In a specific case for poweroff notify, we need to resume the card
|
||||
* before we can shutdown it properly.
|
||||
*/
|
||||
if (mmc_can_poweroff_notify(host->card) &&
|
||||
!(host->caps2 & MMC_CAP2_FULL_PWR_CYCLE))
|
||||
err = _mmc_resume(host);
|
||||
|
||||
BUG_ON(!host);
|
||||
BUG_ON(!host->card);
|
||||
|
||||
mmc_claim_host(host);
|
||||
mmc_power_up(host);
|
||||
mmc_select_voltage(host, host->ocr);
|
||||
err = mmc_init_card(host, host->ocr, host->card);
|
||||
mmc_release_host(host);
|
||||
if (!err)
|
||||
err = _mmc_suspend(host, false);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Callback for resume.
|
||||
*/
|
||||
static int mmc_resume(struct mmc_host *host)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
if (!(host->caps & MMC_CAP_RUNTIME_RESUME)) {
|
||||
err = _mmc_resume(host);
|
||||
pm_runtime_set_active(&host->card->dev);
|
||||
pm_runtime_mark_last_busy(&host->card->dev);
|
||||
}
|
||||
pm_runtime_enable(&host->card->dev);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Callback for runtime_suspend.
|
||||
@@ -1552,18 +1599,11 @@ static int mmc_runtime_suspend(struct mmc_host *host)
|
||||
if (!(host->caps & MMC_CAP_AGGRESSIVE_PM))
|
||||
return 0;
|
||||
|
||||
mmc_claim_host(host);
|
||||
|
||||
err = mmc_suspend(host);
|
||||
if (err) {
|
||||
err = _mmc_suspend(host, true);
|
||||
if (err)
|
||||
pr_err("%s: error %d doing aggessive suspend\n",
|
||||
mmc_hostname(host), err);
|
||||
goto out;
|
||||
}
|
||||
mmc_power_off(host);
|
||||
|
||||
out:
|
||||
mmc_release_host(host);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -1574,18 +1614,14 @@ static int mmc_runtime_resume(struct mmc_host *host)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (!(host->caps & MMC_CAP_AGGRESSIVE_PM))
|
||||
if (!(host->caps & (MMC_CAP_AGGRESSIVE_PM | MMC_CAP_RUNTIME_RESUME)))
|
||||
return 0;
|
||||
|
||||
mmc_claim_host(host);
|
||||
|
||||
mmc_power_up(host);
|
||||
err = mmc_resume(host);
|
||||
err = _mmc_resume(host);
|
||||
if (err)
|
||||
pr_err("%s: error %d doing aggessive resume\n",
|
||||
mmc_hostname(host), err);
|
||||
|
||||
mmc_release_host(host);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1595,7 +1631,7 @@ static int mmc_power_restore(struct mmc_host *host)
|
||||
|
||||
host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200);
|
||||
mmc_claim_host(host);
|
||||
ret = mmc_init_card(host, host->ocr, host->card);
|
||||
ret = mmc_init_card(host, host->card->ocr, host->card);
|
||||
mmc_release_host(host);
|
||||
|
||||
return ret;
|
||||
@@ -1640,7 +1676,7 @@ static void mmc_attach_bus_ops(struct mmc_host *host)
|
||||
int mmc_attach_mmc(struct mmc_host *host)
|
||||
{
|
||||
int err;
|
||||
u32 ocr;
|
||||
u32 ocr, rocr;
|
||||
|
||||
BUG_ON(!host);
|
||||
WARN_ON(!host->claimed);
|
||||
@@ -1666,23 +1702,12 @@ int mmc_attach_mmc(struct mmc_host *host)
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sanity check the voltages that the card claims to
|
||||
* support.
|
||||
*/
|
||||
if (ocr & 0x7F) {
|
||||
pr_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);
|
||||
rocr = mmc_select_voltage(host, ocr);
|
||||
|
||||
/*
|
||||
* Can we support the voltage of the card?
|
||||
*/
|
||||
if (!host->ocr) {
|
||||
if (!rocr) {
|
||||
err = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
@@ -1690,7 +1715,7 @@ int mmc_attach_mmc(struct mmc_host *host)
|
||||
/*
|
||||
* Detect and init the card.
|
||||
*/
|
||||
err = mmc_init_card(host, host->ocr, NULL);
|
||||
err = mmc_init_card(host, rocr, NULL);
|
||||
if (err)
|
||||
goto err;
|
||||
|
||||
|
||||
@@ -23,6 +23,40 @@
|
||||
|
||||
#define MMC_OPS_TIMEOUT_MS (10 * 60 * 1000) /* 10 minute timeout */
|
||||
|
||||
static inline int __mmc_send_status(struct mmc_card *card, u32 *status,
|
||||
bool ignore_crc)
|
||||
{
|
||||
int err;
|
||||
struct mmc_command cmd = {0};
|
||||
|
||||
BUG_ON(!card);
|
||||
BUG_ON(!card->host);
|
||||
|
||||
cmd.opcode = MMC_SEND_STATUS;
|
||||
if (!mmc_host_is_spi(card->host))
|
||||
cmd.arg = card->rca << 16;
|
||||
cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC;
|
||||
if (ignore_crc)
|
||||
cmd.flags &= ~MMC_RSP_CRC;
|
||||
|
||||
err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* NOTE: callers are required to understand the difference
|
||||
* between "native" and SPI format status words!
|
||||
*/
|
||||
if (status)
|
||||
*status = cmd.resp[0];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mmc_send_status(struct mmc_card *card, u32 *status)
|
||||
{
|
||||
return __mmc_send_status(card, status, false);
|
||||
}
|
||||
|
||||
static int _mmc_select_card(struct mmc_host *host, struct mmc_card *card)
|
||||
{
|
||||
int err;
|
||||
@@ -370,16 +404,18 @@ int mmc_spi_set_crc(struct mmc_host *host, int use_crc)
|
||||
* @timeout_ms: timeout (ms) for operation performed by register write,
|
||||
* timeout of zero implies maximum possible timeout
|
||||
* @use_busy_signal: use the busy signal as response type
|
||||
* @send_status: send status cmd to poll for busy
|
||||
*
|
||||
* Modifies the EXT_CSD register for selected card.
|
||||
*/
|
||||
int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
|
||||
unsigned int timeout_ms, bool use_busy_signal)
|
||||
unsigned int timeout_ms, bool use_busy_signal, bool send_status)
|
||||
{
|
||||
int err;
|
||||
struct mmc_command cmd = {0};
|
||||
unsigned long timeout;
|
||||
u32 status;
|
||||
u32 status = 0;
|
||||
bool ignore_crc = false;
|
||||
|
||||
BUG_ON(!card);
|
||||
BUG_ON(!card->host);
|
||||
@@ -408,17 +444,37 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
|
||||
if (!use_busy_signal)
|
||||
return 0;
|
||||
|
||||
/* Must check status to be sure of no errors */
|
||||
/*
|
||||
* Must check status to be sure of no errors
|
||||
* If CMD13 is to check the busy completion of the timing change,
|
||||
* disable the check of CRC error.
|
||||
*/
|
||||
if (index == EXT_CSD_HS_TIMING &&
|
||||
!(card->host->caps & MMC_CAP_WAIT_WHILE_BUSY))
|
||||
ignore_crc = true;
|
||||
|
||||
timeout = jiffies + msecs_to_jiffies(MMC_OPS_TIMEOUT_MS);
|
||||
do {
|
||||
err = mmc_send_status(card, &status);
|
||||
if (err)
|
||||
return err;
|
||||
if (send_status) {
|
||||
err = __mmc_send_status(card, &status, ignore_crc);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
if (card->host->caps & MMC_CAP_WAIT_WHILE_BUSY)
|
||||
break;
|
||||
if (mmc_host_is_spi(card->host))
|
||||
break;
|
||||
|
||||
/*
|
||||
* We are not allowed to issue a status command and the host
|
||||
* does'nt support MMC_CAP_WAIT_WHILE_BUSY, then we can only
|
||||
* rely on waiting for the stated timeout to be sufficient.
|
||||
*/
|
||||
if (!send_status) {
|
||||
mmc_delay(timeout_ms);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Timeout if the device never leaves the program state. */
|
||||
if (time_after(jiffies, timeout)) {
|
||||
pr_err("%s: Card stuck in programming state! %s\n",
|
||||
@@ -445,36 +501,10 @@ EXPORT_SYMBOL_GPL(__mmc_switch);
|
||||
int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
|
||||
unsigned int timeout_ms)
|
||||
{
|
||||
return __mmc_switch(card, set, index, value, timeout_ms, true);
|
||||
return __mmc_switch(card, set, index, value, timeout_ms, true, true);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mmc_switch);
|
||||
|
||||
int mmc_send_status(struct mmc_card *card, u32 *status)
|
||||
{
|
||||
int err;
|
||||
struct mmc_command cmd = {0};
|
||||
|
||||
BUG_ON(!card);
|
||||
BUG_ON(!card->host);
|
||||
|
||||
cmd.opcode = MMC_SEND_STATUS;
|
||||
if (!mmc_host_is_spi(card->host))
|
||||
cmd.arg = card->rca << 16;
|
||||
cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC;
|
||||
|
||||
err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* NOTE: callers are required to understand the difference
|
||||
* between "native" and SPI format status words!
|
||||
*/
|
||||
if (status)
|
||||
*status = cmd.resp[0];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
mmc_send_bus_test(struct mmc_card *card, struct mmc_host *host, u8 opcode,
|
||||
u8 len)
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <linux/err.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/stat.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
#include <linux/mmc/host.h>
|
||||
#include <linux/mmc/card.h>
|
||||
@@ -721,6 +722,7 @@ int mmc_sd_get_cid(struct mmc_host *host, u32 ocr, u32 *cid, u32 *rocr)
|
||||
int err;
|
||||
u32 max_current;
|
||||
int retries = 10;
|
||||
u32 pocr = ocr;
|
||||
|
||||
try_again:
|
||||
if (!retries) {
|
||||
@@ -773,7 +775,8 @@ try_again:
|
||||
*/
|
||||
if (!mmc_host_is_spi(host) && rocr &&
|
||||
((*rocr & 0x41000000) == 0x41000000)) {
|
||||
err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180);
|
||||
err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180,
|
||||
pocr);
|
||||
if (err == -EAGAIN) {
|
||||
retries--;
|
||||
goto try_again;
|
||||
@@ -935,6 +938,7 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
|
||||
if (IS_ERR(card))
|
||||
return PTR_ERR(card);
|
||||
|
||||
card->ocr = ocr;
|
||||
card->type = MMC_TYPE_SD;
|
||||
memcpy(card->raw_cid, cid, sizeof(card->raw_cid));
|
||||
}
|
||||
@@ -1064,10 +1068,7 @@ static void mmc_sd_detect(struct mmc_host *host)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Suspend callback from host.
|
||||
*/
|
||||
static int mmc_sd_suspend(struct mmc_host *host)
|
||||
static int _mmc_sd_suspend(struct mmc_host *host)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
@@ -1075,34 +1076,77 @@ static int mmc_sd_suspend(struct mmc_host *host)
|
||||
BUG_ON(!host->card);
|
||||
|
||||
mmc_claim_host(host);
|
||||
|
||||
if (mmc_card_suspended(host->card))
|
||||
goto out;
|
||||
|
||||
if (!mmc_host_is_spi(host))
|
||||
err = mmc_deselect_cards(host);
|
||||
host->card->state &= ~MMC_STATE_HIGHSPEED;
|
||||
if (!err)
|
||||
if (!err) {
|
||||
mmc_power_off(host);
|
||||
mmc_card_set_suspended(host->card);
|
||||
}
|
||||
|
||||
out:
|
||||
mmc_release_host(host);
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Callback for suspend
|
||||
*/
|
||||
static int mmc_sd_suspend(struct mmc_host *host)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = _mmc_sd_suspend(host);
|
||||
if (!err) {
|
||||
pm_runtime_disable(&host->card->dev);
|
||||
pm_runtime_set_suspended(&host->card->dev);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 int mmc_sd_resume(struct mmc_host *host)
|
||||
static int _mmc_sd_resume(struct mmc_host *host)
|
||||
{
|
||||
int err;
|
||||
int err = 0;
|
||||
|
||||
BUG_ON(!host);
|
||||
BUG_ON(!host->card);
|
||||
|
||||
mmc_claim_host(host);
|
||||
mmc_power_up(host);
|
||||
mmc_select_voltage(host, host->ocr);
|
||||
err = mmc_sd_init_card(host, host->ocr, host->card);
|
||||
|
||||
if (!mmc_card_suspended(host->card))
|
||||
goto out;
|
||||
|
||||
mmc_power_up(host, host->card->ocr);
|
||||
err = mmc_sd_init_card(host, host->card->ocr, host->card);
|
||||
mmc_card_clr_suspended(host->card);
|
||||
|
||||
out:
|
||||
mmc_release_host(host);
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Callback for resume
|
||||
*/
|
||||
static int mmc_sd_resume(struct mmc_host *host)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
if (!(host->caps & MMC_CAP_RUNTIME_RESUME)) {
|
||||
err = _mmc_sd_resume(host);
|
||||
pm_runtime_set_active(&host->card->dev);
|
||||
pm_runtime_mark_last_busy(&host->card->dev);
|
||||
}
|
||||
pm_runtime_enable(&host->card->dev);
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -1117,18 +1161,11 @@ static int mmc_sd_runtime_suspend(struct mmc_host *host)
|
||||
if (!(host->caps & MMC_CAP_AGGRESSIVE_PM))
|
||||
return 0;
|
||||
|
||||
mmc_claim_host(host);
|
||||
|
||||
err = mmc_sd_suspend(host);
|
||||
if (err) {
|
||||
err = _mmc_sd_suspend(host);
|
||||
if (err)
|
||||
pr_err("%s: error %d doing aggessive suspend\n",
|
||||
mmc_hostname(host), err);
|
||||
goto out;
|
||||
}
|
||||
mmc_power_off(host);
|
||||
|
||||
out:
|
||||
mmc_release_host(host);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -1139,18 +1176,14 @@ static int mmc_sd_runtime_resume(struct mmc_host *host)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (!(host->caps & MMC_CAP_AGGRESSIVE_PM))
|
||||
if (!(host->caps & (MMC_CAP_AGGRESSIVE_PM | MMC_CAP_RUNTIME_RESUME)))
|
||||
return 0;
|
||||
|
||||
mmc_claim_host(host);
|
||||
|
||||
mmc_power_up(host);
|
||||
err = mmc_sd_resume(host);
|
||||
err = _mmc_sd_resume(host);
|
||||
if (err)
|
||||
pr_err("%s: error %d doing aggessive resume\n",
|
||||
mmc_hostname(host), err);
|
||||
|
||||
mmc_release_host(host);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1160,7 +1193,7 @@ static int mmc_sd_power_restore(struct mmc_host *host)
|
||||
|
||||
host->card->state &= ~MMC_STATE_HIGHSPEED;
|
||||
mmc_claim_host(host);
|
||||
ret = mmc_sd_init_card(host, host->ocr, host->card);
|
||||
ret = mmc_sd_init_card(host, host->card->ocr, host->card);
|
||||
mmc_release_host(host);
|
||||
|
||||
return ret;
|
||||
@@ -1205,7 +1238,7 @@ static void mmc_sd_attach_bus_ops(struct mmc_host *host)
|
||||
int mmc_attach_sd(struct mmc_host *host)
|
||||
{
|
||||
int err;
|
||||
u32 ocr;
|
||||
u32 ocr, rocr;
|
||||
|
||||
BUG_ON(!host);
|
||||
WARN_ON(!host->claimed);
|
||||
@@ -1229,31 +1262,12 @@ int mmc_attach_sd(struct mmc_host *host)
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sanity check the voltages that the card claims to
|
||||
* support.
|
||||
*/
|
||||
if (ocr & 0x7F) {
|
||||
pr_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) &&
|
||||
!(host->ocr_avail_sd & MMC_VDD_165_195)) {
|
||||
pr_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);
|
||||
rocr = mmc_select_voltage(host, ocr);
|
||||
|
||||
/*
|
||||
* Can we support the voltage(s) of the card(s)?
|
||||
*/
|
||||
if (!host->ocr) {
|
||||
if (!rocr) {
|
||||
err = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
@@ -1261,7 +1275,7 @@ int mmc_attach_sd(struct mmc_host *host)
|
||||
/*
|
||||
* Detect and init the card.
|
||||
*/
|
||||
err = mmc_sd_init_card(host, host->ocr, NULL);
|
||||
err = mmc_sd_init_card(host, rocr, NULL);
|
||||
if (err)
|
||||
goto err;
|
||||
|
||||
|
||||
@@ -593,23 +593,28 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,
|
||||
struct mmc_card *card;
|
||||
int err;
|
||||
int retries = 10;
|
||||
u32 rocr = 0;
|
||||
u32 ocr_card = ocr;
|
||||
|
||||
BUG_ON(!host);
|
||||
WARN_ON(!host->claimed);
|
||||
|
||||
/* to query card if 1.8V signalling is supported */
|
||||
if (mmc_host_uhs(host))
|
||||
ocr |= R4_18V_PRESENT;
|
||||
|
||||
try_again:
|
||||
if (!retries) {
|
||||
pr_warning("%s: Skipping voltage switch\n",
|
||||
mmc_hostname(host));
|
||||
ocr &= ~R4_18V_PRESENT;
|
||||
host->ocr &= ~R4_18V_PRESENT;
|
||||
}
|
||||
|
||||
/*
|
||||
* Inform the card of the voltage
|
||||
*/
|
||||
if (!powered_resume) {
|
||||
err = mmc_send_io_op_cond(host, host->ocr, &ocr);
|
||||
err = mmc_send_io_op_cond(host, ocr, &rocr);
|
||||
if (err)
|
||||
goto err;
|
||||
}
|
||||
@@ -632,8 +637,8 @@ try_again:
|
||||
goto err;
|
||||
}
|
||||
|
||||
if ((ocr & R4_MEMORY_PRESENT) &&
|
||||
mmc_sd_get_cid(host, host->ocr & ocr, card->raw_cid, NULL) == 0) {
|
||||
if ((rocr & R4_MEMORY_PRESENT) &&
|
||||
mmc_sd_get_cid(host, ocr & rocr, card->raw_cid, NULL) == 0) {
|
||||
card->type = MMC_TYPE_SD_COMBO;
|
||||
|
||||
if (oldcard && (oldcard->type != MMC_TYPE_SD_COMBO ||
|
||||
@@ -663,8 +668,9 @@ try_again:
|
||||
* systems that claim 1.8v signalling in fact do not support
|
||||
* it.
|
||||
*/
|
||||
if (!powered_resume && (ocr & R4_18V_PRESENT) && mmc_host_uhs(host)) {
|
||||
err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180);
|
||||
if (!powered_resume && (rocr & ocr & R4_18V_PRESENT)) {
|
||||
err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180,
|
||||
ocr);
|
||||
if (err == -EAGAIN) {
|
||||
sdio_reset(host);
|
||||
mmc_go_idle(host);
|
||||
@@ -674,12 +680,10 @@ try_again:
|
||||
goto try_again;
|
||||
} else if (err) {
|
||||
ocr &= ~R4_18V_PRESENT;
|
||||
host->ocr &= ~R4_18V_PRESENT;
|
||||
}
|
||||
err = 0;
|
||||
} else {
|
||||
ocr &= ~R4_18V_PRESENT;
|
||||
host->ocr &= ~R4_18V_PRESENT;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -759,6 +763,7 @@ try_again:
|
||||
|
||||
card = oldcard;
|
||||
}
|
||||
card->ocr = ocr_card;
|
||||
mmc_fixup_device(card, NULL);
|
||||
|
||||
if (card->type == MMC_TYPE_SD_COMBO) {
|
||||
@@ -981,8 +986,7 @@ static int mmc_sdio_resume(struct mmc_host *host)
|
||||
|
||||
/* Restore power if needed */
|
||||
if (!mmc_card_keep_power(host)) {
|
||||
mmc_power_up(host);
|
||||
mmc_select_voltage(host, host->ocr);
|
||||
mmc_power_up(host, host->card->ocr);
|
||||
/*
|
||||
* Tell runtime PM core we just powered up the card,
|
||||
* since it still believes the card is powered off.
|
||||
@@ -1000,7 +1004,7 @@ static int mmc_sdio_resume(struct mmc_host *host)
|
||||
if (mmc_card_is_removable(host) || !mmc_card_keep_power(host)) {
|
||||
sdio_reset(host);
|
||||
mmc_go_idle(host);
|
||||
err = mmc_sdio_init_card(host, host->ocr, host->card,
|
||||
err = mmc_sdio_init_card(host, host->card->ocr, host->card,
|
||||
mmc_card_keep_power(host));
|
||||
} else if (mmc_card_keep_power(host) && mmc_card_wake_sdio_irq(host)) {
|
||||
/* We may have switched to 1-bit mode during suspend */
|
||||
@@ -1040,7 +1044,6 @@ static int mmc_sdio_resume(struct mmc_host *host)
|
||||
static int mmc_sdio_power_restore(struct mmc_host *host)
|
||||
{
|
||||
int ret;
|
||||
u32 ocr;
|
||||
|
||||
BUG_ON(!host);
|
||||
BUG_ON(!host->card);
|
||||
@@ -1062,32 +1065,17 @@ static int mmc_sdio_power_restore(struct mmc_host *host)
|
||||
* for OLPC SD8686 (which expects a [CMD5,5,3,7] init sequence), and
|
||||
* harmless in other situations.
|
||||
*
|
||||
* With these steps taken, mmc_select_voltage() is also required to
|
||||
* restore the correct voltage setting of the card.
|
||||
*/
|
||||
|
||||
sdio_reset(host);
|
||||
mmc_go_idle(host);
|
||||
mmc_send_if_cond(host, host->ocr_avail);
|
||||
|
||||
ret = mmc_send_io_op_cond(host, 0, &ocr);
|
||||
ret = mmc_send_io_op_cond(host, 0, NULL);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
if (host->ocr_avail_sdio)
|
||||
host->ocr_avail = host->ocr_avail_sdio;
|
||||
|
||||
host->ocr = mmc_select_voltage(host, ocr & ~0x7F);
|
||||
if (!host->ocr) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (mmc_host_uhs(host))
|
||||
/* to query card if 1.8V signalling is supported */
|
||||
host->ocr |= R4_18V_PRESENT;
|
||||
|
||||
ret = mmc_sdio_init_card(host, host->ocr, host->card,
|
||||
ret = mmc_sdio_init_card(host, host->card->ocr, host->card,
|
||||
mmc_card_keep_power(host));
|
||||
if (!ret && host->sdio_irqs)
|
||||
mmc_signal_sdio_irq(host);
|
||||
@@ -1108,7 +1096,7 @@ static int mmc_sdio_runtime_suspend(struct mmc_host *host)
|
||||
static int mmc_sdio_runtime_resume(struct mmc_host *host)
|
||||
{
|
||||
/* Restore power and re-initialize. */
|
||||
mmc_power_up(host);
|
||||
mmc_power_up(host, host->card->ocr);
|
||||
return mmc_sdio_power_restore(host);
|
||||
}
|
||||
|
||||
@@ -1131,7 +1119,7 @@ static const struct mmc_bus_ops mmc_sdio_ops = {
|
||||
int mmc_attach_sdio(struct mmc_host *host)
|
||||
{
|
||||
int err, i, funcs;
|
||||
u32 ocr;
|
||||
u32 ocr, rocr;
|
||||
struct mmc_card *card;
|
||||
|
||||
BUG_ON(!host);
|
||||
@@ -1145,23 +1133,13 @@ int mmc_attach_sdio(struct mmc_host *host)
|
||||
if (host->ocr_avail_sdio)
|
||||
host->ocr_avail = host->ocr_avail_sdio;
|
||||
|
||||
/*
|
||||
* Sanity check the voltages that the card claims to
|
||||
* support.
|
||||
*/
|
||||
if (ocr & 0x7F) {
|
||||
pr_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);
|
||||
rocr = mmc_select_voltage(host, ocr);
|
||||
|
||||
/*
|
||||
* Can we support the voltage(s) of the card(s)?
|
||||
*/
|
||||
if (!host->ocr) {
|
||||
if (!rocr) {
|
||||
err = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
@@ -1169,22 +1147,10 @@ int mmc_attach_sdio(struct mmc_host *host)
|
||||
/*
|
||||
* Detect and init the card.
|
||||
*/
|
||||
if (mmc_host_uhs(host))
|
||||
/* to query card if 1.8V signalling is supported */
|
||||
host->ocr |= R4_18V_PRESENT;
|
||||
err = mmc_sdio_init_card(host, rocr, NULL, 0);
|
||||
if (err)
|
||||
goto err;
|
||||
|
||||
err = mmc_sdio_init_card(host, host->ocr, NULL, 0);
|
||||
if (err) {
|
||||
if (err == -EAGAIN) {
|
||||
/*
|
||||
* Retry initialization with S18R set to 0.
|
||||
*/
|
||||
host->ocr &= ~R4_18V_PRESENT;
|
||||
err = mmc_sdio_init_card(host, host->ocr, NULL, 0);
|
||||
}
|
||||
if (err)
|
||||
goto err;
|
||||
}
|
||||
card = host->card;
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user