diff options
Diffstat (limited to 'drivers/mmc/core')
| -rw-r--r-- | drivers/mmc/core/Kconfig | 15 | ||||
| -rw-r--r-- | drivers/mmc/core/bus.c | 35 | ||||
| -rw-r--r-- | drivers/mmc/core/core.c | 294 | ||||
| -rw-r--r-- | drivers/mmc/core/core.h | 6 | ||||
| -rw-r--r-- | drivers/mmc/core/debugfs.c | 8 | ||||
| -rw-r--r-- | drivers/mmc/core/host.c | 24 | ||||
| -rw-r--r-- | drivers/mmc/core/mmc.c | 858 | ||||
| -rw-r--r-- | drivers/mmc/core/mmc_ops.c | 142 | ||||
| -rw-r--r-- | drivers/mmc/core/quirks.c | 8 | ||||
| -rw-r--r-- | drivers/mmc/core/sd.c | 206 | ||||
| -rw-r--r-- | drivers/mmc/core/sd.h | 1 | ||||
| -rw-r--r-- | drivers/mmc/core/sdio.c | 135 | ||||
| -rw-r--r-- | drivers/mmc/core/sdio_bus.c | 38 | ||||
| -rw-r--r-- | drivers/mmc/core/sdio_irq.c | 52 | ||||
| -rw-r--r-- | drivers/mmc/core/slot-gpio.c | 184 | 
15 files changed, 1081 insertions, 925 deletions
diff --git a/drivers/mmc/core/Kconfig b/drivers/mmc/core/Kconfig index 269d072ef55..9ebee72d9c3 100644 --- a/drivers/mmc/core/Kconfig +++ b/drivers/mmc/core/Kconfig @@ -2,21 +2,6 @@  # MMC core configuration  # -config MMC_UNSAFE_RESUME -	bool "Assume MMC/SD cards are non-removable (DANGEROUS)" -	help -	  If you say Y here, the MMC layer will assume that all cards -	  stayed in their respective slots during the suspend. The -	  normal behaviour is to remove them at suspend and -	  redetecting them at resume. Breaking this assumption will -	  in most cases result in data corruption. - -	  This option is usually just for embedded systems which use -	  a MMC/SD card for rootfs. Most people should say N here. - -	  This option sets a default which can be overridden by the -	  module parameter "removable=0" or "removable=1". -  config MMC_CLKGATE  	bool "MMC host clock gating"  	help diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c index 704bf66f587..d2dbf02022b 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 mmc_type_show(struct device *dev, +static ssize_t type_show(struct device *dev,  	struct device_attribute *attr, char *buf)  {  	struct mmc_card *card = mmc_dev_to_card(dev); @@ -45,11 +45,13 @@ static ssize_t mmc_type_show(struct device *dev,  		return -EFAULT;  	}  } +static DEVICE_ATTR_RO(type); -static struct device_attribute mmc_dev_attrs[] = { -	__ATTR(type, S_IRUGO, mmc_type_show, NULL), -	__ATTR_NULL, +static struct attribute *mmc_dev_attrs[] = { +	&dev_attr_type.attr, +	NULL,  }; +ATTRIBUTE_GROUPS(mmc_dev);  /*   * This currently matches any MMC driver to any MMC card - drivers @@ -183,24 +185,16 @@ static int mmc_runtime_suspend(struct device *dev)  {  	struct mmc_card *card = mmc_dev_to_card(dev);  	struct mmc_host *host = card->host; -	int ret = 0; -	if (host->bus_ops->runtime_suspend) -		ret = host->bus_ops->runtime_suspend(host); - -	return ret; +	return host->bus_ops->runtime_suspend(host);  }  static int mmc_runtime_resume(struct device *dev)  {  	struct mmc_card *card = mmc_dev_to_card(dev);  	struct mmc_host *host = card->host; -	int ret = 0; -	if (host->bus_ops->runtime_resume) -		ret = host->bus_ops->runtime_resume(host); - -	return ret; +	return host->bus_ops->runtime_resume(host);  }  static int mmc_runtime_idle(struct device *dev) @@ -218,7 +212,7 @@ static const struct dev_pm_ops mmc_bus_pm_ops = {  static struct bus_type mmc_bus_type = {  	.name		= "mmc", -	.dev_attrs	= mmc_dev_attrs, +	.dev_groups	= mmc_dev_groups,  	.match		= mmc_bus_match,  	.uevent		= mmc_bus_uevent,  	.probe		= mmc_bus_probe, @@ -340,23 +334,24 @@ 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];  	if (mmc_host_is_spi(card->host)) {  		pr_info("%s: new %s%s%s card on SPI\n",  			mmc_hostname(card->host), -			mmc_card_highspeed(card) ? "high speed " : "", -			mmc_card_ddr_mode(card) ? "DDR " : "", +			mmc_card_hs(card) ? "high speed " : "", +			mmc_card_ddr52(card) ? "DDR " : "",  			type);  	} else {  		pr_info("%s: new %s%s%s%s%s card at address %04x\n",  			mmc_hostname(card->host),  			mmc_card_uhs(card) ? "ultra high speed " : -			(mmc_card_highspeed(card) ? "high speed " : ""), +			(mmc_card_hs(card) ? "high speed " : ""), +			mmc_card_hs400(card) ? "HS400 " :  			(mmc_card_hs200(card) ? "HS200 " : ""), -			mmc_card_ddr_mode(card) ? "DDR " : "", +			mmc_card_ddr52(card) ? "DDR " : "",  			uhs_bus_speed_mode, type, card->rca);  	} 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);  	} diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h index 5345d156493..443a584660f 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); +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)  { diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c index 54829c0ed00..91eb1622324 100644 --- a/drivers/mmc/core/debugfs.c +++ b/drivers/mmc/core/debugfs.c @@ -135,8 +135,14 @@ static int mmc_ios_show(struct seq_file *s, void *data)  	case MMC_TIMING_UHS_DDR50:  		str = "sd uhs DDR50";  		break; +	case MMC_TIMING_MMC_DDR52: +		str = "mmc DDR52"; +		break;  	case MMC_TIMING_MMC_HS200: -		str = "mmc high-speed SDR200"; +		str = "mmc HS200"; +		break; +	case MMC_TIMING_MMC_HS400: +		str = "mmc HS400";  		break;  	default:  		str = "invalid"; diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index 49bc403e31f..95cceae9694 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c @@ -337,7 +337,7 @@ int mmc_of_parse(struct mmc_host *host)  		break;  	default:  		dev_err(host->parent, -			"Invalid \"bus-width\" value %ud!\n", bus_width); +			"Invalid \"bus-width\" value %u!\n", bus_width);  		return -EINVAL;  	} @@ -419,6 +419,16 @@ int mmc_of_parse(struct mmc_host *host)  		host->caps |= MMC_CAP_SD_HIGHSPEED;  	if (of_find_property(np, "cap-mmc-highspeed", &len))  		host->caps |= MMC_CAP_MMC_HIGHSPEED; +	if (of_find_property(np, "sd-uhs-sdr12", &len)) +		host->caps |= MMC_CAP_UHS_SDR12; +	if (of_find_property(np, "sd-uhs-sdr25", &len)) +		host->caps |= MMC_CAP_UHS_SDR25; +	if (of_find_property(np, "sd-uhs-sdr50", &len)) +		host->caps |= MMC_CAP_UHS_SDR50; +	if (of_find_property(np, "sd-uhs-sdr104", &len)) +		host->caps |= MMC_CAP_UHS_SDR104; +	if (of_find_property(np, "sd-uhs-ddr50", &len)) +		host->caps |= MMC_CAP_UHS_DDR50;  	if (of_find_property(np, "cap-power-off-card", &len))  		host->caps |= MMC_CAP_POWER_OFF_CARD;  	if (of_find_property(np, "cap-sdio-irq", &len)) @@ -429,6 +439,18 @@ int mmc_of_parse(struct mmc_host *host)  		host->pm_caps |= MMC_PM_KEEP_POWER;  	if (of_find_property(np, "enable-sdio-wakeup", &len))  		host->pm_caps |= MMC_PM_WAKE_SDIO_IRQ; +	if (of_find_property(np, "mmc-ddr-1_8v", &len)) +		host->caps |= MMC_CAP_1_8V_DDR; +	if (of_find_property(np, "mmc-ddr-1_2v", &len)) +		host->caps |= MMC_CAP_1_2V_DDR; +	if (of_find_property(np, "mmc-hs200-1_8v", &len)) +		host->caps2 |= MMC_CAP2_HS200_1_8V_SDR; +	if (of_find_property(np, "mmc-hs200-1_2v", &len)) +		host->caps2 |= MMC_CAP2_HS200_1_2V_SDR; +	if (of_find_property(np, "mmc-hs400-1_8v", &len)) +		host->caps2 |= MMC_CAP2_HS400_1_8V | MMC_CAP2_HS200_1_8V_SDR; +	if (of_find_property(np, "mmc-hs400-1_2v", &len)) +		host->caps2 |= MMC_CAP2_HS400_1_2V | MMC_CAP2_HS200_1_2V_SDR;  	return 0; diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 6d02012a1d0..793c6f7ddb0 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -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> @@ -239,31 +240,62 @@ static int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd)  static void mmc_select_card_type(struct mmc_card *card)  {  	struct mmc_host *host = card->host; -	u8 card_type = card->ext_csd.raw_card_type & EXT_CSD_CARD_TYPE_MASK; +	u8 card_type = card->ext_csd.raw_card_type;  	u32 caps = host->caps, caps2 = host->caps2; -	unsigned int hs_max_dtr = 0; +	unsigned int hs_max_dtr = 0, hs200_max_dtr = 0; +	unsigned int avail_type = 0; -	if (card_type & EXT_CSD_CARD_TYPE_26) +	if (caps & MMC_CAP_MMC_HIGHSPEED && +	    card_type & EXT_CSD_CARD_TYPE_HS_26) {  		hs_max_dtr = MMC_HIGH_26_MAX_DTR; +		avail_type |= EXT_CSD_CARD_TYPE_HS_26; +	}  	if (caps & MMC_CAP_MMC_HIGHSPEED && -			card_type & EXT_CSD_CARD_TYPE_52) +	    card_type & EXT_CSD_CARD_TYPE_HS_52) {  		hs_max_dtr = MMC_HIGH_52_MAX_DTR; +		avail_type |= EXT_CSD_CARD_TYPE_HS_52; +	} + +	if (caps & MMC_CAP_1_8V_DDR && +	    card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) { +		hs_max_dtr = MMC_HIGH_DDR_MAX_DTR; +		avail_type |= EXT_CSD_CARD_TYPE_DDR_1_8V; +	} -	if ((caps & MMC_CAP_1_8V_DDR && -			card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) || -	    (caps & MMC_CAP_1_2V_DDR && -			card_type & EXT_CSD_CARD_TYPE_DDR_1_2V)) +	if (caps & MMC_CAP_1_2V_DDR && +	    card_type & EXT_CSD_CARD_TYPE_DDR_1_2V) {  		hs_max_dtr = MMC_HIGH_DDR_MAX_DTR; +		avail_type |= EXT_CSD_CARD_TYPE_DDR_1_2V; +	} + +	if (caps2 & MMC_CAP2_HS200_1_8V_SDR && +	    card_type & EXT_CSD_CARD_TYPE_HS200_1_8V) { +		hs200_max_dtr = MMC_HS200_MAX_DTR; +		avail_type |= EXT_CSD_CARD_TYPE_HS200_1_8V; +	} + +	if (caps2 & MMC_CAP2_HS200_1_2V_SDR && +	    card_type & EXT_CSD_CARD_TYPE_HS200_1_2V) { +		hs200_max_dtr = MMC_HS200_MAX_DTR; +		avail_type |= EXT_CSD_CARD_TYPE_HS200_1_2V; +	} -	if ((caps2 & MMC_CAP2_HS200_1_8V_SDR && -			card_type & EXT_CSD_CARD_TYPE_SDR_1_8V) || -	    (caps2 & MMC_CAP2_HS200_1_2V_SDR && -			card_type & EXT_CSD_CARD_TYPE_SDR_1_2V)) -		hs_max_dtr = MMC_HS200_MAX_DTR; +	if (caps2 & MMC_CAP2_HS400_1_8V && +	    card_type & EXT_CSD_CARD_TYPE_HS400_1_8V) { +		hs200_max_dtr = MMC_HS200_MAX_DTR; +		avail_type |= EXT_CSD_CARD_TYPE_HS400_1_8V; +	} + +	if (caps2 & MMC_CAP2_HS400_1_2V && +	    card_type & EXT_CSD_CARD_TYPE_HS400_1_2V) { +		hs200_max_dtr = MMC_HS200_MAX_DTR; +		avail_type |= EXT_CSD_CARD_TYPE_HS400_1_2V; +	}  	card->ext_csd.hs_max_dtr = hs_max_dtr; -	card->ext_csd.card_type = card_type; +	card->ext_csd.hs200_max_dtr = hs200_max_dtr; +	card->mmc_avail_type = avail_type;  }  /* @@ -479,6 +511,8 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)  			ext_csd[EXT_CSD_PWR_CL_DDR_52_195];  		card->ext_csd.raw_pwr_cl_ddr_52_360 =  			ext_csd[EXT_CSD_PWR_CL_DDR_52_360]; +		card->ext_csd.raw_pwr_cl_ddr_200_360 = +			ext_csd[EXT_CSD_PWR_CL_DDR_200_360];  	}  	if (card->ext_csd.rev >= 5) { @@ -645,7 +679,10 @@ static int mmc_compare_ext_csds(struct mmc_card *card, unsigned bus_width)  		(card->ext_csd.raw_pwr_cl_ddr_52_195 ==  			bw_ext_csd[EXT_CSD_PWR_CL_DDR_52_195]) &&  		(card->ext_csd.raw_pwr_cl_ddr_52_360 == -			bw_ext_csd[EXT_CSD_PWR_CL_DDR_52_360])); +			bw_ext_csd[EXT_CSD_PWR_CL_DDR_52_360]) && +		(card->ext_csd.raw_pwr_cl_ddr_200_360 == +			bw_ext_csd[EXT_CSD_PWR_CL_DDR_200_360])); +  	if (err)  		err = -EINVAL; @@ -693,18 +730,10 @@ static struct attribute *mmc_std_attrs[] = {  	&dev_attr_rel_sectors.attr,  	NULL,  }; - -static struct attribute_group mmc_std_attr_group = { -	.attrs = mmc_std_attrs, -}; - -static const struct attribute_group *mmc_attr_groups[] = { -	&mmc_std_attr_group, -	NULL, -}; +ATTRIBUTE_GROUPS(mmc_std);  static struct device_type mmc_type = { -	.groups = mmc_attr_groups, +	.groups = mmc_std_groups,  };  /* @@ -713,17 +742,13 @@ static struct device_type mmc_type = {   * extended CSD register, select it by executing the   * mmc_switch command.   */ -static int mmc_select_powerclass(struct mmc_card *card, -		unsigned int bus_width) +static int __mmc_select_powerclass(struct mmc_card *card, +				   unsigned int bus_width)  { -	int err = 0; +	struct mmc_host *host = card->host; +	struct mmc_ext_csd *ext_csd = &card->ext_csd;  	unsigned int pwrclass_val = 0; -	struct mmc_host *host; - -	BUG_ON(!card); - -	host = card->host; -	BUG_ON(!host); +	int err = 0;  	/* Power class selection is supported for versions >= 4.0 */  	if (card->csd.mmca_vsn < CSD_SPEC_VER_4) @@ -735,14 +760,14 @@ static int mmc_select_powerclass(struct mmc_card *card,  	switch (1 << host->ios.vdd) {  	case MMC_VDD_165_195: -		if (host->ios.clock <= 26000000) -			pwrclass_val = card->ext_csd.raw_pwr_cl_26_195; -		else if	(host->ios.clock <= 52000000) +		if (host->ios.clock <= MMC_HIGH_26_MAX_DTR) +			pwrclass_val = ext_csd->raw_pwr_cl_26_195; +		else if (host->ios.clock <= MMC_HIGH_52_MAX_DTR)  			pwrclass_val = (bus_width <= EXT_CSD_BUS_WIDTH_8) ? -				card->ext_csd.raw_pwr_cl_52_195 : -				card->ext_csd.raw_pwr_cl_ddr_52_195; -		else if (host->ios.clock <= 200000000) -			pwrclass_val = card->ext_csd.raw_pwr_cl_200_195; +				ext_csd->raw_pwr_cl_52_195 : +				ext_csd->raw_pwr_cl_ddr_52_195; +		else if (host->ios.clock <= MMC_HS200_MAX_DTR) +			pwrclass_val = ext_csd->raw_pwr_cl_200_195;  		break;  	case MMC_VDD_27_28:  	case MMC_VDD_28_29: @@ -753,14 +778,16 @@ static int mmc_select_powerclass(struct mmc_card *card,  	case MMC_VDD_33_34:  	case MMC_VDD_34_35:  	case MMC_VDD_35_36: -		if (host->ios.clock <= 26000000) -			pwrclass_val = card->ext_csd.raw_pwr_cl_26_360; -		else if	(host->ios.clock <= 52000000) +		if (host->ios.clock <= MMC_HIGH_26_MAX_DTR) +			pwrclass_val = ext_csd->raw_pwr_cl_26_360; +		else if (host->ios.clock <= MMC_HIGH_52_MAX_DTR)  			pwrclass_val = (bus_width <= EXT_CSD_BUS_WIDTH_8) ? -				card->ext_csd.raw_pwr_cl_52_360 : -				card->ext_csd.raw_pwr_cl_ddr_52_360; -		else if (host->ios.clock <= 200000000) -			pwrclass_val = card->ext_csd.raw_pwr_cl_200_360; +				ext_csd->raw_pwr_cl_52_360 : +				ext_csd->raw_pwr_cl_ddr_52_360; +		else if (host->ios.clock <= MMC_HS200_MAX_DTR) +			pwrclass_val = (bus_width == EXT_CSD_DDR_BUS_WIDTH_8) ? +				ext_csd->raw_pwr_cl_ddr_200_360 : +				ext_csd->raw_pwr_cl_200_360;  		break;  	default:  		pr_warning("%s: Voltage range not supported " @@ -786,40 +813,79 @@ static int mmc_select_powerclass(struct mmc_card *card,  	return err;  } +static int mmc_select_powerclass(struct mmc_card *card) +{ +	struct mmc_host *host = card->host; +	u32 bus_width, ext_csd_bits; +	int err, ddr; + +	/* Power class selection is supported for versions >= 4.0 */ +	if (card->csd.mmca_vsn < CSD_SPEC_VER_4) +		return 0; + +	bus_width = host->ios.bus_width; +	/* Power class values are defined only for 4/8 bit bus */ +	if (bus_width == MMC_BUS_WIDTH_1) +		return 0; + +	ddr = card->mmc_avail_type & EXT_CSD_CARD_TYPE_DDR_52; +	if (ddr) +		ext_csd_bits = (bus_width == MMC_BUS_WIDTH_8) ? +			EXT_CSD_DDR_BUS_WIDTH_8 : EXT_CSD_DDR_BUS_WIDTH_4; +	else +		ext_csd_bits = (bus_width == MMC_BUS_WIDTH_8) ? +			EXT_CSD_BUS_WIDTH_8 :  EXT_CSD_BUS_WIDTH_4; + +	err = __mmc_select_powerclass(card, ext_csd_bits); +	if (err) +		pr_warn("%s: power class selection to bus width %d ddr %d failed\n", +			mmc_hostname(host), 1 << bus_width, ddr); + +	return err; +} +  /* - * Selects the desired buswidth and switch to the HS200 mode - * if bus width set without error + * Set the bus speed for the selected speed mode.   */ -static int mmc_select_hs200(struct mmc_card *card) +static void mmc_set_bus_speed(struct mmc_card *card) +{ +	unsigned int max_dtr = (unsigned int)-1; + +	if ((mmc_card_hs200(card) || mmc_card_hs400(card)) && +	     max_dtr > card->ext_csd.hs200_max_dtr) +		max_dtr = card->ext_csd.hs200_max_dtr; +	else if (mmc_card_hs(card) && max_dtr > card->ext_csd.hs_max_dtr) +		max_dtr = card->ext_csd.hs_max_dtr; +	else if (max_dtr > card->csd.max_dtr) +		max_dtr = card->csd.max_dtr; + +	mmc_set_clock(card->host, max_dtr); +} + +/* + * Select the bus width amoung 4-bit and 8-bit(SDR). + * If the bus width is changed successfully, return the selected width value. + * Zero is returned instead of error value if the wide width is not supported. + */ +static int mmc_select_bus_width(struct mmc_card *card)  { -	int idx, err = -EINVAL; -	struct mmc_host *host;  	static unsigned ext_csd_bits[] = { -		EXT_CSD_BUS_WIDTH_4,  		EXT_CSD_BUS_WIDTH_8, +		EXT_CSD_BUS_WIDTH_4,  	};  	static unsigned bus_widths[] = { -		MMC_BUS_WIDTH_4,  		MMC_BUS_WIDTH_8, +		MMC_BUS_WIDTH_4,  	}; +	struct mmc_host *host = card->host; +	unsigned idx, bus_width = 0; +	int err = 0; -	BUG_ON(!card); - -	host = card->host; - -	if (card->ext_csd.card_type & EXT_CSD_CARD_TYPE_SDR_1_2V && -			host->caps2 & MMC_CAP2_HS200_1_2V_SDR) -		err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120); - -	if (err && card->ext_csd.card_type & EXT_CSD_CARD_TYPE_SDR_1_8V && -			host->caps2 & MMC_CAP2_HS200_1_8V_SDR) -		err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180); - -	/* If fails try again during next card power cycle */ -	if (err) -		goto err; +	if ((card->csd.mmca_vsn < CSD_SPEC_VER_4) && +	    !(host->caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA))) +		return 0; -	idx = (host->caps & MMC_CAP_8_BIT_DATA) ? 1 : 0; +	idx = (host->caps & MMC_CAP_8_BIT_DATA) ? 0 : 1;  	/*  	 * Unlike SD, MMC cards dont have a configuration register to notify @@ -827,8 +893,7 @@ static int mmc_select_hs200(struct mmc_card *card)  	 * the supported bus width or compare the ext csd values of current  	 * bus width and ext csd values of 1 bit mode read earlier.  	 */ -	for (; idx >= 0; idx--) { - +	for (; idx < ARRAY_SIZE(bus_widths); idx++) {  		/*  		 * Host is capable of 8bit transfer, then switch  		 * the device to work in 8bit transfer mode. If the @@ -843,25 +908,266 @@ static int mmc_select_hs200(struct mmc_card *card)  		if (err)  			continue; -		mmc_set_bus_width(card->host, bus_widths[idx]); +		bus_width = bus_widths[idx]; +		mmc_set_bus_width(host, bus_width); +		/* +		 * If controller can't handle bus width test, +		 * compare ext_csd previously read in 1 bit mode +		 * against ext_csd at new bus width +		 */  		if (!(host->caps & MMC_CAP_BUS_WIDTH_TEST)) -			err = mmc_compare_ext_csds(card, bus_widths[idx]); +			err = mmc_compare_ext_csds(card, bus_width);  		else -			err = mmc_bus_test(card, bus_widths[idx]); -		if (!err) +			err = mmc_bus_test(card, bus_width); + +		if (!err) { +			err = bus_width;  			break; +		} else { +			pr_warn("%s: switch to bus width %d failed\n", +				mmc_hostname(host), ext_csd_bits[idx]); +		}  	} -	/* switch to HS200 mode if bus width set successfully */ +	return err; +} + +/* + * Switch to the high-speed mode + */ +static int mmc_select_hs(struct mmc_card *card) +{ +	int err; + +	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, +			   EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS, +			   card->ext_csd.generic_cmd6_time, +			   true, true, true);  	if (!err) -		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, -				 EXT_CSD_HS_TIMING, 2, 0); +		mmc_set_timing(card->host, MMC_TIMING_MMC_HS); + +	return err; +} + +/* + * Activate wide bus and DDR if supported. + */ +static int mmc_select_hs_ddr(struct mmc_card *card) +{ +	struct mmc_host *host = card->host; +	u32 bus_width, ext_csd_bits; +	int err = 0; + +	if (!(card->mmc_avail_type & EXT_CSD_CARD_TYPE_DDR_52)) +		return 0; + +	bus_width = host->ios.bus_width; +	if (bus_width == MMC_BUS_WIDTH_1) +		return 0; + +	ext_csd_bits = (bus_width == MMC_BUS_WIDTH_8) ? +		EXT_CSD_DDR_BUS_WIDTH_8 : EXT_CSD_DDR_BUS_WIDTH_4; + +	err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, +			EXT_CSD_BUS_WIDTH, +			ext_csd_bits, +			card->ext_csd.generic_cmd6_time); +	if (err) { +		pr_warn("%s: switch to bus width %d ddr failed\n", +			mmc_hostname(host), 1 << bus_width); +		return err; +	} + +	/* +	 * eMMC cards can support 3.3V to 1.2V i/o (vccq) +	 * signaling. +	 * +	 * EXT_CSD_CARD_TYPE_DDR_1_8V means 3.3V or 1.8V vccq. +	 * +	 * 1.8V vccq at 3.3V core voltage (vcc) is not required +	 * in the JEDEC spec for DDR. +	 * +	 * Do not force change in vccq since we are obviously +	 * working and no change to vccq is needed. +	 * +	 * WARNING: eMMC rules are NOT the same as SD DDR +	 */ +	if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_DDR_1_2V) { +		err = __mmc_set_signal_voltage(host, +				MMC_SIGNAL_VOLTAGE_120); +		if (err) +			return err; +	} + +	mmc_set_timing(host, MMC_TIMING_MMC_DDR52); + +	return err; +} + +static int mmc_select_hs400(struct mmc_card *card) +{ +	struct mmc_host *host = card->host; +	int err = 0; + +	/* +	 * HS400 mode requires 8-bit bus width +	 */ +	if (!(card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS400 && +	      host->ios.bus_width == MMC_BUS_WIDTH_8)) +		return 0; + +	/* +	 * Before switching to dual data rate operation for HS400, +	 * it is required to convert from HS200 mode to HS mode. +	 */ +	mmc_set_timing(card->host, MMC_TIMING_MMC_HS); +	mmc_set_bus_speed(card); + +	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, +			   EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS, +			   card->ext_csd.generic_cmd6_time, +			   true, true, true); +	if (err) { +		pr_warn("%s: switch to high-speed from hs200 failed, err:%d\n", +			mmc_hostname(host), err); +		return err; +	} + +	err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, +			 EXT_CSD_BUS_WIDTH, +			 EXT_CSD_DDR_BUS_WIDTH_8, +			 card->ext_csd.generic_cmd6_time); +	if (err) { +		pr_warn("%s: switch to bus width for hs400 failed, err:%d\n", +			mmc_hostname(host), err); +		return err; +	} + +	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, +			   EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS400, +			   card->ext_csd.generic_cmd6_time, +			   true, true, true); +	if (err) { +		pr_warn("%s: switch to hs400 failed, err:%d\n", +			 mmc_hostname(host), err); +		return err; +	} + +	mmc_set_timing(host, MMC_TIMING_MMC_HS400); +	mmc_set_bus_speed(card); + +	return 0; +} + +/* + * For device supporting HS200 mode, the following sequence + * should be done before executing the tuning process. + * 1. set the desired bus width(4-bit or 8-bit, 1-bit is not supported) + * 2. switch to HS200 mode + * 3. set the clock to > 52Mhz and <=200MHz + */ +static int mmc_select_hs200(struct mmc_card *card) +{ +	struct mmc_host *host = card->host; +	int err = -EINVAL; + +	if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_2V) +		err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120); + +	if (err && card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_8V) +		err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180); + +	/* If fails try again during next card power cycle */ +	if (err) +		goto err; + +	/* +	 * Set the bus width(4 or 8) with host's support and +	 * switch to HS200 mode if bus width is set successfully. +	 */ +	err = mmc_select_bus_width(card); +	if (!IS_ERR_VALUE(err)) { +		err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, +				   EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS200, +				   card->ext_csd.generic_cmd6_time, +				   true, true, true); +		if (!err) +			mmc_set_timing(host, MMC_TIMING_MMC_HS200); +	}  err:  	return err;  }  /* + * Activate High Speed or HS200 mode if supported. + */ +static int mmc_select_timing(struct mmc_card *card) +{ +	int err = 0; + +	if ((card->csd.mmca_vsn < CSD_SPEC_VER_4 && +	     card->ext_csd.hs_max_dtr == 0)) +		goto bus_speed; + +	if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200) +		err = mmc_select_hs200(card); +	else if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS) +		err = mmc_select_hs(card); + +	if (err && err != -EBADMSG) +		return err; + +	if (err) { +		pr_warn("%s: switch to %s failed\n", +			mmc_card_hs(card) ? "high-speed" : +			(mmc_card_hs200(card) ? "hs200" : ""), +			mmc_hostname(card->host)); +		err = 0; +	} + +bus_speed: +	/* +	 * Set the bus speed to the selected bus timing. +	 * If timing is not selected, backward compatible is the default. +	 */ +	mmc_set_bus_speed(card); +	return err; +} + +/* + * Execute tuning sequence to seek the proper bus operating + * conditions for HS200 and HS400, which sends CMD21 to the device. + */ +static int mmc_hs200_tuning(struct mmc_card *card) +{ +	struct mmc_host *host = card->host; +	int err = 0; + +	/* +	 * Timing should be adjusted to the HS400 target +	 * operation frequency for tuning process +	 */ +	if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS400 && +	    host->ios.bus_width == MMC_BUS_WIDTH_8) +		if (host->ops->prepare_hs400_tuning) +			host->ops->prepare_hs400_tuning(host, &host->ios); + +	if (host->ops->execute_tuning) { +		mmc_host_clk_hold(host); +		err = host->ops->execute_tuning(host, +				MMC_SEND_TUNING_BLOCK_HS200); +		mmc_host_clk_release(host); + +		if (err) +			pr_warn("%s: tuning execution failed\n", +				mmc_hostname(host)); +	} + +	return err; +} + +/*   * Handle the detection and initialisation of a card.   *   * In the case of a resume, "oldcard" will contain the card @@ -871,9 +1177,8 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,  	struct mmc_card *oldcard)  {  	struct mmc_card *card; -	int err, ddr = 0; +	int err;  	u32 cid[4]; -	unsigned int max_dtr;  	u32 rocr;  	u8 *ext_csd = NULL; @@ -934,6 +1239,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)); @@ -1064,209 +1370,34 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,  	}  	/* -	 * Activate high speed (if supported) -	 */ -	if (card->ext_csd.hs_max_dtr != 0) { -		err = 0; -		if (card->ext_csd.hs_max_dtr > 52000000 && -		    host->caps2 & MMC_CAP2_HS200) -			err = mmc_select_hs200(card); -		else if	(host->caps & MMC_CAP_MMC_HIGHSPEED) -			err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, -					 EXT_CSD_HS_TIMING, 1, -					 card->ext_csd.generic_cmd6_time); - -		if (err && err != -EBADMSG) -			goto free_card; - -		if (err) { -			pr_warning("%s: switch to highspeed failed\n", -			       mmc_hostname(card->host)); -			err = 0; -		} else { -			if (card->ext_csd.hs_max_dtr > 52000000 && -			    host->caps2 & MMC_CAP2_HS200) { -				mmc_card_set_hs200(card); -				mmc_set_timing(card->host, -					       MMC_TIMING_MMC_HS200); -			} else { -				mmc_card_set_highspeed(card); -				mmc_set_timing(card->host, MMC_TIMING_MMC_HS); -			} -		} -	} - -	/* -	 * Compute bus speed. -	 */ -	max_dtr = (unsigned int)-1; - -	if (mmc_card_highspeed(card) || mmc_card_hs200(card)) { -		if (max_dtr > card->ext_csd.hs_max_dtr) -			max_dtr = card->ext_csd.hs_max_dtr; -		if (mmc_card_highspeed(card) && (max_dtr > 52000000)) -			max_dtr = 52000000; -	} else if (max_dtr > card->csd.max_dtr) { -		max_dtr = card->csd.max_dtr; -	} - -	mmc_set_clock(host, max_dtr); - -	/* -	 * Indicate DDR mode (if supported). +	 * Select timing interface  	 */ -	if (mmc_card_highspeed(card)) { -		if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) -			&& ((host->caps & (MMC_CAP_1_8V_DDR | -			     MMC_CAP_UHS_DDR50)) -				== (MMC_CAP_1_8V_DDR | MMC_CAP_UHS_DDR50))) -				ddr = MMC_1_8V_DDR_MODE; -		else if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_2V) -			&& ((host->caps & (MMC_CAP_1_2V_DDR | -			     MMC_CAP_UHS_DDR50)) -				== (MMC_CAP_1_2V_DDR | MMC_CAP_UHS_DDR50))) -				ddr = MMC_1_2V_DDR_MODE; -	} +	err = mmc_select_timing(card); +	if (err) +		goto free_card; -	/* -	 * Indicate HS200 SDR mode (if supported). -	 */  	if (mmc_card_hs200(card)) { -		u32 ext_csd_bits; -		u32 bus_width = card->host->ios.bus_width; - -		/* -		 * For devices supporting HS200 mode, the bus width has -		 * to be set before executing the tuning function. If -		 * set before tuning, then device will respond with CRC -		 * errors for responses on CMD line. So for HS200 the -		 * sequence will be -		 * 1. set bus width 4bit / 8 bit (1 bit not supported) -		 * 2. switch to HS200 mode -		 * 3. set the clock to > 52Mhz <=200MHz and -		 * 4. execute tuning for HS200 -		 */ -		if ((host->caps2 & MMC_CAP2_HS200) && -		    card->host->ops->execute_tuning) { -			mmc_host_clk_hold(card->host); -			err = card->host->ops->execute_tuning(card->host, -				MMC_SEND_TUNING_BLOCK_HS200); -			mmc_host_clk_release(card->host); -		} -		if (err) { -			pr_warning("%s: tuning execution failed\n", -				   mmc_hostname(card->host)); +		err = mmc_hs200_tuning(card); +		if (err)  			goto err; -		} -		ext_csd_bits = (bus_width == MMC_BUS_WIDTH_8) ? -				EXT_CSD_BUS_WIDTH_8 : EXT_CSD_BUS_WIDTH_4; -		err = mmc_select_powerclass(card, ext_csd_bits); +		err = mmc_select_hs400(card);  		if (err) -			pr_warning("%s: power class selection to bus width %d" -				   " failed\n", mmc_hostname(card->host), -				   1 << bus_width); +			goto err; +	} else if (mmc_card_hs(card)) { +		/* Select the desired bus width optionally */ +		err = mmc_select_bus_width(card); +		if (!IS_ERR_VALUE(err)) { +			err = mmc_select_hs_ddr(card); +			if (err) +				goto err; +		}  	}  	/* -	 * Activate wide bus and DDR (if supported). +	 * Choose the power class with selected bus interface  	 */ -	if (!mmc_card_hs200(card) && -	    (card->csd.mmca_vsn >= CSD_SPEC_VER_4) && -	    (host->caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA))) { -		static unsigned ext_csd_bits[][2] = { -			{ EXT_CSD_BUS_WIDTH_8, EXT_CSD_DDR_BUS_WIDTH_8 }, -			{ EXT_CSD_BUS_WIDTH_4, EXT_CSD_DDR_BUS_WIDTH_4 }, -			{ EXT_CSD_BUS_WIDTH_1, EXT_CSD_BUS_WIDTH_1 }, -		}; -		static unsigned bus_widths[] = { -			MMC_BUS_WIDTH_8, -			MMC_BUS_WIDTH_4, -			MMC_BUS_WIDTH_1 -		}; -		unsigned idx, bus_width = 0; - -		if (host->caps & MMC_CAP_8_BIT_DATA) -			idx = 0; -		else -			idx = 1; -		for (; idx < ARRAY_SIZE(bus_widths); idx++) { -			bus_width = bus_widths[idx]; -			if (bus_width == MMC_BUS_WIDTH_1) -				ddr = 0; /* no DDR for 1-bit width */ -			err = mmc_select_powerclass(card, ext_csd_bits[idx][0]); -			if (err) -				pr_warning("%s: power class selection to " -					   "bus width %d failed\n", -					   mmc_hostname(card->host), -					   1 << bus_width); - -			err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, -					 EXT_CSD_BUS_WIDTH, -					 ext_csd_bits[idx][0], -					 card->ext_csd.generic_cmd6_time); -			if (!err) { -				mmc_set_bus_width(card->host, bus_width); - -				/* -				 * If controller can't handle bus width test, -				 * compare ext_csd previously read in 1 bit mode -				 * against ext_csd at new bus width -				 */ -				if (!(host->caps & MMC_CAP_BUS_WIDTH_TEST)) -					err = mmc_compare_ext_csds(card, -						bus_width); -				else -					err = mmc_bus_test(card, bus_width); -				if (!err) -					break; -			} -		} - -		if (!err && ddr) { -			err = mmc_select_powerclass(card, ext_csd_bits[idx][1]); -			if (err) -				pr_warning("%s: power class selection to " -					   "bus width %d ddr %d failed\n", -					   mmc_hostname(card->host), -					   1 << bus_width, ddr); - -			err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, -					 EXT_CSD_BUS_WIDTH, -					 ext_csd_bits[idx][1], -					 card->ext_csd.generic_cmd6_time); -		} -		if (err) { -			pr_warning("%s: switch to bus width %d ddr %d " -				"failed\n", mmc_hostname(card->host), -				1 << bus_width, ddr); -			goto free_card; -		} else if (ddr) { -			/* -			 * eMMC cards can support 3.3V to 1.2V i/o (vccq) -			 * signaling. -			 * -			 * EXT_CSD_CARD_TYPE_DDR_1_8V means 3.3V or 1.8V vccq. -			 * -			 * 1.8V vccq at 3.3V core voltage (vcc) is not required -			 * in the JEDEC spec for DDR. -			 * -			 * Do not force change in vccq since we are obviously -			 * working and no change to vccq is needed. -			 * -			 * WARNING: eMMC rules are NOT the same as SD DDR -			 */ -			if (ddr == MMC_1_2V_DDR_MODE) { -				err = __mmc_set_signal_voltage(host, -					MMC_SIGNAL_VOLTAGE_120); -				if (err) -					goto err; -			} -			mmc_card_set_ddr_mode(card); -			mmc_set_timing(card->host, MMC_TIMING_UHS_DDR50); -			mmc_set_bus_width(card->host, bus_width); -		} -	} +	mmc_select_powerclass(card);  	/*  	 * Enable HPI feature (if supported) @@ -1289,8 +1420,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,  	 * If cache size is higher than 0, this indicates  	 * the existence of cache and it can be turned on.  	 */ -	if ((host->caps2 & MMC_CAP2_CACHE_CTRL) && -			card->ext_csd.cache_size > 0) { +	if (card->ext_csd.cache_size > 0) {  		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,  				EXT_CSD_CACHE_CTRL, 1,  				card->ext_csd.generic_cmd6_time); @@ -1358,11 +1488,9 @@ static int mmc_sleep(struct mmc_host *host)  {  	struct mmc_command cmd = {0};  	struct mmc_card *card = host->card; +	unsigned int timeout_ms = DIV_ROUND_UP(card->ext_csd.sa_timeout, 10000);  	int err; -	if (host->caps2 & MMC_CAP2_NO_SLEEP_CMD) -		return 0; -  	err = mmc_deselect_cards(host);  	if (err)  		return err; @@ -1371,7 +1499,19 @@ static int mmc_sleep(struct mmc_host *host)  	cmd.arg = card->rca << 16;  	cmd.arg |= 1 << 15; -	cmd.flags = MMC_RSP_R1B | MMC_CMD_AC; +	/* +	 * If the max_busy_timeout of the host is specified, validate it against +	 * the sleep cmd timeout. A failure means we need to prevent the host +	 * from doing hw busy detection, which is done by converting to a R1 +	 * response instead of a R1B. +	 */ +	if (host->max_busy_timeout && (timeout_ms > host->max_busy_timeout)) { +		cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; +	} else { +		cmd.flags = MMC_RSP_R1B | MMC_CMD_AC; +		cmd.busy_timeout = timeout_ms; +	} +  	err = mmc_wait_for_cmd(host, &cmd, 0);  	if (err)  		return err; @@ -1382,8 +1522,8 @@ static int mmc_sleep(struct mmc_host *host)  	 * SEND_STATUS command to poll the status because that command (and most  	 * others) is invalid while the card sleeps.  	 */ -	if (!(host->caps & MMC_CAP_WAIT_WHILE_BUSY)) -		mmc_delay(DIV_ROUND_UP(card->ext_csd.sa_timeout, 10000)); +	if (!cmd.busy_timeout || !(host->caps & MMC_CAP_WAIT_WHILE_BUSY)) +		mmc_delay(timeout_ms);  	return err;  } @@ -1404,9 +1544,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, false);  	if (err)  		pr_err("%s: Power Off Notification timed out, %u\n",  		       mmc_hostname(card->host), timeout); @@ -1477,13 +1617,16 @@ 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)  			goto out;  	} -	err = mmc_cache_ctrl(host, 0); +	err = mmc_flush_cache(host->card);  	if (err)  		goto out; @@ -1494,53 +1637,94 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend)  		err = mmc_sleep(host);  	else if (!mmc_host_is_spi(host))  		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; -/* - * Shutdown callback - */ -static int mmc_shutdown(struct mmc_host *host) -{ -	return _mmc_suspend(host, false); +	err = _mmc_suspend(host, true); +	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_resume(struct mmc_host *host) +static int _mmc_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_init_card(host, host->ocr, host->card); + +	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; +} + +/* + * 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. @@ -1552,18 +1736,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 +1751,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;  } @@ -1593,9 +1766,8 @@ static int mmc_power_restore(struct mmc_host *host)  {  	int ret; -	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; @@ -1604,16 +1776,6 @@ static int mmc_power_restore(struct mmc_host *host)  static const struct mmc_bus_ops mmc_ops = {  	.remove = mmc_remove,  	.detect = mmc_detect, -	.suspend = NULL, -	.resume = NULL, -	.power_restore = mmc_power_restore, -	.alive = mmc_alive, -	.shutdown = mmc_shutdown, -}; - -static const struct mmc_bus_ops mmc_ops_unsafe = { -	.remove = mmc_remove, -	.detect = mmc_detect,  	.suspend = mmc_suspend,  	.resume = mmc_resume,  	.runtime_suspend = mmc_runtime_suspend, @@ -1623,24 +1785,13 @@ static const struct mmc_bus_ops mmc_ops_unsafe = {  	.shutdown = mmc_shutdown,  }; -static void mmc_attach_bus_ops(struct mmc_host *host) -{ -	const struct mmc_bus_ops *bus_ops; - -	if (!mmc_card_is_removable(host)) -		bus_ops = &mmc_ops_unsafe; -	else -		bus_ops = &mmc_ops; -	mmc_attach_bus(host, bus_ops); -} -  /*   * Starting point for MMC card init.   */  int mmc_attach_mmc(struct mmc_host *host)  {  	int err; -	u32 ocr; +	u32 ocr, rocr;  	BUG_ON(!host);  	WARN_ON(!host->claimed); @@ -1653,7 +1804,7 @@ int mmc_attach_mmc(struct mmc_host *host)  	if (err)  		return err; -	mmc_attach_bus_ops(host); +	mmc_attach_bus(host, &mmc_ops);  	if (host->ocr_avail_mmc)  		host->ocr_avail = host->ocr_avail_mmc; @@ -1666,23 +1817,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 +1830,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; diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index ef183483d5b..f51b5ba3bbe 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -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,19 +404,31 @@ 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 + *	@ignore_crc: ignore CRC errors when sending 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, +		bool ignore_crc)  { +	struct mmc_host *host = card->host;  	int err;  	struct mmc_command cmd = {0};  	unsigned long timeout; -	u32 status; +	u32 status = 0; +	bool use_r1b_resp = use_busy_signal; -	BUG_ON(!card); -	BUG_ON(!card->host); +	/* +	 * If the cmd timeout and the max_busy_timeout of the host are both +	 * specified, let's validate them. A failure means we need to prevent +	 * the host from doing hw busy detection, which is done by converting +	 * to a R1 response instead of a R1B. +	 */ +	if (timeout_ms && host->max_busy_timeout && +		(timeout_ms > host->max_busy_timeout)) +		use_r1b_resp = false;  	cmd.opcode = MMC_SWITCH;  	cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | @@ -390,17 +436,21 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,  		  (value << 8) |  		  set;  	cmd.flags = MMC_CMD_AC; -	if (use_busy_signal) +	if (use_r1b_resp) {  		cmd.flags |= MMC_RSP_SPI_R1B | MMC_RSP_R1B; -	else +		/* +		 * A busy_timeout of zero means the host can decide to use +		 * whatever value it finds suitable. +		 */ +		cmd.busy_timeout = timeout_ms; +	} else {  		cmd.flags |= MMC_RSP_SPI_R1 | MMC_RSP_R1; +	} - -	cmd.cmd_timeout_ms = timeout_ms;  	if (index == EXT_CSD_SANITIZE_START)  		cmd.sanitize_busy = true; -	err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES); +	err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES);  	if (err)  		return err; @@ -408,32 +458,55 @@ 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 */ -	timeout = jiffies + msecs_to_jiffies(MMC_OPS_TIMEOUT_MS); +	/* +	 * CRC errors shall only be ignored in cases were CMD13 is used to poll +	 * to detect busy completion. +	 */ +	if ((host->caps & MMC_CAP_WAIT_WHILE_BUSY) && use_r1b_resp) +		ignore_crc = false; + +	/* We have an unspecified cmd timeout, use the fallback value. */ +	if (!timeout_ms) +		timeout_ms = MMC_OPS_TIMEOUT_MS; + +	/* Must check status to be sure of no errors. */ +	timeout = jiffies + msecs_to_jiffies(timeout_ms);  	do { -		err = mmc_send_status(card, &status); -		if (err) -			return err; -		if (card->host->caps & MMC_CAP_WAIT_WHILE_BUSY) +		if (send_status) { +			err = __mmc_send_status(card, &status, ignore_crc); +			if (err) +				return err; +		} +		if ((host->caps & MMC_CAP_WAIT_WHILE_BUSY) && use_r1b_resp)  			break; -		if (mmc_host_is_spi(card->host)) +		if (mmc_host_is_spi(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", -				mmc_hostname(card->host), __func__); +				mmc_hostname(host), __func__);  			return -ETIMEDOUT;  		}  	} while (R1_CURRENT_STATE(status) == R1_STATE_PRG); -	if (mmc_host_is_spi(card->host)) { +	if (mmc_host_is_spi(host)) {  		if (status & R1_SPI_ILLEGAL_COMMAND)  			return -EBADMSG;  	} else {  		if (status & 0xFDFFA000) -			pr_warning("%s: unexpected status %#x after " -			       "switch", mmc_hostname(card->host), status); +			pr_warn("%s: unexpected status %#x after switch\n", +				mmc_hostname(host), status);  		if (status & R1_SWITCH_ERROR)  			return -EBADMSG;  	} @@ -445,36 +518,11 @@ 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, +				false);  }  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/quirks.c b/drivers/mmc/core/quirks.c index 06ee1aeaace..6c36fccaa1e 100644 --- a/drivers/mmc/core/quirks.c +++ b/drivers/mmc/core/quirks.c @@ -13,6 +13,7 @@  #include <linux/kernel.h>  #include <linux/export.h>  #include <linux/mmc/card.h> +#include <linux/mmc/sdio_ids.h>  #ifndef SDIO_VENDOR_ID_TI  #define SDIO_VENDOR_ID_TI		0x0097 @@ -30,6 +31,10 @@  #define SDIO_DEVICE_ID_STE_CW1200	0x2280  #endif +#ifndef SDIO_DEVICE_ID_MARVELL_8797_F0 +#define SDIO_DEVICE_ID_MARVELL_8797_F0	0x9128 +#endif +  /*   * This hook just adds a quirk for all sdio devices   */ @@ -58,6 +63,9 @@ static const struct mmc_fixup mmc_fixup_methods[] = {  	SDIO_FIXUP(SDIO_VENDOR_ID_STE, SDIO_DEVICE_ID_STE_CW1200,  		   add_quirk, MMC_QUIRK_BROKEN_BYTE_MODE_512), +	SDIO_FIXUP(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8797_F0, +		   add_quirk, MMC_QUIRK_BROKEN_IRQ_POLLING), +  	END_FIXUP  }; diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 5e8823dc3ef..0c44510bf71 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -11,8 +11,10 @@   */  #include <linux/err.h> +#include <linux/sizes.h>  #include <linux/slab.h>  #include <linux/stat.h> +#include <linux/pm_runtime.h>  #include <linux/mmc/host.h>  #include <linux/mmc/card.h> @@ -44,6 +46,13 @@ static const unsigned int tacc_mant[] = {  	35,	40,	45,	50,	55,	60,	70,	80,  }; +static const unsigned int sd_au_size[] = { +	0,		SZ_16K / 512,		SZ_32K / 512,	SZ_64K / 512, +	SZ_128K / 512,	SZ_256K / 512,		SZ_512K / 512,	SZ_1M / 512, +	SZ_2M / 512,	SZ_4M / 512,		SZ_8M / 512,	(SZ_8M + SZ_4M) / 512, +	SZ_16M / 512,	(SZ_16M + SZ_8M) / 512,	SZ_32M / 512,	SZ_64M / 512, +}; +  #define UNSTUFF_BITS(resp,start,size)					\  	({								\  		const int __size = size;				\ @@ -215,7 +224,7 @@ static int mmc_decode_scr(struct mmc_card *card)  static int mmc_read_ssr(struct mmc_card *card)  {  	unsigned int au, es, et, eo; -	int err, i, max_au; +	int err, i;  	u32 *ssr;  	if (!(card->csd.cmdclass & CCC_APP_SPEC)) { @@ -239,26 +248,25 @@ static int mmc_read_ssr(struct mmc_card *card)  	for (i = 0; i < 16; i++)  		ssr[i] = be32_to_cpu(ssr[i]); -	/* SD3.0 increases max AU size to 64MB (0xF) from 4MB (0x9) */ -	max_au = card->scr.sda_spec3 ? 0xF : 0x9; -  	/*  	 * UNSTUFF_BITS only works with four u32s so we have to offset the  	 * bitfield positions accordingly.  	 */  	au = UNSTUFF_BITS(ssr, 428 - 384, 4); -	if (au > 0 && au <= max_au) { -		card->ssr.au = 1 << (au + 4); -		es = UNSTUFF_BITS(ssr, 408 - 384, 16); -		et = UNSTUFF_BITS(ssr, 402 - 384, 6); -		eo = UNSTUFF_BITS(ssr, 400 - 384, 2); -		if (es && et) { -			card->ssr.erase_timeout = (et * 1000) / es; -			card->ssr.erase_offset = eo * 1000; +	if (au) { +		if (au <= 9 || card->scr.sda_spec3) { +			card->ssr.au = sd_au_size[au]; +			es = UNSTUFF_BITS(ssr, 408 - 384, 16); +			et = UNSTUFF_BITS(ssr, 402 - 384, 6); +			if (es && et) { +				eo = UNSTUFF_BITS(ssr, 400 - 384, 2); +				card->ssr.erase_timeout = (et * 1000) / es; +				card->ssr.erase_offset = eo * 1000; +			} +		} else { +			pr_warning("%s: SD Status: Invalid Allocation Unit size.\n", +				   mmc_hostname(card->host));  		} -	} else { -		pr_warning("%s: SD Status: Invalid Allocation Unit " -			"size.\n", mmc_hostname(card->host));  	}  out:  	kfree(ssr); @@ -699,18 +707,10 @@ static struct attribute *sd_std_attrs[] = {  	&dev_attr_serial.attr,  	NULL,  }; - -static struct attribute_group sd_std_attr_group = { -	.attrs = sd_std_attrs, -}; - -static const struct attribute_group *sd_attr_groups[] = { -	&sd_std_attr_group, -	NULL, -}; +ATTRIBUTE_GROUPS(sd_std);  struct device_type sd_type = { -	.groups = sd_attr_groups, +	.groups = sd_std_groups,  };  /* @@ -721,6 +721,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 +774,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; @@ -885,7 +887,7 @@ unsigned mmc_sd_get_max_clock(struct mmc_card *card)  {  	unsigned max_dtr = (unsigned int)-1; -	if (mmc_card_highspeed(card)) { +	if (mmc_card_hs(card)) {  		if (max_dtr > card->sw_caps.hs_max_dtr)  			max_dtr = card->sw_caps.hs_max_dtr;  	} else if (max_dtr > card->csd.max_dtr) { @@ -895,12 +897,6 @@ unsigned mmc_sd_get_max_clock(struct mmc_card *card)  	return max_dtr;  } -void mmc_sd_go_highspeed(struct mmc_card *card) -{ -	mmc_card_set_highspeed(card); -	mmc_set_timing(card->host, MMC_TIMING_SD_HS); -} -  /*   * Handle the detection and initialisation of a card.   * @@ -935,6 +931,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));  	} @@ -974,16 +971,13 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,  		err = mmc_sd_init_uhs_card(card);  		if (err)  			goto free_card; - -		/* Card is an ultra-high-speed card */ -		mmc_card_set_uhs(card);  	} else {  		/*  		 * Attempt to change to high-speed (if supported)  		 */  		err = mmc_sd_switch_hs(card);  		if (err > 0) -			mmc_sd_go_highspeed(card); +			mmc_set_timing(card->host, MMC_TIMING_SD_HS);  		else if (err)  			goto free_card; @@ -1064,10 +1058,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 +1066,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 +1151,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 +1166,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;  } @@ -1158,9 +1181,8 @@ static int mmc_sd_power_restore(struct mmc_host *host)  {  	int ret; -	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; @@ -1169,16 +1191,6 @@ static int mmc_sd_power_restore(struct mmc_host *host)  static const struct mmc_bus_ops mmc_sd_ops = {  	.remove = mmc_sd_remove,  	.detect = mmc_sd_detect, -	.suspend = NULL, -	.resume = NULL, -	.power_restore = mmc_sd_power_restore, -	.alive = mmc_sd_alive, -	.shutdown = mmc_sd_suspend, -}; - -static const struct mmc_bus_ops mmc_sd_ops_unsafe = { -	.remove = mmc_sd_remove, -	.detect = mmc_sd_detect,  	.runtime_suspend = mmc_sd_runtime_suspend,  	.runtime_resume = mmc_sd_runtime_resume,  	.suspend = mmc_sd_suspend, @@ -1188,24 +1200,13 @@ static const struct mmc_bus_ops mmc_sd_ops_unsafe = {  	.shutdown = mmc_sd_suspend,  }; -static void mmc_sd_attach_bus_ops(struct mmc_host *host) -{ -	const struct mmc_bus_ops *bus_ops; - -	if (!mmc_card_is_removable(host)) -		bus_ops = &mmc_sd_ops_unsafe; -	else -		bus_ops = &mmc_sd_ops; -	mmc_attach_bus(host, bus_ops); -} -  /*   * Starting point for SD card init.   */  int mmc_attach_sd(struct mmc_host *host)  {  	int err; -	u32 ocr; +	u32 ocr, rocr;  	BUG_ON(!host);  	WARN_ON(!host->claimed); @@ -1214,7 +1215,7 @@ int mmc_attach_sd(struct mmc_host *host)  	if (err)  		return err; -	mmc_sd_attach_bus_ops(host); +	mmc_attach_bus(host, &mmc_sd_ops);  	if (host->ocr_avail_sd)  		host->ocr_avail = host->ocr_avail_sd; @@ -1229,31 +1230,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 +1243,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; diff --git a/drivers/mmc/core/sd.h b/drivers/mmc/core/sd.h index 4b34b24f3f7..aab824a9a7f 100644 --- a/drivers/mmc/core/sd.h +++ b/drivers/mmc/core/sd.h @@ -12,6 +12,5 @@ int mmc_sd_setup_card(struct mmc_host *host, struct mmc_card *card,  	bool reinit);  unsigned mmc_sd_get_max_clock(struct mmc_card *card);  int mmc_sd_switch_hs(struct mmc_card *card); -void mmc_sd_go_highspeed(struct mmc_card *card);  #endif diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index 80d89cff730..e636d9e99e4 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -363,7 +363,7 @@ static unsigned mmc_sdio_get_max_clock(struct mmc_card *card)  {  	unsigned max_dtr; -	if (mmc_card_highspeed(card)) { +	if (mmc_card_hs(card)) {  		/*  		 * The SDIO specification doesn't mention how  		 * the CIS transfer speed register relates to @@ -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;  	}  	/* @@ -729,7 +733,6 @@ try_again:  		mmc_set_clock(host, card->cis.max_dtr);  		if (card->cccr.high_speed) { -			mmc_card_set_highspeed(card);  			mmc_set_timing(card->host, MMC_TIMING_SD_HS);  		} @@ -759,6 +762,7 @@ try_again:  		card = oldcard;  	} +	card->ocr = ocr_card;  	mmc_fixup_device(card, NULL);  	if (card->type == MMC_TYPE_SD_COMBO) { @@ -787,16 +791,13 @@ try_again:  		err = mmc_sdio_init_uhs_card(card);  		if (err)  			goto remove; - -		/* Card is an ultra-high-speed card */ -		mmc_card_set_uhs(card);  	} else {  		/*  		 * Switch to high-speed (if supported).  		 */  		err = sdio_enable_hs(card);  		if (err > 0) -			mmc_sd_go_highspeed(card); +			mmc_set_timing(card->host, MMC_TIMING_SD_HS);  		else if (err)  			goto remove; @@ -938,40 +939,21 @@ static int mmc_sdio_pre_suspend(struct mmc_host *host)   */  static int mmc_sdio_suspend(struct mmc_host *host)  { -	int i, err = 0; - -	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; -			err = pmops->suspend(&func->dev); -			if (err) -				break; -		} -	} -	while (err && --i >= 0) { -		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; -			pmops->resume(&func->dev); -		} -	} - -	if (!err && mmc_card_keep_power(host) && mmc_card_wake_sdio_irq(host)) { +	if (mmc_card_keep_power(host) && mmc_card_wake_sdio_irq(host)) {  		mmc_claim_host(host);  		sdio_disable_wide(host->card);  		mmc_release_host(host);  	} -	if (!err && !mmc_card_keep_power(host)) +	if (!mmc_card_keep_power(host))  		mmc_power_off(host); -	return err; +	return 0;  }  static int mmc_sdio_resume(struct mmc_host *host)  { -	int i, err = 0; +	int err = 0;  	BUG_ON(!host);  	BUG_ON(!host->card); @@ -981,8 +963,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 +981,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 */ @@ -1015,24 +996,6 @@ static int mmc_sdio_resume(struct mmc_host *host)  		wake_up_process(host->sdio_irq_thread);  	mmc_release_host(host); -	/* -	 * If the card looked to be the same as before suspending, then -	 * we proceed to resume all card functions.  If one of them returns -	 * an error then we simply return that error to the core and the -	 * card will be redetected as new.  It is the responsibility of -	 * the function driver to perform further tests with the extra -	 * knowledge it has of the card to confirm the card is indeed the -	 * same as before suspending (same MAC address for network cards, -	 * etc.) and return an error otherwise. -	 */ -	for (i = 0; !err && 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; -			err = pmops->resume(&func->dev); -		} -	} -  	host->pm_flags &= ~MMC_PM_KEEP_POWER;  	return err;  } @@ -1040,7 +1003,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 +1024,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 +1055,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 +1078,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 +1092,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 +1106,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;  	/* diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c index 6d67492a924..4fa8fef9147 100644 --- a/drivers/mmc/core/sdio_bus.c +++ b/drivers/mmc/core/sdio_bus.c @@ -34,7 +34,8 @@ 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"); @@ -47,14 +48,16 @@ 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 struct device_attribute sdio_dev_attrs[] = { -	__ATTR_RO(class), -	__ATTR_RO(vendor), -	__ATTR_RO(device), -	__ATTR_RO(modalias), -	__ATTR_NULL, +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,  }; +ATTRIBUTE_GROUPS(sdio_dev);  static const struct sdio_device_id *sdio_match_one(struct sdio_func *func,  	const struct sdio_device_id *id) @@ -194,20 +197,8 @@ static int sdio_bus_remove(struct device *dev)  #ifdef CONFIG_PM -#ifdef CONFIG_PM_SLEEP -static int pm_no_operation(struct device *dev) -{ -	/* -	 * Prevent the PM core from calling SDIO device drivers' suspend -	 * callback routines, which it is not supposed to do, by using this -	 * empty function as the bus type suspend callaback for SDIO. -	 */ -	return 0; -} -#endif -  static const struct dev_pm_ops sdio_bus_pm_ops = { -	SET_SYSTEM_SLEEP_PM_OPS(pm_no_operation, pm_no_operation) +	SET_SYSTEM_SLEEP_PM_OPS(pm_generic_suspend, pm_generic_resume)  	SET_RUNTIME_PM_OPS(  		pm_generic_runtime_suspend,  		pm_generic_runtime_resume, @@ -225,7 +216,7 @@ static const struct dev_pm_ops sdio_bus_pm_ops = {  static struct bus_type sdio_bus_type = {  	.name		= "sdio", -	.dev_attrs	= sdio_dev_attrs, +	.dev_groups	= sdio_dev_groups,  	.match		= sdio_bus_match,  	.uevent		= sdio_bus_uevent,  	.probe		= sdio_bus_probe, @@ -305,8 +296,7 @@ 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_HANDLE_SET(&func->dev, -			acpi_get_child(ACPI_HANDLE(host->parent), addr)); +	acpi_preset_companion(&func->dev, ACPI_COMPANION(host->parent), addr);  }  #else  static inline void sdio_acpi_set_handle(struct sdio_func *func) {} diff --git a/drivers/mmc/core/sdio_irq.c b/drivers/mmc/core/sdio_irq.c index 3d8ceb4084d..5cc13c8d35b 100644 --- a/drivers/mmc/core/sdio_irq.c +++ b/drivers/mmc/core/sdio_irq.c @@ -53,6 +53,17 @@ static int process_sdio_pending_irqs(struct mmc_host *host)  		return ret;  	} +	if (pending && mmc_card_broken_irq_polling(card) && +	    !(host->caps & MMC_CAP_SDIO_IRQ)) { +		unsigned char dummy; + +		/* A fake interrupt could be created when we poll SDIO_CCCR_INTx +		 * register with a Marvell SD8797 card. A dummy CMD52 read to +		 * function 0 register 0xff can avoid this. +		 */ +		mmc_io_rw_direct(card, 0, 0, 0xff, 0, &dummy); +	} +  	count = 0;  	for (i = 1; i <= 7; i++) {  		if (pending & (1 << i)) { @@ -79,6 +90,15 @@ static int process_sdio_pending_irqs(struct mmc_host *host)  	return ret;  } +void sdio_run_irqs(struct mmc_host *host) +{ +	mmc_claim_host(host); +	host->sdio_irq_pending = true; +	process_sdio_pending_irqs(host); +	mmc_release_host(host); +} +EXPORT_SYMBOL_GPL(sdio_run_irqs); +  static int sdio_irq_thread(void *_host)  {  	struct mmc_host *host = _host; @@ -178,14 +198,20 @@ static int sdio_card_irq_get(struct mmc_card *card)  	WARN_ON(!host->claimed);  	if (!host->sdio_irqs++) { -		atomic_set(&host->sdio_irq_thread_abort, 0); -		host->sdio_irq_thread = -			kthread_run(sdio_irq_thread, host, "ksdioirqd/%s", -				mmc_hostname(host)); -		if (IS_ERR(host->sdio_irq_thread)) { -			int err = PTR_ERR(host->sdio_irq_thread); -			host->sdio_irqs--; -			return err; +		if (!(host->caps2 & MMC_CAP2_SDIO_IRQ_NOTHREAD)) { +			atomic_set(&host->sdio_irq_thread_abort, 0); +			host->sdio_irq_thread = +				kthread_run(sdio_irq_thread, host, +					    "ksdioirqd/%s", mmc_hostname(host)); +			if (IS_ERR(host->sdio_irq_thread)) { +				int err = PTR_ERR(host->sdio_irq_thread); +				host->sdio_irqs--; +				return err; +			} +		} else { +			mmc_host_clk_hold(host); +			host->ops->enable_sdio_irq(host, 1); +			mmc_host_clk_release(host);  		}  	} @@ -200,8 +226,14 @@ static int sdio_card_irq_put(struct mmc_card *card)  	BUG_ON(host->sdio_irqs < 1);  	if (!--host->sdio_irqs) { -		atomic_set(&host->sdio_irq_thread_abort, 1); -		kthread_stop(host->sdio_irq_thread); +		if (!(host->caps2 & MMC_CAP2_SDIO_IRQ_NOTHREAD)) { +			atomic_set(&host->sdio_irq_thread_abort, 1); +			kthread_stop(host->sdio_irq_thread); +		} else { +			mmc_host_clk_hold(host); +			host->ops->enable_sdio_irq(host, 0); +			mmc_host_clk_release(host); +		}  	}  	return 0; diff --git a/drivers/mmc/core/slot-gpio.c b/drivers/mmc/core/slot-gpio.c index 46596b71a32..5f89cb83d5f 100644 --- a/drivers/mmc/core/slot-gpio.c +++ b/drivers/mmc/core/slot-gpio.c @@ -10,6 +10,7 @@  #include <linux/err.h>  #include <linux/gpio.h> +#include <linux/gpio/consumer.h>  #include <linux/interrupt.h>  #include <linux/jiffies.h>  #include <linux/mmc/host.h> @@ -18,8 +19,10 @@  #include <linux/slab.h>  struct mmc_gpio { -	int ro_gpio; -	int cd_gpio; +	struct gpio_desc *ro_gpio; +	struct gpio_desc *cd_gpio; +	bool override_ro_active_level; +	bool override_cd_active_level;  	char *ro_label;  	char cd_label[0];  }; @@ -29,9 +32,7 @@ static irqreturn_t mmc_gpio_cd_irqt(int irq, void *dev_id)  	/* Schedule a card detection after a debounce timeout */  	struct mmc_host *host = dev_id; -	if (host->ops->card_event) -		host->ops->card_event(host); - +	host->trigger_card_event = true;  	mmc_detect_change(host, msecs_to_jiffies(200));  	return IRQ_HANDLED; @@ -57,8 +58,6 @@ static int mmc_gpio_alloc(struct mmc_host *host)  			ctx->ro_label = ctx->cd_label + len;  			snprintf(ctx->cd_label, len, "%s cd", dev_name(host->parent));  			snprintf(ctx->ro_label, len, "%s ro", dev_name(host->parent)); -			ctx->cd_gpio = -EINVAL; -			ctx->ro_gpio = -EINVAL;  			host->slot.handler_priv = ctx;  		}  	} @@ -72,11 +71,14 @@ int mmc_gpio_get_ro(struct mmc_host *host)  {  	struct mmc_gpio *ctx = host->slot.handler_priv; -	if (!ctx || !gpio_is_valid(ctx->ro_gpio)) +	if (!ctx || !ctx->ro_gpio)  		return -ENOSYS; -	return !gpio_get_value_cansleep(ctx->ro_gpio) ^ -		!!(host->caps2 & MMC_CAP2_RO_ACTIVE_HIGH); +	if (ctx->override_ro_active_level) +		return !gpiod_get_raw_value_cansleep(ctx->ro_gpio) ^ +			!!(host->caps2 & MMC_CAP2_RO_ACTIVE_HIGH); + +	return gpiod_get_value_cansleep(ctx->ro_gpio);  }  EXPORT_SYMBOL(mmc_gpio_get_ro); @@ -84,11 +86,14 @@ int mmc_gpio_get_cd(struct mmc_host *host)  {  	struct mmc_gpio *ctx = host->slot.handler_priv; -	if (!ctx || !gpio_is_valid(ctx->cd_gpio)) +	if (!ctx || !ctx->cd_gpio)  		return -ENOSYS; -	return !gpio_get_value_cansleep(ctx->cd_gpio) ^ -		!!(host->caps2 & MMC_CAP2_CD_ACTIVE_HIGH); +	if (ctx->override_cd_active_level) +		return !gpiod_get_raw_value_cansleep(ctx->cd_gpio) ^ +			!!(host->caps2 & MMC_CAP2_CD_ACTIVE_HIGH); + +	return gpiod_get_value_cansleep(ctx->cd_gpio);  }  EXPORT_SYMBOL(mmc_gpio_get_cd); @@ -125,12 +130,47 @@ int mmc_gpio_request_ro(struct mmc_host *host, unsigned int gpio)  	if (ret < 0)  		return ret; -	ctx->ro_gpio = gpio; +	ctx->override_ro_active_level = true; +	ctx->ro_gpio = gpio_to_desc(gpio);  	return 0;  }  EXPORT_SYMBOL(mmc_gpio_request_ro); +void mmc_gpiod_request_cd_irq(struct mmc_host *host) +{ +	struct mmc_gpio *ctx = host->slot.handler_priv; +	int ret, irq; + +	if (host->slot.cd_irq >= 0 || !ctx || !ctx->cd_gpio) +		return; + +	irq = gpiod_to_irq(ctx->cd_gpio); + +	/* +	 * Even if gpiod_to_irq() returns a valid IRQ number, the platform might +	 * still prefer to poll, e.g., because that IRQ number is already used +	 * by another unit and cannot be shared. +	 */ +	if (irq >= 0 && host->caps & MMC_CAP_NEEDS_POLL) +		irq = -EINVAL; + +	if (irq >= 0) { +		ret = devm_request_threaded_irq(&host->class_dev, irq, +			NULL, mmc_gpio_cd_irqt, +			IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, +			ctx->cd_label, host); +		if (ret < 0) +			irq = ret; +	} + +	host->slot.cd_irq = irq; + +	if (irq < 0) +		host->caps |= MMC_CAP_NEEDS_POLL; +} +EXPORT_SYMBOL(mmc_gpiod_request_cd_irq); +  /**   * mmc_gpio_request_cd - request a gpio for card-detection   * @host: mmc host @@ -154,7 +194,6 @@ int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio,  			unsigned int debounce)  {  	struct mmc_gpio *ctx; -	int irq = gpio_to_irq(gpio);  	int ret;  	ret = mmc_gpio_alloc(host); @@ -179,29 +218,10 @@ int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio,  			return ret;  	} -	/* -	 * Even if gpio_to_irq() returns a valid IRQ number, the platform might -	 * still prefer to poll, e.g., because that IRQ number is already used -	 * by another unit and cannot be shared. -	 */ -	if (irq >= 0 && host->caps & MMC_CAP_NEEDS_POLL) -		irq = -EINVAL; - -	if (irq >= 0) { -		ret = devm_request_threaded_irq(&host->class_dev, irq, -			NULL, mmc_gpio_cd_irqt, -			IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, -			ctx->cd_label, host); -		if (ret < 0) -			irq = ret; -	} - -	host->slot.cd_irq = irq; - -	if (irq < 0) -		host->caps |= MMC_CAP_NEEDS_POLL; +	ctx->override_cd_active_level = true; +	ctx->cd_gpio = gpio_to_desc(gpio); -	ctx->cd_gpio = gpio; +	mmc_gpiod_request_cd_irq(host);  	return 0;  } @@ -219,11 +239,11 @@ void mmc_gpio_free_ro(struct mmc_host *host)  	struct mmc_gpio *ctx = host->slot.handler_priv;  	int gpio; -	if (!ctx || !gpio_is_valid(ctx->ro_gpio)) +	if (!ctx || !ctx->ro_gpio)  		return; -	gpio = ctx->ro_gpio; -	ctx->ro_gpio = -EINVAL; +	gpio = desc_to_gpio(ctx->ro_gpio); +	ctx->ro_gpio = NULL;  	devm_gpio_free(&host->class_dev, gpio);  } @@ -241,7 +261,7 @@ void mmc_gpio_free_cd(struct mmc_host *host)  	struct mmc_gpio *ctx = host->slot.handler_priv;  	int gpio; -	if (!ctx || !gpio_is_valid(ctx->cd_gpio)) +	if (!ctx || !ctx->cd_gpio)  		return;  	if (host->slot.cd_irq >= 0) { @@ -249,9 +269,87 @@ void mmc_gpio_free_cd(struct mmc_host *host)  		host->slot.cd_irq = -EINVAL;  	} -	gpio = ctx->cd_gpio; -	ctx->cd_gpio = -EINVAL; +	gpio = desc_to_gpio(ctx->cd_gpio); +	ctx->cd_gpio = NULL;  	devm_gpio_free(&host->class_dev, gpio);  }  EXPORT_SYMBOL(mmc_gpio_free_cd); + +/** + * mmc_gpiod_request_cd - request a gpio descriptor for card-detection + * @host: mmc host + * @con_id: function within the GPIO consumer + * @idx: index of the GPIO to obtain in the consumer + * @override_active_level: ignore %GPIO_ACTIVE_LOW flag + * @debounce: debounce time in microseconds + * + * Use this function in place of mmc_gpio_request_cd() to use the GPIO + * descriptor API.  Note that it is paired with mmc_gpiod_free_cd() not + * mmc_gpio_free_cd().  Note also that it must be called prior to mmc_add_host() + * otherwise the caller must also call mmc_gpiod_request_cd_irq(). + * + * Returns zero on success, else an error. + */ +int mmc_gpiod_request_cd(struct mmc_host *host, const char *con_id, +			 unsigned int idx, bool override_active_level, +			 unsigned int debounce) +{ +	struct mmc_gpio *ctx; +	struct gpio_desc *desc; +	int ret; + +	ret = mmc_gpio_alloc(host); +	if (ret < 0) +		return ret; + +	ctx = host->slot.handler_priv; + +	if (!con_id) +		con_id = ctx->cd_label; + +	desc = devm_gpiod_get_index(host->parent, con_id, idx); +	if (IS_ERR(desc)) +		return PTR_ERR(desc); + +	ret = gpiod_direction_input(desc); +	if (ret < 0) +		return ret; + +	if (debounce) { +		ret = gpiod_set_debounce(desc, debounce); +		if (ret < 0) +			return ret; +	} + +	ctx->override_cd_active_level = override_active_level; +	ctx->cd_gpio = desc; + +	return 0; +} +EXPORT_SYMBOL(mmc_gpiod_request_cd); + +/** + * mmc_gpiod_free_cd - free the card-detection gpio descriptor + * @host: mmc host + * + * It's provided only for cases that client drivers need to manually free + * up the card-detection gpio requested by mmc_gpiod_request_cd(). + */ +void mmc_gpiod_free_cd(struct mmc_host *host) +{ +	struct mmc_gpio *ctx = host->slot.handler_priv; + +	if (!ctx || !ctx->cd_gpio) +		return; + +	if (host->slot.cd_irq >= 0) { +		devm_free_irq(&host->class_dev, host->slot.cd_irq, host); +		host->slot.cd_irq = -EINVAL; +	} + +	devm_gpiod_put(&host->class_dev, ctx->cd_gpio); + +	ctx->cd_gpio = NULL; +} +EXPORT_SYMBOL(mmc_gpiod_free_cd);  | 
