diff options
Diffstat (limited to 'drivers/mmc')
27 files changed, 929 insertions, 443 deletions
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 276d21ce6bc..f1c84decb19 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -850,9 +850,7 @@ out:  		goto retry;  	if (!err)  		mmc_blk_reset_success(md, type); -	spin_lock_irq(&md->lock); -	__blk_end_request(req, err, blk_rq_bytes(req)); -	spin_unlock_irq(&md->lock); +	blk_end_request(req, err, blk_rq_bytes(req));  	return err ? 0 : 1;  } @@ -934,9 +932,7 @@ out_retry:  	if (!err)  		mmc_blk_reset_success(md, type);  out: -	spin_lock_irq(&md->lock); -	__blk_end_request(req, err, blk_rq_bytes(req)); -	spin_unlock_irq(&md->lock); +	blk_end_request(req, err, blk_rq_bytes(req));  	return err ? 0 : 1;  } @@ -951,9 +947,7 @@ static int mmc_blk_issue_flush(struct mmc_queue *mq, struct request *req)  	if (ret)  		ret = -EIO; -	spin_lock_irq(&md->lock); -	__blk_end_request_all(req, ret); -	spin_unlock_irq(&md->lock); +	blk_end_request_all(req, ret);  	return ret ? 0 : 1;  } @@ -1252,14 +1246,10 @@ static int mmc_blk_cmd_err(struct mmc_blk_data *md, struct mmc_card *card,  		blocks = mmc_sd_num_wr_blocks(card);  		if (blocks != (u32)-1) { -			spin_lock_irq(&md->lock); -			ret = __blk_end_request(req, 0, blocks << 9); -			spin_unlock_irq(&md->lock); +			ret = blk_end_request(req, 0, blocks << 9);  		}  	} else { -		spin_lock_irq(&md->lock); -		ret = __blk_end_request(req, 0, brq->data.bytes_xfered); -		spin_unlock_irq(&md->lock); +		ret = blk_end_request(req, 0, brq->data.bytes_xfered);  	}  	return ret;  } @@ -1311,10 +1301,8 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)  			 * A block was successfully transferred.  			 */  			mmc_blk_reset_success(md, type); -			spin_lock_irq(&md->lock); -			ret = __blk_end_request(req, 0, +			ret = blk_end_request(req, 0,  						brq->data.bytes_xfered); -			spin_unlock_irq(&md->lock);  			/*  			 * If the blk_end_request function returns non-zero even  			 * though all data has been transferred and no errors @@ -1364,10 +1352,8 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)  			 * time, so we only reach here after trying to  			 * read a single sector.  			 */ -			spin_lock_irq(&md->lock); -			ret = __blk_end_request(req, -EIO, +			ret = blk_end_request(req, -EIO,  						brq->data.blksz); -			spin_unlock_irq(&md->lock);  			if (!ret)  				goto start_new_req;  			break; @@ -1388,12 +1374,10 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)  	return 1;   cmd_abort: -	spin_lock_irq(&md->lock);  	if (mmc_card_removed(card))  		req->cmd_flags |= REQ_QUIET;  	while (ret) -		ret = __blk_end_request(req, -EIO, blk_rq_cur_bytes(req)); -	spin_unlock_irq(&md->lock); +		ret = blk_end_request(req, -EIO, blk_rq_cur_bytes(req));   start_new_req:  	if (rqc) { @@ -1417,9 +1401,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)  	ret = mmc_blk_part_switch(card, md);  	if (ret) {  		if (req) { -			spin_lock_irq(&md->lock); -			__blk_end_request_all(req, -EIO); -			spin_unlock_irq(&md->lock); +			blk_end_request_all(req, -EIO);  		}  		ret = 0;  		goto out; diff --git a/drivers/mmc/core/Makefile b/drivers/mmc/core/Makefile index dca4428380f..38ed210ce2f 100644 --- a/drivers/mmc/core/Makefile +++ b/drivers/mmc/core/Makefile @@ -7,6 +7,6 @@ mmc_core-y			:= core.o bus.o host.o \  				   mmc.o mmc_ops.o sd.o sd_ops.o \  				   sdio.o sdio_ops.o sdio_bus.o \  				   sdio_cis.o sdio_io.o sdio_irq.o \ -				   quirks.o cd-gpio.o +				   quirks.o slot-gpio.o  mmc_core-$(CONFIG_DEBUG_FS)	+= debugfs.o diff --git a/drivers/mmc/core/cd-gpio.c b/drivers/mmc/core/cd-gpio.c deleted file mode 100644 index 8f5dc08d659..00000000000 --- a/drivers/mmc/core/cd-gpio.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Generic GPIO card-detect helper - * - * Copyright (C) 2011, Guennadi Liakhovetski <g.liakhovetski@gmx.de> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include <linux/err.h> -#include <linux/gpio.h> -#include <linux/interrupt.h> -#include <linux/jiffies.h> -#include <linux/mmc/cd-gpio.h> -#include <linux/mmc/host.h> -#include <linux/module.h> -#include <linux/slab.h> - -struct mmc_cd_gpio { -	unsigned int gpio; -	char label[0]; -}; - -static irqreturn_t mmc_cd_gpio_irqt(int irq, void *dev_id) -{ -	/* Schedule a card detection after a debounce timeout */ -	mmc_detect_change(dev_id, msecs_to_jiffies(100)); -	return IRQ_HANDLED; -} - -int mmc_cd_gpio_request(struct mmc_host *host, unsigned int gpio) -{ -	size_t len = strlen(dev_name(host->parent)) + 4; -	struct mmc_cd_gpio *cd; -	int irq = gpio_to_irq(gpio); -	int ret; - -	if (irq < 0) -		return irq; - -	cd = kmalloc(sizeof(*cd) + len, GFP_KERNEL); -	if (!cd) -		return -ENOMEM; - -	snprintf(cd->label, len, "%s cd", dev_name(host->parent)); - -	ret = gpio_request_one(gpio, GPIOF_DIR_IN, cd->label); -	if (ret < 0) -		goto egpioreq; - -	ret = request_threaded_irq(irq, NULL, mmc_cd_gpio_irqt, -				   IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | -				   IRQF_ONESHOT, cd->label, host); -	if (ret < 0) -		goto eirqreq; - -	cd->gpio = gpio; -	host->hotplug.irq = irq; -	host->hotplug.handler_priv = cd; - -	return 0; - -eirqreq: -	gpio_free(gpio); -egpioreq: -	kfree(cd); -	return ret; -} -EXPORT_SYMBOL(mmc_cd_gpio_request); - -void mmc_cd_gpio_free(struct mmc_host *host) -{ -	struct mmc_cd_gpio *cd = host->hotplug.handler_priv; - -	if (!cd) -		return; - -	free_irq(host->hotplug.irq, host); -	gpio_free(cd->gpio); -	kfree(cd); -} -EXPORT_SYMBOL(mmc_cd_gpio_free); diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 0b6141d29db..8ac5246e2ab 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -404,6 +404,7 @@ int mmc_interrupt_hpi(struct mmc_card *card)  {  	int err;  	u32 status; +	unsigned long prg_wait;  	BUG_ON(!card); @@ -419,30 +420,38 @@ int mmc_interrupt_hpi(struct mmc_card *card)  		goto out;  	} -	/* -	 * If the card status is in PRG-state, we can send the HPI command. -	 */ -	if (R1_CURRENT_STATE(status) == R1_STATE_PRG) { -		do { -			/* -			 * We don't know when the HPI command will finish -			 * processing, so we need to resend HPI until out -			 * of prg-state, and keep checking the card status -			 * with SEND_STATUS.  If a timeout error occurs when -			 * sending the HPI command, we are already out of -			 * prg-state. -			 */ -			err = mmc_send_hpi_cmd(card, &status); -			if (err) -				pr_debug("%s: abort HPI (%d error)\n", -					 mmc_hostname(card->host), err); +	switch (R1_CURRENT_STATE(status)) { +	case R1_STATE_IDLE: +	case R1_STATE_READY: +	case R1_STATE_STBY: +		/* +		 * In idle states, HPI is not needed and the caller +		 * can issue the next intended command immediately +		 */ +		goto out; +	case R1_STATE_PRG: +		break; +	default: +		/* In all other states, it's illegal to issue HPI */ +		pr_debug("%s: HPI cannot be sent. Card state=%d\n", +			mmc_hostname(card->host), R1_CURRENT_STATE(status)); +		err = -EINVAL; +		goto out; +	} -			err = mmc_send_status(card, &status); -			if (err) -				break; -		} while (R1_CURRENT_STATE(status) == R1_STATE_PRG); -	} else -		pr_debug("%s: Left prg-state\n", mmc_hostname(card->host)); +	err = mmc_send_hpi_cmd(card, &status); +	if (err) +		goto out; + +	prg_wait = jiffies + msecs_to_jiffies(card->ext_csd.out_of_int_time); +	do { +		err = mmc_send_status(card, &status); + +		if (!err && R1_CURRENT_STATE(status) == R1_STATE_TRAN) +			break; +		if (time_after(jiffies, prg_wait)) +			err = -ETIMEDOUT; +	} while (!err);  out:  	mmc_release_host(card->host); @@ -941,7 +950,7 @@ int mmc_regulator_get_ocrmask(struct regulator *supply)  	return result;  } -EXPORT_SYMBOL(mmc_regulator_get_ocrmask); +EXPORT_SYMBOL_GPL(mmc_regulator_get_ocrmask);  /**   * mmc_regulator_set_ocr - set regulator to match host->ios voltage @@ -1011,7 +1020,30 @@ int mmc_regulator_set_ocr(struct mmc_host *mmc,  			"could not set regulator OCR (%d)\n", result);  	return result;  } -EXPORT_SYMBOL(mmc_regulator_set_ocr); +EXPORT_SYMBOL_GPL(mmc_regulator_set_ocr); + +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.vqmmc = devm_regulator_get(dev, "vqmmc"); + +	if (IS_ERR(supply)) +		return PTR_ERR(supply); + +	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); + +	return 0; +} +EXPORT_SYMBOL_GPL(mmc_regulator_get_supply);  #endif /* CONFIG_REGULATOR */ @@ -1180,6 +1212,9 @@ static 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, false); +  	/*  	 * This delay should be sufficient to allow the power supply  	 * to reach the minimum voltage. @@ -1931,9 +1966,6 @@ static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq)  	 */  	mmc_hw_reset_for_init(host); -	/* Initialization should be done at 3.3 V I/O voltage. */ -	mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330, 0); -  	/*  	 * sdio_reset sends CMD52 to reset card.  Since we do not know  	 * if the card is being re-initialized, just send it.  CMD52 @@ -2075,6 +2107,7 @@ void mmc_rescan(struct work_struct *work)  void mmc_start_host(struct mmc_host *host)  {  	host->f_init = max(freqs[0], host->f_min); +	host->rescan_disable = 0;  	mmc_power_up(host);  	mmc_detect_change(host, 0);  } @@ -2088,6 +2121,7 @@ void mmc_stop_host(struct mmc_host *host)  	spin_unlock_irqrestore(&host->lock, flags);  #endif +	host->rescan_disable = 1;  	cancel_delayed_work_sync(&host->detect);  	mmc_flush_scheduled_work(); diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index 91c84c7a182..597f189b442 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c @@ -32,6 +32,7 @@  static void mmc_host_classdev_release(struct device *dev)  {  	struct mmc_host *host = cls_dev_to_mmc_host(dev); +	mutex_destroy(&host->slot.lock);  	kfree(host);  } @@ -312,6 +313,8 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)  	if (!host)  		return NULL; +	/* scanning will be enabled when we're ready */ +	host->rescan_disable = 1;  	spin_lock(&mmc_host_lock);  	err = idr_get_new(&mmc_host_idr, host, &host->index);  	spin_unlock(&mmc_host_lock); @@ -327,6 +330,9 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)  	mmc_host_clk_init(host); +	mutex_init(&host->slot.lock); +	host->slot.cd_irq = -EINVAL; +  	spin_lock_init(&host->lock);  	init_waitqueue_head(&host->wq);  	INIT_DELAYED_WORK(&host->detect, mmc_rescan); diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 4f4489aa6ba..396b25891bb 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -818,9 +818,6 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,  	if (!mmc_host_is_spi(host))  		mmc_set_bus_mode(host, MMC_BUSMODE_OPENDRAIN); -	/* Initialization should be done at 3.3 V I/O voltage. */ -	mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330, 0); -  	/*  	 * Since we're changing the OCR value, we seem to  	 * need to tell some cards to go back to the idle diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 69370f494e0..0ed2cc5f35b 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -569,7 +569,6 @@ int mmc_send_hpi_cmd(struct mmc_card *card, u32 *status)  	cmd.opcode = opcode;  	cmd.arg = card->rca << 16 | 1; -	cmd.cmd_timeout_ms = card->ext_csd.out_of_int_time;  	err = mmc_wait_for_cmd(card->host, &cmd, 0);  	if (err) { diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index b2b43f624b9..74972c241df 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -244,7 +244,7 @@ static int mmc_read_ssr(struct mmc_card *card)  	 * bitfield positions accordingly.  	 */  	au = UNSTUFF_BITS(ssr, 428 - 384, 4); -	if (au > 0 || au <= 9) { +	if (au > 0 && au <= 9) {  		card->ssr.au = 1 << (au + 4);  		es = UNSTUFF_BITS(ssr, 408 - 384, 16);  		et = UNSTUFF_BITS(ssr, 402 - 384, 6); @@ -290,8 +290,12 @@ static int mmc_read_switch(struct mmc_card *card)  		return -ENOMEM;  	} -	/* Find out the supported Bus Speed Modes. */ -	err = mmc_sd_switch(card, 0, 0, 1, status); +	/* +	 * Find out the card's support bits with a mode 0 operation. +	 * The argument does not matter, as the support bits do not +	 * change with the arguments. +	 */ +	err = mmc_sd_switch(card, 0, 0, 0, status);  	if (err) {  		/*  		 * If the host or the card can't do the switch, @@ -312,46 +316,8 @@ static int mmc_read_switch(struct mmc_card *card)  	if (card->scr.sda_spec3) {  		card->sw_caps.sd3_bus_mode = status[13]; - -		/* Find out Driver Strengths supported by the card */ -		err = mmc_sd_switch(card, 0, 2, 1, status); -		if (err) { -			/* -			 * If the host or the card can't do the switch, -			 * fail more gracefully. -			 */ -			if (err != -EINVAL && err != -ENOSYS && err != -EFAULT) -				goto out; - -			pr_warning("%s: problem reading " -				"Driver Strength.\n", -				mmc_hostname(card->host)); -			err = 0; - -			goto out; -		} - +		/* Driver Strengths supported by the card */  		card->sw_caps.sd3_drv_type = status[9]; - -		/* Find out Current Limits supported by the card */ -		err = mmc_sd_switch(card, 0, 3, 1, status); -		if (err) { -			/* -			 * If the host or the card can't do the switch, -			 * fail more gracefully. -			 */ -			if (err != -EINVAL && err != -ENOSYS && err != -EFAULT) -				goto out; - -			pr_warning("%s: problem reading " -				"Current Limit.\n", -				mmc_hostname(card->host)); -			err = 0; - -			goto out; -		} - -		card->sw_caps.sd3_curr_limit = status[7];  	}  out: @@ -551,60 +517,80 @@ static int sd_set_bus_speed_mode(struct mmc_card *card, u8 *status)  	return 0;  } +/* Get host's max current setting at its current voltage */ +static u32 sd_get_host_max_current(struct mmc_host *host) +{ +	u32 voltage, max_current; + +	voltage = 1 << host->ios.vdd; +	switch (voltage) { +	case MMC_VDD_165_195: +		max_current = host->max_current_180; +		break; +	case MMC_VDD_29_30: +	case MMC_VDD_30_31: +		max_current = host->max_current_300; +		break; +	case MMC_VDD_32_33: +	case MMC_VDD_33_34: +		max_current = host->max_current_330; +		break; +	default: +		max_current = 0; +	} + +	return max_current; +} +  static int sd_set_current_limit(struct mmc_card *card, u8 *status)  { -	int current_limit = 0; +	int current_limit = SD_SET_CURRENT_NO_CHANGE;  	int err; +	u32 max_current;  	/*  	 * Current limit switch is only defined for SDR50, SDR104, and DDR50 -	 * bus speed modes. For other bus speed modes, we set the default -	 * current limit of 200mA. +	 * bus speed modes. For other bus speed modes, we do not change the +	 * current limit.  	 */ -	if ((card->sd_bus_speed == UHS_SDR50_BUS_SPEED) || -	    (card->sd_bus_speed == UHS_SDR104_BUS_SPEED) || -	    (card->sd_bus_speed == UHS_DDR50_BUS_SPEED)) { -		if (card->host->caps & MMC_CAP_MAX_CURRENT_800) { -			if (card->sw_caps.sd3_curr_limit & SD_MAX_CURRENT_800) -				current_limit = SD_SET_CURRENT_LIMIT_800; -			else if (card->sw_caps.sd3_curr_limit & -					SD_MAX_CURRENT_600) -				current_limit = SD_SET_CURRENT_LIMIT_600; -			else if (card->sw_caps.sd3_curr_limit & -					SD_MAX_CURRENT_400) -				current_limit = SD_SET_CURRENT_LIMIT_400; -			else if (card->sw_caps.sd3_curr_limit & -					SD_MAX_CURRENT_200) -				current_limit = SD_SET_CURRENT_LIMIT_200; -		} else if (card->host->caps & MMC_CAP_MAX_CURRENT_600) { -			if (card->sw_caps.sd3_curr_limit & SD_MAX_CURRENT_600) -				current_limit = SD_SET_CURRENT_LIMIT_600; -			else if (card->sw_caps.sd3_curr_limit & -					SD_MAX_CURRENT_400) -				current_limit = SD_SET_CURRENT_LIMIT_400; -			else if (card->sw_caps.sd3_curr_limit & -					SD_MAX_CURRENT_200) -				current_limit = SD_SET_CURRENT_LIMIT_200; -		} else if (card->host->caps & MMC_CAP_MAX_CURRENT_400) { -			if (card->sw_caps.sd3_curr_limit & SD_MAX_CURRENT_400) -				current_limit = SD_SET_CURRENT_LIMIT_400; -			else if (card->sw_caps.sd3_curr_limit & -					SD_MAX_CURRENT_200) -				current_limit = SD_SET_CURRENT_LIMIT_200; -		} else if (card->host->caps & MMC_CAP_MAX_CURRENT_200) { -			if (card->sw_caps.sd3_curr_limit & SD_MAX_CURRENT_200) -				current_limit = SD_SET_CURRENT_LIMIT_200; -		} -	} else +	if ((card->sd_bus_speed != UHS_SDR50_BUS_SPEED) && +	    (card->sd_bus_speed != UHS_SDR104_BUS_SPEED) && +	    (card->sd_bus_speed != UHS_DDR50_BUS_SPEED)) +		return 0; + +	/* +	 * Host has different current capabilities when operating at +	 * different voltages, so find out its max current first. +	 */ +	max_current = sd_get_host_max_current(card->host); + +	/* +	 * We only check host's capability here, if we set a limit that is +	 * higher than the card's maximum current, the card will be using its +	 * maximum current, e.g. if the card's maximum current is 300ma, and +	 * when we set current limit to 200ma, the card will draw 200ma, and +	 * when we set current limit to 400/600/800ma, the card will draw its +	 * maximum 300ma from the host. +	 */ +	if (max_current >= 800) +		current_limit = SD_SET_CURRENT_LIMIT_800; +	else if (max_current >= 600) +		current_limit = SD_SET_CURRENT_LIMIT_600; +	else if (max_current >= 400) +		current_limit = SD_SET_CURRENT_LIMIT_400; +	else if (max_current >= 200)  		current_limit = SD_SET_CURRENT_LIMIT_200; -	err = mmc_sd_switch(card, 1, 3, current_limit, status); -	if (err) -		return err; +	if (current_limit != SD_SET_CURRENT_NO_CHANGE) { +		err = mmc_sd_switch(card, 1, 3, current_limit, status); +		if (err) +			return err; -	if (((status[15] >> 4) & 0x0F) != current_limit) -		pr_warning("%s: Problem setting current limit!\n", -			mmc_hostname(card->host)); +		if (((status[15] >> 4) & 0x0F) != current_limit) +			pr_warning("%s: Problem setting current limit!\n", +				mmc_hostname(card->host)); + +	}  	return 0;  } @@ -726,6 +712,7 @@ struct device_type sd_type = {  int mmc_sd_get_cid(struct mmc_host *host, u32 ocr, u32 *cid, u32 *rocr)  {  	int err; +	u32 max_current;  	/*  	 * Since we're changing the OCR value, we seem to @@ -753,9 +740,12 @@ int mmc_sd_get_cid(struct mmc_host *host, u32 ocr, u32 *cid, u32 *rocr)  	    MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_DDR50))  		ocr |= SD_OCR_S18R; -	/* If the host can supply more than 150mA, XPC should be set to 1. */ -	if (host->caps & (MMC_CAP_SET_XPC_330 | MMC_CAP_SET_XPC_300 | -	    MMC_CAP_SET_XPC_180)) +	/* +	 * If the host can supply more than 150mA at current voltage, +	 * XPC should be set to 1. +	 */ +	max_current = sd_get_host_max_current(host); +	if (max_current > 150)  		ocr |= SD_OCR_XPC;  try_again: @@ -911,9 +901,6 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,  	BUG_ON(!host);  	WARN_ON(!host->claimed); -	/* The initialization should be done at 3.3 V I/O voltage. */ -	mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330, 0); -  	err = mmc_sd_get_cid(host, ocr, cid, &rocr);  	if (err)  		return err; diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index 41c5fd8848f..d4619e2ec03 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -591,9 +591,6 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,  	 * Inform the card of the voltage  	 */  	if (!powered_resume) { -		/* The initialization should be done at 3.3 V I/O voltage. */ -		mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330, 0); -  		err = mmc_send_io_op_cond(host, host->ocr, &ocr);  		if (err)  			goto err; @@ -1006,10 +1003,6 @@ static int mmc_sdio_power_restore(struct mmc_host *host)  	 * restore the correct voltage setting of the card.  	 */ -	/* The initialization should be done at 3.3 V I/O voltage. */ -	if (!mmc_card_keep_power(host)) -		mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330, 0); -  	sdio_reset(host);  	mmc_go_idle(host);  	mmc_send_if_cond(host, host->ocr_avail); diff --git a/drivers/mmc/core/sdio_cis.c b/drivers/mmc/core/sdio_cis.c index f1c7ed8f4d8..8e94e555b78 100644 --- a/drivers/mmc/core/sdio_cis.c +++ b/drivers/mmc/core/sdio_cis.c @@ -313,7 +313,7 @@ static int sdio_read_cis(struct mmc_card *card, struct sdio_func *func)  			if (ret == -ENOENT) {  				/* warn about unknown tuples */ -				pr_warning("%s: queuing unknown" +				pr_warn_ratelimited("%s: queuing unknown"  				       " CIS tuple 0x%02x (%u bytes)\n",  				       mmc_hostname(card->host),  				       tpl_code, tpl_link); diff --git a/drivers/mmc/core/slot-gpio.c b/drivers/mmc/core/slot-gpio.c new file mode 100644 index 00000000000..058242916ce --- /dev/null +++ b/drivers/mmc/core/slot-gpio.c @@ -0,0 +1,188 @@ +/* + * Generic GPIO card-detect helper + * + * Copyright (C) 2011, Guennadi Liakhovetski <g.liakhovetski@gmx.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/err.h> +#include <linux/gpio.h> +#include <linux/interrupt.h> +#include <linux/jiffies.h> +#include <linux/mmc/host.h> +#include <linux/mmc/slot-gpio.h> +#include <linux/module.h> +#include <linux/slab.h> + +struct mmc_gpio { +	int ro_gpio; +	int cd_gpio; +	char *ro_label; +	char cd_label[0]; +}; + +static irqreturn_t mmc_gpio_cd_irqt(int irq, void *dev_id) +{ +	/* Schedule a card detection after a debounce timeout */ +	mmc_detect_change(dev_id, msecs_to_jiffies(100)); +	return IRQ_HANDLED; +} + +static int mmc_gpio_alloc(struct mmc_host *host) +{ +	size_t len = strlen(dev_name(host->parent)) + 4; +	struct mmc_gpio *ctx; + +	mutex_lock(&host->slot.lock); + +	ctx = host->slot.handler_priv; +	if (!ctx) { +		/* +		 * devm_kzalloc() can be called after device_initialize(), even +		 * before device_add(), i.e., between mmc_alloc_host() and +		 * mmc_add_host() +		 */ +		ctx = devm_kzalloc(&host->class_dev, sizeof(*ctx) + 2 * len, +				   GFP_KERNEL); +		if (ctx) { +			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; +		} +	} + +	mutex_unlock(&host->slot.lock); + +	return ctx ? 0 : -ENOMEM; +} + +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)) +		return -ENOSYS; + +	return !gpio_get_value_cansleep(ctx->ro_gpio) ^ +		!!(host->caps2 & MMC_CAP2_RO_ACTIVE_HIGH); +} +EXPORT_SYMBOL(mmc_gpio_get_ro); + +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)) +		return -ENOSYS; + +	return !gpio_get_value_cansleep(ctx->cd_gpio) ^ +		!!(host->caps2 & MMC_CAP2_CD_ACTIVE_HIGH); +} +EXPORT_SYMBOL(mmc_gpio_get_cd); + +int mmc_gpio_request_ro(struct mmc_host *host, unsigned int gpio) +{ +	struct mmc_gpio *ctx; +	int ret; + +	if (!gpio_is_valid(gpio)) +		return -EINVAL; + +	ret = mmc_gpio_alloc(host); +	if (ret < 0) +		return ret; + +	ctx = host->slot.handler_priv; + +	return gpio_request_one(gpio, GPIOF_DIR_IN, ctx->ro_label); +} +EXPORT_SYMBOL(mmc_gpio_request_ro); + +int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio) +{ +	struct mmc_gpio *ctx; +	int irq = gpio_to_irq(gpio); +	int ret; + +	ret = mmc_gpio_alloc(host); +	if (ret < 0) +		return ret; + +	ctx = host->slot.handler_priv; + +	ret = gpio_request_one(gpio, GPIOF_DIR_IN, ctx->cd_label); +	if (ret < 0) +		/* +		 * don't bother freeing memory. It might still get used by other +		 * slot functions, in any case it will be freed, when the device +		 * is destroyed. +		 */ +		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 = request_threaded_irq(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->cd_gpio = gpio; + +	return 0; +} +EXPORT_SYMBOL(mmc_gpio_request_cd); + +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)) +		return; + +	gpio = ctx->ro_gpio; +	ctx->ro_gpio = -EINVAL; + +	gpio_free(gpio); +} +EXPORT_SYMBOL(mmc_gpio_free_ro); + +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)) +		return; + +	if (host->slot.cd_irq >= 0) { +		free_irq(host->slot.cd_irq, host); +		host->slot.cd_irq = -EINVAL; +	} + +	gpio = ctx->cd_gpio; +	ctx->cd_gpio = -EINVAL; + +	gpio_free(gpio); +} +EXPORT_SYMBOL(mmc_gpio_free_cd); diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index f2c115e0643..322412cec4e 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -391,11 +391,17 @@ static int atmci_regs_show(struct seq_file *s, void *v)  	clk_disable(host->mck);  	spin_unlock_bh(&host->lock); -	seq_printf(s, "MR:\t0x%08x%s%s CLKDIV=%u\n", +	seq_printf(s, "MR:\t0x%08x%s%s ",  			buf[ATMCI_MR / 4],  			buf[ATMCI_MR / 4] & ATMCI_MR_RDPROOF ? " RDPROOF" : "", -			buf[ATMCI_MR / 4] & ATMCI_MR_WRPROOF ? " WRPROOF" : "", -			buf[ATMCI_MR / 4] & 0xff); +			buf[ATMCI_MR / 4] & ATMCI_MR_WRPROOF ? " WRPROOF" : ""); +	if (host->caps.has_odd_clk_div) +		seq_printf(s, "{CLKDIV,CLKODD}=%u\n", +				((buf[ATMCI_MR / 4] & 0xff) << 1) +				| ((buf[ATMCI_MR / 4] >> 16) & 1)); +	else +		seq_printf(s, "CLKDIV=%u\n", +				(buf[ATMCI_MR / 4] & 0xff));  	seq_printf(s, "DTOR:\t0x%08x\n", buf[ATMCI_DTOR / 4]);  	seq_printf(s, "SDCR:\t0x%08x\n", buf[ATMCI_SDCR / 4]);  	seq_printf(s, "ARGR:\t0x%08x\n", buf[ATMCI_ARGR / 4]); @@ -1685,7 +1691,6 @@ static void atmci_tasklet_func(unsigned long priv)  			dev_dbg(&host->pdev->dev, "FSM: cmd ready\n");  			host->cmd = NULL; -			host->data = NULL;  			data->bytes_xfered = data->blocks * data->blksz;  			data->error = 0;  			atmci_command_complete(host, mrq->stop); @@ -1699,6 +1704,7 @@ static void atmci_tasklet_func(unsigned long priv)  				atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY);  				state = STATE_WAITING_NOTBUSY;  			} +			host->data = NULL;  			break;  		case STATE_END_REQUEST: diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 1ca5e72ceb6..72dc3cde646 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -405,11 +405,23 @@ static void dw_mci_idmac_start_dma(struct dw_mci *host, unsigned int sg_len)  static int dw_mci_idmac_init(struct dw_mci *host)  {  	struct idmac_desc *p; -	int i; +	int i, dma_support;  	/* Number of descriptors in the ring buffer */  	host->ring_size = PAGE_SIZE / sizeof(struct idmac_desc); +	/* Check if Hardware Configuration Register has support for DMA */ +	dma_support = (mci_readl(host, HCON) >> 16) & 0x3; + +	if (!dma_support || dma_support > 2) { +		dev_err(&host->dev, +			"Host Controller does not support IDMA Tx.\n"); +		host->dma_ops = NULL; +		return -ENODEV; +	} + +	dev_info(&host->dev, "Using internal DMA controller.\n"); +  	/* Forward link the descriptor list */  	for (i = 0, p = host->sg_cpu; i < host->ring_size - 1; i++, p++)  		p->des3 = host->sg_dma + (sizeof(struct idmac_desc) * (i + 1)); @@ -1876,7 +1888,6 @@ static void dw_mci_init_dma(struct dw_mci *host)  	/* Determine which DMA interface to use */  #ifdef CONFIG_MMC_DW_IDMAC  	host->dma_ops = &dw_mci_idmac_ops; -	dev_info(&host->dev, "Using internal DMA controller.\n");  #endif  	if (!host->dma_ops) @@ -2175,7 +2186,7 @@ int dw_mci_resume(struct dw_mci *host)  		return ret;  	} -	if (host->dma_ops->init) +	if (host->use_dma && host->dma_ops->init)  		host->dma_ops->init(host);  	/* Restore the old value at FIFOTH register */ diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c index 277161d279b..a51f9309ffb 100644 --- a/drivers/mmc/host/mxs-mmc.c +++ b/drivers/mmc/host/mxs-mmc.c @@ -164,16 +164,23 @@ struct mxs_mmc_host {  	spinlock_t			lock;  	int				sdio_irq_en;  	int				wp_gpio; +	bool				wp_inverted;  };  static int mxs_mmc_get_ro(struct mmc_host *mmc)  {  	struct mxs_mmc_host *host = mmc_priv(mmc); +	int ret;  	if (!gpio_is_valid(host->wp_gpio))  		return -EINVAL; -	return gpio_get_value(host->wp_gpio); +	ret = gpio_get_value(host->wp_gpio); + +	if (host->wp_inverted) +		ret = !ret; + +	return ret;  }  static int mxs_mmc_get_cd(struct mmc_host *mmc) @@ -707,6 +714,8 @@ static int mxs_mmc_probe(struct platform_device *pdev)  	struct pinctrl *pinctrl;  	int ret = 0, irq_err, irq_dma;  	dma_cap_mask_t mask; +	struct regulator *reg_vmmc; +	enum of_gpio_flags flags;  	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0); @@ -747,6 +756,16 @@ static int mxs_mmc_probe(struct platform_device *pdev)  	host->mmc = mmc;  	host->sdio_irq_en = 0; +	reg_vmmc = devm_regulator_get(&pdev->dev, "vmmc"); +	if (!IS_ERR(reg_vmmc)) { +		ret = regulator_enable(reg_vmmc); +		if (ret) { +			dev_err(&pdev->dev, +				"Failed to enable vmmc regulator: %d\n", ret); +			goto out_mmc_free; +		} +	} +  	pinctrl = devm_pinctrl_get_select_default(&pdev->dev);  	if (IS_ERR(pinctrl)) {  		ret = PTR_ERR(pinctrl); @@ -785,7 +804,10 @@ static int mxs_mmc_probe(struct platform_device *pdev)  			mmc->caps |= MMC_CAP_4_BIT_DATA;  		else if (bus_width == 8)  			mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA; -		host->wp_gpio = of_get_named_gpio(np, "wp-gpios", 0); +		host->wp_gpio = of_get_named_gpio_flags(np, "wp-gpios", 0, +							&flags); +		if (flags & OF_GPIO_ACTIVE_LOW) +			host->wp_inverted = 1;  	} else {  		if (pdata->flags & SLOTF_8_BIT_CAPABLE)  			mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA; diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 389a3eedfc2..bc28627af66 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -1089,7 +1089,7 @@ static int omap_hsmmc_switch_opcond(struct omap_hsmmc_host *host, int vdd)  	/* Disable the clocks */  	pm_runtime_put_sync(host->dev);  	if (host->dbclk) -		clk_disable(host->dbclk); +		clk_disable_unprepare(host->dbclk);  	/* Turn the power off */  	ret = mmc_slot(host).set_power(host->dev, host->slot_id, 0, 0); @@ -1100,7 +1100,7 @@ static int omap_hsmmc_switch_opcond(struct omap_hsmmc_host *host, int vdd)  					       vdd);  	pm_runtime_get_sync(host->dev);  	if (host->dbclk) -		clk_enable(host->dbclk); +		clk_prepare_enable(host->dbclk);  	if (ret != 0)  		goto err; @@ -1899,7 +1899,7 @@ static int __devinit omap_hsmmc_probe(struct platform_device *pdev)  	if (IS_ERR(host->dbclk)) {  		dev_warn(mmc_dev(host->mmc), "Failed to get debounce clk\n");  		host->dbclk = NULL; -	} else if (clk_enable(host->dbclk) != 0) { +	} else if (clk_prepare_enable(host->dbclk) != 0) {  		dev_warn(mmc_dev(host->mmc), "Failed to enable debounce clk\n");  		clk_put(host->dbclk);  		host->dbclk = NULL; @@ -1931,6 +1931,7 @@ static int __devinit omap_hsmmc_probe(struct platform_device *pdev)  	res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx");  	if (!res) {  		dev_err(mmc_dev(host->mmc), "cannot get DMA TX channel\n"); +		ret = -ENXIO;  		goto err_irq;  	}  	host->dma_line_tx = res->start; @@ -1938,6 +1939,7 @@ static int __devinit omap_hsmmc_probe(struct platform_device *pdev)  	res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx");  	if (!res) {  		dev_err(mmc_dev(host->mmc), "cannot get DMA RX channel\n"); +		ret = -ENXIO;  		goto err_irq;  	}  	host->dma_line_rx = res->start; @@ -2023,7 +2025,7 @@ err_irq:  	pm_runtime_disable(host->dev);  	clk_put(host->fclk);  	if (host->dbclk) { -		clk_disable(host->dbclk); +		clk_disable_unprepare(host->dbclk);  		clk_put(host->dbclk);  	}  err1: @@ -2058,7 +2060,7 @@ static int __devexit omap_hsmmc_remove(struct platform_device *pdev)  	pm_runtime_disable(host->dev);  	clk_put(host->fclk);  	if (host->dbclk) { -		clk_disable(host->dbclk); +		clk_disable_unprepare(host->dbclk);  		clk_put(host->dbclk);  	} @@ -2116,7 +2118,7 @@ static int omap_hsmmc_suspend(struct device *dev)  	}  	if (host->dbclk) -		clk_disable(host->dbclk); +		clk_disable_unprepare(host->dbclk);  err:  	pm_runtime_put_sync(host->dev);  	return ret; @@ -2137,7 +2139,7 @@ static int omap_hsmmc_resume(struct device *dev)  	pm_runtime_get_sync(host->dev);  	if (host->dbclk) -		clk_enable(host->dbclk); +		clk_prepare_enable(host->dbclk);  	if (!(host->mmc->pm_flags & MMC_PM_KEEP_POWER))  		omap_hsmmc_conf_bus_power(host); diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c index c3622a69f43..bd5a5cce122 100644 --- a/drivers/mmc/host/s3cmci.c +++ b/drivers/mmc/host/s3cmci.c @@ -26,7 +26,6 @@  #include <mach/dma.h>  #include <mach/regs-sdi.h> -#include <mach/regs-gpio.h>  #include <plat/mci.h> @@ -1237,12 +1236,9 @@ static void s3cmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)  	switch (ios->power_mode) {  	case MMC_POWER_ON:  	case MMC_POWER_UP: -		s3c2410_gpio_cfgpin(S3C2410_GPE(5), S3C2410_GPE5_SDCLK); -		s3c2410_gpio_cfgpin(S3C2410_GPE(6), S3C2410_GPE6_SDCMD); -		s3c2410_gpio_cfgpin(S3C2410_GPE(7), S3C2410_GPE7_SDDAT0); -		s3c2410_gpio_cfgpin(S3C2410_GPE(8), S3C2410_GPE8_SDDAT1); -		s3c2410_gpio_cfgpin(S3C2410_GPE(9), S3C2410_GPE9_SDDAT2); -		s3c2410_gpio_cfgpin(S3C2410_GPE(10), S3C2410_GPE10_SDDAT3); +		/* Configure GPE5...GPE10 pins in SD mode */ +		s3c_gpio_cfgall_range(S3C2410_GPE(5), 6, S3C_GPIO_SFN(2), +				      S3C_GPIO_PULL_NONE);  		if (host->pdata->set_power)  			host->pdata->set_power(ios->power_mode, ios->vdd); diff --git a/drivers/mmc/host/sdhci-dove.c b/drivers/mmc/host/sdhci-dove.c index 177f697b583..a6e53a1ebb0 100644 --- a/drivers/mmc/host/sdhci-dove.c +++ b/drivers/mmc/host/sdhci-dove.c @@ -20,11 +20,17 @@   */  #include <linux/io.h> +#include <linux/clk.h> +#include <linux/err.h>  #include <linux/module.h>  #include <linux/mmc/host.h>  #include "sdhci-pltfm.h" +struct sdhci_dove_priv { +	struct clk *clk; +}; +  static u16 sdhci_dove_readw(struct sdhci_host *host, int reg)  {  	u16 ret; @@ -66,16 +72,57 @@ static struct sdhci_pltfm_data sdhci_dove_pdata = {  	.quirks	= SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER |  		  SDHCI_QUIRK_NO_BUSY_IRQ |  		  SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | -		  SDHCI_QUIRK_FORCE_DMA, +		  SDHCI_QUIRK_FORCE_DMA | +		  SDHCI_QUIRK_NO_HISPD_BIT,  };  static int __devinit sdhci_dove_probe(struct platform_device *pdev)  { -	return sdhci_pltfm_register(pdev, &sdhci_dove_pdata); +	struct sdhci_host *host; +	struct sdhci_pltfm_host *pltfm_host; +	struct sdhci_dove_priv *priv; +	int ret; + +	ret = sdhci_pltfm_register(pdev, &sdhci_dove_pdata); +	if (ret) +		goto sdhci_dove_register_fail; + +	priv = devm_kzalloc(&pdev->dev, sizeof(struct sdhci_dove_priv), +			    GFP_KERNEL); +	if (!priv) { +		dev_err(&pdev->dev, "unable to allocate private data"); +		ret = -ENOMEM; +		goto sdhci_dove_allocate_fail; +	} + +	host = platform_get_drvdata(pdev); +	pltfm_host = sdhci_priv(host); +	pltfm_host->priv = priv; + +	priv->clk = clk_get(&pdev->dev, NULL); +	if (!IS_ERR(priv->clk)) +		clk_prepare_enable(priv->clk); +	return 0; + +sdhci_dove_allocate_fail: +	sdhci_pltfm_unregister(pdev); +sdhci_dove_register_fail: +	return ret;  }  static int __devexit sdhci_dove_remove(struct platform_device *pdev)  { +	struct sdhci_host *host = platform_get_drvdata(pdev); +	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); +	struct sdhci_dove_priv *priv = pltfm_host->priv; + +	if (priv->clk) { +		if (!IS_ERR(priv->clk)) { +			clk_disable_unprepare(priv->clk); +			clk_put(priv->clk); +		} +		devm_kfree(&pdev->dev, priv->clk); +	}  	return sdhci_pltfm_unregister(pdev);  } diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index ebbe984e5d0..e23f8134591 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -299,6 +299,8 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)  static void esdhc_writeb_le(struct sdhci_host *host, u8 val, int reg)  { +	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); +	struct pltfm_imx_data *imx_data = pltfm_host->priv;  	u32 new_val;  	switch (reg) { @@ -315,8 +317,11 @@ static void esdhc_writeb_le(struct sdhci_host *host, u8 val, int reg)  				SDHCI_CTRL_D3CD);  		/* ensure the endianess */  		new_val |= ESDHC_HOST_CONTROL_LE; -		/* DMA mode bits are shifted */ -		new_val |= (val & SDHCI_CTRL_DMA_MASK) << 5; +		/* bits 8&9 are reserved on mx25 */ +		if (!is_imx25_esdhc(imx_data)) { +			/* DMA mode bits are shifted */ +			new_val |= (val & SDHCI_CTRL_DMA_MASK) << 5; +		}  		esdhc_clrset_le(host, 0xffff, new_val, reg);  		return; diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c index 69ef0beae10..504da715a41 100644 --- a/drivers/mmc/host/sdhci-pci.c +++ b/drivers/mmc/host/sdhci-pci.c @@ -157,6 +157,7 @@ static const struct sdhci_pci_fixes sdhci_ene_714 = {  static const struct sdhci_pci_fixes sdhci_cafe = {  	.quirks		= SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER |  			  SDHCI_QUIRK_NO_BUSY_IRQ | +			  SDHCI_QUIRK_BROKEN_CARD_DETECTION |  			  SDHCI_QUIRK_BROKEN_TIMEOUT_VAL,  }; diff --git a/drivers/mmc/host/sdhci-pxav2.c b/drivers/mmc/host/sdhci-pxav2.c index dbb75bfbcff..b6ee8857e22 100644 --- a/drivers/mmc/host/sdhci-pxav2.c +++ b/drivers/mmc/host/sdhci-pxav2.c @@ -28,6 +28,9 @@  #include <linux/mmc/host.h>  #include <linux/platform_data/pxa_sdhci.h>  #include <linux/slab.h> +#include <linux/of.h> +#include <linux/of_device.h> +  #include "sdhci.h"  #include "sdhci-pltfm.h" @@ -121,6 +124,48 @@ static struct sdhci_ops pxav2_sdhci_ops = {  	.platform_8bit_width = pxav2_mmc_set_width,  }; +#ifdef CONFIG_OF +static const struct of_device_id sdhci_pxav2_of_match[] = { +	{ +		.compatible = "mrvl,pxav2-mmc", +	}, +	{}, +}; +MODULE_DEVICE_TABLE(of, sdhci_pxav2_of_match); + +static struct sdhci_pxa_platdata *pxav2_get_mmc_pdata(struct device *dev) +{ +	struct sdhci_pxa_platdata *pdata; +	struct device_node *np = dev->of_node; +	u32 bus_width; +	u32 clk_delay_cycles; + +	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); +	if (!pdata) +		return NULL; + +	if (of_find_property(np, "non-removable", NULL)) +		pdata->flags |= PXA_FLAG_CARD_PERMANENT; + +	of_property_read_u32(np, "bus-width", &bus_width); +	if (bus_width == 8) +		pdata->flags |= PXA_FLAG_SD_8_BIT_CAPABLE_SLOT; + +	of_property_read_u32(np, "mrvl,clk-delay-cycles", &clk_delay_cycles); +	if (clk_delay_cycles > 0) { +		pdata->clk_delay_sel = 1; +		pdata->clk_delay_cycles = clk_delay_cycles; +	} + +	return pdata; +} +#else +static inline struct sdhci_pxa_platdata *pxav2_get_mmc_pdata(struct device *dev) +{ +	return NULL; +} +#endif +  static int __devinit sdhci_pxav2_probe(struct platform_device *pdev)  {  	struct sdhci_pltfm_host *pltfm_host; @@ -128,6 +173,8 @@ static int __devinit sdhci_pxav2_probe(struct platform_device *pdev)  	struct device *dev = &pdev->dev;  	struct sdhci_host *host = NULL;  	struct sdhci_pxa *pxa = NULL; +	const struct of_device_id *match; +  	int ret;  	struct clk *clk; @@ -156,6 +203,10 @@ static int __devinit sdhci_pxav2_probe(struct platform_device *pdev)  		| SDHCI_QUIRK_BROKEN_TIMEOUT_VAL  		| SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN; +	match = of_match_device(of_match_ptr(sdhci_pxav2_of_match), &pdev->dev); +	if (match) { +		pdata = pxav2_get_mmc_pdata(dev); +	}  	if (pdata) {  		if (pdata->flags & PXA_FLAG_CARD_PERMANENT) {  			/* on-chip device */ @@ -218,6 +269,9 @@ static struct platform_driver sdhci_pxav2_driver = {  	.driver		= {  		.name	= "sdhci-pxav2",  		.owner	= THIS_MODULE, +#ifdef CONFIG_OF +		.of_match_table = sdhci_pxav2_of_match, +#endif  		.pm	= SDHCI_PLTFM_PMOPS,  	},  	.probe		= sdhci_pxav2_probe, diff --git a/drivers/mmc/host/sdhci-pxav3.c b/drivers/mmc/host/sdhci-pxav3.c index f2969568355..07fe3834fe0 100644 --- a/drivers/mmc/host/sdhci-pxav3.c +++ b/drivers/mmc/host/sdhci-pxav3.c @@ -28,6 +28,9 @@  #include <linux/slab.h>  #include <linux/delay.h>  #include <linux/module.h> +#include <linux/of.h> +#include <linux/of_device.h> +  #include "sdhci.h"  #include "sdhci-pltfm.h" @@ -164,6 +167,46 @@ static struct sdhci_ops pxav3_sdhci_ops = {  	.platform_send_init_74_clocks = pxav3_gen_init_74_clocks,  }; +#ifdef CONFIG_OF +static const struct of_device_id sdhci_pxav3_of_match[] = { +	{ +		.compatible = "mrvl,pxav3-mmc", +	}, +	{}, +}; +MODULE_DEVICE_TABLE(of, sdhci_pxav3_of_match); + +static struct sdhci_pxa_platdata *pxav3_get_mmc_pdata(struct device *dev) +{ +	struct sdhci_pxa_platdata *pdata; +	struct device_node *np = dev->of_node; +	u32 bus_width; +	u32 clk_delay_cycles; + +	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); +	if (!pdata) +		return NULL; + +	if (of_find_property(np, "non-removable", NULL)) +		pdata->flags |= PXA_FLAG_CARD_PERMANENT; + +	of_property_read_u32(np, "bus-width", &bus_width); +	if (bus_width == 8) +		pdata->flags |= PXA_FLAG_SD_8_BIT_CAPABLE_SLOT; + +	of_property_read_u32(np, "mrvl,clk-delay-cycles", &clk_delay_cycles); +	if (clk_delay_cycles > 0) +		pdata->clk_delay_cycles = clk_delay_cycles; + +	return pdata; +} +#else +static inline struct sdhci_pxa_platdata *pxav3_get_mmc_pdata(struct device *dev) +{ +	return NULL; +} +#endif +  static int __devinit sdhci_pxav3_probe(struct platform_device *pdev)  {  	struct sdhci_pltfm_host *pltfm_host; @@ -171,6 +214,8 @@ static int __devinit sdhci_pxav3_probe(struct platform_device *pdev)  	struct device *dev = &pdev->dev;  	struct sdhci_host *host = NULL;  	struct sdhci_pxa *pxa = NULL; +	const struct of_device_id *match; +  	int ret;  	struct clk *clk; @@ -202,6 +247,10 @@ static int __devinit sdhci_pxav3_probe(struct platform_device *pdev)  	/* enable 1/8V DDR capable */  	host->mmc->caps |= MMC_CAP_1_8V_DDR; +	match = of_match_device(of_match_ptr(sdhci_pxav3_of_match), &pdev->dev); +	if (match) +		pdata = pxav3_get_mmc_pdata(dev); +  	if (pdata) {  		if (pdata->flags & PXA_FLAG_CARD_PERMANENT) {  			/* on-chip device */ @@ -263,6 +312,9 @@ static int __devexit sdhci_pxav3_remove(struct platform_device *pdev)  static struct platform_driver sdhci_pxav3_driver = {  	.driver		= {  		.name	= "sdhci-pxav3", +#ifdef CONFIG_OF +		.of_match_table = sdhci_pxav3_of_match, +#endif  		.owner	= THIS_MODULE,  		.pm	= SDHCI_PLTFM_PMOPS,  	}, diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c index b38d8a78f6a..6e5338a071c 100644 --- a/drivers/mmc/host/sdhci-tegra.c +++ b/drivers/mmc/host/sdhci-tegra.c @@ -223,6 +223,7 @@ static struct tegra_sdhci_platform_data * __devinit sdhci_tegra_dt_parse_pdata(  {  	struct tegra_sdhci_platform_data *plat;  	struct device_node *np = pdev->dev.of_node; +	u32 bus_width;  	if (!np)  		return NULL; @@ -236,7 +237,9 @@ static struct tegra_sdhci_platform_data * __devinit sdhci_tegra_dt_parse_pdata(  	plat->cd_gpio = of_get_named_gpio(np, "cd-gpios", 0);  	plat->wp_gpio = of_get_named_gpio(np, "wp-gpios", 0);  	plat->power_gpio = of_get_named_gpio(np, "power-gpios", 0); -	if (of_find_property(np, "support-8bit", NULL)) + +	if (of_property_read_u32(np, "bus-width", &bus_width) == 0 && +	    bus_width == 8)  		plat->is_8bit = 1;  	return plat; diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index f4b8b4db3a9..9a11dc39921 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -27,6 +27,7 @@  #include <linux/mmc/mmc.h>  #include <linux/mmc/host.h> +#include <linux/mmc/card.h>  #include "sdhci.h" @@ -244,6 +245,19 @@ static void sdhci_init(struct sdhci_host *host, int soft)  static void sdhci_reinit(struct sdhci_host *host)  {  	sdhci_init(host, 0); +	/* +	 * Retuning stuffs are affected by different cards inserted and only +	 * applicable to UHS-I cards. So reset these fields to their initial +	 * value when card is removed. +	 */ +	if (host->flags & SDHCI_USING_RETUNING_TIMER) { +		host->flags &= ~SDHCI_USING_RETUNING_TIMER; + +		del_timer_sync(&host->tuning_timer); +		host->flags &= ~SDHCI_NEEDS_RETUNING; +		host->mmc->max_blk_count = +			(host->quirks & SDHCI_QUIRK_NO_MULTIBLOCK) ? 1 : 65535; +	}  	sdhci_enable_card_detection(host);  } @@ -1245,6 +1259,7 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)  	struct sdhci_host *host;  	bool present;  	unsigned long flags; +	u32 tuning_opcode;  	host = mmc_priv(mmc); @@ -1292,8 +1307,12 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)  		 */  		if ((host->flags & SDHCI_NEEDS_RETUNING) &&  		    !(present_state & (SDHCI_DOING_WRITE | SDHCI_DOING_READ))) { +			/* eMMC uses cmd21 while sd and sdio use cmd19 */ +			tuning_opcode = mmc->card->type == MMC_TYPE_MMC ? +				MMC_SEND_TUNING_BLOCK_HS200 : +				MMC_SEND_TUNING_BLOCK;  			spin_unlock_irqrestore(&host->lock, flags); -			sdhci_execute_tuning(mmc, mrq->cmd->opcode); +			sdhci_execute_tuning(mmc, tuning_opcode);  			spin_lock_irqsave(&host->lock, flags);  			/* Restore original mmc_request structure */ @@ -1663,11 +1682,15 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,  		pwr = sdhci_readb(host, SDHCI_POWER_CONTROL);  		pwr &= ~SDHCI_POWER_ON;  		sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); +		if (host->vmmc) +			regulator_disable(host->vmmc);  		/* Wait for 1ms as per the spec */  		usleep_range(1000, 1500);  		pwr |= SDHCI_POWER_ON;  		sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); +		if (host->vmmc) +			regulator_enable(host->vmmc);  		pr_info(DRIVER_NAME ": Switching to 1.8V signalling "  			"voltage failed, retrying with S18R set to 0\n"); @@ -1855,6 +1878,7 @@ out:  	 */  	if (!(host->flags & SDHCI_NEEDS_RETUNING) && host->tuning_count &&  	    (host->tuning_mode == SDHCI_TUNING_MODE_1)) { +		host->flags |= SDHCI_USING_RETUNING_TIMER;  		mod_timer(&host->tuning_timer, jiffies +  			host->tuning_count * HZ);  		/* Tuning mode 1 limits the maximum data length to 4MB */ @@ -1872,10 +1896,10 @@ out:  	 * try tuning again at a later time, when the re-tuning timer expires.  	 * So for these controllers, we return 0. Since there might be other  	 * controllers who do not have this capability, we return error for -	 * them. +	 * them. SDHCI_USING_RETUNING_TIMER means the host is currently using +	 * a retuning timer to do the retuning for the card.  	 */ -	if (err && host->tuning_count && -	    host->tuning_mode == SDHCI_TUNING_MODE_1) +	if (err && (host->flags & SDHCI_USING_RETUNING_TIMER))  		err = 0;  	sdhci_clear_set_irqs(host, SDHCI_INT_DATA_AVAIL, ier); @@ -2382,7 +2406,6 @@ out:  int sdhci_suspend_host(struct sdhci_host *host)  {  	int ret; -	bool has_tuning_timer;  	if (host->ops->platform_suspend)  		host->ops->platform_suspend(host); @@ -2390,16 +2413,14 @@ int sdhci_suspend_host(struct sdhci_host *host)  	sdhci_disable_card_detection(host);  	/* Disable tuning since we are suspending */ -	has_tuning_timer = host->version >= SDHCI_SPEC_300 && -		host->tuning_count && host->tuning_mode == SDHCI_TUNING_MODE_1; -	if (has_tuning_timer) { +	if (host->flags & SDHCI_USING_RETUNING_TIMER) {  		del_timer_sync(&host->tuning_timer);  		host->flags &= ~SDHCI_NEEDS_RETUNING;  	}  	ret = mmc_suspend_host(host->mmc);  	if (ret) { -		if (has_tuning_timer) { +		if (host->flags & SDHCI_USING_RETUNING_TIMER) {  			host->flags |= SDHCI_NEEDS_RETUNING;  			mod_timer(&host->tuning_timer, jiffies +  					host->tuning_count * HZ); @@ -2450,8 +2471,7 @@ int sdhci_resume_host(struct sdhci_host *host)  		host->ops->platform_resume(host);  	/* Set the re-tuning expiration flag */ -	if ((host->version >= SDHCI_SPEC_300) && host->tuning_count && -	    (host->tuning_mode == SDHCI_TUNING_MODE_1)) +	if (host->flags & SDHCI_USING_RETUNING_TIMER)  		host->flags |= SDHCI_NEEDS_RETUNING;  	return ret; @@ -2490,8 +2510,7 @@ int sdhci_runtime_suspend_host(struct sdhci_host *host)  	int ret = 0;  	/* Disable tuning since we are suspending */ -	if (host->version >= SDHCI_SPEC_300 && -	    host->tuning_mode == SDHCI_TUNING_MODE_1) { +	if (host->flags & SDHCI_USING_RETUNING_TIMER) {  		del_timer_sync(&host->tuning_timer);  		host->flags &= ~SDHCI_NEEDS_RETUNING;  	} @@ -2532,8 +2551,7 @@ int sdhci_runtime_resume_host(struct sdhci_host *host)  		sdhci_do_enable_preset_value(host, true);  	/* Set the re-tuning expiration flag */ -	if ((host->version >= SDHCI_SPEC_300) && host->tuning_count && -	    (host->tuning_mode == SDHCI_TUNING_MODE_1)) +	if (host->flags & SDHCI_USING_RETUNING_TIMER)  		host->flags |= SDHCI_NEEDS_RETUNING;  	spin_lock_irqsave(&host->lock, flags); @@ -2584,7 +2602,7 @@ EXPORT_SYMBOL_GPL(sdhci_alloc_host);  int sdhci_add_host(struct sdhci_host *host)  {  	struct mmc_host *mmc; -	u32 caps[2]; +	u32 caps[2] = {0, 0};  	u32 max_current_caps;  	unsigned int ocr_avail;  	int ret; @@ -2614,8 +2632,10 @@ int sdhci_add_host(struct sdhci_host *host)  	caps[0] = (host->quirks & SDHCI_QUIRK_MISSING_CAPS) ? host->caps :  		sdhci_readl(host, SDHCI_CAPABILITIES); -	caps[1] = (host->version >= SDHCI_SPEC_300) ? -		sdhci_readl(host, SDHCI_CAPABILITIES_1) : 0; +	if (host->version >= SDHCI_SPEC_300) +		caps[1] = (host->quirks & SDHCI_QUIRK_MISSING_CAPS) ? +			host->caps1 : +			sdhci_readl(host, SDHCI_CAPABILITIES_1);  	if (host->quirks & SDHCI_QUIRK_FORCE_DMA)  		host->flags |= SDHCI_USE_SDMA; @@ -2779,7 +2799,7 @@ int sdhci_add_host(struct sdhci_host *host)  		mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED;  	if ((host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) && -	    mmc_card_is_removable(mmc)) +	    !(host->mmc->caps & MMC_CAP_NONREMOVABLE))  		mmc->caps |= MMC_CAP_NEEDS_POLL;  	/* Any UHS-I mode in caps implies SDR12 and SDR25 support. */ @@ -2837,6 +2857,30 @@ int sdhci_add_host(struct sdhci_host *host)  			     SDHCI_RETUNING_MODE_SHIFT;  	ocr_avail = 0; + +	host->vmmc = regulator_get(mmc_dev(mmc), "vmmc"); +	if (IS_ERR(host->vmmc)) { +		pr_info("%s: no vmmc regulator found\n", mmc_hostname(mmc)); +		host->vmmc = NULL; +	} + +#ifdef CONFIG_REGULATOR +	if (host->vmmc) { +		ret = regulator_is_supported_voltage(host->vmmc, 3300000, +			3300000); +		if ((ret <= 0) || (!(caps[0] & SDHCI_CAN_VDD_330))) +			caps[0] &= ~SDHCI_CAN_VDD_330; +		ret = regulator_is_supported_voltage(host->vmmc, 3000000, +			3000000); +		if ((ret <= 0) || (!(caps[0] & SDHCI_CAN_VDD_300))) +			caps[0] &= ~SDHCI_CAN_VDD_300; +		ret = regulator_is_supported_voltage(host->vmmc, 1800000, +			1800000); +		if ((ret <= 0) || (!(caps[0] & SDHCI_CAN_VDD_180))) +			caps[0] &= ~SDHCI_CAN_VDD_180; +	} +#endif /* CONFIG_REGULATOR */ +  	/*  	 * According to SD Host Controller spec v3.00, if the Host System  	 * can afford more than 150mA, Host Driver should set XPC to 1. Also @@ -2845,55 +2889,45 @@ int sdhci_add_host(struct sdhci_host *host)  	 * value.  	 */  	max_current_caps = sdhci_readl(host, SDHCI_MAX_CURRENT); +	if (!max_current_caps && host->vmmc) { +		u32 curr = regulator_get_current_limit(host->vmmc); +		if (curr > 0) { -	if (caps[0] & SDHCI_CAN_VDD_330) { -		int max_current_330; +			/* convert to SDHCI_MAX_CURRENT format */ +			curr = curr/1000;  /* convert to mA */ +			curr = curr/SDHCI_MAX_CURRENT_MULTIPLIER; + +			curr = min_t(u32, curr, SDHCI_MAX_CURRENT_LIMIT); +			max_current_caps = +				(curr << SDHCI_MAX_CURRENT_330_SHIFT) | +				(curr << SDHCI_MAX_CURRENT_300_SHIFT) | +				(curr << SDHCI_MAX_CURRENT_180_SHIFT); +		} +	} +	if (caps[0] & SDHCI_CAN_VDD_330) {  		ocr_avail |= MMC_VDD_32_33 | MMC_VDD_33_34; -		max_current_330 = ((max_current_caps & +		mmc->max_current_330 = ((max_current_caps &  				   SDHCI_MAX_CURRENT_330_MASK) >>  				   SDHCI_MAX_CURRENT_330_SHIFT) *  				   SDHCI_MAX_CURRENT_MULTIPLIER; - -		if (max_current_330 > 150) -			mmc->caps |= MMC_CAP_SET_XPC_330;  	}  	if (caps[0] & SDHCI_CAN_VDD_300) { -		int max_current_300; -  		ocr_avail |= MMC_VDD_29_30 | MMC_VDD_30_31; -		max_current_300 = ((max_current_caps & +		mmc->max_current_300 = ((max_current_caps &  				   SDHCI_MAX_CURRENT_300_MASK) >>  				   SDHCI_MAX_CURRENT_300_SHIFT) *  				   SDHCI_MAX_CURRENT_MULTIPLIER; - -		if (max_current_300 > 150) -			mmc->caps |= MMC_CAP_SET_XPC_300;  	}  	if (caps[0] & SDHCI_CAN_VDD_180) { -		int max_current_180; -  		ocr_avail |= MMC_VDD_165_195; -		max_current_180 = ((max_current_caps & +		mmc->max_current_180 = ((max_current_caps &  				   SDHCI_MAX_CURRENT_180_MASK) >>  				   SDHCI_MAX_CURRENT_180_SHIFT) *  				   SDHCI_MAX_CURRENT_MULTIPLIER; - -		if (max_current_180 > 150) -			mmc->caps |= MMC_CAP_SET_XPC_180; - -		/* Maximum current capabilities of the host at 1.8V */ -		if (max_current_180 >= 800) -			mmc->caps |= MMC_CAP_MAX_CURRENT_800; -		else if (max_current_180 >= 600) -			mmc->caps |= MMC_CAP_MAX_CURRENT_600; -		else if (max_current_180 >= 400) -			mmc->caps |= MMC_CAP_MAX_CURRENT_400; -		else -			mmc->caps |= MMC_CAP_MAX_CURRENT_200;  	}  	mmc->ocr_avail = ocr_avail; @@ -2992,13 +3026,10 @@ int sdhci_add_host(struct sdhci_host *host)  	ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED,  		mmc_hostname(mmc), host); -	if (ret) +	if (ret) { +		pr_err("%s: Failed to request IRQ %d: %d\n", +		       mmc_hostname(mmc), host->irq, ret);  		goto untasklet; - -	host->vmmc = regulator_get(mmc_dev(mmc), "vmmc"); -	if (IS_ERR(host->vmmc)) { -		pr_info("%s: no vmmc regulator found\n", mmc_hostname(mmc)); -		host->vmmc = NULL;  	}  	sdhci_init(host, 0); @@ -3016,8 +3047,11 @@ int sdhci_add_host(struct sdhci_host *host)  	host->led.brightness_set = sdhci_led_control;  	ret = led_classdev_register(mmc_dev(mmc), &host->led); -	if (ret) +	if (ret) { +		pr_err("%s: Failed to register LED device: %d\n", +		       mmc_hostname(mmc), ret);  		goto reset; +	}  #endif  	mmiowb(); @@ -3081,8 +3115,6 @@ void sdhci_remove_host(struct sdhci_host *host, int dead)  	free_irq(host->irq, host);  	del_timer_sync(&host->timer); -	if (host->version >= SDHCI_SPEC_300) -		del_timer_sync(&host->tuning_timer);  	tasklet_kill(&host->card_tasklet);  	tasklet_kill(&host->finish_tasklet); diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index f761f23d2a2..97653ea8942 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -205,6 +205,7 @@  #define SDHCI_CAPABILITIES_1	0x44  #define SDHCI_MAX_CURRENT		0x48 +#define  SDHCI_MAX_CURRENT_LIMIT	0xFF  #define  SDHCI_MAX_CURRENT_330_MASK	0x0000FF  #define  SDHCI_MAX_CURRENT_330_SHIFT	0  #define  SDHCI_MAX_CURRENT_300_MASK	0x00FF00 diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index 724b35e85a2..b2af7136cd2 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c @@ -54,6 +54,8 @@  #include <linux/mmc/mmc.h>  #include <linux/mmc/sdio.h>  #include <linux/mmc/sh_mmcif.h> +#include <linux/mmc/slot-gpio.h> +#include <linux/mod_devicetable.h>  #include <linux/pagemap.h>  #include <linux/platform_device.h>  #include <linux/pm_qos.h> @@ -384,6 +386,9 @@ static void sh_mmcif_request_dma(struct sh_mmcif_host *host,  	struct sh_dmae_slave *tx, *rx;  	host->dma_active = false; +	if (!pdata) +		return; +  	/* We can only either use DMA for both Tx and Rx or not use it at all */  	if (pdata->dma) {  		dev_warn(&host->pd->dev, @@ -444,13 +449,14 @@ static void sh_mmcif_release_dma(struct sh_mmcif_host *host)  static void sh_mmcif_clock_control(struct sh_mmcif_host *host, unsigned int clk)  {  	struct sh_mmcif_plat_data *p = host->pd->dev.platform_data; +	bool sup_pclk = p ? p->sup_pclk : false;  	sh_mmcif_bitclr(host, MMCIF_CE_CLK_CTRL, CLK_ENABLE);  	sh_mmcif_bitclr(host, MMCIF_CE_CLK_CTRL, CLK_CLEAR);  	if (!clk)  		return; -	if (p->sup_pclk && clk == host->clk) +	if (sup_pclk && clk == host->clk)  		sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, CLK_SUP_PCLK);  	else  		sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, CLK_CLEAR & @@ -892,21 +898,15 @@ static void sh_mmcif_request(struct mmc_host *mmc, struct mmc_request *mrq)  	switch (mrq->cmd->opcode) {  	/* MMCIF does not support SD/SDIO command */ -	case SD_IO_SEND_OP_COND: +	case MMC_SLEEP_AWAKE: /* = SD_IO_SEND_OP_COND (5) */ +	case MMC_SEND_EXT_CSD: /* = SD_SEND_IF_COND (8) */ +		if ((mrq->cmd->flags & MMC_CMD_MASK) != MMC_CMD_BCR) +			break;  	case MMC_APP_CMD:  		host->state = STATE_IDLE;  		mrq->cmd->error = -ETIMEDOUT;  		mmc_request_done(mmc, mrq);  		return; -	case MMC_SEND_EXT_CSD: /* = SD_SEND_IF_COND (8) */ -		if (!mrq->data) { -			/* send_if_cond cmd (not support) */ -			host->state = STATE_IDLE; -			mrq->cmd->error = -ETIMEDOUT; -			mmc_request_done(mmc, mrq); -			return; -		} -		break;  	default:  		break;  	} @@ -916,10 +916,35 @@ static void sh_mmcif_request(struct mmc_host *mmc, struct mmc_request *mrq)  	sh_mmcif_start_cmd(host, mrq);  } +static int sh_mmcif_clk_update(struct sh_mmcif_host *host) +{ +	int ret = clk_enable(host->hclk); + +	if (!ret) { +		host->clk = clk_get_rate(host->hclk); +		host->mmc->f_max = host->clk / 2; +		host->mmc->f_min = host->clk / 512; +	} + +	return ret; +} + +static void sh_mmcif_set_power(struct sh_mmcif_host *host, struct mmc_ios *ios) +{ +	struct sh_mmcif_plat_data *pd = host->pd->dev.platform_data; +	struct mmc_host *mmc = host->mmc; + +	if (pd && pd->set_pwr) +		pd->set_pwr(host->pd, ios->power_mode != MMC_POWER_OFF); +	if (!IS_ERR(mmc->supply.vmmc)) +		/* Errors ignored... */ +		mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, +				      ios->power_mode ? ios->vdd : 0); +} +  static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)  {  	struct sh_mmcif_host *host = mmc_priv(mmc); -	struct sh_mmcif_plat_data *p = host->pd->dev.platform_data;  	unsigned long flags;  	spin_lock_irqsave(&host->lock, flags); @@ -937,6 +962,7 @@ static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)  			sh_mmcif_request_dma(host, host->pd->dev.platform_data);  			host->card_present = true;  		} +		sh_mmcif_set_power(host, ios);  	} else if (ios->power_mode == MMC_POWER_OFF || !ios->clock) {  		/* clock stop */  		sh_mmcif_clock_control(host, 0); @@ -948,9 +974,10 @@ static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)  		}  		if (host->power) {  			pm_runtime_put(&host->pd->dev); +			clk_disable(host->hclk);  			host->power = false; -			if (p->down_pwr && ios->power_mode == MMC_POWER_OFF) -				p->down_pwr(host->pd); +			if (ios->power_mode == MMC_POWER_OFF) +				sh_mmcif_set_power(host, ios);  		}  		host->state = STATE_IDLE;  		return; @@ -958,8 +985,7 @@ static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)  	if (ios->clock) {  		if (!host->power) { -			if (p->set_pwr) -				p->set_pwr(host->pd, ios->power_mode); +			sh_mmcif_clk_update(host);  			pm_runtime_get_sync(&host->pd->dev);  			host->power = true;  			sh_mmcif_sync_reset(host); @@ -975,8 +1001,12 @@ static int sh_mmcif_get_cd(struct mmc_host *mmc)  {  	struct sh_mmcif_host *host = mmc_priv(mmc);  	struct sh_mmcif_plat_data *p = host->pd->dev.platform_data; +	int ret = mmc_gpio_get_cd(mmc); -	if (!p->get_cd) +	if (ret >= 0) +		return ret; + +	if (!p || !p->get_cd)  		return -ENOSYS;  	else  		return p->get_cd(host->pd); @@ -1242,12 +1272,28 @@ static void mmcif_timeout_work(struct work_struct *work)  	mmc_request_done(host->mmc, mrq);  } +static void sh_mmcif_init_ocr(struct sh_mmcif_host *host) +{ +	struct sh_mmcif_plat_data *pd = host->pd->dev.platform_data; +	struct mmc_host *mmc = host->mmc; + +	mmc_regulator_get_supply(mmc); + +	if (!pd) +		return; + +	if (!mmc->ocr_avail) +		mmc->ocr_avail = pd->ocr; +	else if (pd->ocr) +		dev_warn(mmc_dev(mmc), "Platform OCR mask is ignored\n"); +} +  static int __devinit sh_mmcif_probe(struct platform_device *pdev)  {  	int ret = 0, irq[2];  	struct mmc_host *mmc;  	struct sh_mmcif_host *host; -	struct sh_mmcif_plat_data *pd; +	struct sh_mmcif_plat_data *pd = pdev->dev.platform_data;  	struct resource *res;  	void __iomem *reg;  	char clk_name[8]; @@ -1268,42 +1314,26 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev)  		dev_err(&pdev->dev, "ioremap error.\n");  		return -ENOMEM;  	} -	pd = pdev->dev.platform_data; -	if (!pd) { -		dev_err(&pdev->dev, "sh_mmcif plat data error.\n"); -		ret = -ENXIO; -		goto clean_up; -	} +  	mmc = mmc_alloc_host(sizeof(struct sh_mmcif_host), &pdev->dev);  	if (!mmc) {  		ret = -ENOMEM; -		goto clean_up; +		goto ealloch;  	}  	host		= mmc_priv(mmc);  	host->mmc	= mmc;  	host->addr	= reg;  	host->timeout	= 1000; -	snprintf(clk_name, sizeof(clk_name), "mmc%d", pdev->id); -	host->hclk = clk_get(&pdev->dev, clk_name); -	if (IS_ERR(host->hclk)) { -		dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name); -		ret = PTR_ERR(host->hclk); -		goto clean_up1; -	} -	clk_enable(host->hclk); -	host->clk = clk_get_rate(host->hclk);  	host->pd = pdev;  	spin_lock_init(&host->lock);  	mmc->ops = &sh_mmcif_ops; -	mmc->f_max = host->clk / 2; -	mmc->f_min = host->clk / 512; -	if (pd->ocr) -		mmc->ocr_avail = pd->ocr; +	sh_mmcif_init_ocr(host); +  	mmc->caps = MMC_CAP_MMC_HIGHSPEED; -	if (pd->caps) +	if (pd && pd->caps)  		mmc->caps |= pd->caps;  	mmc->max_segs = 32;  	mmc->max_blk_size = 512; @@ -1311,34 +1341,52 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev)  	mmc->max_blk_count = mmc->max_req_size / mmc->max_blk_size;  	mmc->max_seg_size = mmc->max_req_size; -	sh_mmcif_sync_reset(host);  	platform_set_drvdata(pdev, host);  	pm_runtime_enable(&pdev->dev);  	host->power = false; +	snprintf(clk_name, sizeof(clk_name), "mmc%d", pdev->id); +	host->hclk = clk_get(&pdev->dev, clk_name); +	if (IS_ERR(host->hclk)) { +		ret = PTR_ERR(host->hclk); +		dev_err(&pdev->dev, "cannot get clock \"%s\": %d\n", clk_name, ret); +		goto eclkget; +	} +	ret = sh_mmcif_clk_update(host); +	if (ret < 0) +		goto eclkupdate; +  	ret = pm_runtime_resume(&pdev->dev);  	if (ret < 0) -		goto clean_up2; +		goto eresume;  	INIT_DELAYED_WORK(&host->timeout_work, mmcif_timeout_work); +	sh_mmcif_sync_reset(host);  	sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL);  	ret = request_threaded_irq(irq[0], sh_mmcif_intr, sh_mmcif_irqt, 0, "sh_mmc:error", host);  	if (ret) {  		dev_err(&pdev->dev, "request_irq error (sh_mmc:error)\n"); -		goto clean_up3; +		goto ereqirq0;  	}  	ret = request_threaded_irq(irq[1], sh_mmcif_intr, sh_mmcif_irqt, 0, "sh_mmc:int", host);  	if (ret) {  		dev_err(&pdev->dev, "request_irq error (sh_mmc:int)\n"); -		goto clean_up4; +		goto ereqirq1;  	} +	if (pd && pd->use_cd_gpio) { +		ret = mmc_gpio_request_cd(mmc, pd->cd_gpio); +		if (ret < 0) +			goto erqcd; +	} + +	clk_disable(host->hclk);  	ret = mmc_add_host(mmc);  	if (ret < 0) -		goto clean_up5; +		goto emmcaddh;  	dev_pm_qos_expose_latency_limit(&pdev->dev, 100); @@ -1347,33 +1395,42 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev)  		sh_mmcif_readl(host->addr, MMCIF_CE_VERSION) & 0x0000ffff);  	return ret; -clean_up5: +emmcaddh: +	if (pd && pd->use_cd_gpio) +		mmc_gpio_free_cd(mmc); +erqcd:  	free_irq(irq[1], host); -clean_up4: +ereqirq1:  	free_irq(irq[0], host); -clean_up3: +ereqirq0:  	pm_runtime_suspend(&pdev->dev); -clean_up2: -	pm_runtime_disable(&pdev->dev); +eresume:  	clk_disable(host->hclk); -clean_up1: +eclkupdate: +	clk_put(host->hclk); +eclkget: +	pm_runtime_disable(&pdev->dev);  	mmc_free_host(mmc); -clean_up: -	if (reg) -		iounmap(reg); +ealloch: +	iounmap(reg);  	return ret;  }  static int __devexit sh_mmcif_remove(struct platform_device *pdev)  {  	struct sh_mmcif_host *host = platform_get_drvdata(pdev); +	struct sh_mmcif_plat_data *pd = pdev->dev.platform_data;  	int irq[2];  	host->dying = true; +	clk_enable(host->hclk);  	pm_runtime_get_sync(&pdev->dev);  	dev_pm_qos_hide_latency_limit(&pdev->dev); +	if (pd && pd->use_cd_gpio) +		mmc_gpio_free_cd(host->mmc); +  	mmc_remove_host(host->mmc);  	sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL); @@ -1395,9 +1452,9 @@ static int __devexit sh_mmcif_remove(struct platform_device *pdev)  	platform_set_drvdata(pdev, NULL); -	clk_disable(host->hclk);  	mmc_free_host(host->mmc);  	pm_runtime_put_sync(&pdev->dev); +	clk_disable(host->hclk);  	pm_runtime_disable(&pdev->dev);  	return 0; @@ -1406,24 +1463,18 @@ static int __devexit sh_mmcif_remove(struct platform_device *pdev)  #ifdef CONFIG_PM  static int sh_mmcif_suspend(struct device *dev)  { -	struct platform_device *pdev = to_platform_device(dev); -	struct sh_mmcif_host *host = platform_get_drvdata(pdev); +	struct sh_mmcif_host *host = dev_get_drvdata(dev);  	int ret = mmc_suspend_host(host->mmc); -	if (!ret) { +	if (!ret)  		sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL); -		clk_disable(host->hclk); -	}  	return ret;  }  static int sh_mmcif_resume(struct device *dev)  { -	struct platform_device *pdev = to_platform_device(dev); -	struct sh_mmcif_host *host = platform_get_drvdata(pdev); - -	clk_enable(host->hclk); +	struct sh_mmcif_host *host = dev_get_drvdata(dev);  	return mmc_resume_host(host->mmc);  } @@ -1432,6 +1483,12 @@ static int sh_mmcif_resume(struct device *dev)  #define sh_mmcif_resume		NULL  #endif	/* CONFIG_PM */ +static const struct of_device_id mmcif_of_match[] = { +	{ .compatible = "renesas,sh-mmcif" }, +	{ } +}; +MODULE_DEVICE_TABLE(of, mmcif_of_match); +  static const struct dev_pm_ops sh_mmcif_dev_pm_ops = {  	.suspend = sh_mmcif_suspend,  	.resume = sh_mmcif_resume, @@ -1443,6 +1500,8 @@ static struct platform_driver sh_mmcif_driver = {  	.driver		= {  		.name	= DRIVER_NAME,  		.pm	= &sh_mmcif_dev_pm_ops, +		.owner	= THIS_MODULE, +		.of_match_table = mmcif_of_match,  	},  }; diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c index 934b68e9efc..a842939e465 100644 --- a/drivers/mmc/host/sh_mobile_sdhi.c +++ b/drivers/mmc/host/sh_mobile_sdhi.c @@ -21,6 +21,7 @@  #include <linux/kernel.h>  #include <linux/clk.h>  #include <linux/slab.h> +#include <linux/mod_devicetable.h>  #include <linux/module.h>  #include <linux/platform_device.h>  #include <linux/mmc/host.h> @@ -39,22 +40,39 @@ struct sh_mobile_sdhi {  	struct tmio_mmc_dma dma_priv;  }; +static int sh_mobile_sdhi_clk_enable(struct platform_device *pdev, unsigned int *f) +{ +	struct mmc_host *mmc = dev_get_drvdata(&pdev->dev); +	struct tmio_mmc_host *host = mmc_priv(mmc); +	struct sh_mobile_sdhi *priv = container_of(host->pdata, struct sh_mobile_sdhi, mmc_data); +	int ret = clk_enable(priv->clk); +	if (ret < 0) +		return ret; + +	*f = clk_get_rate(priv->clk); +	return 0; +} + +static void sh_mobile_sdhi_clk_disable(struct platform_device *pdev) +{ +	struct mmc_host *mmc = dev_get_drvdata(&pdev->dev); +	struct tmio_mmc_host *host = mmc_priv(mmc); +	struct sh_mobile_sdhi *priv = container_of(host->pdata, struct sh_mobile_sdhi, mmc_data); +	clk_disable(priv->clk); +} +  static void sh_mobile_sdhi_set_pwr(struct platform_device *pdev, int state)  {  	struct sh_mobile_sdhi_info *p = pdev->dev.platform_data; -	if (p && p->set_pwr) -		p->set_pwr(pdev, state); +	p->set_pwr(pdev, state);  }  static int sh_mobile_sdhi_get_cd(struct platform_device *pdev)  {  	struct sh_mobile_sdhi_info *p = pdev->dev.platform_data; -	if (p && p->get_cd) -		return p->get_cd(pdev); -	else -		return -ENOSYS; +	return p->get_cd(pdev);  }  static int sh_mobile_sdhi_wait_idle(struct tmio_mmc_host *host) @@ -116,12 +134,14 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)  	}  	mmc_data = &priv->mmc_data; -	p->pdata = mmc_data; -	if (p->init) { -		ret = p->init(pdev, &sdhi_ops); -		if (ret) -			goto einit; +	if (p) { +		p->pdata = mmc_data; +		if (p->init) { +			ret = p->init(pdev, &sdhi_ops); +			if (ret) +				goto einit; +		}  	}  	snprintf(clk_name, sizeof(clk_name), "sdhi%d", pdev->id); @@ -132,9 +152,8 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)  		goto eclkget;  	} -	mmc_data->hclk = clk_get_rate(priv->clk); -	mmc_data->set_pwr = sh_mobile_sdhi_set_pwr; -	mmc_data->get_cd = sh_mobile_sdhi_get_cd; +	mmc_data->clk_enable = sh_mobile_sdhi_clk_enable; +	mmc_data->clk_disable = sh_mobile_sdhi_clk_disable;  	mmc_data->capabilities = MMC_CAP_MMC_HIGHSPEED;  	if (p) {  		mmc_data->flags = p->tmio_flags; @@ -142,7 +161,12 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)  			mmc_data->write16_hook = sh_mobile_sdhi_write16_hook;  		mmc_data->ocr_mask = p->tmio_ocr_mask;  		mmc_data->capabilities |= p->tmio_caps; +		mmc_data->capabilities2 |= p->tmio_caps2;  		mmc_data->cd_gpio = p->cd_gpio; +		if (p->set_pwr) +			mmc_data->set_pwr = sh_mobile_sdhi_set_pwr; +		if (p->get_cd) +			mmc_data->get_cd = sh_mobile_sdhi_get_cd;  		if (p->dma_slave_tx > 0 && p->dma_slave_rx > 0) {  			priv->param_tx.slave_id = p->dma_slave_tx; @@ -248,7 +272,7 @@ eirq_card_detect:  eprobe:  	clk_put(priv->clk);  eclkget: -	if (p->cleanup) +	if (p && p->cleanup)  		p->cleanup(pdev);  einit:  	kfree(priv); @@ -263,7 +287,8 @@ static int sh_mobile_sdhi_remove(struct platform_device *pdev)  	struct sh_mobile_sdhi_info *p = pdev->dev.platform_data;  	int i = 0, irq; -	p->pdata = NULL; +	if (p) +		p->pdata = NULL;  	tmio_mmc_host_remove(host); @@ -276,7 +301,7 @@ static int sh_mobile_sdhi_remove(struct platform_device *pdev)  	clk_put(priv->clk); -	if (p->cleanup) +	if (p && p->cleanup)  		p->cleanup(pdev);  	kfree(priv); @@ -291,11 +316,18 @@ static const struct dev_pm_ops tmio_mmc_dev_pm_ops = {  	.runtime_resume = tmio_mmc_host_runtime_resume,  }; +static const struct of_device_id sh_mobile_sdhi_of_match[] = { +	{ .compatible = "renesas,shmobile-sdhi" }, +	{ } +}; +MODULE_DEVICE_TABLE(of, sh_mobile_sdhi_of_match); +  static struct platform_driver sh_mobile_sdhi_driver = {  	.driver		= {  		.name	= "sh_mobile_sdhi",  		.owner	= THIS_MODULE,  		.pm	= &tmio_mmc_dev_pm_ops, +		.of_match_table = sh_mobile_sdhi_of_match,  	},  	.probe		= sh_mobile_sdhi_probe,  	.remove		= __devexit_p(sh_mobile_sdhi_remove), diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c index 9a7996ade58..0d8a9bbe30b 100644 --- a/drivers/mmc/host/tmio_mmc_pio.c +++ b/drivers/mmc/host/tmio_mmc_pio.c @@ -34,8 +34,9 @@  #include <linux/io.h>  #include <linux/irq.h>  #include <linux/mfd/tmio.h> -#include <linux/mmc/cd-gpio.h>  #include <linux/mmc/host.h> +#include <linux/mmc/mmc.h> +#include <linux/mmc/slot-gpio.h>  #include <linux/mmc/tmio.h>  #include <linux/module.h>  #include <linux/pagemap.h> @@ -305,8 +306,8 @@ static int tmio_mmc_start_command(struct tmio_mmc_host *host, struct mmc_command  	int c = cmd->opcode;  	u32 irq_mask = TMIO_MASK_CMD; -	/* Command 12 is handled by hardware */ -	if (cmd->opcode == 12 && !cmd->arg) { +	/* CMD12 is handled by hardware */ +	if (cmd->opcode == MMC_STOP_TRANSMISSION && !cmd->arg) {  		sd_ctrl_write16(host, CTL_STOP_INTERNAL_ACTION, 0x001);  		return 0;  	} @@ -449,7 +450,7 @@ void tmio_mmc_do_data_irq(struct tmio_mmc_host *host)  	}  	if (stop) { -		if (stop->opcode == 12 && !stop->arg) +		if (stop->opcode == MMC_STOP_TRANSMISSION && !stop->arg)  			sd_ctrl_write16(host, CTL_STOP_INTERNAL_ACTION, 0x000);  		else  			BUG(); @@ -751,6 +752,34 @@ fail:  	mmc_request_done(mmc, mrq);  } +static int tmio_mmc_clk_update(struct mmc_host *mmc) +{ +	struct tmio_mmc_host *host = mmc_priv(mmc); +	struct tmio_mmc_data *pdata = host->pdata; +	int ret; + +	if (!pdata->clk_enable) +		return -ENOTSUPP; + +	ret = pdata->clk_enable(host->pdev, &mmc->f_max); +	if (!ret) +		mmc->f_min = mmc->f_max / 512; + +	return ret; +} + +static void tmio_mmc_set_power(struct tmio_mmc_host *host, struct mmc_ios *ios) +{ +	struct mmc_host *mmc = host->mmc; + +	if (host->set_pwr) +		host->set_pwr(host->pdev, ios->power_mode != MMC_POWER_OFF); +	if (!IS_ERR(mmc->supply.vmmc)) +		/* Errors ignored... */ +		mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, +				      ios->power_mode ? ios->vdd : 0); +} +  /* Set MMC clock / power.   * Note: This controller uses a simple divider scheme therefore it cannot   * run a MMC card at full speed (20MHz). The max clock is 24MHz on SD, but as @@ -797,32 +826,37 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)  	 */  	if (ios->power_mode == MMC_POWER_ON && ios->clock) {  		if (!host->power) { +			tmio_mmc_clk_update(mmc);  			pm_runtime_get_sync(dev);  			host->power = true;  		}  		tmio_mmc_set_clock(host, ios->clock);  		/* power up SD bus */ -		if (host->set_pwr) -			host->set_pwr(host->pdev, 1); +		tmio_mmc_set_power(host, ios);  		/* start bus clock */  		tmio_mmc_clk_start(host);  	} else if (ios->power_mode != MMC_POWER_UP) { -		if (host->set_pwr && ios->power_mode == MMC_POWER_OFF) -			host->set_pwr(host->pdev, 0); +		if (ios->power_mode == MMC_POWER_OFF) +			tmio_mmc_set_power(host, ios);  		if (host->power) { +			struct tmio_mmc_data *pdata = host->pdata; +			tmio_mmc_clk_stop(host);  			host->power = false;  			pm_runtime_put(dev); +			if (pdata->clk_disable) +				pdata->clk_disable(host->pdev);  		} -		tmio_mmc_clk_stop(host);  	} -	switch (ios->bus_width) { -	case MMC_BUS_WIDTH_1: -		sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, 0x80e0); -	break; -	case MMC_BUS_WIDTH_4: -		sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, 0x00e0); -	break; +	if (host->power) { +		switch (ios->bus_width) { +		case MMC_BUS_WIDTH_1: +			sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, 0x80e0); +		break; +		case MMC_BUS_WIDTH_4: +			sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, 0x00e0); +		break; +		}  	}  	/* Let things settle. delay taken from winCE driver */ @@ -841,6 +875,9 @@ static int tmio_mmc_get_ro(struct mmc_host *mmc)  {  	struct tmio_mmc_host *host = mmc_priv(mmc);  	struct tmio_mmc_data *pdata = host->pdata; +	int ret = mmc_gpio_get_ro(mmc); +	if (ret >= 0) +		return ret;  	return !((pdata->flags & TMIO_MMC_WRPROTECT_DISABLE) ||  		 (sd_ctrl_read32(host, CTL_STATUS) & TMIO_STAT_WRPROTECT)); @@ -850,6 +887,9 @@ static int tmio_mmc_get_cd(struct mmc_host *mmc)  {  	struct tmio_mmc_host *host = mmc_priv(mmc);  	struct tmio_mmc_data *pdata = host->pdata; +	int ret = mmc_gpio_get_cd(mmc); +	if (ret >= 0) +		return ret;  	if (!pdata->get_cd)  		return -ENOSYS; @@ -865,6 +905,19 @@ static const struct mmc_host_ops tmio_mmc_ops = {  	.enable_sdio_irq = tmio_mmc_enable_sdio_irq,  }; +static void tmio_mmc_init_ocr(struct tmio_mmc_host *host) +{ +	struct tmio_mmc_data *pdata = host->pdata; +	struct mmc_host *mmc = host->mmc; + +	mmc_regulator_get_supply(mmc); + +	if (!mmc->ocr_avail) +		mmc->ocr_avail = pdata->ocr_mask ? : MMC_VDD_32_33 | MMC_VDD_33_34; +	else if (pdata->ocr_mask) +		dev_warn(mmc_dev(mmc), "Platform OCR mask is ignored\n"); +} +  int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,  				  struct platform_device *pdev,  				  struct tmio_mmc_data *pdata) @@ -904,18 +957,14 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,  	mmc->ops = &tmio_mmc_ops;  	mmc->caps = MMC_CAP_4_BIT_DATA | pdata->capabilities; -	mmc->f_max = pdata->hclk; -	mmc->f_min = mmc->f_max / 512; +	mmc->caps2 = pdata->capabilities2;  	mmc->max_segs = 32;  	mmc->max_blk_size = 512;  	mmc->max_blk_count = (PAGE_CACHE_SIZE / mmc->max_blk_size) *  		mmc->max_segs;  	mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;  	mmc->max_seg_size = mmc->max_req_size; -	if (pdata->ocr_mask) -		mmc->ocr_avail = pdata->ocr_mask; -	else -		mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; +	tmio_mmc_init_ocr(_host);  	_host->native_hotplug = !(pdata->flags & TMIO_MMC_USE_GPIO_CD ||  				  mmc->caps & MMC_CAP_NEEDS_POLL || @@ -927,6 +976,11 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,  	if (ret < 0)  		goto pm_disable; +	if (tmio_mmc_clk_update(mmc) < 0) { +		mmc->f_max = pdata->hclk; +		mmc->f_min = mmc->f_max / 512; +	} +  	/*  	 * There are 4 different scenarios for the card detection:  	 *  1) an external gpio irq handles the cd (best for power savings) @@ -937,7 +991,6 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,  	 *  While we increment the runtime PM counter for all scenarios when  	 *  the mmc core activates us by calling an appropriate set_ios(), we  	 *  must additionally ensure that in case 2) the tmio mmc hardware stays -	 *  additionally ensure that in case 2) the tmio mmc hardware stays  	 *  powered on during runtime for the card detection to work.  	 */  	if (_host->native_hotplug) @@ -948,6 +1001,17 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,  	_host->sdcard_irq_mask = sd_ctrl_read32(_host, CTL_IRQ_MASK);  	tmio_mmc_disable_mmc_irqs(_host, TMIO_MASK_ALL); + +	/* Unmask the IRQs we want to know about */ +	if (!_host->chan_rx) +		irq_mask |= TMIO_MASK_READOP; +	if (!_host->chan_tx) +		irq_mask |= TMIO_MASK_WRITEOP; +	if (!_host->native_hotplug) +		irq_mask &= ~(TMIO_STAT_CARD_REMOVE | TMIO_STAT_CARD_INSERT); + +	_host->sdcard_irq_mask &= ~irq_mask; +  	if (pdata->flags & TMIO_MMC_SDIO_IRQ)  		tmio_mmc_enable_sdio_irq(mmc, 0); @@ -961,22 +1025,18 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,  	/* See if we also get DMA */  	tmio_mmc_request_dma(_host, pdata); -	mmc_add_host(mmc); +	ret = mmc_add_host(mmc); +	if (pdata->clk_disable) +		pdata->clk_disable(pdev); +	if (ret < 0) { +		tmio_mmc_host_remove(_host); +		return ret; +	}  	dev_pm_qos_expose_latency_limit(&pdev->dev, 100); -	/* Unmask the IRQs we want to know about */ -	if (!_host->chan_rx) -		irq_mask |= TMIO_MASK_READOP; -	if (!_host->chan_tx) -		irq_mask |= TMIO_MASK_WRITEOP; -	if (!_host->native_hotplug) -		irq_mask &= ~(TMIO_STAT_CARD_REMOVE | TMIO_STAT_CARD_INSERT); - -	tmio_mmc_enable_mmc_irqs(_host, irq_mask); -  	if (pdata->flags & TMIO_MMC_USE_GPIO_CD) { -		ret = mmc_cd_gpio_request(mmc, pdata->cd_gpio); +		ret = mmc_gpio_request_cd(mmc, pdata->cd_gpio);  		if (ret < 0) {  			tmio_mmc_host_remove(_host);  			return ret; @@ -1008,7 +1068,7 @@ void tmio_mmc_host_remove(struct tmio_mmc_host *host)  		 * This means we can miss a card-eject, but this is anyway  		 * possible, because of delayed processing of hotplug events.  		 */ -		mmc_cd_gpio_free(mmc); +		mmc_gpio_free_cd(mmc);  	if (!host->native_hotplug)  		pm_runtime_get_sync(&pdev->dev);  |