diff options
Diffstat (limited to 'drivers/mmc')
39 files changed, 1284 insertions, 488 deletions
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 2206d4477dbb..c3335112e68c 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -142,8 +142,6 @@ static inline void mmc_blk_clear_packed(struct mmc_queue_req *mqrq)  {  	struct mmc_packed *packed = mqrq->packed; -	BUG_ON(!packed); -  	mqrq->cmd_type = MMC_PACKED_NONE;  	packed->nr_entries = MMC_PACKED_NR_ZERO;  	packed->idx_failure = MMC_PACKED_NR_IDX; @@ -1443,8 +1441,6 @@ static int mmc_blk_packed_err_check(struct mmc_card *card,  	int err, check, status;  	u8 *ext_csd; -	BUG_ON(!packed); -  	packed->retries--;  	check = mmc_blk_err_check(card, areq);  	err = get_card_status(card, &status, 0); @@ -1673,6 +1669,18 @@ static u8 mmc_blk_prep_packed_list(struct mmc_queue *mq, struct request *req)  	u8 max_packed_rw = 0;  	u8 reqs = 0; +	/* +	 * We don't need to check packed for any further +	 * operation of packed stuff as we set MMC_PACKED_NONE +	 * and return zero for reqs if geting null packed. Also +	 * we clean the flag of MMC_BLK_PACKED_CMD to avoid doing +	 * it again when removing blk req. +	 */ +	if (!mqrq->packed) { +		md->flags &= (~MMC_BLK_PACKED_CMD); +		goto no_packed; +	} +  	if (!(md->flags & MMC_BLK_PACKED_CMD))  		goto no_packed; @@ -1782,8 +1790,6 @@ static void mmc_blk_packed_hdr_wrq_prep(struct mmc_queue_req *mqrq,  	u8 hdr_blocks;  	u8 i = 1; -	BUG_ON(!packed); -  	mqrq->cmd_type = MMC_PACKED_WRITE;  	packed->blocks = 0;  	packed->idx_failure = MMC_PACKED_NR_IDX; @@ -1887,8 +1893,6 @@ static int mmc_blk_end_packed_req(struct mmc_queue_req *mq_rq)  	int idx = packed->idx_failure, i = 0;  	int ret = 0; -	BUG_ON(!packed); -  	while (!list_empty(&packed->list)) {  		prq = list_entry_rq(packed->list.next);  		if (idx == i) { @@ -1917,8 +1921,6 @@ static void mmc_blk_abort_packed_req(struct mmc_queue_req *mq_rq)  	struct request *prq;  	struct mmc_packed *packed = mq_rq->packed; -	BUG_ON(!packed); -  	while (!list_empty(&packed->list)) {  		prq = list_entry_rq(packed->list.next);  		list_del_init(&prq->queuelist); @@ -1935,8 +1937,6 @@ static void mmc_blk_revert_packed_req(struct mmc_queue *mq,  	struct request_queue *q = mq->queue;  	struct mmc_packed *packed = mq_rq->packed; -	BUG_ON(!packed); -  	while (!list_empty(&packed->list)) {  		prq = list_entry_rq(packed->list.prev);  		if (prq->queuelist.prev != &packed->list) { @@ -2144,7 +2144,7 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)  	return 0;  } -static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) +int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)  {  	int ret;  	struct mmc_blk_data *md = mq->data; @@ -2265,7 +2265,6 @@ again:  	if (ret)  		goto err_putdisk; -	md->queue.issue_fn = mmc_blk_issue_rq;  	md->queue.data = md;  	md->disk->major	= MMC_BLOCK_MAJOR; @@ -2303,7 +2302,8 @@ again:  	set_capacity(md->disk, size);  	if (mmc_host_cmd23(card->host)) { -		if (mmc_card_mmc(card) || +		if ((mmc_card_mmc(card) && +		     card->csd.mmca_vsn >= CSD_SPEC_VER_3) ||  		    (mmc_card_sd(card) &&  		     card->scr.cmds & SD_SCR_CMD23_SUPPORT))  			md->flags |= MMC_BLK_CMD23; diff --git a/drivers/mmc/card/block.h b/drivers/mmc/card/block.h new file mode 100644 index 000000000000..cdabb2ee74be --- /dev/null +++ b/drivers/mmc/card/block.h @@ -0,0 +1 @@ +int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req); diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c index c032eef45762..5a8dc5a76e0d 100644 --- a/drivers/mmc/card/mmc_test.c +++ b/drivers/mmc/card/mmc_test.c @@ -184,6 +184,29 @@ static int mmc_test_set_blksize(struct mmc_test_card *test, unsigned size)  	return mmc_set_blocklen(test->card, size);  } +static bool mmc_test_card_cmd23(struct mmc_card *card) +{ +	return mmc_card_mmc(card) || +	       (mmc_card_sd(card) && card->scr.cmds & SD_SCR_CMD23_SUPPORT); +} + +static void mmc_test_prepare_sbc(struct mmc_test_card *test, +				 struct mmc_request *mrq, unsigned int blocks) +{ +	struct mmc_card *card = test->card; + +	if (!mrq->sbc || !mmc_host_cmd23(card->host) || +	    !mmc_test_card_cmd23(card) || !mmc_op_multi(mrq->cmd->opcode) || +	    (card->quirks & MMC_QUIRK_BLK_NO_CMD23)) { +		mrq->sbc = NULL; +		return; +	} + +	mrq->sbc->opcode = MMC_SET_BLOCK_COUNT; +	mrq->sbc->arg = blocks; +	mrq->sbc->flags = MMC_RSP_R1 | MMC_CMD_AC; +} +  /*   * Fill in the mmc_request structure given a set of transfer parameters.   */ @@ -221,6 +244,8 @@ static void mmc_test_prepare_mrq(struct mmc_test_card *test,  	mrq->data->sg = sg;  	mrq->data->sg_len = sg_len; +	mmc_test_prepare_sbc(test, mrq, blocks); +  	mmc_set_data_timeout(mrq->data, test->card);  } @@ -693,6 +718,8 @@ static int mmc_test_check_result(struct mmc_test_card *test,  	ret = 0; +	if (mrq->sbc && mrq->sbc->error) +		ret = mrq->sbc->error;  	if (!ret && mrq->cmd->error)  		ret = mrq->cmd->error;  	if (!ret && mrq->data->error) @@ -2278,6 +2305,245 @@ static int mmc_test_reset(struct mmc_test_card *test)  	return RESULT_FAIL;  } +struct mmc_test_req { +	struct mmc_request mrq; +	struct mmc_command sbc; +	struct mmc_command cmd; +	struct mmc_command stop; +	struct mmc_command status; +	struct mmc_data data; +}; + +static struct mmc_test_req *mmc_test_req_alloc(void) +{ +	struct mmc_test_req *rq = kzalloc(sizeof(*rq), GFP_KERNEL); + +	if (rq) { +		rq->mrq.cmd = &rq->cmd; +		rq->mrq.data = &rq->data; +		rq->mrq.stop = &rq->stop; +	} + +	return rq; +} + +static int mmc_test_send_status(struct mmc_test_card *test, +				struct mmc_command *cmd) +{ +	memset(cmd, 0, sizeof(*cmd)); + +	cmd->opcode = MMC_SEND_STATUS; +	if (!mmc_host_is_spi(test->card->host)) +		cmd->arg = test->card->rca << 16; +	cmd->flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC; + +	return mmc_wait_for_cmd(test->card->host, cmd, 0); +} + +static int mmc_test_ongoing_transfer(struct mmc_test_card *test, +				     unsigned int dev_addr, int use_sbc, +				     int repeat_cmd, int write, int use_areq) +{ +	struct mmc_test_req *rq = mmc_test_req_alloc(); +	struct mmc_host *host = test->card->host; +	struct mmc_test_area *t = &test->area; +	struct mmc_async_req areq; +	struct mmc_request *mrq; +	unsigned long timeout; +	bool expired = false; +	int ret = 0, cmd_ret; +	u32 status = 0; +	int count = 0; + +	if (!rq) +		return -ENOMEM; + +	mrq = &rq->mrq; +	if (use_sbc) +		mrq->sbc = &rq->sbc; +	mrq->cap_cmd_during_tfr = true; + +	areq.mrq = mrq; +	areq.err_check = mmc_test_check_result_async; + +	mmc_test_prepare_mrq(test, mrq, t->sg, t->sg_len, dev_addr, t->blocks, +			     512, write); + +	if (use_sbc && t->blocks > 1 && !mrq->sbc) { +		ret =  mmc_host_cmd23(host) ? +		       RESULT_UNSUP_CARD : +		       RESULT_UNSUP_HOST; +		goto out_free; +	} + +	/* Start ongoing data request */ +	if (use_areq) { +		mmc_start_req(host, &areq, &ret); +		if (ret) +			goto out_free; +	} else { +		mmc_wait_for_req(host, mrq); +	} + +	timeout = jiffies + msecs_to_jiffies(3000); +	do { +		count += 1; + +		/* Send status command while data transfer in progress */ +		cmd_ret = mmc_test_send_status(test, &rq->status); +		if (cmd_ret) +			break; + +		status = rq->status.resp[0]; +		if (status & R1_ERROR) { +			cmd_ret = -EIO; +			break; +		} + +		if (mmc_is_req_done(host, mrq)) +			break; + +		expired = time_after(jiffies, timeout); +		if (expired) { +			pr_info("%s: timeout waiting for Tran state status %#x\n", +				mmc_hostname(host), status); +			cmd_ret = -ETIMEDOUT; +			break; +		} +	} while (repeat_cmd && R1_CURRENT_STATE(status) != R1_STATE_TRAN); + +	/* Wait for data request to complete */ +	if (use_areq) +		mmc_start_req(host, NULL, &ret); +	else +		mmc_wait_for_req_done(test->card->host, mrq); + +	/* +	 * For cap_cmd_during_tfr request, upper layer must send stop if +	 * required. +	 */ +	if (mrq->data->stop && (mrq->data->error || !mrq->sbc)) { +		if (ret) +			mmc_wait_for_cmd(host, mrq->data->stop, 0); +		else +			ret = mmc_wait_for_cmd(host, mrq->data->stop, 0); +	} + +	if (ret) +		goto out_free; + +	if (cmd_ret) { +		pr_info("%s: Send Status failed: status %#x, error %d\n", +			mmc_hostname(test->card->host), status, cmd_ret); +	} + +	ret = mmc_test_check_result(test, mrq); +	if (ret) +		goto out_free; + +	ret = mmc_test_wait_busy(test); +	if (ret) +		goto out_free; + +	if (repeat_cmd && (t->blocks + 1) << 9 > t->max_tfr) +		pr_info("%s: %d commands completed during transfer of %u blocks\n", +			mmc_hostname(test->card->host), count, t->blocks); + +	if (cmd_ret) +		ret = cmd_ret; +out_free: +	kfree(rq); + +	return ret; +} + +static int __mmc_test_cmds_during_tfr(struct mmc_test_card *test, +				      unsigned long sz, int use_sbc, int write, +				      int use_areq) +{ +	struct mmc_test_area *t = &test->area; +	int ret; + +	if (!(test->card->host->caps & MMC_CAP_CMD_DURING_TFR)) +		return RESULT_UNSUP_HOST; + +	ret = mmc_test_area_map(test, sz, 0, 0); +	if (ret) +		return ret; + +	ret = mmc_test_ongoing_transfer(test, t->dev_addr, use_sbc, 0, write, +					use_areq); +	if (ret) +		return ret; + +	return mmc_test_ongoing_transfer(test, t->dev_addr, use_sbc, 1, write, +					 use_areq); +} + +static int mmc_test_cmds_during_tfr(struct mmc_test_card *test, int use_sbc, +				    int write, int use_areq) +{ +	struct mmc_test_area *t = &test->area; +	unsigned long sz; +	int ret; + +	for (sz = 512; sz <= t->max_tfr; sz += 512) { +		ret = __mmc_test_cmds_during_tfr(test, sz, use_sbc, write, +						 use_areq); +		if (ret) +			return ret; +	} +	return 0; +} + +/* + * Commands during read - no Set Block Count (CMD23). + */ +static int mmc_test_cmds_during_read(struct mmc_test_card *test) +{ +	return mmc_test_cmds_during_tfr(test, 0, 0, 0); +} + +/* + * Commands during write - no Set Block Count (CMD23). + */ +static int mmc_test_cmds_during_write(struct mmc_test_card *test) +{ +	return mmc_test_cmds_during_tfr(test, 0, 1, 0); +} + +/* + * Commands during read - use Set Block Count (CMD23). + */ +static int mmc_test_cmds_during_read_cmd23(struct mmc_test_card *test) +{ +	return mmc_test_cmds_during_tfr(test, 1, 0, 0); +} + +/* + * Commands during write - use Set Block Count (CMD23). + */ +static int mmc_test_cmds_during_write_cmd23(struct mmc_test_card *test) +{ +	return mmc_test_cmds_during_tfr(test, 1, 1, 0); +} + +/* + * Commands during non-blocking read - use Set Block Count (CMD23). + */ +static int mmc_test_cmds_during_read_cmd23_nonblock(struct mmc_test_card *test) +{ +	return mmc_test_cmds_during_tfr(test, 1, 0, 1); +} + +/* + * Commands during non-blocking write - use Set Block Count (CMD23). + */ +static int mmc_test_cmds_during_write_cmd23_nonblock(struct mmc_test_card *test) +{ +	return mmc_test_cmds_during_tfr(test, 1, 1, 1); +} +  static const struct mmc_test_case mmc_test_cases[] = {  	{  		.name = "Basic write (no data verification)", @@ -2605,6 +2871,48 @@ static const struct mmc_test_case mmc_test_cases[] = {  		.name = "Reset test",  		.run = mmc_test_reset,  	}, + +	{ +		.name = "Commands during read - no Set Block Count (CMD23)", +		.prepare = mmc_test_area_prepare, +		.run = mmc_test_cmds_during_read, +		.cleanup = mmc_test_area_cleanup, +	}, + +	{ +		.name = "Commands during write - no Set Block Count (CMD23)", +		.prepare = mmc_test_area_prepare, +		.run = mmc_test_cmds_during_write, +		.cleanup = mmc_test_area_cleanup, +	}, + +	{ +		.name = "Commands during read - use Set Block Count (CMD23)", +		.prepare = mmc_test_area_prepare, +		.run = mmc_test_cmds_during_read_cmd23, +		.cleanup = mmc_test_area_cleanup, +	}, + +	{ +		.name = "Commands during write - use Set Block Count (CMD23)", +		.prepare = mmc_test_area_prepare, +		.run = mmc_test_cmds_during_write_cmd23, +		.cleanup = mmc_test_area_cleanup, +	}, + +	{ +		.name = "Commands during non-blocking read - use Set Block Count (CMD23)", +		.prepare = mmc_test_area_prepare, +		.run = mmc_test_cmds_during_read_cmd23_nonblock, +		.cleanup = mmc_test_area_cleanup, +	}, + +	{ +		.name = "Commands during non-blocking write - use Set Block Count (CMD23)", +		.prepare = mmc_test_area_prepare, +		.run = mmc_test_cmds_during_write_cmd23_nonblock, +		.cleanup = mmc_test_area_cleanup, +	},  };  static DEFINE_MUTEX(mmc_test_lock); diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c index 708057261b38..8037f73a109a 100644 --- a/drivers/mmc/card/queue.c +++ b/drivers/mmc/card/queue.c @@ -19,7 +19,9 @@  #include <linux/mmc/card.h>  #include <linux/mmc/host.h> +  #include "queue.h" +#include "block.h"  #define MMC_QUEUE_BOUNCESZ	65536 @@ -68,7 +70,7 @@ static int mmc_queue_thread(void *d)  			bool req_is_special = mmc_req_is_special(req);  			set_current_state(TASK_RUNNING); -			mq->issue_fn(mq, req); +			mmc_blk_issue_rq(mq, req);  			cond_resched();  			if (mq->flags & MMC_QUEUE_NEW_REQUEST) {  				mq->flags &= ~MMC_QUEUE_NEW_REQUEST; diff --git a/drivers/mmc/card/queue.h b/drivers/mmc/card/queue.h index fee5e1271465..3c15a75bae86 100644 --- a/drivers/mmc/card/queue.h +++ b/drivers/mmc/card/queue.h @@ -57,8 +57,6 @@ struct mmc_queue {  	unsigned int		flags;  #define MMC_QUEUE_SUSPENDED	(1 << 0)  #define MMC_QUEUE_NEW_REQUEST	(1 << 1) - -	int			(*issue_fn)(struct mmc_queue *, struct request *);  	void			*data;  	struct request_queue	*queue;  	struct mmc_queue_req	mqrq[2]; diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index e55cde6d436d..2553d903a82b 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -58,6 +58,9 @@   */  #define MMC_BKOPS_MAX_TIMEOUT	(4 * 60 * 1000) /* max time to wait in ms */ +/* The max erase timeout, used when host->max_busy_timeout isn't specified */ +#define MMC_ERASE_TIMEOUT_MS	(60 * 1000) /* 60 s */ +  static const unsigned freqs[] = { 400000, 300000, 200000, 100000 };  /* @@ -117,6 +120,24 @@ static inline void mmc_should_fail_request(struct mmc_host *host,  #endif /* CONFIG_FAIL_MMC_REQUEST */ +static inline void mmc_complete_cmd(struct mmc_request *mrq) +{ +	if (mrq->cap_cmd_during_tfr && !completion_done(&mrq->cmd_completion)) +		complete_all(&mrq->cmd_completion); +} + +void mmc_command_done(struct mmc_host *host, struct mmc_request *mrq) +{ +	if (!mrq->cap_cmd_during_tfr) +		return; + +	mmc_complete_cmd(mrq); + +	pr_debug("%s: cmd done, tfr ongoing (CMD%u)\n", +		 mmc_hostname(host), mrq->cmd->opcode); +} +EXPORT_SYMBOL(mmc_command_done); +  /**   *	mmc_request_done - finish processing an MMC request   *	@host: MMC host which completed request @@ -143,6 +164,11 @@ void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq)  			cmd->retries = 0;  	} +	if (host->ongoing_mrq == mrq) +		host->ongoing_mrq = NULL; + +	mmc_complete_cmd(mrq); +  	trace_mmc_request_done(host, mrq);  	if (err && cmd->retries && !mmc_card_removed(host->card)) { @@ -155,7 +181,8 @@ void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq)  	} else {  		mmc_should_fail_request(host, mrq); -		led_trigger_event(host->led, LED_OFF); +		if (!host->ongoing_mrq) +			led_trigger_event(host->led, LED_OFF);  		if (mrq->sbc) {  			pr_debug("%s: req done <CMD%u>: %d: %08x %08x %08x %08x\n", @@ -220,6 +247,15 @@ static void __mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)  		}  	} +	if (mrq->cap_cmd_during_tfr) { +		host->ongoing_mrq = mrq; +		/* +		 * Retry path could come through here without having waiting on +		 * cmd_completion, so ensure it is reinitialised. +		 */ +		reinit_completion(&mrq->cmd_completion); +	} +  	trace_mmc_request_start(host, mrq);  	host->ops->request(host, mrq); @@ -386,6 +422,18 @@ static void mmc_wait_done(struct mmc_request *mrq)  	complete(&mrq->completion);  } +static inline void mmc_wait_ongoing_tfr_cmd(struct mmc_host *host) +{ +	struct mmc_request *ongoing_mrq = READ_ONCE(host->ongoing_mrq); + +	/* +	 * If there is an ongoing transfer, wait for the command line to become +	 * available. +	 */ +	if (ongoing_mrq && !completion_done(&ongoing_mrq->cmd_completion)) +		wait_for_completion(&ongoing_mrq->cmd_completion); +} +  /*   *__mmc_start_data_req() - starts data request   * @host: MMC host to start the request @@ -393,17 +441,24 @@ static void mmc_wait_done(struct mmc_request *mrq)   *   * Sets the done callback to be called when request is completed by the card.   * Starts data mmc request execution + * If an ongoing transfer is already in progress, wait for the command line + * to become available before sending another command.   */  static int __mmc_start_data_req(struct mmc_host *host, struct mmc_request *mrq)  {  	int err; +	mmc_wait_ongoing_tfr_cmd(host); +  	mrq->done = mmc_wait_data_done;  	mrq->host = host; +	init_completion(&mrq->cmd_completion); +  	err = mmc_start_request(host, mrq);  	if (err) {  		mrq->cmd->error = err; +		mmc_complete_cmd(mrq);  		mmc_wait_data_done(mrq);  	} @@ -414,12 +469,17 @@ static int __mmc_start_req(struct mmc_host *host, struct mmc_request *mrq)  {  	int err; +	mmc_wait_ongoing_tfr_cmd(host); +  	init_completion(&mrq->completion);  	mrq->done = mmc_wait_done; +	init_completion(&mrq->cmd_completion); +  	err = mmc_start_request(host, mrq);  	if (err) {  		mrq->cmd->error = err; +		mmc_complete_cmd(mrq);  		complete(&mrq->completion);  	} @@ -483,8 +543,7 @@ static int mmc_wait_for_data_req_done(struct mmc_host *host,  	return err;  } -static void mmc_wait_for_req_done(struct mmc_host *host, -				  struct mmc_request *mrq) +void mmc_wait_for_req_done(struct mmc_host *host, struct mmc_request *mrq)  {  	struct mmc_command *cmd; @@ -525,6 +584,28 @@ static void mmc_wait_for_req_done(struct mmc_host *host,  	mmc_retune_release(host);  } +EXPORT_SYMBOL(mmc_wait_for_req_done); + +/** + *	mmc_is_req_done - Determine if a 'cap_cmd_during_tfr' request is done + *	@host: MMC host + *	@mrq: MMC request + * + *	mmc_is_req_done() is used with requests that have + *	mrq->cap_cmd_during_tfr = true. mmc_is_req_done() must be called after + *	starting a request and before waiting for it to complete. That is, + *	either in between calls to mmc_start_req(), or after mmc_wait_for_req() + *	and before mmc_wait_for_req_done(). If it is called at other times the + *	result is not meaningful. + */ +bool mmc_is_req_done(struct mmc_host *host, struct mmc_request *mrq) +{ +	if (host->areq) +		return host->context_info.is_done_rcv; +	else +		return completion_done(&mrq->completion); +} +EXPORT_SYMBOL(mmc_is_req_done);  /**   *	mmc_pre_req - Prepare for a new request @@ -645,13 +726,18 @@ EXPORT_SYMBOL(mmc_start_req);   *	@mrq: MMC request to start   *   *	Start a new MMC custom command request for a host, and wait - *	for the command to complete. Does not attempt to parse the - *	response. + *	for the command to complete. In the case of 'cap_cmd_during_tfr' + *	requests, the transfer is ongoing and the caller can issue further + *	commands that do not use the data lines, and then wait by calling + *	mmc_wait_for_req_done(). + *	Does not attempt to parse the response.   */  void mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq)  {  	__mmc_start_req(host, mrq); -	mmc_wait_for_req_done(host, mrq); + +	if (!mrq->cap_cmd_during_tfr) +		mmc_wait_for_req_done(host, mrq);  }  EXPORT_SYMBOL(mmc_wait_for_req); @@ -2202,6 +2288,54 @@ out:  	return err;  } +static unsigned int mmc_align_erase_size(struct mmc_card *card, +					 unsigned int *from, +					 unsigned int *to, +					 unsigned int nr) +{ +	unsigned int from_new = *from, nr_new = nr, rem; + +	/* +	 * When the 'card->erase_size' is power of 2, we can use round_up/down() +	 * to align the erase size efficiently. +	 */ +	if (is_power_of_2(card->erase_size)) { +		unsigned int temp = from_new; + +		from_new = round_up(temp, card->erase_size); +		rem = from_new - temp; + +		if (nr_new > rem) +			nr_new -= rem; +		else +			return 0; + +		nr_new = round_down(nr_new, card->erase_size); +	} else { +		rem = from_new % card->erase_size; +		if (rem) { +			rem = card->erase_size - rem; +			from_new += rem; +			if (nr_new > rem) +				nr_new -= rem; +			else +				return 0; +		} + +		rem = nr_new % card->erase_size; +		if (rem) +			nr_new -= rem; +	} + +	if (nr_new == 0) +		return 0; + +	*to = from_new + nr_new; +	*from = from_new; + +	return nr_new; +} +  /**   * mmc_erase - erase sectors.   * @card: card to erase @@ -2240,26 +2374,12 @@ int mmc_erase(struct mmc_card *card, unsigned int from, unsigned int nr,  			return -EINVAL;  	} -	if (arg == MMC_ERASE_ARG) { -		rem = from % card->erase_size; -		if (rem) { -			rem = card->erase_size - rem; -			from += rem; -			if (nr > rem) -				nr -= rem; -			else -				return 0; -		} -		rem = nr % card->erase_size; -		if (rem) -			nr -= rem; -	} +	if (arg == MMC_ERASE_ARG) +		nr = mmc_align_erase_size(card, &from, &to, nr);  	if (nr == 0)  		return 0; -	to = from + nr; -  	if (to <= from)  		return -EINVAL; @@ -2352,6 +2472,8 @@ static unsigned int mmc_do_calc_max_discard(struct mmc_card *card,  	struct mmc_host *host = card->host;  	unsigned int max_discard, x, y, qty = 0, max_qty, min_qty, timeout;  	unsigned int last_timeout = 0; +	unsigned int max_busy_timeout = host->max_busy_timeout ? +			host->max_busy_timeout : MMC_ERASE_TIMEOUT_MS;  	if (card->erase_shift) {  		max_qty = UINT_MAX >> card->erase_shift; @@ -2374,15 +2496,15 @@ static unsigned int mmc_do_calc_max_discard(struct mmc_card *card,  	 * matter what size of 'host->max_busy_timeout', but if the  	 * 'host->max_busy_timeout' is large enough for more discard sectors,  	 * then we can continue to increase the max discard sectors until we -	 * get a balance value. +	 * get a balance value. In cases when the 'host->max_busy_timeout' +	 * isn't specified, use the default max erase timeout.  	 */  	do {  		y = 0;  		for (x = 1; x && x <= max_qty && max_qty - x >= qty; x <<= 1) {  			timeout = mmc_erase_timeout(card, arg, qty + x); -			if (qty + x > min_qty && -			    timeout > host->max_busy_timeout) +			if (qty + x > min_qty && timeout > max_busy_timeout)  				break;  			if (timeout < last_timeout) @@ -2427,9 +2549,6 @@ 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_busy_timeout) -		return UINT_MAX; -  	/*  	 * Without erase_group_def set, MMC erase timeout depends on clock  	 * frequence which can change.  In that case, the best choice is @@ -2447,7 +2566,8 @@ 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_busy_timeout); +		mmc_hostname(host), max_discard, host->max_busy_timeout ? +		host->max_busy_timeout : MMC_ERASE_TIMEOUT_MS);  	return max_discard;  }  EXPORT_SYMBOL(mmc_calc_max_discard); @@ -2456,7 +2576,8 @@ int mmc_set_blocklen(struct mmc_card *card, unsigned int blocklen)  {  	struct mmc_command cmd = {0}; -	if (mmc_card_blockaddr(card) || mmc_card_ddr52(card)) +	if (mmc_card_blockaddr(card) || mmc_card_ddr52(card) || +	    mmc_card_hs400(card) || mmc_card_hs400es(card))  		return 0;  	cmd.opcode = MMC_SET_BLOCKLEN; diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index f2d185cf8a8b..3486bc7fbb64 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -1029,6 +1029,10 @@ static int mmc_select_hs(struct mmc_card *card)  		err = mmc_switch_status(card);  	} +	if (err) +		pr_warn("%s: switch to high-speed failed, err:%d\n", +			mmc_hostname(card->host), err); +  	return err;  } @@ -1265,11 +1269,8 @@ static int mmc_select_hs400es(struct mmc_card *card)  	/* Switch card to HS mode */  	err = mmc_select_hs(card); -	if (err) { -		pr_err("%s: switch to high-speed failed, err:%d\n", -			mmc_hostname(host), err); +	if (err)  		goto out_err; -	}  	err = mmc_switch_status(card);  	if (err) diff --git a/drivers/mmc/core/pwrseq_simple.c b/drivers/mmc/core/pwrseq_simple.c index 450d907c6e6c..1304160de168 100644 --- a/drivers/mmc/core/pwrseq_simple.c +++ b/drivers/mmc/core/pwrseq_simple.c @@ -16,6 +16,8 @@  #include <linux/device.h>  #include <linux/err.h>  #include <linux/gpio/consumer.h> +#include <linux/delay.h> +#include <linux/property.h>  #include <linux/mmc/host.h> @@ -24,6 +26,7 @@  struct mmc_pwrseq_simple {  	struct mmc_pwrseq pwrseq;  	bool clk_enabled; +	u32 post_power_on_delay_ms;  	struct clk *ext_clk;  	struct gpio_descs *reset_gpios;  }; @@ -64,6 +67,9 @@ static void mmc_pwrseq_simple_post_power_on(struct mmc_host *host)  	struct mmc_pwrseq_simple *pwrseq = to_pwrseq_simple(host->pwrseq);  	mmc_pwrseq_simple_set_gpios_value(pwrseq, 0); + +	if (pwrseq->post_power_on_delay_ms) +		msleep(pwrseq->post_power_on_delay_ms);  }  static void mmc_pwrseq_simple_power_off(struct mmc_host *host) @@ -111,6 +117,9 @@ static int mmc_pwrseq_simple_probe(struct platform_device *pdev)  		return PTR_ERR(pwrseq->reset_gpios);  	} +	device_property_read_u32(dev, "post-power-on-delay-ms", +				 &pwrseq->post_power_on_delay_ms); +  	pwrseq->pwrseq.dev = dev;  	pwrseq->pwrseq.ops = &mmc_pwrseq_simple_ops;  	pwrseq->pwrseq.owner = THIS_MODULE; diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 0123936241b0..73c762a28dfe 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -223,8 +223,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; -	u32 *ssr; +	int i;  	if (!(card->csd.cmdclass & CCC_APP_SPEC)) {  		pr_warn("%s: card lacks mandatory SD Status function\n", @@ -232,33 +231,27 @@ static int mmc_read_ssr(struct mmc_card *card)  		return 0;  	} -	ssr = kmalloc(64, GFP_KERNEL); -	if (!ssr) -		return -ENOMEM; - -	err = mmc_app_sd_status(card, ssr); -	if (err) { +	if (mmc_app_sd_status(card, card->raw_ssr)) {  		pr_warn("%s: problem reading SD Status register\n",  			mmc_hostname(card->host)); -		err = 0; -		goto out; +		return 0;  	}  	for (i = 0; i < 16; i++) -		ssr[i] = be32_to_cpu(ssr[i]); +		card->raw_ssr[i] = be32_to_cpu(card->raw_ssr[i]);  	/*  	 * UNSTUFF_BITS only works with four u32s so we have to offset the  	 * bitfield positions accordingly.  	 */ -	au = UNSTUFF_BITS(ssr, 428 - 384, 4); +	au = UNSTUFF_BITS(card->raw_ssr, 428 - 384, 4);  	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); +			es = UNSTUFF_BITS(card->raw_ssr, 408 - 384, 16); +			et = UNSTUFF_BITS(card->raw_ssr, 402 - 384, 6);  			if (es && et) { -				eo = UNSTUFF_BITS(ssr, 400 - 384, 2); +				eo = UNSTUFF_BITS(card->raw_ssr, 400 - 384, 2);  				card->ssr.erase_timeout = (et * 1000) / es;  				card->ssr.erase_offset = eo * 1000;  			} @@ -267,9 +260,8 @@ static int mmc_read_ssr(struct mmc_card *card)  				mmc_hostname(card->host));  		}  	} -out: -	kfree(ssr); -	return err; + +	return 0;  }  /* @@ -666,6 +658,14 @@ MMC_DEV_ATTR(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1],  MMC_DEV_ATTR(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1],  	card->raw_csd[2], card->raw_csd[3]);  MMC_DEV_ATTR(scr, "%08x%08x\n", card->raw_scr[0], card->raw_scr[1]); +MMC_DEV_ATTR(ssr, +	"%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x\n", +		card->raw_ssr[0], card->raw_ssr[1], card->raw_ssr[2], +		card->raw_ssr[3], card->raw_ssr[4], card->raw_ssr[5], +		card->raw_ssr[6], card->raw_ssr[7], card->raw_ssr[8], +		card->raw_ssr[9], card->raw_ssr[10], card->raw_ssr[11], +		card->raw_ssr[12], card->raw_ssr[13], card->raw_ssr[14], +		card->raw_ssr[15]);  MMC_DEV_ATTR(date, "%02d/%04d\n", card->cid.month, card->cid.year);  MMC_DEV_ATTR(erase_size, "%u\n", card->erase_size << 9);  MMC_DEV_ATTR(preferred_erase_size, "%u\n", card->pref_erase << 9); @@ -698,6 +698,7 @@ static struct attribute *sd_std_attrs[] = {  	&dev_attr_cid.attr,  	&dev_attr_csd.attr,  	&dev_attr_scr.attr, +	&dev_attr_ssr.attr,  	&dev_attr_date.attr,  	&dev_attr_erase_size.attr,  	&dev_attr_preferred_erase_size.attr, diff --git a/drivers/mmc/core/sdio_io.c b/drivers/mmc/core/sdio_io.c index 78cb4d5d9d58..406e5f037e32 100644 --- a/drivers/mmc/core/sdio_io.c +++ b/drivers/mmc/core/sdio_io.c @@ -26,8 +26,8 @@   */  void sdio_claim_host(struct sdio_func *func)  { -	BUG_ON(!func); -	BUG_ON(!func->card); +	if (WARN_ON(!func)) +		return;  	mmc_claim_host(func->card->host);  } @@ -42,8 +42,8 @@ EXPORT_SYMBOL_GPL(sdio_claim_host);   */  void sdio_release_host(struct sdio_func *func)  { -	BUG_ON(!func); -	BUG_ON(!func->card); +	if (WARN_ON(!func)) +		return;  	mmc_release_host(func->card->host);  } @@ -62,8 +62,8 @@ int sdio_enable_func(struct sdio_func *func)  	unsigned char reg;  	unsigned long timeout; -	BUG_ON(!func); -	BUG_ON(!func->card); +	if (!func) +		return -EINVAL;  	pr_debug("SDIO: Enabling device %s...\n", sdio_func_id(func)); @@ -112,8 +112,8 @@ int sdio_disable_func(struct sdio_func *func)  	int ret;  	unsigned char reg; -	BUG_ON(!func); -	BUG_ON(!func->card); +	if (!func) +		return -EINVAL;  	pr_debug("SDIO: Disabling device %s...\n", sdio_func_id(func)); @@ -307,6 +307,9 @@ static int sdio_io_rw_ext_helper(struct sdio_func *func, int write,  	unsigned max_blocks;  	int ret; +	if (!func || (func->num > 7)) +		return -EINVAL; +  	/* Do the bulk of the transfer using block mode (if supported). */  	if (func->card->cccr.multi_block && (size > sdio_max_byte_size(func))) {  		/* Blocks per command is limited by host count, host transfer @@ -367,7 +370,10 @@ u8 sdio_readb(struct sdio_func *func, unsigned int addr, int *err_ret)  	int ret;  	u8 val; -	BUG_ON(!func); +	if (!func) { +		*err_ret = -EINVAL; +		return 0xFF; +	}  	if (err_ret)  		*err_ret = 0; @@ -398,7 +404,10 @@ void sdio_writeb(struct sdio_func *func, u8 b, unsigned int addr, int *err_ret)  {  	int ret; -	BUG_ON(!func); +	if (!func) { +		*err_ret = -EINVAL; +		return; +	}  	ret = mmc_io_rw_direct(func->card, 1, func->num, addr, b, NULL);  	if (err_ret) @@ -623,7 +632,10 @@ unsigned char sdio_f0_readb(struct sdio_func *func, unsigned int addr,  	int ret;  	unsigned char val; -	BUG_ON(!func); +	if (!func) { +		*err_ret = -EINVAL; +		return 0xFF; +	}  	if (err_ret)  		*err_ret = 0; @@ -658,7 +670,10 @@ void sdio_f0_writeb(struct sdio_func *func, unsigned char b, unsigned int addr,  {  	int ret; -	BUG_ON(!func); +	if (!func) { +		*err_ret = -EINVAL; +		return; +	}  	if ((addr < 0xF0 || addr > 0xFF) && (!mmc_card_lenient_fn0(func->card))) {  		if (err_ret) @@ -684,8 +699,8 @@ EXPORT_SYMBOL_GPL(sdio_f0_writeb);   */  mmc_pm_flag_t sdio_get_host_pm_caps(struct sdio_func *func)  { -	BUG_ON(!func); -	BUG_ON(!func->card); +	if (!func) +		return 0;  	return func->card->host->pm_caps;  } @@ -707,8 +722,8 @@ int sdio_set_host_pm_flags(struct sdio_func *func, mmc_pm_flag_t flags)  {  	struct mmc_host *host; -	BUG_ON(!func); -	BUG_ON(!func->card); +	if (!func) +		return -EINVAL;  	host = func->card->host; diff --git a/drivers/mmc/core/sdio_ops.c b/drivers/mmc/core/sdio_ops.c index 34f6e8015306..90fe5545c677 100644 --- a/drivers/mmc/core/sdio_ops.c +++ b/drivers/mmc/core/sdio_ops.c @@ -24,8 +24,6 @@ int mmc_send_io_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)  	struct mmc_command cmd = {0};  	int i, err = 0; -	BUG_ON(!host); -  	cmd.opcode = SD_IO_SEND_OP_COND;  	cmd.arg = ocr;  	cmd.flags = MMC_RSP_SPI_R4 | MMC_RSP_R4 | MMC_CMD_BCR; @@ -71,8 +69,8 @@ static int mmc_io_rw_direct_host(struct mmc_host *host, int write, unsigned fn,  	struct mmc_command cmd = {0};  	int err; -	BUG_ON(!host); -	BUG_ON(fn > 7); +	if (fn > 7) +		return -EINVAL;  	/* sanity check */  	if (addr & ~0x1FFFF) @@ -114,7 +112,6 @@ static int mmc_io_rw_direct_host(struct mmc_host *host, int write, unsigned fn,  int mmc_io_rw_direct(struct mmc_card *card, int write, unsigned fn,  	unsigned addr, u8 in, u8 *out)  { -	BUG_ON(!card);  	return mmc_io_rw_direct_host(card->host, write, fn, addr, in, out);  } @@ -129,8 +126,6 @@ int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn,  	unsigned int nents, left_size, i;  	unsigned int seg_size = card->host->max_seg_size; -	BUG_ON(!card); -	BUG_ON(fn > 7);  	WARN_ON(blksz == 0);  	/* sanity check */ diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c index a56373c75983..8fa478c3b0db 100644 --- a/drivers/mmc/host/davinci_mmc.c +++ b/drivers/mmc/host/davinci_mmc.c @@ -1216,9 +1216,11 @@ static int __init davinci_mmcsd_probe(struct platform_device *pdev)  	}  	r = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	irq = platform_get_irq(pdev, 0); -	if (!r || irq == NO_IRQ) +	if (!r)  		return -ENODEV; +	irq = platform_get_irq(pdev, 0); +	if (irq < 0) +		return irq;  	mem_size = resource_size(r);  	mem = devm_request_mem_region(&pdev->dev, r->start, mem_size, diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c index da0ef1765735..7ab3d749b5ae 100644 --- a/drivers/mmc/host/dw_mmc-exynos.c +++ b/drivers/mmc/host/dw_mmc-exynos.c @@ -225,8 +225,12 @@ static void dw_mci_exynos_config_hs400(struct dw_mci *host, u32 timing)  	 * Not supported to configure register  	 * related to HS400  	 */ -	if (priv->ctrl_type < DW_MCI_TYPE_EXYNOS5420) +	if (priv->ctrl_type < DW_MCI_TYPE_EXYNOS5420) { +		if (timing == MMC_TIMING_MMC_HS400) +			dev_warn(host->dev, +				 "cannot configure HS400, unsupported chipset\n");  		return; +	}  	dqs = priv->saved_dqs_en;  	strobe = priv->saved_strobe_ctrl; diff --git a/drivers/mmc/host/dw_mmc-k3.c b/drivers/mmc/host/dw_mmc-k3.c index 8e9d886bfcda..624789496dce 100644 --- a/drivers/mmc/host/dw_mmc-k3.c +++ b/drivers/mmc/host/dw_mmc-k3.c @@ -131,11 +131,17 @@ static void dw_mci_hi6220_set_ios(struct dw_mci *host, struct mmc_ios *ios)  	host->bus_hz = clk_get_rate(host->biu_clk);  } +static int dw_mci_hi6220_execute_tuning(struct dw_mci_slot *slot, u32 opcode) +{ +	return 0; +} +  static const struct dw_mci_drv_data hi6220_data = {  	.caps			= dw_mci_hi6220_caps,  	.switch_voltage		= dw_mci_hi6220_switch_voltage,  	.set_ios		= dw_mci_hi6220_set_ios,  	.parse_dt		= dw_mci_hi6220_parse_dt, +	.execute_tuning		= dw_mci_hi6220_execute_tuning,  };  static const struct of_device_id dw_mci_k3_match[] = { diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 32380d5d4f6b..4fcbc4012ed0 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -61,6 +61,8 @@  				 SDMMC_IDMAC_INT_FBE | SDMMC_IDMAC_INT_RI | \  				 SDMMC_IDMAC_INT_TI) +#define DESC_RING_BUF_SZ	PAGE_SIZE +  struct idmac_desc_64addr {  	u32		des0;	/* Control Descriptor */ @@ -467,136 +469,6 @@ static void dw_mci_dmac_complete_dma(void *arg)  	}  } -static void dw_mci_translate_sglist(struct dw_mci *host, struct mmc_data *data, -				    unsigned int sg_len) -{ -	unsigned int desc_len; -	int i; - -	if (host->dma_64bit_address == 1) { -		struct idmac_desc_64addr *desc_first, *desc_last, *desc; - -		desc_first = desc_last = desc = host->sg_cpu; - -		for (i = 0; i < sg_len; i++) { -			unsigned int length = sg_dma_len(&data->sg[i]); - -			u64 mem_addr = sg_dma_address(&data->sg[i]); - -			for ( ; length ; desc++) { -				desc_len = (length <= DW_MCI_DESC_DATA_LENGTH) ? -					   length : DW_MCI_DESC_DATA_LENGTH; - -				length -= desc_len; - -				/* -				 * Set the OWN bit and disable interrupts -				 * for this descriptor -				 */ -				desc->des0 = IDMAC_DES0_OWN | IDMAC_DES0_DIC | -							IDMAC_DES0_CH; - -				/* Buffer length */ -				IDMAC_64ADDR_SET_BUFFER1_SIZE(desc, desc_len); - -				/* Physical address to DMA to/from */ -				desc->des4 = mem_addr & 0xffffffff; -				desc->des5 = mem_addr >> 32; - -				/* Update physical address for the next desc */ -				mem_addr += desc_len; - -				/* Save pointer to the last descriptor */ -				desc_last = desc; -			} -		} - -		/* Set first descriptor */ -		desc_first->des0 |= IDMAC_DES0_FD; - -		/* Set last descriptor */ -		desc_last->des0 &= ~(IDMAC_DES0_CH | IDMAC_DES0_DIC); -		desc_last->des0 |= IDMAC_DES0_LD; - -	} else { -		struct idmac_desc *desc_first, *desc_last, *desc; - -		desc_first = desc_last = desc = host->sg_cpu; - -		for (i = 0; i < sg_len; i++) { -			unsigned int length = sg_dma_len(&data->sg[i]); - -			u32 mem_addr = sg_dma_address(&data->sg[i]); - -			for ( ; length ; desc++) { -				desc_len = (length <= DW_MCI_DESC_DATA_LENGTH) ? -					   length : DW_MCI_DESC_DATA_LENGTH; - -				length -= desc_len; - -				/* -				 * Set the OWN bit and disable interrupts -				 * for this descriptor -				 */ -				desc->des0 = cpu_to_le32(IDMAC_DES0_OWN | -							 IDMAC_DES0_DIC | -							 IDMAC_DES0_CH); - -				/* Buffer length */ -				IDMAC_SET_BUFFER1_SIZE(desc, desc_len); - -				/* Physical address to DMA to/from */ -				desc->des2 = cpu_to_le32(mem_addr); - -				/* Update physical address for the next desc */ -				mem_addr += desc_len; - -				/* Save pointer to the last descriptor */ -				desc_last = desc; -			} -		} - -		/* Set first descriptor */ -		desc_first->des0 |= cpu_to_le32(IDMAC_DES0_FD); - -		/* Set last descriptor */ -		desc_last->des0 &= cpu_to_le32(~(IDMAC_DES0_CH | -					       IDMAC_DES0_DIC)); -		desc_last->des0 |= cpu_to_le32(IDMAC_DES0_LD); -	} - -	wmb(); /* drain writebuffer */ -} - -static int dw_mci_idmac_start_dma(struct dw_mci *host, unsigned int sg_len) -{ -	u32 temp; - -	dw_mci_translate_sglist(host, host->data, sg_len); - -	/* Make sure to reset DMA in case we did PIO before this */ -	dw_mci_ctrl_reset(host, SDMMC_CTRL_DMA_RESET); -	dw_mci_idmac_reset(host); - -	/* Select IDMAC interface */ -	temp = mci_readl(host, CTRL); -	temp |= SDMMC_CTRL_USE_IDMAC; -	mci_writel(host, CTRL, temp); - -	/* drain writebuffer */ -	wmb(); - -	/* Enable the IDMAC */ -	temp = mci_readl(host, BMOD); -	temp |= SDMMC_IDMAC_ENABLE | SDMMC_IDMAC_FB; -	mci_writel(host, BMOD, temp); - -	/* Start it running */ -	mci_writel(host, PLDMND, 1); - -	return 0; -} -  static int dw_mci_idmac_init(struct dw_mci *host)  {  	int i; @@ -604,7 +476,8 @@ static int dw_mci_idmac_init(struct dw_mci *host)  	if (host->dma_64bit_address == 1) {  		struct idmac_desc_64addr *p;  		/* Number of descriptors in the ring buffer */ -		host->ring_size = PAGE_SIZE / sizeof(struct idmac_desc_64addr); +		host->ring_size = +			DESC_RING_BUF_SZ / sizeof(struct idmac_desc_64addr);  		/* Forward link the descriptor list */  		for (i = 0, p = host->sg_cpu; i < host->ring_size - 1; @@ -630,7 +503,8 @@ static int dw_mci_idmac_init(struct dw_mci *host)  	} else {  		struct idmac_desc *p;  		/* Number of descriptors in the ring buffer */ -		host->ring_size = PAGE_SIZE / sizeof(struct idmac_desc); +		host->ring_size = +			DESC_RING_BUF_SZ / sizeof(struct idmac_desc);  		/* Forward link the descriptor list */  		for (i = 0, p = host->sg_cpu; @@ -671,6 +545,195 @@ static int dw_mci_idmac_init(struct dw_mci *host)  	return 0;  } +static inline int dw_mci_prepare_desc64(struct dw_mci *host, +					 struct mmc_data *data, +					 unsigned int sg_len) +{ +	unsigned int desc_len; +	struct idmac_desc_64addr *desc_first, *desc_last, *desc; +	unsigned long timeout; +	int i; + +	desc_first = desc_last = desc = host->sg_cpu; + +	for (i = 0; i < sg_len; i++) { +		unsigned int length = sg_dma_len(&data->sg[i]); + +		u64 mem_addr = sg_dma_address(&data->sg[i]); + +		for ( ; length ; desc++) { +			desc_len = (length <= DW_MCI_DESC_DATA_LENGTH) ? +				   length : DW_MCI_DESC_DATA_LENGTH; + +			length -= desc_len; + +			/* +			 * Wait for the former clear OWN bit operation +			 * of IDMAC to make sure that this descriptor +			 * isn't still owned by IDMAC as IDMAC's write +			 * ops and CPU's read ops are asynchronous. +			 */ +			timeout = jiffies + msecs_to_jiffies(100); +			while (readl(&desc->des0) & IDMAC_DES0_OWN) { +				if (time_after(jiffies, timeout)) +					goto err_own_bit; +				udelay(10); +			} + +			/* +			 * Set the OWN bit and disable interrupts +			 * for this descriptor +			 */ +			desc->des0 = IDMAC_DES0_OWN | IDMAC_DES0_DIC | +						IDMAC_DES0_CH; + +			/* Buffer length */ +			IDMAC_64ADDR_SET_BUFFER1_SIZE(desc, desc_len); + +			/* Physical address to DMA to/from */ +			desc->des4 = mem_addr & 0xffffffff; +			desc->des5 = mem_addr >> 32; + +			/* Update physical address for the next desc */ +			mem_addr += desc_len; + +			/* Save pointer to the last descriptor */ +			desc_last = desc; +		} +	} + +	/* Set first descriptor */ +	desc_first->des0 |= IDMAC_DES0_FD; + +	/* Set last descriptor */ +	desc_last->des0 &= ~(IDMAC_DES0_CH | IDMAC_DES0_DIC); +	desc_last->des0 |= IDMAC_DES0_LD; + +	return 0; +err_own_bit: +	/* restore the descriptor chain as it's polluted */ +	dev_dbg(host->dev, "desciptor is still owned by IDMAC.\n"); +	memset(host->sg_cpu, 0, DESC_RING_BUF_SZ); +	dw_mci_idmac_init(host); +	return -EINVAL; +} + + +static inline int dw_mci_prepare_desc32(struct dw_mci *host, +					 struct mmc_data *data, +					 unsigned int sg_len) +{ +	unsigned int desc_len; +	struct idmac_desc *desc_first, *desc_last, *desc; +	unsigned long timeout; +	int i; + +	desc_first = desc_last = desc = host->sg_cpu; + +	for (i = 0; i < sg_len; i++) { +		unsigned int length = sg_dma_len(&data->sg[i]); + +		u32 mem_addr = sg_dma_address(&data->sg[i]); + +		for ( ; length ; desc++) { +			desc_len = (length <= DW_MCI_DESC_DATA_LENGTH) ? +				   length : DW_MCI_DESC_DATA_LENGTH; + +			length -= desc_len; + +			/* +			 * Wait for the former clear OWN bit operation +			 * of IDMAC to make sure that this descriptor +			 * isn't still owned by IDMAC as IDMAC's write +			 * ops and CPU's read ops are asynchronous. +			 */ +			timeout = jiffies + msecs_to_jiffies(100); +			while (readl(&desc->des0) & +			       cpu_to_le32(IDMAC_DES0_OWN)) { +				if (time_after(jiffies, timeout)) +					goto err_own_bit; +				udelay(10); +			} + +			/* +			 * Set the OWN bit and disable interrupts +			 * for this descriptor +			 */ +			desc->des0 = cpu_to_le32(IDMAC_DES0_OWN | +						 IDMAC_DES0_DIC | +						 IDMAC_DES0_CH); + +			/* Buffer length */ +			IDMAC_SET_BUFFER1_SIZE(desc, desc_len); + +			/* Physical address to DMA to/from */ +			desc->des2 = cpu_to_le32(mem_addr); + +			/* Update physical address for the next desc */ +			mem_addr += desc_len; + +			/* Save pointer to the last descriptor */ +			desc_last = desc; +		} +	} + +	/* Set first descriptor */ +	desc_first->des0 |= cpu_to_le32(IDMAC_DES0_FD); + +	/* Set last descriptor */ +	desc_last->des0 &= cpu_to_le32(~(IDMAC_DES0_CH | +				       IDMAC_DES0_DIC)); +	desc_last->des0 |= cpu_to_le32(IDMAC_DES0_LD); + +	return 0; +err_own_bit: +	/* restore the descriptor chain as it's polluted */ +	dev_dbg(host->dev, "desciptor is still owned by IDMAC.\n"); +	memset(host->sg_cpu, 0, DESC_RING_BUF_SZ); +	dw_mci_idmac_init(host); +	return -EINVAL; +} + +static int dw_mci_idmac_start_dma(struct dw_mci *host, unsigned int sg_len) +{ +	u32 temp; +	int ret; + +	if (host->dma_64bit_address == 1) +		ret = dw_mci_prepare_desc64(host, host->data, sg_len); +	else +		ret = dw_mci_prepare_desc32(host, host->data, sg_len); + +	if (ret) +		goto out; + +	/* drain writebuffer */ +	wmb(); + +	/* Make sure to reset DMA in case we did PIO before this */ +	dw_mci_ctrl_reset(host, SDMMC_CTRL_DMA_RESET); +	dw_mci_idmac_reset(host); + +	/* Select IDMAC interface */ +	temp = mci_readl(host, CTRL); +	temp |= SDMMC_CTRL_USE_IDMAC; +	mci_writel(host, CTRL, temp); + +	/* drain writebuffer */ +	wmb(); + +	/* Enable the IDMAC */ +	temp = mci_readl(host, BMOD); +	temp |= SDMMC_IDMAC_ENABLE | SDMMC_IDMAC_FB; +	mci_writel(host, BMOD, temp); + +	/* Start it running */ +	mci_writel(host, PLDMND, 1); + +out: +	return ret; +} +  static const struct dw_mci_dma_ops dw_mci_idmac_ops = {  	.init = dw_mci_idmac_init,  	.start = dw_mci_idmac_start_dma, @@ -876,11 +939,8 @@ static void dw_mci_adjust_fifoth(struct dw_mci *host, struct mmc_data *data)  	 * MSIZE is '1',  	 * if blksz is not a multiple of the FIFO width  	 */ -	if (blksz % fifo_width) { -		msize = 0; -		rx_wmark = 1; +	if (blksz % fifo_width)  		goto done; -	}  	do {  		if (!((blksz_depth % mszs[idx]) || @@ -998,8 +1058,10 @@ static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data)  	spin_unlock_irqrestore(&host->irq_lock, irqflags);  	if (host->dma_ops->start(host, sg_len)) { -		/* We can't do DMA */ -		dev_err(host->dev, "%s: failed to start DMA.\n", __func__); +		/* We can't do DMA, try PIO for this one */ +		dev_dbg(host->dev, +			"%s: fall back to PIO mode for current transfer\n", +			__func__);  		return -ENODEV;  	} @@ -1112,11 +1174,12 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot, bool force_clkinit)  		div = (host->bus_hz != clock) ? DIV_ROUND_UP(div, 2) : 0; -		dev_info(&slot->mmc->class_dev, -			 "Bus speed (slot %d) = %dHz (slot req %dHz, actual %dHZ div = %d)\n", -			 slot->id, host->bus_hz, clock, -			 div ? ((host->bus_hz / div) >> 1) : -			 host->bus_hz, div); +		if (clock != slot->__clk_old || force_clkinit) +			dev_info(&slot->mmc->class_dev, +				 "Bus speed (slot %d) = %dHz (slot req %dHz, actual %dHZ div = %d)\n", +				 slot->id, host->bus_hz, clock, +				 div ? ((host->bus_hz / div) >> 1) : +				 host->bus_hz, div);  		/* disable clock */  		mci_writel(host, CLKENA, 0); @@ -1139,6 +1202,9 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot, bool force_clkinit)  		/* inform CIU */  		mci_send_cmd(slot, sdmmc_cmd_bits, 0); + +		/* keep the last clock value that was requested from core */ +		slot->__clk_old = clock;  	}  	host->current_speed = clock; @@ -1691,11 +1757,11 @@ static int dw_mci_data_complete(struct dw_mci *host, struct mmc_data *data)  				data->error = -ETIMEDOUT;  			} else if (host->dir_status ==  					DW_MCI_RECV_STATUS) { -				data->error = -EIO; +				data->error = -EILSEQ;  			}  		} else {  			/* SDMMC_INT_SBE is included */ -			data->error = -EIO; +			data->error = -EILSEQ;  		}  		dev_dbg(host->dev, "data error, status 0x%08x\n", status); @@ -2523,47 +2589,6 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)  	return IRQ_HANDLED;  } -#ifdef CONFIG_OF -/* given a slot, find out the device node representing that slot */ -static struct device_node *dw_mci_of_find_slot_node(struct dw_mci_slot *slot) -{ -	struct device *dev = slot->mmc->parent; -	struct device_node *np; -	const __be32 *addr; -	int len; - -	if (!dev || !dev->of_node) -		return NULL; - -	for_each_child_of_node(dev->of_node, np) { -		addr = of_get_property(np, "reg", &len); -		if (!addr || (len < sizeof(int))) -			continue; -		if (be32_to_cpup(addr) == slot->id) -			return np; -	} -	return NULL; -} - -static void dw_mci_slot_of_parse(struct dw_mci_slot *slot) -{ -	struct device_node *np = dw_mci_of_find_slot_node(slot); - -	if (!np) -		return; - -	if (of_property_read_bool(np, "disable-wp")) { -		slot->mmc->caps2 |= MMC_CAP2_NO_WRITE_PROTECT; -		dev_warn(slot->mmc->parent, -			"Slot quirk 'disable-wp' is deprecated\n"); -	} -} -#else /* CONFIG_OF */ -static void dw_mci_slot_of_parse(struct dw_mci_slot *slot) -{ -} -#endif /* CONFIG_OF */ -  static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)  {  	struct mmc_host *mmc; @@ -2626,8 +2651,6 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)  	if (host->pdata->caps2)  		mmc->caps2 = host->pdata->caps2; -	dw_mci_slot_of_parse(slot); -  	ret = mmc_of_parse(mmc);  	if (ret)  		goto err_host_allocated; @@ -2732,7 +2755,8 @@ static void dw_mci_init_dma(struct dw_mci *host)  		}  		/* Alloc memory for sg translation */ -		host->sg_cpu = dmam_alloc_coherent(host->dev, PAGE_SIZE, +		host->sg_cpu = dmam_alloc_coherent(host->dev, +						   DESC_RING_BUF_SZ,  						   &host->sg_dma, GFP_KERNEL);  		if (!host->sg_cpu) {  			dev_err(host->dev, @@ -2915,6 +2939,13 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)  	if (!pdata)  		return ERR_PTR(-ENOMEM); +	/* find reset controller when exist */ +	pdata->rstc = devm_reset_control_get_optional(dev, NULL); +	if (IS_ERR(pdata->rstc)) { +		if (PTR_ERR(pdata->rstc) == -EPROBE_DEFER) +			return ERR_PTR(-EPROBE_DEFER); +	} +  	/* find out number of slots supported */  	of_property_read_u32(np, "num-slots", &pdata->num_slots); @@ -2933,11 +2964,6 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)  			return ERR_PTR(ret);  	} -	if (of_find_property(np, "supports-highspeed", NULL)) { -		dev_info(dev, "supports-highspeed property is deprecated.\n"); -		pdata->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED; -	} -  	return pdata;  } @@ -2986,7 +3012,9 @@ int dw_mci_probe(struct dw_mci *host)  	if (!host->pdata) {  		host->pdata = dw_mci_parse_dt(host); -		if (IS_ERR(host->pdata)) { +		if (PTR_ERR(host->pdata) == -EPROBE_DEFER) { +			return -EPROBE_DEFER; +		} else if (IS_ERR(host->pdata)) {  			dev_err(host->dev, "platform data not available\n");  			return -EINVAL;  		} @@ -3040,6 +3068,12 @@ int dw_mci_probe(struct dw_mci *host)  		}  	} +	if (!IS_ERR(host->pdata->rstc)) { +		reset_control_assert(host->pdata->rstc); +		usleep_range(10, 50); +		reset_control_deassert(host->pdata->rstc); +	} +  	setup_timer(&host->cmd11_timer,  		    dw_mci_cmd11_timer, (unsigned long)host); @@ -3189,13 +3223,14 @@ err_dmaunmap:  	if (host->use_dma && host->dma_ops->exit)  		host->dma_ops->exit(host); +	if (!IS_ERR(host->pdata->rstc)) +		reset_control_assert(host->pdata->rstc); +  err_clk_ciu: -	if (!IS_ERR(host->ciu_clk)) -		clk_disable_unprepare(host->ciu_clk); +	clk_disable_unprepare(host->ciu_clk);  err_clk_biu: -	if (!IS_ERR(host->biu_clk)) -		clk_disable_unprepare(host->biu_clk); +	clk_disable_unprepare(host->biu_clk);  	return ret;  } @@ -3221,11 +3256,11 @@ void dw_mci_remove(struct dw_mci *host)  	if (host->use_dma && host->dma_ops->exit)  		host->dma_ops->exit(host); -	if (!IS_ERR(host->ciu_clk)) -		clk_disable_unprepare(host->ciu_clk); +	if (!IS_ERR(host->pdata->rstc)) +		reset_control_assert(host->pdata->rstc); -	if (!IS_ERR(host->biu_clk)) -		clk_disable_unprepare(host->biu_clk); +	clk_disable_unprepare(host->ciu_clk); +	clk_disable_unprepare(host->biu_clk);  }  EXPORT_SYMBOL(dw_mci_remove); diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h index 9e740bc232a8..e8cd2dec3263 100644 --- a/drivers/mmc/host/dw_mmc.h +++ b/drivers/mmc/host/dw_mmc.h @@ -249,6 +249,8 @@ extern int dw_mci_resume(struct dw_mci *host);   * @queue_node: List node for placing this node in the @queue list of   *	&struct dw_mci.   * @clock: Clock rate configured by set_ios(). Protected by host->lock. + * @__clk_old: The last clock value that was requested from core. + *	Keeping track of this helps us to avoid spamming the console.   * @flags: Random state bits associated with the slot.   * @id: Number of this slot.   * @sdio_id: Number of this slot in the SDIO interrupt registers. @@ -263,6 +265,7 @@ struct dw_mci_slot {  	struct list_head	queue_node;  	unsigned int		clock; +	unsigned int		__clk_old;  	unsigned long		flags;  #define DW_MMC_CARD_PRESENT	0 diff --git a/drivers/mmc/host/moxart-mmc.c b/drivers/mmc/host/moxart-mmc.c index 79905ce895ad..bbad309679cf 100644 --- a/drivers/mmc/host/moxart-mmc.c +++ b/drivers/mmc/host/moxart-mmc.c @@ -257,7 +257,7 @@ static void moxart_dma_complete(void *param)  static void moxart_transfer_dma(struct mmc_data *data, struct moxart_host *host)  {  	u32 len, dir_data, dir_slave; -	unsigned long dma_time; +	long dma_time;  	struct dma_async_tx_descriptor *desc = NULL;  	struct dma_chan *dma_chan; @@ -397,7 +397,8 @@ static void moxart_prepare_data(struct moxart_host *host)  static void moxart_request(struct mmc_host *mmc, struct mmc_request *mrq)  {  	struct moxart_host *host = mmc_priv(mmc); -	unsigned long pio_time, flags; +	long pio_time; +	unsigned long flags;  	u32 status;  	spin_lock_irqsave(&host->lock, flags); diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c index f23d65eb070d..be3c49fa7382 100644 --- a/drivers/mmc/host/omap.c +++ b/drivers/mmc/host/omap.c @@ -1016,14 +1016,16 @@ mmc_omap_prepare_data(struct mmc_omap_host *host, struct mmc_request *req)  		/* Only reconfigure if we have a different burst size */  		if (*bp != burst) { -			struct dma_slave_config cfg; - -			cfg.src_addr = host->phys_base + OMAP_MMC_REG(host, DATA); -			cfg.dst_addr = host->phys_base + OMAP_MMC_REG(host, DATA); -			cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; -			cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; -			cfg.src_maxburst = burst; -			cfg.dst_maxburst = burst; +			struct dma_slave_config cfg = { +				.src_addr = host->phys_base + +					    OMAP_MMC_REG(host, DATA), +				.dst_addr = host->phys_base + +					    OMAP_MMC_REG(host, DATA), +				.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES, +				.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES, +				.src_maxburst = burst, +				.dst_maxburst = burst, +			};  			if (dmaengine_slave_config(c, &cfg))  				goto use_pio; diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 24ebc9a8de89..5f2f24a7360d 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -1409,11 +1409,18 @@ static int omap_hsmmc_pre_dma_transfer(struct omap_hsmmc_host *host,  static int omap_hsmmc_setup_dma_transfer(struct omap_hsmmc_host *host,  					struct mmc_request *req)  { -	struct dma_slave_config cfg;  	struct dma_async_tx_descriptor *tx;  	int ret = 0, i;  	struct mmc_data *data = req->data;  	struct dma_chan *chan; +	struct dma_slave_config cfg = { +		.src_addr = host->mapbase + OMAP_HSMMC_DATA, +		.dst_addr = host->mapbase + OMAP_HSMMC_DATA, +		.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES, +		.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES, +		.src_maxburst = data->blksz / 4, +		.dst_maxburst = data->blksz / 4, +	};  	/* Sanity check: all the SG entries must be aligned by block size. */  	for (i = 0; i < data->sg_len; i++) { @@ -1433,13 +1440,6 @@ static int omap_hsmmc_setup_dma_transfer(struct omap_hsmmc_host *host,  	chan = omap_hsmmc_get_dma_chan(host, data); -	cfg.src_addr = host->mapbase + OMAP_HSMMC_DATA; -	cfg.dst_addr = host->mapbase + OMAP_HSMMC_DATA; -	cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; -	cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; -	cfg.src_maxburst = data->blksz / 4; -	cfg.dst_maxburst = data->blksz / 4; -  	ret = dmaengine_slave_config(chan, &cfg);  	if (ret)  		return ret; diff --git a/drivers/mmc/host/rtsx_pci_sdmmc.c b/drivers/mmc/host/rtsx_pci_sdmmc.c index 396c9b7e4121..3ccaa1415f33 100644 --- a/drivers/mmc/host/rtsx_pci_sdmmc.c +++ b/drivers/mmc/host/rtsx_pci_sdmmc.c @@ -126,7 +126,7 @@ static int sd_response_type(struct mmc_command *cmd)  		return SD_RSP_TYPE_R0;  	case MMC_RSP_R1:  		return SD_RSP_TYPE_R1; -	case MMC_RSP_R1 & ~MMC_RSP_CRC: +	case MMC_RSP_R1_NO_CRC:  		return SD_RSP_TYPE_R1 | SD_NO_CHECK_CRC7;  	case MMC_RSP_R1B:  		return SD_RSP_TYPE_R1b; diff --git a/drivers/mmc/host/rtsx_usb_sdmmc.c b/drivers/mmc/host/rtsx_usb_sdmmc.c index 6c71fc9f76c7..4106295527b9 100644 --- a/drivers/mmc/host/rtsx_usb_sdmmc.c +++ b/drivers/mmc/host/rtsx_usb_sdmmc.c @@ -324,7 +324,7 @@ static void sd_send_cmd_get_rsp(struct rtsx_usb_sdmmc *host,  	case MMC_RSP_R1:  		rsp_type = SD_RSP_TYPE_R1;  		break; -	case MMC_RSP_R1 & ~MMC_RSP_CRC: +	case MMC_RSP_R1_NO_CRC:  		rsp_type = SD_RSP_TYPE_R1 | SD_NO_CHECK_CRC7;  		break;  	case MMC_RSP_R1B: diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c index 8fe0756c8e1e..81d4dc034793 100644 --- a/drivers/mmc/host/sdhci-acpi.c +++ b/drivers/mmc/host/sdhci-acpi.c @@ -275,7 +275,7 @@ static const struct sdhci_acpi_slot sdhci_acpi_slot_int_emmc = {  	.chip    = &sdhci_acpi_chip_int,  	.caps    = MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE |  		   MMC_CAP_HW_RESET | MMC_CAP_1_8V_DDR | -		   MMC_CAP_WAIT_WHILE_BUSY, +		   MMC_CAP_CMD_DURING_TFR | MMC_CAP_WAIT_WHILE_BUSY,  	.caps2   = MMC_CAP2_HC_ERASE_SZ,  	.flags   = SDHCI_ACPI_RUNTIME_PM,  	.quirks  = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, diff --git a/drivers/mmc/host/sdhci-bcm-kona.c b/drivers/mmc/host/sdhci-bcm-kona.c index e5c634bdfdd9..51dd2fd65000 100644 --- a/drivers/mmc/host/sdhci-bcm-kona.c +++ b/drivers/mmc/host/sdhci-bcm-kona.c @@ -253,12 +253,14 @@ static int sdhci_bcm_kona_probe(struct platform_device *pdev)  		goto err_pltfm_free;  	} -	if (clk_set_rate(pltfm_priv->clk, host->mmc->f_max) != 0) { +	ret = clk_set_rate(pltfm_priv->clk, host->mmc->f_max); +	if (ret) {  		dev_err(dev, "Failed to set rate core clock\n");  		goto err_pltfm_free;  	} -	if (clk_prepare_enable(pltfm_priv->clk) != 0) { +	ret = clk_prepare_enable(pltfm_priv->clk); +	if (ret) {  		dev_err(dev, "Failed to enable core clock\n");  		goto err_pltfm_free;  	} diff --git a/drivers/mmc/host/sdhci-brcmstb.c b/drivers/mmc/host/sdhci-brcmstb.c index cce10fe3e19e..159f6f64c68e 100644 --- a/drivers/mmc/host/sdhci-brcmstb.c +++ b/drivers/mmc/host/sdhci-brcmstb.c @@ -98,6 +98,8 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev)  	 * properties through mmc_of_parse().  	 */  	host->caps = sdhci_readl(host, SDHCI_CAPABILITIES); +	if (of_device_is_compatible(pdev->dev.of_node, "brcm,bcm7425-sdhci")) +		host->caps &= ~SDHCI_CAN_64BIT;  	host->caps1 = sdhci_readl(host, SDHCI_CAPABILITIES_1);  	host->caps1 &= ~(SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_SDR104 |  			SDHCI_SUPPORT_DDR50); @@ -121,6 +123,7 @@ err_clk:  static const struct of_device_id sdhci_brcm_of_match[] = {  	{ .compatible = "brcm,bcm7425-sdhci" }, +	{ .compatible = "brcm,bcm7445-sdhci" },  	{},  };  MODULE_DEVICE_TABLE(of, sdhci_brcm_of_match); @@ -128,7 +131,6 @@ MODULE_DEVICE_TABLE(of, sdhci_brcm_of_match);  static struct platform_driver sdhci_brcmstb_driver = {  	.driver		= {  		.name	= "sdhci-brcmstb", -		.owner	= THIS_MODULE,  		.pm	= &sdhci_brcmstb_pmops,  		.of_match_table = of_match_ptr(sdhci_brcm_of_match),  	}, diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index 99e0b334f9df..1f54fd8755c8 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -31,6 +31,7 @@  #include "sdhci-pltfm.h"  #include "sdhci-esdhc.h" +#define ESDHC_SYS_CTRL_DTOCV_MASK	0x0f  #define	ESDHC_CTRL_D3CD			0x08  #define ESDHC_BURST_LEN_EN_INCR		(1 << 27)  /* VENDOR SPEC register */ @@ -928,7 +929,8 @@ static unsigned int esdhc_get_max_timeout_count(struct sdhci_host *host)  	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);  	struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host); -	return esdhc_is_usdhc(imx_data) ? 1 << 28 : 1 << 27; +	/* Doc Errata: the uSDHC actual maximum timeout count is 1 << 29 */ +	return esdhc_is_usdhc(imx_data) ? 1 << 29 : 1 << 27;  }  static void esdhc_set_timeout(struct sdhci_host *host, struct mmc_command *cmd) @@ -937,7 +939,8 @@ static void esdhc_set_timeout(struct sdhci_host *host, struct mmc_command *cmd)  	struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host);  	/* use maximum timeout counter */ -	sdhci_writeb(host, esdhc_is_usdhc(imx_data) ? 0xF : 0xE, +	esdhc_clrset_le(host, ESDHC_SYS_CTRL_DTOCV_MASK, +			esdhc_is_usdhc(imx_data) ? 0xF : 0xE,  			SDHCI_TIMEOUT_CONTROL);  } diff --git a/drivers/mmc/host/sdhci-of-arasan.c b/drivers/mmc/host/sdhci-of-arasan.c index e0f193f7e3e5..da8e40af6f85 100644 --- a/drivers/mmc/host/sdhci-of-arasan.c +++ b/drivers/mmc/host/sdhci-of-arasan.c @@ -26,6 +26,7 @@  #include <linux/phy/phy.h>  #include <linux/regmap.h>  #include "sdhci-pltfm.h" +#include <linux/of.h>  #define SDHCI_ARASAN_CLK_CTRL_OFFSET	0x2c  #define SDHCI_ARASAN_VENDOR_REGISTER	0x78 @@ -35,6 +36,8 @@  #define CLK_CTRL_TIMEOUT_MASK		(0xf << CLK_CTRL_TIMEOUT_SHIFT)  #define CLK_CTRL_TIMEOUT_MIN_EXP	13 +#define PHY_CLK_TOO_SLOW_HZ		400000 +  /*   * On some SoCs the syscon area has a feature where the upper 16-bits of   * each 32-bit register act as a write mask for the lower 16-bits.  This allows @@ -65,10 +68,12 @@ struct sdhci_arasan_soc_ctl_field {   * accessible via the syscon API.   *   * @baseclkfreq:	Where to find corecfg_baseclkfreq + * @clockmultiplier:	Where to find corecfg_clockmultiplier   * @hiword_update:	If true, use HIWORD_UPDATE to access the syscon   */  struct sdhci_arasan_soc_ctl_map {  	struct sdhci_arasan_soc_ctl_field	baseclkfreq; +	struct sdhci_arasan_soc_ctl_field	clockmultiplier;  	bool					hiword_update;  }; @@ -77,6 +82,7 @@ struct sdhci_arasan_soc_ctl_map {   * @host:		Pointer to the main SDHCI host structure.   * @clk_ahb:		Pointer to the AHB clock   * @phy:		Pointer to the generic phy + * @is_phy_on:		True if the PHY is on; false if not.   * @sdcardclk_hw:	Struct for the clock we might provide to a PHY.   * @sdcardclk:		Pointer to normal 'struct clock' for sdcardclk_hw.   * @soc_ctl_base:	Pointer to regmap for syscon for soc_ctl registers. @@ -86,16 +92,22 @@ struct sdhci_arasan_data {  	struct sdhci_host *host;  	struct clk	*clk_ahb;  	struct phy	*phy; +	bool		is_phy_on;  	struct clk_hw	sdcardclk_hw;  	struct clk      *sdcardclk;  	struct regmap	*soc_ctl_base;  	const struct sdhci_arasan_soc_ctl_map *soc_ctl_map; +	unsigned int	quirks; /* Arasan deviations from spec */ + +/* Controller does not have CD wired and will not function normally without */ +#define SDHCI_ARASAN_QUIRK_FORCE_CDTEST	BIT(0)  };  static const struct sdhci_arasan_soc_ctl_map rk3399_soc_ctl_map = {  	.baseclkfreq = { .reg = 0xf000, .width = 8, .shift = 8 }, +	.clockmultiplier = { .reg = 0xf02c, .width = 8, .shift = 0},  	.hiword_update = true,  }; @@ -170,13 +182,47 @@ static void sdhci_arasan_set_clock(struct sdhci_host *host, unsigned int clock)  	struct sdhci_arasan_data *sdhci_arasan = sdhci_pltfm_priv(pltfm_host);  	bool ctrl_phy = false; -	if (clock > MMC_HIGH_52_MAX_DTR && (!IS_ERR(sdhci_arasan->phy))) -		ctrl_phy = true; +	if (!IS_ERR(sdhci_arasan->phy)) { +		if (!sdhci_arasan->is_phy_on && clock <= PHY_CLK_TOO_SLOW_HZ) { +			/* +			 * If PHY off, set clock to max speed and power PHY on. +			 * +			 * Although PHY docs apparently suggest power cycling +			 * when changing the clock the PHY doesn't like to be +			 * powered on while at low speeds like those used in ID +			 * mode.  Even worse is powering the PHY on while the +			 * clock is off. +			 * +			 * To workaround the PHY limitations, the best we can +			 * do is to power it on at a faster speed and then slam +			 * through low speeds without power cycling. +			 */ +			sdhci_set_clock(host, host->max_clk); +			spin_unlock_irq(&host->lock); +			phy_power_on(sdhci_arasan->phy); +			spin_lock_irq(&host->lock); +			sdhci_arasan->is_phy_on = true; + +			/* +			 * We'll now fall through to the below case with +			 * ctrl_phy = false (so we won't turn off/on).  The +			 * sdhci_set_clock() will set the real clock. +			 */ +		} else if (clock > PHY_CLK_TOO_SLOW_HZ) { +			/* +			 * At higher clock speeds the PHY is fine being power +			 * cycled and docs say you _should_ power cycle when +			 * changing clock speeds. +			 */ +			ctrl_phy = true; +		} +	} -	if (ctrl_phy) { +	if (ctrl_phy && sdhci_arasan->is_phy_on) {  		spin_unlock_irq(&host->lock);  		phy_power_off(sdhci_arasan->phy);  		spin_lock_irq(&host->lock); +		sdhci_arasan->is_phy_on = false;  	}  	sdhci_set_clock(host, clock); @@ -185,6 +231,7 @@ static void sdhci_arasan_set_clock(struct sdhci_host *host, unsigned int clock)  		spin_unlock_irq(&host->lock);  		phy_power_on(sdhci_arasan->phy);  		spin_lock_irq(&host->lock); +		sdhci_arasan->is_phy_on = true;  	}  } @@ -203,12 +250,27 @@ static void sdhci_arasan_hs400_enhanced_strobe(struct mmc_host *mmc,  	writel(vendor, host->ioaddr + SDHCI_ARASAN_VENDOR_REGISTER);  } +void sdhci_arasan_reset(struct sdhci_host *host, u8 mask) +{ +	u8 ctrl; +	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); +	struct sdhci_arasan_data *sdhci_arasan = sdhci_pltfm_priv(pltfm_host); + +	sdhci_reset(host, mask); + +	if (sdhci_arasan->quirks & SDHCI_ARASAN_QUIRK_FORCE_CDTEST) { +		ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); +		ctrl |= SDHCI_CTRL_CDTEST_INS | SDHCI_CTRL_CDTEST_EN; +		sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); +	} +} +  static struct sdhci_ops sdhci_arasan_ops = {  	.set_clock = sdhci_arasan_set_clock,  	.get_max_clock = sdhci_pltfm_clk_get_max_clock,  	.get_timeout_clock = sdhci_arasan_get_timeout_clock,  	.set_bus_width = sdhci_set_bus_width, -	.reset = sdhci_reset, +	.reset = sdhci_arasan_reset,  	.set_uhs_signaling = sdhci_set_uhs_signaling,  }; @@ -239,13 +301,14 @@ static int sdhci_arasan_suspend(struct device *dev)  	if (ret)  		return ret; -	if (!IS_ERR(sdhci_arasan->phy)) { +	if (!IS_ERR(sdhci_arasan->phy) && sdhci_arasan->is_phy_on) {  		ret = phy_power_off(sdhci_arasan->phy);  		if (ret) {  			dev_err(dev, "Cannot power off phy.\n");  			sdhci_resume_host(host);  			return ret;  		} +		sdhci_arasan->is_phy_on = false;  	}  	clk_disable(pltfm_host->clk); @@ -281,12 +344,13 @@ static int sdhci_arasan_resume(struct device *dev)  		return ret;  	} -	if (!IS_ERR(sdhci_arasan->phy)) { +	if (!IS_ERR(sdhci_arasan->phy) && host->mmc->actual_clock) {  		ret = phy_power_on(sdhci_arasan->phy);  		if (ret) {  			dev_err(dev, "Cannot power on phy.\n");  			return ret;  		} +		sdhci_arasan->is_phy_on = true;  	}  	return sdhci_resume_host(host); @@ -338,6 +402,45 @@ static const struct clk_ops arasan_sdcardclk_ops = {  };  /** + * sdhci_arasan_update_clockmultiplier - Set corecfg_clockmultiplier + * + * The corecfg_clockmultiplier is supposed to contain clock multiplier + * value of programmable clock generator. + * + * NOTES: + * - Many existing devices don't seem to do this and work fine.  To keep + *   compatibility for old hardware where the device tree doesn't provide a + *   register map, this function is a noop if a soc_ctl_map hasn't been provided + *   for this platform. + * - The value of corecfg_clockmultiplier should sync with that of corresponding + *   value reading from sdhci_capability_register. So this function is called + *   once at probe time and never called again. + * + * @host:		The sdhci_host + */ +static void sdhci_arasan_update_clockmultiplier(struct sdhci_host *host, +						u32 value) +{ +	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); +	struct sdhci_arasan_data *sdhci_arasan = sdhci_pltfm_priv(pltfm_host); +	const struct sdhci_arasan_soc_ctl_map *soc_ctl_map = +		sdhci_arasan->soc_ctl_map; + +	/* Having a map is optional */ +	if (!soc_ctl_map) +		return; + +	/* If we have a map, we expect to have a syscon */ +	if (!sdhci_arasan->soc_ctl_base) { +		pr_warn("%s: Have regmap, but no soc-ctl-syscon\n", +			mmc_hostname(host->mmc)); +		return; +	} + +	sdhci_arasan_syscon_write(host, &soc_ctl_map->clockmultiplier, value); +} + +/**   * sdhci_arasan_update_baseclkfreq - Set corecfg_baseclkfreq   *   * The corecfg_baseclkfreq is supposed to contain the MHz of clk_xin.  This @@ -462,6 +565,7 @@ static int sdhci_arasan_probe(struct platform_device *pdev)  	struct sdhci_host *host;  	struct sdhci_pltfm_host *pltfm_host;  	struct sdhci_arasan_data *sdhci_arasan; +	struct device_node *np = pdev->dev.of_node;  	host = sdhci_pltfm_init(pdev, &sdhci_arasan_pdata,  				sizeof(*sdhci_arasan)); @@ -516,8 +620,16 @@ static int sdhci_arasan_probe(struct platform_device *pdev)  	}  	sdhci_get_of_property(pdev); + +	if (of_property_read_bool(np, "xlnx,fails-without-test-cd")) +		sdhci_arasan->quirks |= SDHCI_ARASAN_QUIRK_FORCE_CDTEST; +  	pltfm_host->clk = clk_xin; +	if (of_device_is_compatible(pdev->dev.of_node, +				    "rockchip,rk3399-sdhci-5.1")) +		sdhci_arasan_update_clockmultiplier(host, 0x0); +  	sdhci_arasan_update_baseclkfreq(host);  	ret = sdhci_arasan_register_sdclk(sdhci_arasan, clk_xin, &pdev->dev); @@ -547,12 +659,6 @@ static int sdhci_arasan_probe(struct platform_device *pdev)  			goto unreg_clk;  		} -		ret = phy_power_on(sdhci_arasan->phy); -		if (ret < 0) { -			dev_err(&pdev->dev, "phy_power_on err.\n"); -			goto err_phy_power; -		} -  		host->mmc_host_ops.hs400_enhanced_strobe =  					sdhci_arasan_hs400_enhanced_strobe;  	} @@ -565,9 +671,6 @@ static int sdhci_arasan_probe(struct platform_device *pdev)  err_add_host:  	if (!IS_ERR(sdhci_arasan->phy)) -		phy_power_off(sdhci_arasan->phy); -err_phy_power: -	if (!IS_ERR(sdhci_arasan->phy))  		phy_exit(sdhci_arasan->phy);  unreg_clk:  	sdhci_arasan_unregister_sdclk(&pdev->dev); @@ -589,7 +692,8 @@ static int sdhci_arasan_remove(struct platform_device *pdev)  	struct clk *clk_ahb = sdhci_arasan->clk_ahb;  	if (!IS_ERR(sdhci_arasan->phy)) { -		phy_power_off(sdhci_arasan->phy); +		if (sdhci_arasan->is_phy_on) +			phy_power_off(sdhci_arasan->phy);  		phy_exit(sdhci_arasan->phy);  	} diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c index 239be2fde242..fb71c866eacc 100644 --- a/drivers/mmc/host/sdhci-of-esdhc.c +++ b/drivers/mmc/host/sdhci-of-esdhc.c @@ -583,7 +583,7 @@ static int sdhci_esdhc_probe(struct platform_device *pdev)  	np = pdev->dev.of_node; -	if (of_get_property(np, "little-endian", NULL)) +	if (of_property_read_bool(np, "little-endian"))  		host = sdhci_pltfm_init(pdev, &sdhci_esdhc_le_pdata,  					sizeof(struct sdhci_esdhc));  	else diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c index 897cfd24ca2e..72a1f1f5180a 100644 --- a/drivers/mmc/host/sdhci-pci-core.c +++ b/drivers/mmc/host/sdhci-pci-core.c @@ -156,7 +156,7 @@ static void sdhci_pci_add_own_cd(struct sdhci_pci_slot *slot)  	if (!gpio_is_valid(gpio))  		return; -	err = gpio_request(gpio, "sd_cd"); +	err = devm_gpio_request(&slot->chip->pdev->dev, gpio, "sd_cd");  	if (err < 0)  		goto out; @@ -179,7 +179,7 @@ static void sdhci_pci_add_own_cd(struct sdhci_pci_slot *slot)  	return;  out_free: -	gpio_free(gpio); +	devm_gpio_free(&slot->chip->pdev->dev, gpio);  out:  	dev_warn(&slot->chip->pdev->dev, "failed to setup card detect wake up\n");  } @@ -188,8 +188,6 @@ static void sdhci_pci_remove_own_cd(struct sdhci_pci_slot *slot)  {  	if (slot->cd_irq >= 0)  		free_irq(slot->cd_irq, slot); -	if (gpio_is_valid(slot->cd_gpio)) -		gpio_free(slot->cd_gpio);  }  #else @@ -356,6 +354,7 @@ static int byt_emmc_probe_slot(struct sdhci_pci_slot *slot)  {  	slot->host->mmc->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE |  				 MMC_CAP_HW_RESET | MMC_CAP_1_8V_DDR | +				 MMC_CAP_CMD_DURING_TFR |  				 MMC_CAP_WAIT_WHILE_BUSY;  	slot->host->mmc->caps2 |= MMC_CAP2_HC_ERASE_SZ;  	slot->hw_reset = sdhci_pci_int_hw_reset; @@ -421,17 +420,30 @@ static const struct sdhci_pci_fixes sdhci_intel_byt_sd = {  /* Define Host controllers for Intel Merrifield platform */  #define INTEL_MRFLD_EMMC_0	0  #define INTEL_MRFLD_EMMC_1	1 +#define INTEL_MRFLD_SD		2 +#define INTEL_MRFLD_SDIO	3  static int intel_mrfld_mmc_probe_slot(struct sdhci_pci_slot *slot)  { -	if ((PCI_FUNC(slot->chip->pdev->devfn) != INTEL_MRFLD_EMMC_0) && -	    (PCI_FUNC(slot->chip->pdev->devfn) != INTEL_MRFLD_EMMC_1)) -		/* SD support is not ready yet */ +	unsigned int func = PCI_FUNC(slot->chip->pdev->devfn); + +	switch (func) { +	case INTEL_MRFLD_EMMC_0: +	case INTEL_MRFLD_EMMC_1: +		slot->host->mmc->caps |= MMC_CAP_NONREMOVABLE | +					 MMC_CAP_8_BIT_DATA | +					 MMC_CAP_1_8V_DDR; +		break; +	case INTEL_MRFLD_SD: +		slot->host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V; +		break; +	case INTEL_MRFLD_SDIO: +		slot->host->mmc->caps |= MMC_CAP_NONREMOVABLE | +					 MMC_CAP_POWER_OFF_CARD; +		break; +	default:  		return -ENODEV; - -	slot->host->mmc->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE | -				 MMC_CAP_1_8V_DDR; - +	}  	return 0;  } @@ -1615,7 +1627,6 @@ static struct sdhci_pci_slot *sdhci_pci_probe_slot(  	slot->chip = chip;  	slot->host = host; -	slot->pci_bar = bar;  	slot->rst_n_gpio = -EINVAL;  	slot->cd_gpio = -EINVAL;  	slot->cd_idx = -1; @@ -1643,27 +1654,22 @@ static struct sdhci_pci_slot *sdhci_pci_probe_slot(  	host->irq = pdev->irq; -	ret = pci_request_region(pdev, bar, mmc_hostname(host->mmc)); +	ret = pcim_iomap_regions(pdev, BIT(bar), mmc_hostname(host->mmc));  	if (ret) {  		dev_err(&pdev->dev, "cannot request region\n");  		goto cleanup;  	} -	host->ioaddr = pci_ioremap_bar(pdev, bar); -	if (!host->ioaddr) { -		dev_err(&pdev->dev, "failed to remap registers\n"); -		ret = -ENOMEM; -		goto release; -	} +	host->ioaddr = pcim_iomap_table(pdev)[bar];  	if (chip->fixes && chip->fixes->probe_slot) {  		ret = chip->fixes->probe_slot(slot);  		if (ret) -			goto unmap; +			goto cleanup;  	}  	if (gpio_is_valid(slot->rst_n_gpio)) { -		if (!gpio_request(slot->rst_n_gpio, "eMMC_reset")) { +		if (!devm_gpio_request(&pdev->dev, slot->rst_n_gpio, "eMMC_reset")) {  			gpio_direction_output(slot->rst_n_gpio, 1);  			slot->host->mmc->caps |= MMC_CAP_HW_RESET;  			slot->hw_reset = sdhci_pci_gpio_hw_reset; @@ -1702,18 +1708,9 @@ static struct sdhci_pci_slot *sdhci_pci_probe_slot(  	return slot;  remove: -	if (gpio_is_valid(slot->rst_n_gpio)) -		gpio_free(slot->rst_n_gpio); -  	if (chip->fixes && chip->fixes->remove_slot)  		chip->fixes->remove_slot(slot, 0); -unmap: -	iounmap(host->ioaddr); - -release: -	pci_release_region(pdev, bar); -  cleanup:  	if (slot->data && slot->data->cleanup)  		slot->data->cleanup(slot->data); @@ -1738,17 +1735,12 @@ static void sdhci_pci_remove_slot(struct sdhci_pci_slot *slot)  	sdhci_remove_host(slot->host, dead); -	if (gpio_is_valid(slot->rst_n_gpio)) -		gpio_free(slot->rst_n_gpio); -  	if (slot->chip->fixes && slot->chip->fixes->remove_slot)  		slot->chip->fixes->remove_slot(slot, dead);  	if (slot->data && slot->data->cleanup)  		slot->data->cleanup(slot->data); -	pci_release_region(slot->chip->pdev, slot->pci_bar); -  	sdhci_free_host(slot->host);  } diff --git a/drivers/mmc/host/sdhci-pci.h b/drivers/mmc/host/sdhci-pci.h index 7e0788712e1a..9c7c08b93223 100644 --- a/drivers/mmc/host/sdhci-pci.h +++ b/drivers/mmc/host/sdhci-pci.h @@ -72,7 +72,6 @@ struct sdhci_pci_slot {  	struct sdhci_host	*host;  	struct sdhci_pci_data	*data; -	int			pci_bar;  	int			rst_n_gpio;  	int			cd_gpio;  	int			cd_irq; diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c index 1d17dcfc3ffb..ad49bfaf5bf8 100644 --- a/drivers/mmc/host/sdhci-pltfm.c +++ b/drivers/mmc/host/sdhci-pltfm.c @@ -156,13 +156,6 @@ struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev,  		host->quirks2 = pdata->quirks2;  	} -	/* -	 * Some platforms need to probe the controller to be able to -	 * determine which caps should be used. -	 */ -	if (host->ops && host->ops->platform_init) -		host->ops->platform_init(host); -  	platform_set_drvdata(pdev, host);  	return host; diff --git a/drivers/mmc/host/sdhci-st.c b/drivers/mmc/host/sdhci-st.c index c95ba83366a0..ed92ce729dde 100644 --- a/drivers/mmc/host/sdhci-st.c +++ b/drivers/mmc/host/sdhci-st.c @@ -28,6 +28,7 @@  struct st_mmc_platform_data {  	struct  reset_control *rstc; +	struct  clk *icnclk;  	void __iomem *top_ioaddr;  }; @@ -353,7 +354,7 @@ static int sdhci_st_probe(struct platform_device *pdev)  	struct sdhci_host *host;  	struct st_mmc_platform_data *pdata;  	struct sdhci_pltfm_host *pltfm_host; -	struct clk *clk; +	struct clk *clk, *icnclk;  	int ret = 0;  	u16 host_version;  	struct resource *res; @@ -365,6 +366,11 @@ static int sdhci_st_probe(struct platform_device *pdev)  		return PTR_ERR(clk);  	} +	/* ICN clock isn't compulsory, but use it if it's provided. */ +	icnclk = devm_clk_get(&pdev->dev, "icn"); +	if (IS_ERR(icnclk)) +		icnclk = NULL; +  	rstc = devm_reset_control_get(&pdev->dev, NULL);  	if (IS_ERR(rstc))  		rstc = NULL; @@ -389,6 +395,7 @@ static int sdhci_st_probe(struct platform_device *pdev)  	}  	clk_prepare_enable(clk); +	clk_prepare_enable(icnclk);  	/* Configure the FlashSS Top registers for setting eMMC TX/RX delay */  	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, @@ -400,6 +407,7 @@ static int sdhci_st_probe(struct platform_device *pdev)  	}  	pltfm_host->clk = clk; +	pdata->icnclk = icnclk;  	/* Configure the Arasan HC inside the flashSS */  	st_mmcss_cconfig(np, host); @@ -422,6 +430,7 @@ static int sdhci_st_probe(struct platform_device *pdev)  	return 0;  err_out: +	clk_disable_unprepare(icnclk);  	clk_disable_unprepare(clk);  err_of:  	sdhci_pltfm_free(pdev); @@ -442,6 +451,8 @@ static int sdhci_st_remove(struct platform_device *pdev)  	ret = sdhci_pltfm_unregister(pdev); +	clk_disable_unprepare(pdata->icnclk); +  	if (rstc)  		reset_control_assert(rstc); @@ -462,6 +473,7 @@ static int sdhci_st_suspend(struct device *dev)  	if (pdata->rstc)  		reset_control_assert(pdata->rstc); +	clk_disable_unprepare(pdata->icnclk);  	clk_disable_unprepare(pltfm_host->clk);  out:  	return ret; @@ -475,6 +487,7 @@ static int sdhci_st_resume(struct device *dev)  	struct device_node *np = dev->of_node;  	clk_prepare_enable(pltfm_host->clk); +	clk_prepare_enable(pdata->icnclk);  	if (pdata->rstc)  		reset_control_deassert(pdata->rstc); diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c index 1e93dc4e303e..20b6ff5b4af1 100644 --- a/drivers/mmc/host/sdhci-tegra.c +++ b/drivers/mmc/host/sdhci-tegra.c @@ -391,6 +391,31 @@ static const struct sdhci_tegra_soc_data soc_data_tegra114 = {  	.pdata = &sdhci_tegra114_pdata,  }; +static const struct sdhci_pltfm_data sdhci_tegra124_pdata = { +	.quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | +		  SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | +		  SDHCI_QUIRK_SINGLE_POWER_WRITE | +		  SDHCI_QUIRK_NO_HISPD_BIT | +		  SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC | +		  SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN, +	.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | +		   /* +		    * The TRM states that the SD/MMC controller found on +		    * Tegra124 can address 34 bits (the maximum supported by +		    * the Tegra memory controller), but tests show that DMA +		    * to or from above 4 GiB doesn't work. This is possibly +		    * caused by missing programming, though it's not obvious +		    * what sequence is required. Mark 64-bit DMA broken for +		    * now to fix this for existing users (e.g. Nyan boards). +		    */ +		   SDHCI_QUIRK2_BROKEN_64_BIT_DMA, +	.ops  = &tegra114_sdhci_ops, +}; + +static const struct sdhci_tegra_soc_data soc_data_tegra124 = { +	.pdata = &sdhci_tegra124_pdata, +}; +  static const struct sdhci_pltfm_data sdhci_tegra210_pdata = {  	.quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |  		  SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | @@ -408,7 +433,7 @@ static const struct sdhci_tegra_soc_data soc_data_tegra210 = {  static const struct of_device_id sdhci_tegra_dt_match[] = {  	{ .compatible = "nvidia,tegra210-sdhci", .data = &soc_data_tegra210 }, -	{ .compatible = "nvidia,tegra124-sdhci", .data = &soc_data_tegra114 }, +	{ .compatible = "nvidia,tegra124-sdhci", .data = &soc_data_tegra124 },  	{ .compatible = "nvidia,tegra114-sdhci", .data = &soc_data_tegra114 },  	{ .compatible = "nvidia,tegra30-sdhci", .data = &soc_data_tegra30 },  	{ .compatible = "nvidia,tegra20-sdhci", .data = &soc_data_tegra20 }, diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index cd65d474afa2..48055666c655 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -888,7 +888,8 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd)  static inline bool sdhci_auto_cmd12(struct sdhci_host *host,  				    struct mmc_request *mrq)  { -	return !mrq->sbc && (host->flags & SDHCI_AUTO_CMD12); +	return !mrq->sbc && (host->flags & SDHCI_AUTO_CMD12) && +	       !mrq->cap_cmd_during_tfr;  }  static void sdhci_set_transfer_mode(struct sdhci_host *host, @@ -1031,9 +1032,18 @@ static void sdhci_finish_data(struct sdhci_host *host)  			sdhci_do_reset(host, SDHCI_RESET_DATA);  		} -		/* Avoid triggering warning in sdhci_send_command() */ -		host->cmd = NULL; -		sdhci_send_command(host, data->stop); +		/* +		 * 'cap_cmd_during_tfr' request must not use the command line +		 * after mmc_command_done() has been called. It is upper layer's +		 * responsibility to send the stop command if required. +		 */ +		if (data->mrq->cap_cmd_during_tfr) { +			sdhci_finish_mrq(host, data->mrq); +		} else { +			/* Avoid triggering warning in sdhci_send_command() */ +			host->cmd = NULL; +			sdhci_send_command(host, data->stop); +		}  	} else {  		sdhci_finish_mrq(host, data->mrq);  	} @@ -1165,6 +1175,9 @@ static void sdhci_finish_command(struct sdhci_host *host)  		}  	} +	if (cmd->mrq->cap_cmd_during_tfr && cmd == cmd->mrq->cmd) +		mmc_command_done(host->mmc, cmd->mrq); +  	/*  	 * The host can send and interrupt when the busy state has  	 * ended, allowing us to wait without wasting CPU cycles. @@ -2062,7 +2075,7 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)  		spin_unlock_irqrestore(&host->lock, flags);  		/* Wait for Buffer Read Ready interrupt */ -		wait_event_interruptible_timeout(host->buf_ready_int, +		wait_event_timeout(host->buf_ready_int,  					(host->tuning_done == 1),  					msecs_to_jiffies(50));  		spin_lock_irqsave(&host->lock, flags); diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 0411c9f36461..c722cd23205c 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -84,6 +84,8 @@  #define   SDHCI_CTRL_ADMA32	0x10  #define   SDHCI_CTRL_ADMA64	0x18  #define   SDHCI_CTRL_8BITBUS	0x20 +#define  SDHCI_CTRL_CDTEST_INS	0x40 +#define  SDHCI_CTRL_CDTEST_EN	0x80  #define SDHCI_POWER_CONTROL	0x29  #define  SDHCI_POWER_ON		0x01 @@ -555,7 +557,6 @@ struct sdhci_ops {  	void	(*set_uhs_signaling)(struct sdhci_host *host, unsigned int uhs);  	void	(*hw_reset)(struct sdhci_host *host);  	void    (*adma_workaround)(struct sdhci_host *host, u32 intmask); -	void	(*platform_init)(struct sdhci_host *host);  	void    (*card_event)(struct sdhci_host *host);  	void	(*voltage_switch)(struct sdhci_host *host);  	int	(*select_drive_strength)(struct sdhci_host *host, diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c index c3b651bf89cb..49edff7fee49 100644 --- a/drivers/mmc/host/sh_mobile_sdhi.c +++ b/drivers/mmc/host/sh_mobile_sdhi.c @@ -94,6 +94,7 @@ static const struct of_device_id sh_mobile_sdhi_of_match[] = {  	{ .compatible = "renesas,sdhi-r8a7793", .data = &of_rcar_gen2_compatible, },  	{ .compatible = "renesas,sdhi-r8a7794", .data = &of_rcar_gen2_compatible, },  	{ .compatible = "renesas,sdhi-r8a7795", .data = &of_rcar_gen3_compatible, }, +	{ .compatible = "renesas,sdhi-r8a7796", .data = &of_rcar_gen3_compatible, },  	{},  };  MODULE_DEVICE_TABLE(of, sh_mobile_sdhi_of_match); @@ -213,6 +214,13 @@ static void sh_mobile_sdhi_clk_disable(struct tmio_mmc_host *host)  	clk_disable_unprepare(priv->clk);  } +static int sh_mobile_sdhi_card_busy(struct mmc_host *mmc) +{ +	struct tmio_mmc_host *host = mmc_priv(mmc); + +	return !(sd_ctrl_read16_and_16_as_32(host, CTL_STATUS) & TMIO_STAT_DAT0); +} +  static int sh_mobile_sdhi_start_signal_voltage_switch(struct mmc_host *mmc,  						      struct mmc_ios *ios)  { @@ -369,7 +377,14 @@ static int sh_mobile_sdhi_probe(struct platform_device *pdev)  	host->clk_update	= sh_mobile_sdhi_clk_update;  	host->clk_disable	= sh_mobile_sdhi_clk_disable;  	host->multi_io_quirk	= sh_mobile_sdhi_multi_io_quirk; -	host->start_signal_voltage_switch = sh_mobile_sdhi_start_signal_voltage_switch; + +	/* SDR speeds are only available on Gen2+ */ +	if (mmc_data->flags & TMIO_MMC_MIN_RCAR2) { +		/* card_busy caused issues on r8a73a4 (pre-Gen2) CD-less SDHI */ +		host->card_busy	= sh_mobile_sdhi_card_busy; +		host->start_signal_voltage_switch = +			sh_mobile_sdhi_start_signal_voltage_switch; +	}  	/* Orginally registers were 16 bit apart, could be 32 or 64 nowadays */  	if (!host->bus_shift && resource_size(res) > 0x100) /* old way to determine the shift */ diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c index 2ee4c21ec55e..c0a5c676d0e8 100644 --- a/drivers/mmc/host/sunxi-mmc.c +++ b/drivers/mmc/host/sunxi-mmc.c @@ -72,6 +72,13 @@  #define SDXC_REG_CHDA	(0x90)  #define SDXC_REG_CBDA	(0x94) +/* New registers introduced in A64 */ +#define SDXC_REG_A12A		0x058 /* SMC Auto Command 12 Register */ +#define SDXC_REG_SD_NTSR	0x05C /* SMC New Timing Set Register */ +#define SDXC_REG_DRV_DL		0x140 /* Drive Delay Control Register */ +#define SDXC_REG_SAMP_DL_REG	0x144 /* SMC sample delay control */ +#define SDXC_REG_DS_DL_REG	0x148 /* SMC data strobe delay control */ +  #define mmc_readl(host, reg) \  	readl((host)->reg_base + SDXC_##reg)  #define mmc_writel(host, reg, value) \ @@ -217,21 +224,41 @@  #define SDXC_CLK_50M_DDR	3  #define SDXC_CLK_50M_DDR_8BIT	4 +#define SDXC_2X_TIMING_MODE	BIT(31) + +#define SDXC_CAL_START		BIT(15) +#define SDXC_CAL_DONE		BIT(14) +#define SDXC_CAL_DL_SHIFT	8 +#define SDXC_CAL_DL_SW_EN	BIT(7) +#define SDXC_CAL_DL_SW_SHIFT	0 +#define SDXC_CAL_DL_MASK	0x3f + +#define SDXC_CAL_TIMEOUT	3	/* in seconds, 3s is enough*/ +  struct sunxi_mmc_clk_delay {  	u32 output;  	u32 sample;  };  struct sunxi_idma_des { -	u32	config; -	u32	buf_size; -	u32	buf_addr_ptr1; -	u32	buf_addr_ptr2; +	__le32 config; +	__le32 buf_size; +	__le32 buf_addr_ptr1; +	__le32 buf_addr_ptr2; +}; + +struct sunxi_mmc_cfg { +	u32 idma_des_size_bits; +	const struct sunxi_mmc_clk_delay *clk_delays; + +	/* does the IP block support autocalibration? */ +	bool can_calibrate;  };  struct sunxi_mmc_host {  	struct mmc_host	*mmc;  	struct reset_control *reset; +	const struct sunxi_mmc_cfg *cfg;  	/* IO mapping base */  	void __iomem	*reg_base; @@ -241,7 +268,6 @@ struct sunxi_mmc_host {  	struct clk	*clk_mmc;  	struct clk	*clk_sample;  	struct clk	*clk_output; -	const struct sunxi_mmc_clk_delay *clk_delays;  	/* irq */  	spinlock_t	lock; @@ -250,7 +276,6 @@ struct sunxi_mmc_host {  	u32		sdio_imask;  	/* dma */ -	u32		idma_des_size_bits;  	dma_addr_t	sg_dma;  	void		*sg_cpu;  	bool		wait_dma; @@ -322,25 +347,28 @@ static void sunxi_mmc_init_idma_des(struct sunxi_mmc_host *host,  {  	struct sunxi_idma_des *pdes = (struct sunxi_idma_des *)host->sg_cpu;  	dma_addr_t next_desc = host->sg_dma; -	int i, max_len = (1 << host->idma_des_size_bits); +	int i, max_len = (1 << host->cfg->idma_des_size_bits);  	for (i = 0; i < data->sg_len; i++) { -		pdes[i].config = SDXC_IDMAC_DES0_CH | SDXC_IDMAC_DES0_OWN | -				 SDXC_IDMAC_DES0_DIC; +		pdes[i].config = cpu_to_le32(SDXC_IDMAC_DES0_CH | +					     SDXC_IDMAC_DES0_OWN | +					     SDXC_IDMAC_DES0_DIC);  		if (data->sg[i].length == max_len)  			pdes[i].buf_size = 0; /* 0 == max_len */  		else -			pdes[i].buf_size = data->sg[i].length; +			pdes[i].buf_size = cpu_to_le32(data->sg[i].length);  		next_desc += sizeof(struct sunxi_idma_des); -		pdes[i].buf_addr_ptr1 = sg_dma_address(&data->sg[i]); -		pdes[i].buf_addr_ptr2 = (u32)next_desc; +		pdes[i].buf_addr_ptr1 = +			cpu_to_le32(sg_dma_address(&data->sg[i])); +		pdes[i].buf_addr_ptr2 = cpu_to_le32((u32)next_desc);  	} -	pdes[0].config |= SDXC_IDMAC_DES0_FD; -	pdes[i - 1].config |= SDXC_IDMAC_DES0_LD | SDXC_IDMAC_DES0_ER; -	pdes[i - 1].config &= ~SDXC_IDMAC_DES0_DIC; +	pdes[0].config |= cpu_to_le32(SDXC_IDMAC_DES0_FD); +	pdes[i - 1].config |= cpu_to_le32(SDXC_IDMAC_DES0_LD | +					  SDXC_IDMAC_DES0_ER); +	pdes[i - 1].config &= cpu_to_le32(~SDXC_IDMAC_DES0_DIC);  	pdes[i - 1].buf_addr_ptr2 = 0;  	/* @@ -653,11 +681,84 @@ static int sunxi_mmc_oclk_onoff(struct sunxi_mmc_host *host, u32 oclk_en)  	return 0;  } +static int sunxi_mmc_calibrate(struct sunxi_mmc_host *host, int reg_off) +{ +	u32 reg = readl(host->reg_base + reg_off); +	u32 delay; +	unsigned long timeout; + +	if (!host->cfg->can_calibrate) +		return 0; + +	reg &= ~(SDXC_CAL_DL_MASK << SDXC_CAL_DL_SW_SHIFT); +	reg &= ~SDXC_CAL_DL_SW_EN; + +	writel(reg | SDXC_CAL_START, host->reg_base + reg_off); + +	dev_dbg(mmc_dev(host->mmc), "calibration started\n"); + +	timeout = jiffies + HZ * SDXC_CAL_TIMEOUT; + +	while (!((reg = readl(host->reg_base + reg_off)) & SDXC_CAL_DONE)) { +		if (time_before(jiffies, timeout)) +			cpu_relax(); +		else { +			reg &= ~SDXC_CAL_START; +			writel(reg, host->reg_base + reg_off); + +			return -ETIMEDOUT; +		} +	} + +	delay = (reg >> SDXC_CAL_DL_SHIFT) & SDXC_CAL_DL_MASK; + +	reg &= ~SDXC_CAL_START; +	reg |= (delay << SDXC_CAL_DL_SW_SHIFT) | SDXC_CAL_DL_SW_EN; + +	writel(reg, host->reg_base + reg_off); + +	dev_dbg(mmc_dev(host->mmc), "calibration ended, reg is 0x%x\n", reg); + +	return 0; +} + +static int sunxi_mmc_clk_set_phase(struct sunxi_mmc_host *host, +				   struct mmc_ios *ios, u32 rate) +{ +	int index; + +	if (!host->cfg->clk_delays) +		return 0; + +	/* determine delays */ +	if (rate <= 400000) { +		index = SDXC_CLK_400K; +	} else if (rate <= 25000000) { +		index = SDXC_CLK_25M; +	} else if (rate <= 52000000) { +		if (ios->timing != MMC_TIMING_UHS_DDR50 && +		    ios->timing != MMC_TIMING_MMC_DDR52) { +			index = SDXC_CLK_50M; +		} else if (ios->bus_width == MMC_BUS_WIDTH_8) { +			index = SDXC_CLK_50M_DDR_8BIT; +		} else { +			index = SDXC_CLK_50M_DDR; +		} +	} else { +		return -EINVAL; +	} + +	clk_set_phase(host->clk_sample, host->cfg->clk_delays[index].sample); +	clk_set_phase(host->clk_output, host->cfg->clk_delays[index].output); + +	return 0; +} +  static int sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *host,  				  struct mmc_ios *ios)  { -	u32 rate, oclk_dly, rval, sclk_dly; -	u32 clock = ios->clock; +	long rate; +	u32 rval, clock = ios->clock;  	int ret;  	/* 8 bit DDR requires a higher module clock */ @@ -666,13 +767,18 @@ static int sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *host,  		clock <<= 1;  	rate = clk_round_rate(host->clk_mmc, clock); -	dev_dbg(mmc_dev(host->mmc), "setting clk to %d, rounded %d\n", +	if (rate < 0) { +		dev_err(mmc_dev(host->mmc), "error rounding clk to %d: %ld\n", +			clock, rate); +		return rate; +	} +	dev_dbg(mmc_dev(host->mmc), "setting clk to %d, rounded %ld\n",  		clock, rate);  	/* setting clock rate */  	ret = clk_set_rate(host->clk_mmc, rate);  	if (ret) { -		dev_err(mmc_dev(host->mmc), "error setting clk to %d: %d\n", +		dev_err(mmc_dev(host->mmc), "error setting clk to %ld: %d\n",  			rate, ret);  		return ret;  	} @@ -692,31 +798,15 @@ static int sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *host,  	}  	mmc_writel(host, REG_CLKCR, rval); -	/* determine delays */ -	if (rate <= 400000) { -		oclk_dly = host->clk_delays[SDXC_CLK_400K].output; -		sclk_dly = host->clk_delays[SDXC_CLK_400K].sample; -	} else if (rate <= 25000000) { -		oclk_dly = host->clk_delays[SDXC_CLK_25M].output; -		sclk_dly = host->clk_delays[SDXC_CLK_25M].sample; -	} else if (rate <= 52000000) { -		if (ios->timing != MMC_TIMING_UHS_DDR50 && -		    ios->timing != MMC_TIMING_MMC_DDR52) { -			oclk_dly = host->clk_delays[SDXC_CLK_50M].output; -			sclk_dly = host->clk_delays[SDXC_CLK_50M].sample; -		} else if (ios->bus_width == MMC_BUS_WIDTH_8) { -			oclk_dly = host->clk_delays[SDXC_CLK_50M_DDR_8BIT].output; -			sclk_dly = host->clk_delays[SDXC_CLK_50M_DDR_8BIT].sample; -		} else { -			oclk_dly = host->clk_delays[SDXC_CLK_50M_DDR].output; -			sclk_dly = host->clk_delays[SDXC_CLK_50M_DDR].sample; -		} -	} else { -		return -EINVAL; -	} +	ret = sunxi_mmc_clk_set_phase(host, ios, rate); +	if (ret) +		return ret; + +	ret = sunxi_mmc_calibrate(host, SDXC_REG_SAMP_DL_REG); +	if (ret) +		return ret; -	clk_set_phase(host->clk_sample, sclk_dly); -	clk_set_phase(host->clk_output, oclk_dly); +	/* TODO: enable calibrate on sdc2 SDXC_REG_DS_DL_REG of A64 */  	return sunxi_mmc_oclk_onoff(host, 1);  } @@ -938,14 +1028,6 @@ static int sunxi_mmc_card_busy(struct mmc_host *mmc)  	return !!(mmc_readl(host, REG_STAS) & SDXC_CARD_DATA_BUSY);  } -static const struct of_device_id sunxi_mmc_of_match[] = { -	{ .compatible = "allwinner,sun4i-a10-mmc", }, -	{ .compatible = "allwinner,sun5i-a13-mmc", }, -	{ .compatible = "allwinner,sun9i-a80-mmc", }, -	{ /* sentinel */ } -}; -MODULE_DEVICE_TABLE(of, sunxi_mmc_of_match); -  static struct mmc_host_ops sunxi_mmc_ops = {  	.request	 = sunxi_mmc_request,  	.set_ios	 = sunxi_mmc_set_ios, @@ -974,21 +1056,54 @@ static const struct sunxi_mmc_clk_delay sun9i_mmc_clk_delays[] = {  	[SDXC_CLK_50M_DDR_8BIT]	= { .output =  72, .sample =  72 },  }; +static const struct sunxi_mmc_cfg sun4i_a10_cfg = { +	.idma_des_size_bits = 13, +	.clk_delays = NULL, +	.can_calibrate = false, +}; + +static const struct sunxi_mmc_cfg sun5i_a13_cfg = { +	.idma_des_size_bits = 16, +	.clk_delays = NULL, +	.can_calibrate = false, +}; + +static const struct sunxi_mmc_cfg sun7i_a20_cfg = { +	.idma_des_size_bits = 16, +	.clk_delays = sunxi_mmc_clk_delays, +	.can_calibrate = false, +}; + +static const struct sunxi_mmc_cfg sun9i_a80_cfg = { +	.idma_des_size_bits = 16, +	.clk_delays = sun9i_mmc_clk_delays, +	.can_calibrate = false, +}; + +static const struct sunxi_mmc_cfg sun50i_a64_cfg = { +	.idma_des_size_bits = 16, +	.clk_delays = NULL, +	.can_calibrate = true, +}; + +static const struct of_device_id sunxi_mmc_of_match[] = { +	{ .compatible = "allwinner,sun4i-a10-mmc", .data = &sun4i_a10_cfg }, +	{ .compatible = "allwinner,sun5i-a13-mmc", .data = &sun5i_a13_cfg }, +	{ .compatible = "allwinner,sun7i-a20-mmc", .data = &sun7i_a20_cfg }, +	{ .compatible = "allwinner,sun9i-a80-mmc", .data = &sun9i_a80_cfg }, +	{ .compatible = "allwinner,sun50i-a64-mmc", .data = &sun50i_a64_cfg }, +	{ /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, sunxi_mmc_of_match); +  static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host,  				      struct platform_device *pdev)  { -	struct device_node *np = pdev->dev.of_node;  	int ret; -	if (of_device_is_compatible(np, "allwinner,sun4i-a10-mmc")) -		host->idma_des_size_bits = 13; -	else -		host->idma_des_size_bits = 16; - -	if (of_device_is_compatible(np, "allwinner,sun9i-a80-mmc")) -		host->clk_delays = sun9i_mmc_clk_delays; -	else -		host->clk_delays = sunxi_mmc_clk_delays; +	host->cfg = of_device_get_match_data(&pdev->dev); +	if (!host->cfg) +		return -EINVAL;  	ret = mmc_regulator_get_supply(host->mmc);  	if (ret) { @@ -1014,16 +1129,18 @@ static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host,  		return PTR_ERR(host->clk_mmc);  	} -	host->clk_output = devm_clk_get(&pdev->dev, "output"); -	if (IS_ERR(host->clk_output)) { -		dev_err(&pdev->dev, "Could not get output clock\n"); -		return PTR_ERR(host->clk_output); -	} +	if (host->cfg->clk_delays) { +		host->clk_output = devm_clk_get(&pdev->dev, "output"); +		if (IS_ERR(host->clk_output)) { +			dev_err(&pdev->dev, "Could not get output clock\n"); +			return PTR_ERR(host->clk_output); +		} -	host->clk_sample = devm_clk_get(&pdev->dev, "sample"); -	if (IS_ERR(host->clk_sample)) { -		dev_err(&pdev->dev, "Could not get sample clock\n"); -		return PTR_ERR(host->clk_sample); +		host->clk_sample = devm_clk_get(&pdev->dev, "sample"); +		if (IS_ERR(host->clk_sample)) { +			dev_err(&pdev->dev, "Could not get sample clock\n"); +			return PTR_ERR(host->clk_sample); +		}  	}  	host->reset = devm_reset_control_get_optional(&pdev->dev, "ahb"); @@ -1120,15 +1237,17 @@ static int sunxi_mmc_probe(struct platform_device *pdev)  	mmc->max_blk_count	= 8192;  	mmc->max_blk_size	= 4096;  	mmc->max_segs		= PAGE_SIZE / sizeof(struct sunxi_idma_des); -	mmc->max_seg_size	= (1 << host->idma_des_size_bits); +	mmc->max_seg_size	= (1 << host->cfg->idma_des_size_bits);  	mmc->max_req_size	= mmc->max_seg_size * mmc->max_segs;  	/* 400kHz ~ 52MHz */  	mmc->f_min		=   400000;  	mmc->f_max		= 52000000;  	mmc->caps	       |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED | -				  MMC_CAP_1_8V_DDR |  				  MMC_CAP_ERASE | MMC_CAP_SDIO_IRQ; +	if (host->cfg->clk_delays) +		mmc->caps      |= MMC_CAP_1_8V_DDR; +  	ret = mmc_of_parse(mmc);  	if (ret)  		goto error_free_dma; @@ -1160,6 +1279,8 @@ static int sunxi_mmc_remove(struct platform_device *pdev)  	if (!IS_ERR(host->reset))  		reset_control_assert(host->reset); +	clk_disable_unprepare(host->clk_sample); +	clk_disable_unprepare(host->clk_output);  	clk_disable_unprepare(host->clk_mmc);  	clk_disable_unprepare(host->clk_ahb); diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h index 7f63ec05bdf4..8e126afd988c 100644 --- a/drivers/mmc/host/tmio_mmc.h +++ b/drivers/mmc/host/tmio_mmc.h @@ -79,6 +79,9 @@  #define	CLK_CTL_DIV_MASK	0xff  #define	CLK_CTL_SCLKEN		BIT(8) +#define CARD_OPT_WIDTH8		BIT(13) +#define CARD_OPT_WIDTH		BIT(15) +  #define TMIO_BBS		512		/* Boot block size */  /* Definitions for values the CTRL_SDIO_STATUS register can take. */ @@ -158,6 +161,7 @@ struct tmio_mmc_host {  	void (*clk_disable)(struct tmio_mmc_host *host);  	int (*multi_io_quirk)(struct mmc_card *card,  			      unsigned int direction, int blk_size); +	int (*card_busy)(struct mmc_host *mmc);  	int (*start_signal_voltage_switch)(struct mmc_host *mmc,  					   struct mmc_ios *ios);  }; diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c index 92467efc4e2c..700567603107 100644 --- a/drivers/mmc/host/tmio_mmc_pio.c +++ b/drivers/mmc/host/tmio_mmc_pio.c @@ -336,7 +336,9 @@ static int tmio_mmc_start_command(struct tmio_mmc_host *host, struct mmc_command  	switch (mmc_resp_type(cmd)) {  	case MMC_RSP_NONE: c |= RESP_NONE; break; -	case MMC_RSP_R1:   c |= RESP_R1;   break; +	case MMC_RSP_R1: +	case MMC_RSP_R1_NO_CRC: +			   c |= RESP_R1;   break;  	case MMC_RSP_R1B:  c |= RESP_R1B;  break;  	case MMC_RSP_R2:   c |= RESP_R2;   break;  	case MMC_RSP_R3:   c |= RESP_R3;   break; @@ -730,12 +732,13 @@ static int tmio_mmc_start_data(struct tmio_mmc_host *host,  	pr_debug("setup data transfer: blocksize %08x  nr_blocks %d\n",  		 data->blksz, data->blocks); -	/* Some hardware cannot perform 2 byte requests in 4 bit mode */ -	if (host->mmc->ios.bus_width == MMC_BUS_WIDTH_4) { +	/* Some hardware cannot perform 2 byte requests in 4/8 bit mode */ +	if (host->mmc->ios.bus_width == MMC_BUS_WIDTH_4 || +	    host->mmc->ios.bus_width == MMC_BUS_WIDTH_8) {  		int blksz_2bytes = pdata->flags & TMIO_MMC_BLKSZ_2BYTES;  		if (data->blksz < 2 || (data->blksz < 4 && !blksz_2bytes)) { -			pr_err("%s: %d byte block unsupported in 4 bit mode\n", +			pr_err("%s: %d byte block unsupported in 4/8 bit mode\n",  			       mmc_hostname(host->mmc), data->blksz);  			return -EINVAL;  		} @@ -857,14 +860,16 @@ static void tmio_mmc_power_off(struct tmio_mmc_host *host)  static void tmio_mmc_set_bus_width(struct tmio_mmc_host *host,  				unsigned char bus_width)  { -	switch (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; -	} +	u16 reg = sd_ctrl_read16(host, CTL_SD_MEM_CARD_OPT) +				& ~(CARD_OPT_WIDTH | CARD_OPT_WIDTH8); + +	/* reg now applies to MMC_BUS_WIDTH_4 */ +	if (bus_width == MMC_BUS_WIDTH_1) +		reg |= CARD_OPT_WIDTH; +	else if (bus_width == MMC_BUS_WIDTH_8) +		reg |= CARD_OPT_WIDTH8; + +	sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, reg);  }  /* Set MMC clock / power. @@ -960,20 +965,12 @@ static int tmio_multi_io_quirk(struct mmc_card *card,  	return blk_size;  } -static int tmio_mmc_card_busy(struct mmc_host *mmc) -{ -	struct tmio_mmc_host *host = mmc_priv(mmc); - -	return !(sd_ctrl_read16_and_16_as_32(host, CTL_STATUS) & TMIO_STAT_DAT0); -} -  static struct mmc_host_ops tmio_mmc_ops = {  	.request	= tmio_mmc_request,  	.set_ios	= tmio_mmc_set_ios,  	.get_ro         = tmio_mmc_get_ro,  	.get_cd		= mmc_gpio_get_cd,  	.enable_sdio_irq = tmio_mmc_enable_sdio_irq, -	.card_busy	= tmio_mmc_card_busy,  	.multi_io_quirk	= tmio_multi_io_quirk,  }; @@ -1072,6 +1069,7 @@ int tmio_mmc_host_probe(struct tmio_mmc_host *_host,  		goto host_free;  	} +	tmio_mmc_ops.card_busy = _host->card_busy;  	tmio_mmc_ops.start_signal_voltage_switch = _host->start_signal_voltage_switch;  	mmc->ops = &tmio_mmc_ops; @@ -1089,6 +1087,15 @@ int tmio_mmc_host_probe(struct tmio_mmc_host *_host,  				  !mmc_card_is_removable(mmc) ||  				  mmc->slot.cd_irq >= 0); +	/* +	 * On Gen2+, eMMC with NONREMOVABLE currently fails because native +	 * hotplug gets disabled. It seems RuntimePM related yet we need further +	 * research. Since we are planning a PM overhaul anyway, let's enforce +	 * for now the device being active by enabling native hotplug always. +	 */ +	if (pdata->flags & TMIO_MMC_MIN_RCAR2) +		_host->native_hotplug = true; +  	if (tmio_mmc_clk_enable(_host) < 0) {  		mmc->f_max = pdata->hclk;  		mmc->f_min = mmc->f_max / 512; diff --git a/drivers/mmc/host/vub300.c b/drivers/mmc/host/vub300.c index 1e819f98b94f..bb3e0d1dd355 100644 --- a/drivers/mmc/host/vub300.c +++ b/drivers/mmc/host/vub300.c @@ -2116,13 +2116,11 @@ static int vub300_probe(struct usb_interface *interface,  	command_out_urb = usb_alloc_urb(0, GFP_KERNEL);  	if (!command_out_urb) {  		retval = -ENOMEM; -		dev_err(&udev->dev, "not enough memory for command_out_urb\n");  		goto error0;  	}  	command_res_urb = usb_alloc_urb(0, GFP_KERNEL);  	if (!command_res_urb) {  		retval = -ENOMEM; -		dev_err(&udev->dev, "not enough memory for command_res_urb\n");  		goto error1;  	}  	/* this also allocates memory for our VUB300 mmc host device */  |