diff options
Diffstat (limited to 'drivers/mmc/core/core.c')
| -rw-r--r-- | drivers/mmc/core/core.c | 294 | 
1 files changed, 110 insertions, 184 deletions
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index bf18b6bfce4..7dc0c85fdb6 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -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> @@ -33,6 +34,7 @@  #include <linux/mmc/host.h>  #include <linux/mmc/mmc.h>  #include <linux/mmc/sd.h> +#include <linux/mmc/slot-gpio.h>  #include "core.h"  #include "bus.h" @@ -64,23 +66,6 @@ bool use_spi_crc = 1;  module_param(use_spi_crc, bool, 0);  /* - * We normally treat cards as removed during suspend if they are not - * known to be on a non-removable bus, to avoid the risk of writing - * back data to a different card after resume.  Allow this to be - * overridden if necessary. - */ -#ifdef CONFIG_MMC_UNSAFE_RESUME -bool mmc_assume_removable; -#else -bool mmc_assume_removable = 1; -#endif -EXPORT_SYMBOL(mmc_assume_removable); -module_param_named(removable, mmc_assume_removable, bool, 0644); -MODULE_PARM_DESC( -	removable, -	"MMC/SD cards are removable and may be removed during suspend"); - -/*   * Internal function. Schedule delayed work in the MMC work queue.   */  static int mmc_schedule_delayed_work(struct delayed_work *work, @@ -301,7 +286,8 @@ 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, false);  	if (err) {  		pr_warn("%s: Error %d starting bkops\n",  			mmc_hostname(card->host), err); @@ -814,6 +800,10 @@ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card)  			data->timeout_ns = limit_us * 1000;  			data->timeout_clks = 0;  		} + +		/* assign limit value if invalid */ +		if (timeout_us == 0) +			data->timeout_ns = limit_us * 1000;  	}  	/* @@ -918,31 +908,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   * @@ -1349,31 +1314,38 @@ int mmc_regulator_set_ocr(struct mmc_host *mmc,  }  EXPORT_SYMBOL_GPL(mmc_regulator_set_ocr); +#endif /* CONFIG_REGULATOR */ +  int mmc_regulator_get_supply(struct mmc_host *mmc)  {  	struct device *dev = mmc_dev(mmc); -	struct regulator *supply;  	int ret; -	supply = devm_regulator_get(dev, "vmmc"); -	mmc->supply.vmmc = supply; +	mmc->supply.vmmc = devm_regulator_get_optional(dev, "vmmc");  	mmc->supply.vqmmc = devm_regulator_get_optional(dev, "vqmmc"); -	if (IS_ERR(supply)) -		return PTR_ERR(supply); +	if (IS_ERR(mmc->supply.vmmc)) { +		if (PTR_ERR(mmc->supply.vmmc) == -EPROBE_DEFER) +			return -EPROBE_DEFER; +		dev_info(dev, "No vmmc regulator found\n"); +	} else { +		ret = mmc_regulator_get_ocrmask(mmc->supply.vmmc); +		if (ret > 0) +			mmc->ocr_avail = ret; +		else +			dev_warn(dev, "Failed getting OCR mask: %d\n", ret); +	} -	ret = mmc_regulator_get_ocrmask(supply); -	if (ret > 0) -		mmc->ocr_avail = ret; -	else -		dev_warn(mmc_dev(mmc), "Failed getting OCR mask: %d\n", ret); +	if (IS_ERR(mmc->supply.vqmmc)) { +		if (PTR_ERR(mmc->supply.vqmmc) == -EPROBE_DEFER) +			return -EPROBE_DEFER; +		dev_info(dev, "No vqmmc regulator found\n"); +	}  	return 0;  }  EXPORT_SYMBOL_GPL(mmc_regulator_get_supply); -#endif /* CONFIG_REGULATOR */ -  /*   * Mask off any voltages we don't support and select   * the lowest voltage @@ -1382,22 +1354,31 @@ u32 mmc_select_voltage(struct mmc_host *host, u32 ocr)  {  	int bit; -	ocr &= host->ocr_avail; +	/* +	 * 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; +	} -	bit = ffs(ocr); -	if (bit) { -		bit -= 1; +	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;  		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 +1403,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 +1485,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 +1526,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 @@ -1571,8 +1544,13 @@ void mmc_power_up(struct mmc_host *host)  	host->ios.timing = MMC_TIMING_LEGACY;  	mmc_set_ios(host); -	/* Set signal voltage to 3.3V */ -	__mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330); +	/* Try to set signal voltage to 3.3V but fall back to 1.8v or 1.2v */ +	if (__mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330) == 0) +		dev_dbg(mmc_dev(host), "Initial signal voltage of 3.3v\n"); +	else if (__mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180) == 0) +		dev_dbg(mmc_dev(host), "Initial signal voltage of 1.8v\n"); +	else if (__mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120) == 0) +		dev_dbg(mmc_dev(host), "Initial signal voltage of 1.2v\n");  	/*  	 * This delay should be sufficient to allow the power supply @@ -1604,13 +1582,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 +1601,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 +1694,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 +1728,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) @@ -1966,7 +1951,7 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from,  	cmd.opcode = MMC_ERASE;  	cmd.arg = arg;  	cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; -	cmd.cmd_timeout_ms = mmc_erase_timeout(card, arg, qty); +	cmd.busy_timeout = mmc_erase_timeout(card, arg, qty);  	err = mmc_wait_for_cmd(card->host, &cmd, 0);  	if (err) {  		pr_err("mmc_erase: erase error %d, status %#x\n", @@ -2153,7 +2138,7 @@ static unsigned int mmc_do_calc_max_discard(struct mmc_card *card,  		y = 0;  		for (x = 1; x && x <= max_qty && max_qty - x >= qty; x <<= 1) {  			timeout = mmc_erase_timeout(card, arg, qty + x); -			if (timeout > host->max_discard_to) +			if (timeout > host->max_busy_timeout)  				break;  			if (timeout < last_timeout)  				break; @@ -2185,7 +2170,7 @@ unsigned int mmc_calc_max_discard(struct mmc_card *card)  	struct mmc_host *host = card->host;  	unsigned int max_discard, max_trim; -	if (!host->max_discard_to) +	if (!host->max_busy_timeout)  		return UINT_MAX;  	/* @@ -2205,7 +2190,7 @@ unsigned int mmc_calc_max_discard(struct mmc_card *card)  		max_discard = 0;  	}  	pr_debug("%s: calculated max. discard sectors %u for timeout %u ms\n", -		 mmc_hostname(host), max_discard, host->max_discard_to); +		 mmc_hostname(host), max_discard, host->max_busy_timeout);  	return max_discard;  }  EXPORT_SYMBOL(mmc_calc_max_discard); @@ -2214,7 +2199,7 @@ int mmc_set_blocklen(struct mmc_card *card, unsigned int blocklen)  {  	struct mmc_command cmd = {0}; -	if (mmc_card_blockaddr(card) || mmc_card_ddr_mode(card)) +	if (mmc_card_blockaddr(card) || mmc_card_ddr52(card))  		return 0;  	cmd.opcode = MMC_SET_BLOCKLEN; @@ -2264,9 +2249,6 @@ static int mmc_do_hw_reset(struct mmc_host *host, int check)  {  	struct mmc_card *card = host->card; -	if (!host->bus_ops->power_restore) -		return -EOPNOTSUPP; -  	if (!(host->caps & MMC_CAP_HW_RESET) || !host->ops->hw_reset)  		return -EOPNOTSUPP; @@ -2297,7 +2279,6 @@ static int mmc_do_hw_reset(struct mmc_host *host, int check)  		}  	} -	host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_DDR);  	if (mmc_host_is_spi(host)) {  		host->ios.chip_select = MMC_CS_HIGH;  		host->ios.bus_mode = MMC_BUSMODE_PUSHPULL; @@ -2334,7 +2315,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 @@ -2368,7 +2349,7 @@ int _mmc_detect_card_removed(struct mmc_host *host)  {  	int ret; -	if ((host->caps & MMC_CAP_NONREMOVABLE) || !host->bus_ops->alive) +	if (host->caps & MMC_CAP_NONREMOVABLE)  		return 0;  	if (!host->card || mmc_card_removed(host->card)) @@ -2423,7 +2404,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);  		}  	} @@ -2437,6 +2418,11 @@ void mmc_rescan(struct work_struct *work)  		container_of(work, struct mmc_host, detect.work);  	int i; +	if (host->trigger_card_event && host->ops->card_event) { +		host->ops->card_event(host); +		host->trigger_card_event = false; +	} +  	if (host->rescan_disable)  		return; @@ -2451,7 +2437,7 @@ void mmc_rescan(struct work_struct *work)  	 * if there is a _removable_ card registered, check whether it is  	 * still present  	 */ -	if (host->bus_ops && host->bus_ops->detect && !host->bus_dead +	if (host->bus_ops && !host->bus_dead  	    && !(host->caps & MMC_CAP_NONREMOVABLE))  		host->bus_ops->detect(host); @@ -2476,7 +2462,8 @@ void mmc_rescan(struct work_struct *work)  	 */  	mmc_bus_put(host); -	if (host->ops->get_cd && host->ops->get_cd(host) == 0) { +	if (!(host->caps & MMC_CAP_NONREMOVABLE) && host->ops->get_cd && +			host->ops->get_cd(host) == 0) {  		mmc_claim_host(host);  		mmc_power_off(host);  		mmc_release_host(host); @@ -2504,8 +2491,9 @@ 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_gpiod_request_cd_irq(host); +	_mmc_detect_change(host, 0, false);  }  void mmc_stop_host(struct mmc_host *host) @@ -2516,6 +2504,8 @@ void mmc_stop_host(struct mmc_host *host)  	host->removed = 1;  	spin_unlock_irqrestore(&host->lock, flags);  #endif +	if (host->slot.cd_irq >= 0) +		disable_irq(host->slot.cd_irq);  	host->rescan_disable = 1;  	cancel_delayed_work_sync(&host->detect); @@ -2552,7 +2542,7 @@ int mmc_power_save_host(struct mmc_host *host)  	mmc_bus_get(host); -	if (!host->bus_ops || host->bus_dead || !host->bus_ops->power_restore) { +	if (!host->bus_ops || host->bus_dead) {  		mmc_bus_put(host);  		return -EINVAL;  	} @@ -2578,12 +2568,12 @@ int mmc_power_restore_host(struct mmc_host *host)  	mmc_bus_get(host); -	if (!host->bus_ops || host->bus_dead || !host->bus_ops->power_restore) { +	if (!host->bus_ops || host->bus_dead) {  		mmc_bus_put(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); @@ -2597,12 +2587,8 @@ EXPORT_SYMBOL(mmc_power_restore_host);   */  int mmc_flush_cache(struct mmc_card *card)  { -	struct mmc_host *host = card->host;  	int err = 0; -	if (!(host->caps2 & MMC_CAP2_CACHE_CTRL)) -		return err; -  	if (mmc_card_mmc(card) &&  			(card->ext_csd.cache_size > 0) &&  			(card->ext_csd.cache_ctrl & 1)) { @@ -2617,68 +2603,8 @@ int mmc_flush_cache(struct mmc_card *card)  }  EXPORT_SYMBOL(mmc_flush_cache); -/* - * Turn the cache ON/OFF. - * Turning the cache OFF shall trigger flushing of the data - * to the non-volatile storage. - * This function should be called with host claimed - */ -int mmc_cache_ctrl(struct mmc_host *host, u8 enable) -{ -	struct mmc_card *card = host->card; -	unsigned int timeout; -	int err = 0; - -	if (!(host->caps2 & MMC_CAP2_CACHE_CTRL) || -			mmc_card_is_removable(host)) -		return err; - -	if (card && mmc_card_mmc(card) && -			(card->ext_csd.cache_size > 0)) { -		enable = !!enable; - -		if (card->ext_csd.cache_ctrl ^ enable) { -			timeout = enable ? card->ext_csd.generic_cmd6_time : 0; -			err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, -					EXT_CSD_CACHE_CTRL, enable, timeout); -			if (err) -				pr_err("%s: cache %s error %d\n", -						mmc_hostname(card->host), -						enable ? "on" : "off", -						err); -			else -				card->ext_csd.cache_ctrl = enable; -		} -	} - -	return err; -} -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. @@ -2705,7 +2631,7 @@ int mmc_pm_notify(struct notifier_block *notify_block,  		/* Validate prerequisites for suspend */  		if (host->bus_ops->pre_suspend)  			err = host->bus_ops->pre_suspend(host); -		if (!err && host->bus_ops->suspend) +		if (!err)  			break;  		/* Calling bus_ops->remove() with a claimed host can deadlock */ @@ -2724,7 +2650,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);  	}  | 
