xref: /openbmc/linux/drivers/mmc/core/mmc_ops.c (revision a61ad2b4)
1da7fbe58SPierre Ossman /*
270f10482SPierre Ossman  *  linux/drivers/mmc/core/mmc_ops.h
3da7fbe58SPierre Ossman  *
4da7fbe58SPierre Ossman  *  Copyright 2006-2007 Pierre Ossman
5da7fbe58SPierre Ossman  *
6da7fbe58SPierre Ossman  * This program is free software; you can redistribute it and/or modify
7da7fbe58SPierre Ossman  * it under the terms of the GNU General Public License as published by
8da7fbe58SPierre Ossman  * the Free Software Foundation; either version 2 of the License, or (at
9da7fbe58SPierre Ossman  * your option) any later version.
10da7fbe58SPierre Ossman  */
11da7fbe58SPierre Ossman 
125a0e3ad6STejun Heo #include <linux/slab.h>
13da7fbe58SPierre Ossman #include <linux/types.h>
14da7fbe58SPierre Ossman #include <linux/scatterlist.h>
15da7fbe58SPierre Ossman 
16da7fbe58SPierre Ossman #include <linux/mmc/host.h>
17da7fbe58SPierre Ossman #include <linux/mmc/card.h>
18da7fbe58SPierre Ossman #include <linux/mmc/mmc.h>
19da7fbe58SPierre Ossman 
20da7fbe58SPierre Ossman #include "core.h"
21da7fbe58SPierre Ossman #include "mmc_ops.h"
22da7fbe58SPierre Ossman 
23da7fbe58SPierre Ossman static int _mmc_select_card(struct mmc_host *host, struct mmc_card *card)
24da7fbe58SPierre Ossman {
25da7fbe58SPierre Ossman 	int err;
261278dba1SChris Ball 	struct mmc_command cmd = {0};
27da7fbe58SPierre Ossman 
28da7fbe58SPierre Ossman 	BUG_ON(!host);
29da7fbe58SPierre Ossman 
30da7fbe58SPierre Ossman 	cmd.opcode = MMC_SELECT_CARD;
31da7fbe58SPierre Ossman 
32da7fbe58SPierre Ossman 	if (card) {
33da7fbe58SPierre Ossman 		cmd.arg = card->rca << 16;
34da7fbe58SPierre Ossman 		cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
35da7fbe58SPierre Ossman 	} else {
36da7fbe58SPierre Ossman 		cmd.arg = 0;
37da7fbe58SPierre Ossman 		cmd.flags = MMC_RSP_NONE | MMC_CMD_AC;
38da7fbe58SPierre Ossman 	}
39da7fbe58SPierre Ossman 
40da7fbe58SPierre Ossman 	err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES);
4117b0429dSPierre Ossman 	if (err)
42da7fbe58SPierre Ossman 		return err;
43da7fbe58SPierre Ossman 
4417b0429dSPierre Ossman 	return 0;
45da7fbe58SPierre Ossman }
46da7fbe58SPierre Ossman 
47da7fbe58SPierre Ossman int mmc_select_card(struct mmc_card *card)
48da7fbe58SPierre Ossman {
49da7fbe58SPierre Ossman 	BUG_ON(!card);
50da7fbe58SPierre Ossman 
51da7fbe58SPierre Ossman 	return _mmc_select_card(card->host, card);
52da7fbe58SPierre Ossman }
53da7fbe58SPierre Ossman 
54da7fbe58SPierre Ossman int mmc_deselect_cards(struct mmc_host *host)
55da7fbe58SPierre Ossman {
56da7fbe58SPierre Ossman 	return _mmc_select_card(host, NULL);
57da7fbe58SPierre Ossman }
58da7fbe58SPierre Ossman 
59b1ebe384SJarkko Lavinen int mmc_card_sleepawake(struct mmc_host *host, int sleep)
60b1ebe384SJarkko Lavinen {
611278dba1SChris Ball 	struct mmc_command cmd = {0};
62b1ebe384SJarkko Lavinen 	struct mmc_card *card = host->card;
63b1ebe384SJarkko Lavinen 	int err;
64b1ebe384SJarkko Lavinen 
65b1ebe384SJarkko Lavinen 	if (sleep)
66b1ebe384SJarkko Lavinen 		mmc_deselect_cards(host);
67b1ebe384SJarkko Lavinen 
68b1ebe384SJarkko Lavinen 	cmd.opcode = MMC_SLEEP_AWAKE;
69b1ebe384SJarkko Lavinen 	cmd.arg = card->rca << 16;
70b1ebe384SJarkko Lavinen 	if (sleep)
71b1ebe384SJarkko Lavinen 		cmd.arg |= 1 << 15;
72b1ebe384SJarkko Lavinen 
73b1ebe384SJarkko Lavinen 	cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
74b1ebe384SJarkko Lavinen 	err = mmc_wait_for_cmd(host, &cmd, 0);
75b1ebe384SJarkko Lavinen 	if (err)
76b1ebe384SJarkko Lavinen 		return err;
77b1ebe384SJarkko Lavinen 
78b1ebe384SJarkko Lavinen 	/*
79b1ebe384SJarkko Lavinen 	 * If the host does not wait while the card signals busy, then we will
80b1ebe384SJarkko Lavinen 	 * will have to wait the sleep/awake timeout.  Note, we cannot use the
81b1ebe384SJarkko Lavinen 	 * SEND_STATUS command to poll the status because that command (and most
82b1ebe384SJarkko Lavinen 	 * others) is invalid while the card sleeps.
83b1ebe384SJarkko Lavinen 	 */
84b1ebe384SJarkko Lavinen 	if (!(host->caps & MMC_CAP_WAIT_WHILE_BUSY))
85b1ebe384SJarkko Lavinen 		mmc_delay(DIV_ROUND_UP(card->ext_csd.sa_timeout, 10000));
86b1ebe384SJarkko Lavinen 
87b1ebe384SJarkko Lavinen 	if (!sleep)
88b1ebe384SJarkko Lavinen 		err = mmc_select_card(card);
89b1ebe384SJarkko Lavinen 
90b1ebe384SJarkko Lavinen 	return err;
91b1ebe384SJarkko Lavinen }
92b1ebe384SJarkko Lavinen 
93da7fbe58SPierre Ossman int mmc_go_idle(struct mmc_host *host)
94da7fbe58SPierre Ossman {
95da7fbe58SPierre Ossman 	int err;
961278dba1SChris Ball 	struct mmc_command cmd = {0};
97da7fbe58SPierre Ossman 
98af517150SDavid Brownell 	/*
99af517150SDavid Brownell 	 * Non-SPI hosts need to prevent chipselect going active during
100af517150SDavid Brownell 	 * GO_IDLE; that would put chips into SPI mode.  Remind them of
101af517150SDavid Brownell 	 * that in case of hardware that won't pull up DAT3/nCS otherwise.
102af517150SDavid Brownell 	 *
103af517150SDavid Brownell 	 * SPI hosts ignore ios.chip_select; it's managed according to
10425985edcSLucas De Marchi 	 * rules that must accommodate non-MMC slaves which this layer
105af517150SDavid Brownell 	 * won't even know about.
106af517150SDavid Brownell 	 */
107af517150SDavid Brownell 	if (!mmc_host_is_spi(host)) {
108da7fbe58SPierre Ossman 		mmc_set_chip_select(host, MMC_CS_HIGH);
109da7fbe58SPierre Ossman 		mmc_delay(1);
110af517150SDavid Brownell 	}
111da7fbe58SPierre Ossman 
112da7fbe58SPierre Ossman 	cmd.opcode = MMC_GO_IDLE_STATE;
113da7fbe58SPierre Ossman 	cmd.arg = 0;
114af517150SDavid Brownell 	cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_NONE | MMC_CMD_BC;
115da7fbe58SPierre Ossman 
116da7fbe58SPierre Ossman 	err = mmc_wait_for_cmd(host, &cmd, 0);
117da7fbe58SPierre Ossman 
118da7fbe58SPierre Ossman 	mmc_delay(1);
119da7fbe58SPierre Ossman 
120af517150SDavid Brownell 	if (!mmc_host_is_spi(host)) {
121da7fbe58SPierre Ossman 		mmc_set_chip_select(host, MMC_CS_DONTCARE);
122da7fbe58SPierre Ossman 		mmc_delay(1);
123af517150SDavid Brownell 	}
124af517150SDavid Brownell 
125af517150SDavid Brownell 	host->use_spi_crc = 0;
126da7fbe58SPierre Ossman 
127da7fbe58SPierre Ossman 	return err;
128da7fbe58SPierre Ossman }
129da7fbe58SPierre Ossman 
130da7fbe58SPierre Ossman int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
131da7fbe58SPierre Ossman {
1321278dba1SChris Ball 	struct mmc_command cmd = {0};
133da7fbe58SPierre Ossman 	int i, err = 0;
134da7fbe58SPierre Ossman 
135da7fbe58SPierre Ossman 	BUG_ON(!host);
136da7fbe58SPierre Ossman 
137da7fbe58SPierre Ossman 	cmd.opcode = MMC_SEND_OP_COND;
138af517150SDavid Brownell 	cmd.arg = mmc_host_is_spi(host) ? 0 : ocr;
139af517150SDavid Brownell 	cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R3 | MMC_CMD_BCR;
140da7fbe58SPierre Ossman 
141da7fbe58SPierre Ossman 	for (i = 100; i; i--) {
142da7fbe58SPierre Ossman 		err = mmc_wait_for_cmd(host, &cmd, 0);
14317b0429dSPierre Ossman 		if (err)
144da7fbe58SPierre Ossman 			break;
145da7fbe58SPierre Ossman 
146af517150SDavid Brownell 		/* if we're just probing, do a single pass */
147af517150SDavid Brownell 		if (ocr == 0)
148da7fbe58SPierre Ossman 			break;
149da7fbe58SPierre Ossman 
150af517150SDavid Brownell 		/* otherwise wait until reset completes */
151af517150SDavid Brownell 		if (mmc_host_is_spi(host)) {
152af517150SDavid Brownell 			if (!(cmd.resp[0] & R1_SPI_IDLE))
153af517150SDavid Brownell 				break;
154af517150SDavid Brownell 		} else {
155af517150SDavid Brownell 			if (cmd.resp[0] & MMC_CARD_BUSY)
156af517150SDavid Brownell 				break;
157af517150SDavid Brownell 		}
158af517150SDavid Brownell 
15917b0429dSPierre Ossman 		err = -ETIMEDOUT;
160da7fbe58SPierre Ossman 
161da7fbe58SPierre Ossman 		mmc_delay(10);
162da7fbe58SPierre Ossman 	}
163da7fbe58SPierre Ossman 
164af517150SDavid Brownell 	if (rocr && !mmc_host_is_spi(host))
165da7fbe58SPierre Ossman 		*rocr = cmd.resp[0];
166da7fbe58SPierre Ossman 
167da7fbe58SPierre Ossman 	return err;
168da7fbe58SPierre Ossman }
169da7fbe58SPierre Ossman 
170da7fbe58SPierre Ossman int mmc_all_send_cid(struct mmc_host *host, u32 *cid)
171da7fbe58SPierre Ossman {
172da7fbe58SPierre Ossman 	int err;
1731278dba1SChris Ball 	struct mmc_command cmd = {0};
174da7fbe58SPierre Ossman 
175da7fbe58SPierre Ossman 	BUG_ON(!host);
176da7fbe58SPierre Ossman 	BUG_ON(!cid);
177da7fbe58SPierre Ossman 
178da7fbe58SPierre Ossman 	cmd.opcode = MMC_ALL_SEND_CID;
179da7fbe58SPierre Ossman 	cmd.arg = 0;
180da7fbe58SPierre Ossman 	cmd.flags = MMC_RSP_R2 | MMC_CMD_BCR;
181da7fbe58SPierre Ossman 
182da7fbe58SPierre Ossman 	err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES);
18317b0429dSPierre Ossman 	if (err)
184da7fbe58SPierre Ossman 		return err;
185da7fbe58SPierre Ossman 
186da7fbe58SPierre Ossman 	memcpy(cid, cmd.resp, sizeof(u32) * 4);
187da7fbe58SPierre Ossman 
18817b0429dSPierre Ossman 	return 0;
189da7fbe58SPierre Ossman }
190da7fbe58SPierre Ossman 
191da7fbe58SPierre Ossman int mmc_set_relative_addr(struct mmc_card *card)
192da7fbe58SPierre Ossman {
193da7fbe58SPierre Ossman 	int err;
1941278dba1SChris Ball 	struct mmc_command cmd = {0};
195da7fbe58SPierre Ossman 
196da7fbe58SPierre Ossman 	BUG_ON(!card);
197da7fbe58SPierre Ossman 	BUG_ON(!card->host);
198da7fbe58SPierre Ossman 
199da7fbe58SPierre Ossman 	cmd.opcode = MMC_SET_RELATIVE_ADDR;
200da7fbe58SPierre Ossman 	cmd.arg = card->rca << 16;
201da7fbe58SPierre Ossman 	cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
202da7fbe58SPierre Ossman 
203da7fbe58SPierre Ossman 	err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
20417b0429dSPierre Ossman 	if (err)
205da7fbe58SPierre Ossman 		return err;
206da7fbe58SPierre Ossman 
20717b0429dSPierre Ossman 	return 0;
208da7fbe58SPierre Ossman }
209da7fbe58SPierre Ossman 
210af517150SDavid Brownell static int
211af517150SDavid Brownell mmc_send_cxd_native(struct mmc_host *host, u32 arg, u32 *cxd, int opcode)
212da7fbe58SPierre Ossman {
213da7fbe58SPierre Ossman 	int err;
2141278dba1SChris Ball 	struct mmc_command cmd = {0};
215da7fbe58SPierre Ossman 
216af517150SDavid Brownell 	BUG_ON(!host);
217af517150SDavid Brownell 	BUG_ON(!cxd);
218da7fbe58SPierre Ossman 
219af517150SDavid Brownell 	cmd.opcode = opcode;
220af517150SDavid Brownell 	cmd.arg = arg;
221da7fbe58SPierre Ossman 	cmd.flags = MMC_RSP_R2 | MMC_CMD_AC;
222da7fbe58SPierre Ossman 
223af517150SDavid Brownell 	err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES);
22417b0429dSPierre Ossman 	if (err)
225da7fbe58SPierre Ossman 		return err;
226da7fbe58SPierre Ossman 
227af517150SDavid Brownell 	memcpy(cxd, cmd.resp, sizeof(u32) * 4);
228da7fbe58SPierre Ossman 
22917b0429dSPierre Ossman 	return 0;
230da7fbe58SPierre Ossman }
231da7fbe58SPierre Ossman 
232af517150SDavid Brownell static int
233af517150SDavid Brownell mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host,
234af517150SDavid Brownell 		u32 opcode, void *buf, unsigned len)
235da7fbe58SPierre Ossman {
236da7fbe58SPierre Ossman 	struct mmc_request mrq;
2371278dba1SChris Ball 	struct mmc_command cmd = {0};
238a61ad2b4SChris Ball 	struct mmc_data data = {0};
239da7fbe58SPierre Ossman 	struct scatterlist sg;
240af517150SDavid Brownell 	void *data_buf;
241da7fbe58SPierre Ossman 
242af517150SDavid Brownell 	/* dma onto stack is unsafe/nonportable, but callers to this
243af517150SDavid Brownell 	 * routine normally provide temporary on-stack buffers ...
244af517150SDavid Brownell 	 */
245af517150SDavid Brownell 	data_buf = kmalloc(len, GFP_KERNEL);
246af517150SDavid Brownell 	if (data_buf == NULL)
247af517150SDavid Brownell 		return -ENOMEM;
248da7fbe58SPierre Ossman 
249da7fbe58SPierre Ossman 	memset(&mrq, 0, sizeof(struct mmc_request));
250da7fbe58SPierre Ossman 
251da7fbe58SPierre Ossman 	mrq.cmd = &cmd;
252da7fbe58SPierre Ossman 	mrq.data = &data;
253da7fbe58SPierre Ossman 
254af517150SDavid Brownell 	cmd.opcode = opcode;
255da7fbe58SPierre Ossman 	cmd.arg = 0;
256da7fbe58SPierre Ossman 
257af517150SDavid Brownell 	/* NOTE HACK:  the MMC_RSP_SPI_R1 is always correct here, but we
258af517150SDavid Brownell 	 * rely on callers to never use this with "native" calls for reading
259af517150SDavid Brownell 	 * CSD or CID.  Native versions of those commands use the R2 type,
260af517150SDavid Brownell 	 * not R1 plus a data block.
261af517150SDavid Brownell 	 */
262af517150SDavid Brownell 	cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
263af517150SDavid Brownell 
264af517150SDavid Brownell 	data.blksz = len;
265da7fbe58SPierre Ossman 	data.blocks = 1;
266da7fbe58SPierre Ossman 	data.flags = MMC_DATA_READ;
267da7fbe58SPierre Ossman 	data.sg = &sg;
268da7fbe58SPierre Ossman 	data.sg_len = 1;
269da7fbe58SPierre Ossman 
270af517150SDavid Brownell 	sg_init_one(&sg, data_buf, len);
271da7fbe58SPierre Ossman 
272cda56ac2SAdrian Hunter 	if (opcode == MMC_SEND_CSD || opcode == MMC_SEND_CID) {
2730d3e0460SMatthew Fleming 		/*
2740d3e0460SMatthew Fleming 		 * The spec states that CSR and CID accesses have a timeout
2750d3e0460SMatthew Fleming 		 * of 64 clock cycles.
2760d3e0460SMatthew Fleming 		 */
2770d3e0460SMatthew Fleming 		data.timeout_ns = 0;
2780d3e0460SMatthew Fleming 		data.timeout_clks = 64;
279cda56ac2SAdrian Hunter 	} else
280cda56ac2SAdrian Hunter 		mmc_set_data_timeout(&data, card);
281da7fbe58SPierre Ossman 
282af517150SDavid Brownell 	mmc_wait_for_req(host, &mrq);
283af517150SDavid Brownell 
284af517150SDavid Brownell 	memcpy(buf, data_buf, len);
285af517150SDavid Brownell 	kfree(data_buf);
286da7fbe58SPierre Ossman 
28717b0429dSPierre Ossman 	if (cmd.error)
288da7fbe58SPierre Ossman 		return cmd.error;
28917b0429dSPierre Ossman 	if (data.error)
290da7fbe58SPierre Ossman 		return data.error;
291da7fbe58SPierre Ossman 
29217b0429dSPierre Ossman 	return 0;
293da7fbe58SPierre Ossman }
294da7fbe58SPierre Ossman 
295af517150SDavid Brownell int mmc_send_csd(struct mmc_card *card, u32 *csd)
296af517150SDavid Brownell {
29778e48073SPierre Ossman 	int ret, i;
29878e48073SPierre Ossman 
299af517150SDavid Brownell 	if (!mmc_host_is_spi(card->host))
300af517150SDavid Brownell 		return mmc_send_cxd_native(card->host, card->rca << 16,
301af517150SDavid Brownell 				csd, MMC_SEND_CSD);
302af517150SDavid Brownell 
30378e48073SPierre Ossman 	ret = mmc_send_cxd_data(card, card->host, MMC_SEND_CSD, csd, 16);
30478e48073SPierre Ossman 	if (ret)
30578e48073SPierre Ossman 		return ret;
30678e48073SPierre Ossman 
30778e48073SPierre Ossman 	for (i = 0;i < 4;i++)
30878e48073SPierre Ossman 		csd[i] = be32_to_cpu(csd[i]);
30978e48073SPierre Ossman 
31078e48073SPierre Ossman 	return 0;
311af517150SDavid Brownell }
312af517150SDavid Brownell 
313af517150SDavid Brownell int mmc_send_cid(struct mmc_host *host, u32 *cid)
314af517150SDavid Brownell {
31578e48073SPierre Ossman 	int ret, i;
31678e48073SPierre Ossman 
317af517150SDavid Brownell 	if (!mmc_host_is_spi(host)) {
318af517150SDavid Brownell 		if (!host->card)
319af517150SDavid Brownell 			return -EINVAL;
320af517150SDavid Brownell 		return mmc_send_cxd_native(host, host->card->rca << 16,
321af517150SDavid Brownell 				cid, MMC_SEND_CID);
322af517150SDavid Brownell 	}
323af517150SDavid Brownell 
32478e48073SPierre Ossman 	ret = mmc_send_cxd_data(NULL, host, MMC_SEND_CID, cid, 16);
32578e48073SPierre Ossman 	if (ret)
32678e48073SPierre Ossman 		return ret;
32778e48073SPierre Ossman 
32878e48073SPierre Ossman 	for (i = 0;i < 4;i++)
32978e48073SPierre Ossman 		cid[i] = be32_to_cpu(cid[i]);
33078e48073SPierre Ossman 
33178e48073SPierre Ossman 	return 0;
332af517150SDavid Brownell }
333af517150SDavid Brownell 
334af517150SDavid Brownell int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd)
335af517150SDavid Brownell {
336af517150SDavid Brownell 	return mmc_send_cxd_data(card, card->host, MMC_SEND_EXT_CSD,
337af517150SDavid Brownell 			ext_csd, 512);
338af517150SDavid Brownell }
339af517150SDavid Brownell 
340af517150SDavid Brownell int mmc_spi_read_ocr(struct mmc_host *host, int highcap, u32 *ocrp)
341af517150SDavid Brownell {
3421278dba1SChris Ball 	struct mmc_command cmd = {0};
343af517150SDavid Brownell 	int err;
344af517150SDavid Brownell 
345af517150SDavid Brownell 	cmd.opcode = MMC_SPI_READ_OCR;
346af517150SDavid Brownell 	cmd.arg = highcap ? (1 << 30) : 0;
347af517150SDavid Brownell 	cmd.flags = MMC_RSP_SPI_R3;
348af517150SDavid Brownell 
349af517150SDavid Brownell 	err = mmc_wait_for_cmd(host, &cmd, 0);
350af517150SDavid Brownell 
351af517150SDavid Brownell 	*ocrp = cmd.resp[1];
352af517150SDavid Brownell 	return err;
353af517150SDavid Brownell }
354af517150SDavid Brownell 
355af517150SDavid Brownell int mmc_spi_set_crc(struct mmc_host *host, int use_crc)
356af517150SDavid Brownell {
3571278dba1SChris Ball 	struct mmc_command cmd = {0};
358af517150SDavid Brownell 	int err;
359af517150SDavid Brownell 
360af517150SDavid Brownell 	cmd.opcode = MMC_SPI_CRC_ON_OFF;
361af517150SDavid Brownell 	cmd.flags = MMC_RSP_SPI_R1;
362af517150SDavid Brownell 	cmd.arg = use_crc;
363af517150SDavid Brownell 
364af517150SDavid Brownell 	err = mmc_wait_for_cmd(host, &cmd, 0);
365af517150SDavid Brownell 	if (!err)
366af517150SDavid Brownell 		host->use_spi_crc = use_crc;
367af517150SDavid Brownell 	return err;
368af517150SDavid Brownell }
369af517150SDavid Brownell 
370d3a8d95dSAndrei Warkentin /**
371d3a8d95dSAndrei Warkentin  *	mmc_switch - modify EXT_CSD register
372d3a8d95dSAndrei Warkentin  *	@card: the MMC card associated with the data transfer
373d3a8d95dSAndrei Warkentin  *	@set: cmd set values
374d3a8d95dSAndrei Warkentin  *	@index: EXT_CSD register index
375d3a8d95dSAndrei Warkentin  *	@value: value to program into EXT_CSD register
376d3a8d95dSAndrei Warkentin  *	@timeout_ms: timeout (ms) for operation performed by register write,
377d3a8d95dSAndrei Warkentin  *                   timeout of zero implies maximum possible timeout
378d3a8d95dSAndrei Warkentin  *
379d3a8d95dSAndrei Warkentin  *	Modifies the EXT_CSD register for selected card.
380d3a8d95dSAndrei Warkentin  */
381d3a8d95dSAndrei Warkentin int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
382d3a8d95dSAndrei Warkentin 	       unsigned int timeout_ms)
383da7fbe58SPierre Ossman {
384da7fbe58SPierre Ossman 	int err;
3851278dba1SChris Ball 	struct mmc_command cmd = {0};
386ef0b27d4SAdrian Hunter 	u32 status;
387da7fbe58SPierre Ossman 
388da7fbe58SPierre Ossman 	BUG_ON(!card);
389da7fbe58SPierre Ossman 	BUG_ON(!card->host);
390da7fbe58SPierre Ossman 
391da7fbe58SPierre Ossman 	cmd.opcode = MMC_SWITCH;
392da7fbe58SPierre Ossman 	cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
393da7fbe58SPierre Ossman 		  (index << 16) |
394da7fbe58SPierre Ossman 		  (value << 8) |
395da7fbe58SPierre Ossman 		  set;
396af517150SDavid Brownell 	cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
397d3a8d95dSAndrei Warkentin 	cmd.cmd_timeout_ms = timeout_ms;
398da7fbe58SPierre Ossman 
399da7fbe58SPierre Ossman 	err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
40017b0429dSPierre Ossman 	if (err)
401da7fbe58SPierre Ossman 		return err;
402da7fbe58SPierre Ossman 
403ef0b27d4SAdrian Hunter 	/* Must check status to be sure of no errors */
404ef0b27d4SAdrian Hunter 	do {
405ef0b27d4SAdrian Hunter 		err = mmc_send_status(card, &status);
406ef0b27d4SAdrian Hunter 		if (err)
407ef0b27d4SAdrian Hunter 			return err;
408ef0b27d4SAdrian Hunter 		if (card->host->caps & MMC_CAP_WAIT_WHILE_BUSY)
409ef0b27d4SAdrian Hunter 			break;
410ef0b27d4SAdrian Hunter 		if (mmc_host_is_spi(card->host))
411ef0b27d4SAdrian Hunter 			break;
412ef0b27d4SAdrian Hunter 	} while (R1_CURRENT_STATE(status) == 7);
413ef0b27d4SAdrian Hunter 
414ef0b27d4SAdrian Hunter 	if (mmc_host_is_spi(card->host)) {
415ef0b27d4SAdrian Hunter 		if (status & R1_SPI_ILLEGAL_COMMAND)
416ef0b27d4SAdrian Hunter 			return -EBADMSG;
417ef0b27d4SAdrian Hunter 	} else {
418ef0b27d4SAdrian Hunter 		if (status & 0xFDFFA000)
419ef0b27d4SAdrian Hunter 			printk(KERN_WARNING "%s: unexpected status %#x after "
420ef0b27d4SAdrian Hunter 			       "switch", mmc_hostname(card->host), status);
421ef0b27d4SAdrian Hunter 		if (status & R1_SWITCH_ERROR)
422ef0b27d4SAdrian Hunter 			return -EBADMSG;
423ef0b27d4SAdrian Hunter 	}
424ef0b27d4SAdrian Hunter 
42517b0429dSPierre Ossman 	return 0;
426da7fbe58SPierre Ossman }
427d3a8d95dSAndrei Warkentin EXPORT_SYMBOL_GPL(mmc_switch);
428da7fbe58SPierre Ossman 
429da7fbe58SPierre Ossman int mmc_send_status(struct mmc_card *card, u32 *status)
430da7fbe58SPierre Ossman {
431da7fbe58SPierre Ossman 	int err;
4321278dba1SChris Ball 	struct mmc_command cmd = {0};
433da7fbe58SPierre Ossman 
434da7fbe58SPierre Ossman 	BUG_ON(!card);
435da7fbe58SPierre Ossman 	BUG_ON(!card->host);
436da7fbe58SPierre Ossman 
437da7fbe58SPierre Ossman 	cmd.opcode = MMC_SEND_STATUS;
438af517150SDavid Brownell 	if (!mmc_host_is_spi(card->host))
439da7fbe58SPierre Ossman 		cmd.arg = card->rca << 16;
440af517150SDavid Brownell 	cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC;
441da7fbe58SPierre Ossman 
442da7fbe58SPierre Ossman 	err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
44317b0429dSPierre Ossman 	if (err)
444da7fbe58SPierre Ossman 		return err;
445da7fbe58SPierre Ossman 
446af517150SDavid Brownell 	/* NOTE: callers are required to understand the difference
447af517150SDavid Brownell 	 * between "native" and SPI format status words!
448af517150SDavid Brownell 	 */
449da7fbe58SPierre Ossman 	if (status)
450da7fbe58SPierre Ossman 		*status = cmd.resp[0];
451da7fbe58SPierre Ossman 
45217b0429dSPierre Ossman 	return 0;
453da7fbe58SPierre Ossman }
454da7fbe58SPierre Ossman 
45522113efdSAries Lee static int
45622113efdSAries Lee mmc_send_bus_test(struct mmc_card *card, struct mmc_host *host, u8 opcode,
45722113efdSAries Lee 		  u8 len)
45822113efdSAries Lee {
45922113efdSAries Lee 	struct mmc_request mrq;
4601278dba1SChris Ball 	struct mmc_command cmd = {0};
461a61ad2b4SChris Ball 	struct mmc_data data = {0};
46222113efdSAries Lee 	struct scatterlist sg;
46322113efdSAries Lee 	u8 *data_buf;
46422113efdSAries Lee 	u8 *test_buf;
46522113efdSAries Lee 	int i, err;
46622113efdSAries Lee 	static u8 testdata_8bit[8] = { 0x55, 0xaa, 0, 0, 0, 0, 0, 0 };
46722113efdSAries Lee 	static u8 testdata_4bit[4] = { 0x5a, 0, 0, 0 };
46822113efdSAries Lee 
46922113efdSAries Lee 	/* dma onto stack is unsafe/nonportable, but callers to this
47022113efdSAries Lee 	 * routine normally provide temporary on-stack buffers ...
47122113efdSAries Lee 	 */
47222113efdSAries Lee 	data_buf = kmalloc(len, GFP_KERNEL);
47322113efdSAries Lee 	if (!data_buf)
47422113efdSAries Lee 		return -ENOMEM;
47522113efdSAries Lee 
47622113efdSAries Lee 	if (len == 8)
47722113efdSAries Lee 		test_buf = testdata_8bit;
47822113efdSAries Lee 	else if (len == 4)
47922113efdSAries Lee 		test_buf = testdata_4bit;
48022113efdSAries Lee 	else {
48122113efdSAries Lee 		printk(KERN_ERR "%s: Invalid bus_width %d\n",
48222113efdSAries Lee 		       mmc_hostname(host), len);
48322113efdSAries Lee 		kfree(data_buf);
48422113efdSAries Lee 		return -EINVAL;
48522113efdSAries Lee 	}
48622113efdSAries Lee 
48722113efdSAries Lee 	if (opcode == MMC_BUS_TEST_W)
48822113efdSAries Lee 		memcpy(data_buf, test_buf, len);
48922113efdSAries Lee 
49022113efdSAries Lee 	memset(&mrq, 0, sizeof(struct mmc_request));
49122113efdSAries Lee 
49222113efdSAries Lee 	mrq.cmd = &cmd;
49322113efdSAries Lee 	mrq.data = &data;
49422113efdSAries Lee 	cmd.opcode = opcode;
49522113efdSAries Lee 	cmd.arg = 0;
49622113efdSAries Lee 
49722113efdSAries Lee 	/* NOTE HACK:  the MMC_RSP_SPI_R1 is always correct here, but we
49822113efdSAries Lee 	 * rely on callers to never use this with "native" calls for reading
49922113efdSAries Lee 	 * CSD or CID.  Native versions of those commands use the R2 type,
50022113efdSAries Lee 	 * not R1 plus a data block.
50122113efdSAries Lee 	 */
50222113efdSAries Lee 	cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
50322113efdSAries Lee 
50422113efdSAries Lee 	data.blksz = len;
50522113efdSAries Lee 	data.blocks = 1;
50622113efdSAries Lee 	if (opcode == MMC_BUS_TEST_R)
50722113efdSAries Lee 		data.flags = MMC_DATA_READ;
50822113efdSAries Lee 	else
50922113efdSAries Lee 		data.flags = MMC_DATA_WRITE;
51022113efdSAries Lee 
51122113efdSAries Lee 	data.sg = &sg;
51222113efdSAries Lee 	data.sg_len = 1;
51322113efdSAries Lee 	sg_init_one(&sg, data_buf, len);
51422113efdSAries Lee 	mmc_wait_for_req(host, &mrq);
51522113efdSAries Lee 	err = 0;
51622113efdSAries Lee 	if (opcode == MMC_BUS_TEST_R) {
51722113efdSAries Lee 		for (i = 0; i < len / 4; i++)
51822113efdSAries Lee 			if ((test_buf[i] ^ data_buf[i]) != 0xff) {
51922113efdSAries Lee 				err = -EIO;
52022113efdSAries Lee 				break;
52122113efdSAries Lee 			}
52222113efdSAries Lee 	}
52322113efdSAries Lee 	kfree(data_buf);
52422113efdSAries Lee 
52522113efdSAries Lee 	if (cmd.error)
52622113efdSAries Lee 		return cmd.error;
52722113efdSAries Lee 	if (data.error)
52822113efdSAries Lee 		return data.error;
52922113efdSAries Lee 
53022113efdSAries Lee 	return err;
53122113efdSAries Lee }
53222113efdSAries Lee 
53322113efdSAries Lee int mmc_bus_test(struct mmc_card *card, u8 bus_width)
53422113efdSAries Lee {
53522113efdSAries Lee 	int err, width;
53622113efdSAries Lee 
53722113efdSAries Lee 	if (bus_width == MMC_BUS_WIDTH_8)
53822113efdSAries Lee 		width = 8;
53922113efdSAries Lee 	else if (bus_width == MMC_BUS_WIDTH_4)
54022113efdSAries Lee 		width = 4;
54122113efdSAries Lee 	else if (bus_width == MMC_BUS_WIDTH_1)
54222113efdSAries Lee 		return 0; /* no need for test */
54322113efdSAries Lee 	else
54422113efdSAries Lee 		return -EINVAL;
54522113efdSAries Lee 
54622113efdSAries Lee 	/*
54722113efdSAries Lee 	 * Ignore errors from BUS_TEST_W.  BUS_TEST_R will fail if there
54822113efdSAries Lee 	 * is a problem.  This improves chances that the test will work.
54922113efdSAries Lee 	 */
55022113efdSAries Lee 	mmc_send_bus_test(card, card->host, MMC_BUS_TEST_W, width);
55122113efdSAries Lee 	err = mmc_send_bus_test(card, card->host, MMC_BUS_TEST_R, width);
55222113efdSAries Lee 	return err;
55322113efdSAries Lee }
554