diff options
| -rw-r--r-- | MAINTAINERS | 1 | ||||
| -rw-r--r-- | drivers/mmc/card/block.c | 11 | ||||
| -rw-r--r-- | drivers/mmc/core/mmc.c | 93 | ||||
| -rw-r--r-- | drivers/mmc/host/Kconfig | 1 | ||||
| -rw-r--r-- | drivers/mmc/host/mtk-sd.c | 2 | ||||
| -rw-r--r-- | drivers/mmc/host/pxamci.c | 2 | 
6 files changed, 75 insertions, 35 deletions
| diff --git a/MAINTAINERS b/MAINTAINERS index ea1751283b49..b16bffabe70a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9315,7 +9315,6 @@ F:	drivers/i2c/busses/i2c-designware-*  F:	include/linux/platform_data/i2c-designware.h  SYNOPSYS DESIGNWARE MMC/SD/SDIO DRIVER -M:	Seungwon Jeon <tgih.jun@samsung.com>  M:	Jaehoon Chung <jh80.chung@samsung.com>  L:	linux-mmc@vger.kernel.org  S:	Maintained diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 23b6c8e8701c..d8486168415a 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -65,8 +65,7 @@ MODULE_ALIAS("mmc:block");  #define MMC_SANITIZE_REQ_TIMEOUT 240000  #define MMC_EXTRACT_INDEX_FROM_ARG(x) ((x & 0x00FF0000) >> 16) -#define mmc_req_rel_wr(req)	(((req->cmd_flags & REQ_FUA) || \ -				  (req->cmd_flags & REQ_META)) && \ +#define mmc_req_rel_wr(req)	((req->cmd_flags & REQ_FUA) && \  				  (rq_data_dir(req) == WRITE))  #define PACKED_CMD_VER	0x01  #define PACKED_CMD_WR	0x02 @@ -1467,13 +1466,9 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq,  	/*  	 * Reliable writes are used to implement Forced Unit Access and -	 * REQ_META accesses, and are supported only on MMCs. -	 * -	 * XXX: this really needs a good explanation of why REQ_META -	 * is treated special. +	 * are supported only on MMCs.  	 */ -	bool do_rel_wr = ((req->cmd_flags & REQ_FUA) || -			  (req->cmd_flags & REQ_META)) && +	bool do_rel_wr = (req->cmd_flags & REQ_FUA) &&  		(rq_data_dir(req) == WRITE) &&  		(md->flags & MMC_BLK_REL_WR); diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index c793fda27321..3a9a79ec4343 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -1040,9 +1040,24 @@ static int mmc_select_hs_ddr(struct mmc_card *card)  	return err;  } +/* Caller must hold re-tuning */ +static int mmc_switch_status(struct mmc_card *card) +{ +	u32 status; +	int err; + +	err = mmc_send_status(card, &status); +	if (err) +		return err; + +	return mmc_switch_status_error(card->host, status); +} +  static int mmc_select_hs400(struct mmc_card *card)  {  	struct mmc_host *host = card->host; +	bool send_status = true; +	unsigned int max_dtr;  	int err = 0;  	u8 val; @@ -1053,25 +1068,36 @@ static int mmc_select_hs400(struct mmc_card *card)  	      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); +	if (host->caps & MMC_CAP_WAIT_WHILE_BUSY) +		send_status = false; +	/* Reduce frequency to HS frequency */ +	max_dtr = card->ext_csd.hs_max_dtr; +	mmc_set_clock(host, max_dtr); + +	/* Switch card to HS mode */  	val = EXT_CSD_TIMING_HS |  	      card->drive_strength << EXT_CSD_DRV_STR_SHIFT;  	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,  			   EXT_CSD_HS_TIMING, val,  			   card->ext_csd.generic_cmd6_time, -			   true, true, true); +			   true, send_status, true);  	if (err) {  		pr_err("%s: switch to high-speed from hs200 failed, err:%d\n",  			mmc_hostname(host), err);  		return err;  	} +	/* Set host controller to HS timing */ +	mmc_set_timing(card->host, MMC_TIMING_MMC_HS); + +	if (!send_status) { +		err = mmc_switch_status(card); +		if (err) +			goto out_err; +	} + +	/* Switch card to DDR */  	err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,  			 EXT_CSD_BUS_WIDTH,  			 EXT_CSD_DDR_BUS_WIDTH_8, @@ -1082,22 +1108,35 @@ static int mmc_select_hs400(struct mmc_card *card)  		return err;  	} +	/* Switch card to HS400 */  	val = EXT_CSD_TIMING_HS400 |  	      card->drive_strength << EXT_CSD_DRV_STR_SHIFT;  	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,  			   EXT_CSD_HS_TIMING, val,  			   card->ext_csd.generic_cmd6_time, -			   true, true, true); +			   true, send_status, true);  	if (err) {  		pr_err("%s: switch to hs400 failed, err:%d\n",  			 mmc_hostname(host), err);  		return err;  	} +	/* Set host controller to HS400 timing and frequency */  	mmc_set_timing(host, MMC_TIMING_MMC_HS400);  	mmc_set_bus_speed(card); +	if (!send_status) { +		err = mmc_switch_status(card); +		if (err) +			goto out_err; +	} +  	return 0; + +out_err: +	pr_err("%s: %s failed, error %d\n", mmc_hostname(card->host), +	       __func__, err); +	return err;  }  int mmc_hs200_to_hs400(struct mmc_card *card) @@ -1105,19 +1144,6 @@ int mmc_hs200_to_hs400(struct mmc_card *card)  	return mmc_select_hs400(card);  } -/* Caller must hold re-tuning */ -static int mmc_switch_status(struct mmc_card *card) -{ -	u32 status; -	int err; - -	err = mmc_send_status(card, &status); -	if (err) -		return err; - -	return mmc_switch_status_error(card->host, status); -} -  int mmc_hs400_to_hs200(struct mmc_card *card)  {  	struct mmc_host *host = card->host; @@ -1219,6 +1245,8 @@ static void mmc_select_driver_type(struct mmc_card *card)  static int mmc_select_hs200(struct mmc_card *card)  {  	struct mmc_host *host = card->host; +	bool send_status = true; +	unsigned int old_timing;  	int err = -EINVAL;  	u8 val; @@ -1234,6 +1262,9 @@ static int mmc_select_hs200(struct mmc_card *card)  	mmc_select_driver_type(card); +	if (host->caps & MMC_CAP_WAIT_WHILE_BUSY) +		send_status = false; +  	/*  	 * Set the bus width(4 or 8) with host's support and  	 * switch to HS200 mode if bus width is set successfully. @@ -1245,11 +1276,25 @@ static int mmc_select_hs200(struct mmc_card *card)  		err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,  				   EXT_CSD_HS_TIMING, val,  				   card->ext_csd.generic_cmd6_time, -				   true, true, true); -		if (!err) -			mmc_set_timing(host, MMC_TIMING_MMC_HS200); +				   true, send_status, true); +		if (err) +			goto err; +		old_timing = host->ios.timing; +		mmc_set_timing(host, MMC_TIMING_MMC_HS200); +		if (!send_status) { +			err = mmc_switch_status(card); +			/* +			 * mmc_select_timing() assumes timing has not changed if +			 * it is a switch error. +			 */ +			if (err == -EBADMSG) +				mmc_set_timing(host, old_timing); +		}  	}  err: +	if (err) +		pr_err("%s: %s failed, error %d\n", mmc_hostname(card->host), +		       __func__, err);  	return err;  } diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index af71de5fda3b..1dee533634c9 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -473,6 +473,7 @@ config MMC_DAVINCI  config MMC_GOLDFISH  	tristate "goldfish qemu Multimedia Card Interface support" +	depends on HAS_DMA  	depends on GOLDFISH || COMPILE_TEST  	help  	  This selects the Goldfish Multimedia card Interface emulation diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c index 39568cc29a2a..33dfd7e72516 100644 --- a/drivers/mmc/host/mtk-sd.c +++ b/drivers/mmc/host/mtk-sd.c @@ -1276,7 +1276,7 @@ static struct msdc_delay_phase get_best_delay(struct msdc_host *host, u32 delay)  	int start = 0, len = 0;  	int start_final = 0, len_final = 0;  	u8 final_phase = 0xff; -	struct msdc_delay_phase delay_phase; +	struct msdc_delay_phase delay_phase = { 0, };  	if (delay == 0) {  		dev_err(host->dev, "phase error: [map:%x]\n", delay); diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c index 8cadd74e8407..ce08896b9d69 100644 --- a/drivers/mmc/host/pxamci.c +++ b/drivers/mmc/host/pxamci.c @@ -805,7 +805,7 @@ static int pxamci_probe(struct platform_device *pdev)  		goto out;  	} else {  		mmc->caps |= host->pdata->gpio_card_ro_invert ? -			MMC_CAP2_RO_ACTIVE_HIGH : 0; +			0 : MMC_CAP2_RO_ACTIVE_HIGH;  	}  	if (gpio_is_valid(gpio_cd)) | 
