diff options
author | Scott Wood <scottwood@freescale.com> | 2014-04-08 01:00:49 (GMT) |
---|---|---|
committer | Scott Wood <scottwood@freescale.com> | 2014-04-08 19:58:35 (GMT) |
commit | 47d2261a3fa71cde24263559a4219a25e50d8c89 (patch) | |
tree | 28774d5b330ccf1b777a3af222d8356918328013 /drivers/mmc/core | |
parent | fb7f27080adc65cd5f341bdf56a1d0c14f316c1b (diff) | |
parent | 5fb9d37f27351e42f002e372074249f92cbdf815 (diff) | |
download | linux-fsl-qoriq-47d2261a3fa71cde24263559a4219a25e50d8c89.tar.xz |
Merge branch 'merge' into sdk-v1.6.x
This reverts v3.13-rc3+ (78fd82238d0e5716) to v3.12, except for
commits which I noticed which appear relevant to the SDK.
Signed-off-by: Scott Wood <scottwood@freescale.com>
Conflicts:
arch/powerpc/include/asm/kvm_host.h
arch/powerpc/kvm/book3s_hv_rmhandlers.S
arch/powerpc/kvm/book3s_interrupts.S
arch/powerpc/kvm/e500.c
arch/powerpc/kvm/e500mc.c
arch/powerpc/sysdev/fsl_soc.h
drivers/Kconfig
drivers/cpufreq/ppc-corenet-cpufreq.c
drivers/dma/fsldma.c
drivers/dma/s3c24xx-dma.c
drivers/misc/Makefile
drivers/mmc/host/sdhci-of-esdhc.c
drivers/mtd/devices/m25p80.c
drivers/net/ethernet/freescale/gianfar.h
drivers/platform/Kconfig
drivers/platform/Makefile
drivers/spi/spi-fsl-espi.c
include/crypto/algapi.h
include/linux/netdev_features.h
include/linux/skbuff.h
include/net/ip.h
net/core/ethtool.c
Diffstat (limited to 'drivers/mmc/core')
-rw-r--r-- | drivers/mmc/core/bus.c | 14 | ||||
-rw-r--r-- | drivers/mmc/core/core.c | 154 | ||||
-rw-r--r-- | drivers/mmc/core/core.h | 6 | ||||
-rw-r--r-- | drivers/mmc/core/mmc.c | 127 | ||||
-rw-r--r-- | drivers/mmc/core/mmc_ops.c | 96 | ||||
-rw-r--r-- | drivers/mmc/core/sd.c | 118 | ||||
-rw-r--r-- | drivers/mmc/core/sdio.c | 82 | ||||
-rw-r--r-- | drivers/mmc/core/sdio_bus.c | 24 |
8 files changed, 310 insertions, 311 deletions
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c index 64145a3..704bf66 100644 --- a/drivers/mmc/core/bus.c +++ b/drivers/mmc/core/bus.c @@ -27,7 +27,7 @@ #define to_mmc_driver(d) container_of(d, struct mmc_driver, drv) -static ssize_t type_show(struct device *dev, +static ssize_t mmc_type_show(struct device *dev, struct device_attribute *attr, char *buf) { struct mmc_card *card = mmc_dev_to_card(dev); @@ -45,13 +45,11 @@ static ssize_t type_show(struct device *dev, return -EFAULT; } } -static DEVICE_ATTR_RO(type); -static struct attribute *mmc_dev_attrs[] = { - &dev_attr_type.attr, - NULL, +static struct device_attribute mmc_dev_attrs[] = { + __ATTR(type, S_IRUGO, mmc_type_show, NULL), + __ATTR_NULL, }; -ATTRIBUTE_GROUPS(mmc_dev); /* * This currently matches any MMC driver to any MMC card - drivers @@ -220,7 +218,7 @@ static const struct dev_pm_ops mmc_bus_pm_ops = { static struct bus_type mmc_bus_type = { .name = "mmc", - .dev_groups = mmc_dev_groups, + .dev_attrs = mmc_dev_attrs, .match = mmc_bus_match, .uevent = mmc_bus_uevent, .probe = mmc_bus_probe, @@ -342,7 +340,7 @@ int mmc_add_card(struct mmc_card *card) break; } - if (mmc_card_uhs(card) && + if (mmc_sd_card_uhs(card) && (card->sd_bus_speed < ARRAY_SIZE(uhs_speeds))) uhs_bus_speed_mode = uhs_speeds[card->sd_bus_speed]; diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 4ecaac7..59cf22a 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -23,7 +23,6 @@ #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> @@ -302,7 +301,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, true); + EXT_CSD_BKOPS_START, 1, timeout, use_busy_signal); if (err) { pr_warn("%s: Error %d starting bkops\n", mmc_hostname(card->host), err); @@ -931,6 +930,31 @@ 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 * @@ -1370,31 +1394,22 @@ 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; - } - if (host->caps2 & MMC_CAP2_FULL_PWR_CYCLE) { - bit = ffs(ocr) - 1; + bit = ffs(ocr); + if (bit) { + bit -= 1; + ocr &= 3 << bit; - mmc_power_cycle(host, ocr); + + mmc_host_clk_hold(host); + host->ios.vdd = bit; + mmc_set_ios(host); + mmc_host_clk_release(host); } else { - bit = fls(ocr) - 1; - ocr &= 3 << bit; - if (bit != host->ios.vdd) - dev_warn(mmc_dev(host), "exceeding card's volts\n"); + pr_warning("%s: host doesn't support card's voltages\n", + mmc_hostname(host)); + ocr = 0; } return ocr; @@ -1419,7 +1434,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, u32 ocr) +int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage) { struct mmc_command cmd = {0}; int err = 0; @@ -1501,7 +1516,7 @@ power_cycle: if (err) { pr_debug("%s: Signal voltage switch failed, " "power cycling card\n", mmc_hostname(host)); - mmc_power_cycle(host, ocr); + mmc_power_cycle(host); } mmc_host_clk_release(host); @@ -1542,14 +1557,22 @@ 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, u32 ocr) +void mmc_power_up(struct mmc_host *host) { + int bit; + if (host->ios.power_mode == MMC_POWER_ON) return; mmc_host_clk_hold(host); - host->ios.vdd = fls(ocr) - 1; + /* 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; if (mmc_host_is_spi(host)) host->ios.chip_select = MMC_CS_HIGH; else @@ -1593,6 +1616,13 @@ 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; @@ -1612,12 +1642,12 @@ void mmc_power_off(struct mmc_host *host) mmc_host_clk_release(host); } -void mmc_power_cycle(struct mmc_host *host, u32 ocr) +void mmc_power_cycle(struct mmc_host *host) { mmc_power_off(host); /* Wait at least 1 ms according to SD spec */ mmc_delay(1); - mmc_power_up(host, ocr); + mmc_power_up(host); } /* @@ -1705,28 +1735,6 @@ 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. @@ -1739,8 +1747,16 @@ static void _mmc_detect_change(struct mmc_host *host, unsigned long delay, */ void mmc_detect_change(struct mmc_host *host, unsigned long delay) { - _mmc_detect_change(host, delay, true); +#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); } + EXPORT_SYMBOL(mmc_detect_change); void mmc_init_erase(struct mmc_card *card) @@ -2335,7 +2351,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, host->ocr_avail); + mmc_power_up(host); /* * Some eMMCs (with VCCQ always on) may not be reset after power up, so @@ -2429,7 +2445,7 @@ int mmc_detect_card_removed(struct mmc_host *host) spin_unlock_irqrestore(&host->lock, flags); cancel_delayed_work(&host->detect); - _mmc_detect_change(host, 0, false); + mmc_detect_change(host, 0); } } @@ -2510,8 +2526,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, host->ocr_avail); - _mmc_detect_change(host, 0, false); + mmc_power_up(host); + mmc_detect_change(host, 0); } void mmc_stop_host(struct mmc_host *host) @@ -2589,7 +2605,7 @@ int mmc_power_restore_host(struct mmc_host *host) return -EINVAL; } - mmc_power_up(host, host->card->ocr); + mmc_power_up(host); ret = host->bus_ops->power_restore(host); mmc_bus_put(host); @@ -2663,6 +2679,28 @@ 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. @@ -2708,7 +2746,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, false); + mmc_detect_change(host, 0); } diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h index 443a584..5345d15 100644 --- a/drivers/mmc/core/core.h +++ b/drivers/mmc/core/core.h @@ -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, 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); 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, u32 ocr); +void mmc_power_up(struct mmc_host *host); void mmc_power_off(struct mmc_host *host); -void mmc_power_cycle(struct mmc_host *host, u32 ocr); +void mmc_power_cycle(struct mmc_host *host); static inline void mmc_delay(unsigned int ms) { diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index f631f5a..6d02012 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -13,7 +13,6 @@ #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> @@ -935,7 +934,6 @@ 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)); @@ -1406,9 +1404,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, true, false); + err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, + EXT_CSD_POWER_OFF_NOTIFICATION, + notify_type, timeout); if (err) pr_err("%s: Power Off Notification timed out, %u\n", mmc_hostname(card->host), timeout); @@ -1479,9 +1477,6 @@ 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) @@ -1501,93 +1496,51 @@ 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 + * Suspend callback from host. */ static int mmc_suspend(struct mmc_host *host) { - int err; - - err = _mmc_suspend(host, true); - if (!err) { - pm_runtime_disable(&host->card->dev); - pm_runtime_set_suspended(&host->card->dev); - } + return _mmc_suspend(host, true); +} - return err; +/* + * Shutdown callback + */ +static int mmc_shutdown(struct mmc_host *host) +{ + return _mmc_suspend(host, false); } /* + * 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) +static int mmc_resume(struct mmc_host *host) { - int err = 0; + int err; 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_power_up(host); + mmc_select_voltage(host, host->ocr); + err = mmc_init_card(host, host->ocr, host->card); mmc_release_host(host); - return err; -} - -/* - * Shutdown callback - */ -static int mmc_shutdown(struct mmc_host *host) -{ - int err = 0; - - /* - * 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); - - 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. @@ -1599,11 +1552,18 @@ static int mmc_runtime_suspend(struct mmc_host *host) if (!(host->caps & MMC_CAP_AGGRESSIVE_PM)) return 0; - err = _mmc_suspend(host, true); - if (err) + mmc_claim_host(host); + + err = mmc_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; } @@ -1614,14 +1574,18 @@ static int mmc_runtime_resume(struct mmc_host *host) { int err; - if (!(host->caps & (MMC_CAP_AGGRESSIVE_PM | MMC_CAP_RUNTIME_RESUME))) + if (!(host->caps & MMC_CAP_AGGRESSIVE_PM)) return 0; - err = _mmc_resume(host); + mmc_claim_host(host); + + mmc_power_up(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; } @@ -1631,7 +1595,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->card->ocr, host->card); + ret = mmc_init_card(host, host->ocr, host->card); mmc_release_host(host); return ret; @@ -1676,7 +1640,7 @@ static void mmc_attach_bus_ops(struct mmc_host *host) int mmc_attach_mmc(struct mmc_host *host) { int err; - u32 ocr, rocr; + u32 ocr; BUG_ON(!host); WARN_ON(!host->claimed); @@ -1702,12 +1666,23 @@ int mmc_attach_mmc(struct mmc_host *host) goto err; } - rocr = mmc_select_voltage(host, ocr); + /* + * 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); /* * Can we support the voltage of the card? */ - if (!rocr) { + if (!host->ocr) { err = -EINVAL; goto err; } @@ -1715,7 +1690,7 @@ int mmc_attach_mmc(struct mmc_host *host) /* * Detect and init the card. */ - err = mmc_init_card(host, rocr, NULL); + err = mmc_init_card(host, host->ocr, NULL); if (err) goto err; diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index e5b5eeb..ef18348 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -23,40 +23,6 @@ #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; @@ -404,18 +370,16 @@ 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, bool send_status) + unsigned int timeout_ms, bool use_busy_signal) { int err; struct mmc_command cmd = {0}; unsigned long timeout; - u32 status = 0; - bool ignore_crc = false; + u32 status; BUG_ON(!card); BUG_ON(!card->host); @@ -444,37 +408,17 @@ 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 - * 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; - + /* Must check status to be sure of no errors */ timeout = jiffies + msecs_to_jiffies(MMC_OPS_TIMEOUT_MS); do { - if (send_status) { - err = __mmc_send_status(card, &status, ignore_crc); - if (err) - return err; - } + err = mmc_send_status(card, &status); + 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", @@ -501,10 +445,36 @@ 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, true); + return __mmc_switch(card, set, index, value, timeout_ms, 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) diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 6f42050..5e8823d 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -13,7 +13,6 @@ #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> @@ -722,7 +721,6 @@ 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) { @@ -775,8 +773,7 @@ try_again: */ if (!mmc_host_is_spi(host) && rocr && ((*rocr & 0x41000000) == 0x41000000)) { - err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180, - pocr); + err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180); if (err == -EAGAIN) { retries--; goto try_again; @@ -938,7 +935,6 @@ 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)); } @@ -1068,7 +1064,10 @@ static void mmc_sd_detect(struct mmc_host *host) } } -static int _mmc_sd_suspend(struct mmc_host *host) +/* + * Suspend callback from host. + */ +static int mmc_sd_suspend(struct mmc_host *host) { int err = 0; @@ -1076,77 +1075,34 @@ 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 = 0; + int err; 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_sd_init_card(host, host->card->ocr, host->card); - mmc_card_clr_suspended(host->card); - -out: + mmc_power_up(host); + mmc_select_voltage(host, host->ocr); + err = mmc_sd_init_card(host, host->ocr, host->card); 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; } @@ -1161,11 +1117,18 @@ static int mmc_sd_runtime_suspend(struct mmc_host *host) if (!(host->caps & MMC_CAP_AGGRESSIVE_PM)) return 0; - err = _mmc_sd_suspend(host); - if (err) + mmc_claim_host(host); + + 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; } @@ -1176,14 +1139,18 @@ static int mmc_sd_runtime_resume(struct mmc_host *host) { int err; - if (!(host->caps & (MMC_CAP_AGGRESSIVE_PM | MMC_CAP_RUNTIME_RESUME))) + if (!(host->caps & MMC_CAP_AGGRESSIVE_PM)) return 0; - err = _mmc_sd_resume(host); + mmc_claim_host(host); + + mmc_power_up(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; } @@ -1193,7 +1160,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->card->ocr, host->card); + ret = mmc_sd_init_card(host, host->ocr, host->card); mmc_release_host(host); return ret; @@ -1238,7 +1205,7 @@ static void mmc_sd_attach_bus_ops(struct mmc_host *host) int mmc_attach_sd(struct mmc_host *host) { int err; - u32 ocr, rocr; + u32 ocr; BUG_ON(!host); WARN_ON(!host->claimed); @@ -1262,12 +1229,31 @@ int mmc_attach_sd(struct mmc_host *host) goto err; } - rocr = mmc_select_voltage(host, ocr); + /* + * 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); /* * Can we support the voltage(s) of the card(s)? */ - if (!rocr) { + if (!host->ocr) { err = -EINVAL; goto err; } @@ -1275,7 +1261,7 @@ int mmc_attach_sd(struct mmc_host *host) /* * Detect and init the card. */ - err = mmc_sd_init_card(host, rocr, NULL); + err = mmc_sd_init_card(host, host->ocr, NULL); if (err) goto err; diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index 4d721c6..80d89cff 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -593,28 +593,23 @@ 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, ocr, &rocr); + err = mmc_send_io_op_cond(host, host->ocr, &ocr); if (err) goto err; } @@ -637,8 +632,8 @@ try_again: goto err; } - if ((rocr & R4_MEMORY_PRESENT) && - mmc_sd_get_cid(host, ocr & rocr, card->raw_cid, NULL) == 0) { + if ((ocr & R4_MEMORY_PRESENT) && + mmc_sd_get_cid(host, host->ocr & ocr, card->raw_cid, NULL) == 0) { card->type = MMC_TYPE_SD_COMBO; if (oldcard && (oldcard->type != MMC_TYPE_SD_COMBO || @@ -668,9 +663,8 @@ try_again: * systems that claim 1.8v signalling in fact do not support * it. */ - if (!powered_resume && (rocr & ocr & R4_18V_PRESENT)) { - err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180, - ocr); + if (!powered_resume && (ocr & R4_18V_PRESENT) && mmc_host_uhs(host)) { + err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180); if (err == -EAGAIN) { sdio_reset(host); mmc_go_idle(host); @@ -680,10 +674,12 @@ 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; } /* @@ -763,7 +759,6 @@ try_again: card = oldcard; } - card->ocr = ocr_card; mmc_fixup_device(card, NULL); if (card->type == MMC_TYPE_SD_COMBO) { @@ -986,7 +981,8 @@ static int mmc_sdio_resume(struct mmc_host *host) /* Restore power if needed */ if (!mmc_card_keep_power(host)) { - mmc_power_up(host, host->card->ocr); + mmc_power_up(host); + mmc_select_voltage(host, host->ocr); /* * Tell runtime PM core we just powered up the card, * since it still believes the card is powered off. @@ -1004,7 +1000,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->card->ocr, host->card, + err = mmc_sdio_init_card(host, host->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 */ @@ -1044,6 +1040,7 @@ 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); @@ -1065,17 +1062,32 @@ 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, NULL); + ret = mmc_send_io_op_cond(host, 0, &ocr); if (ret) goto out; - ret = mmc_sdio_init_card(host, host->card->ocr, host->card, + 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, mmc_card_keep_power(host)); if (!ret && host->sdio_irqs) mmc_signal_sdio_irq(host); @@ -1096,7 +1108,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, host->card->ocr); + mmc_power_up(host); return mmc_sdio_power_restore(host); } @@ -1119,7 +1131,7 @@ static const struct mmc_bus_ops mmc_sdio_ops = { int mmc_attach_sdio(struct mmc_host *host) { int err, i, funcs; - u32 ocr, rocr; + u32 ocr; struct mmc_card *card; BUG_ON(!host); @@ -1133,13 +1145,23 @@ 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; + } - rocr = mmc_select_voltage(host, ocr); + host->ocr = mmc_select_voltage(host, ocr); /* * Can we support the voltage(s) of the card(s)? */ - if (!rocr) { + if (!host->ocr) { err = -EINVAL; goto err; } @@ -1147,10 +1169,22 @@ int mmc_attach_sdio(struct mmc_host *host) /* * Detect and init the card. */ - err = mmc_sdio_init_card(host, rocr, NULL, 0); - if (err) - goto err; + 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, 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; /* diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c index 157b570..6d67492 100644 --- a/drivers/mmc/core/sdio_bus.c +++ b/drivers/mmc/core/sdio_bus.c @@ -34,8 +34,7 @@ field##_show(struct device *dev, struct device_attribute *attr, char *buf) \ \ func = dev_to_sdio_func (dev); \ return sprintf (buf, format_string, func->field); \ -} \ -static DEVICE_ATTR_RO(field) +} sdio_config_attr(class, "0x%02x\n"); sdio_config_attr(vendor, "0x%04x\n"); @@ -48,16 +47,14 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, return sprintf(buf, "sdio:c%02Xv%04Xd%04X\n", func->class, func->vendor, func->device); } -static DEVICE_ATTR_RO(modalias); - -static struct attribute *sdio_dev_attrs[] = { - &dev_attr_class.attr, - &dev_attr_vendor.attr, - &dev_attr_device.attr, - &dev_attr_modalias.attr, - NULL, + +static struct device_attribute sdio_dev_attrs[] = { + __ATTR_RO(class), + __ATTR_RO(vendor), + __ATTR_RO(device), + __ATTR_RO(modalias), + __ATTR_NULL, }; -ATTRIBUTE_GROUPS(sdio_dev); static const struct sdio_device_id *sdio_match_one(struct sdio_func *func, const struct sdio_device_id *id) @@ -228,7 +225,7 @@ static const struct dev_pm_ops sdio_bus_pm_ops = { static struct bus_type sdio_bus_type = { .name = "sdio", - .dev_groups = sdio_dev_groups, + .dev_attrs = sdio_dev_attrs, .match = sdio_bus_match, .uevent = sdio_bus_uevent, .probe = sdio_bus_probe, @@ -308,7 +305,8 @@ static void sdio_acpi_set_handle(struct sdio_func *func) struct mmc_host *host = func->card->host; u64 addr = (host->slotno << 16) | func->num; - acpi_preset_companion(&func->dev, ACPI_HANDLE(host->parent), addr); + ACPI_HANDLE_SET(&func->dev, + acpi_get_child(ACPI_HANDLE(host->parent), addr)); } #else static inline void sdio_acpi_set_handle(struct sdio_func *func) {} |