xref: /openbmc/linux/drivers/mmc/core/mmc_ops.c (revision ef0b27d4)
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 
12da7fbe58SPierre Ossman #include <linux/types.h>
13da7fbe58SPierre Ossman #include <linux/scatterlist.h>
14da7fbe58SPierre Ossman 
15da7fbe58SPierre Ossman #include <linux/mmc/host.h>
16da7fbe58SPierre Ossman #include <linux/mmc/card.h>
17da7fbe58SPierre Ossman #include <linux/mmc/mmc.h>
18da7fbe58SPierre Ossman 
19da7fbe58SPierre Ossman #include "core.h"
20da7fbe58SPierre Ossman #include "mmc_ops.h"
21da7fbe58SPierre Ossman 
22da7fbe58SPierre Ossman static int _mmc_select_card(struct mmc_host *host, struct mmc_card *card)
23da7fbe58SPierre Ossman {
24da7fbe58SPierre Ossman 	int err;
25da7fbe58SPierre Ossman 	struct mmc_command cmd;
26da7fbe58SPierre Ossman 
27da7fbe58SPierre Ossman 	BUG_ON(!host);
28da7fbe58SPierre Ossman 
29da7fbe58SPierre Ossman 	memset(&cmd, 0, sizeof(struct mmc_command));
30da7fbe58SPierre Ossman 
31da7fbe58SPierre Ossman 	cmd.opcode = MMC_SELECT_CARD;
32da7fbe58SPierre Ossman 
33da7fbe58SPierre Ossman 	if (card) {
34da7fbe58SPierre Ossman 		cmd.arg = card->rca << 16;
35da7fbe58SPierre Ossman 		cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
36da7fbe58SPierre Ossman 	} else {
37da7fbe58SPierre Ossman 		cmd.arg = 0;
38da7fbe58SPierre Ossman 		cmd.flags = MMC_RSP_NONE | MMC_CMD_AC;
39da7fbe58SPierre Ossman 	}
40da7fbe58SPierre Ossman 
41da7fbe58SPierre Ossman 	err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES);
4217b0429dSPierre Ossman 	if (err)
43da7fbe58SPierre Ossman 		return err;
44da7fbe58SPierre Ossman 
4517b0429dSPierre Ossman 	return 0;
46da7fbe58SPierre Ossman }
47da7fbe58SPierre Ossman 
48da7fbe58SPierre Ossman int mmc_select_card(struct mmc_card *card)
49da7fbe58SPierre Ossman {
50da7fbe58SPierre Ossman 	BUG_ON(!card);
51da7fbe58SPierre Ossman 
52da7fbe58SPierre Ossman 	return _mmc_select_card(card->host, card);
53da7fbe58SPierre Ossman }
54da7fbe58SPierre Ossman 
55da7fbe58SPierre Ossman int mmc_deselect_cards(struct mmc_host *host)
56da7fbe58SPierre Ossman {
57da7fbe58SPierre Ossman 	return _mmc_select_card(host, NULL);
58da7fbe58SPierre Ossman }
59da7fbe58SPierre Ossman 
60b1ebe384SJarkko Lavinen int mmc_card_sleepawake(struct mmc_host *host, int sleep)
61b1ebe384SJarkko Lavinen {
62b1ebe384SJarkko Lavinen 	struct mmc_command cmd;
63b1ebe384SJarkko Lavinen 	struct mmc_card *card = host->card;
64b1ebe384SJarkko Lavinen 	int err;
65b1ebe384SJarkko Lavinen 
66b1ebe384SJarkko Lavinen 	if (sleep)
67b1ebe384SJarkko Lavinen 		mmc_deselect_cards(host);
68b1ebe384SJarkko Lavinen 
69b1ebe384SJarkko Lavinen 	memset(&cmd, 0, sizeof(struct mmc_command));
70b1ebe384SJarkko Lavinen 
71b1ebe384SJarkko Lavinen 	cmd.opcode = MMC_SLEEP_AWAKE;
72b1ebe384SJarkko Lavinen 	cmd.arg = card->rca << 16;
73b1ebe384SJarkko Lavinen 	if (sleep)
74b1ebe384SJarkko Lavinen 		cmd.arg |= 1 << 15;
75b1ebe384SJarkko Lavinen 
76b1ebe384SJarkko Lavinen 	cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
77b1ebe384SJarkko Lavinen 	err = mmc_wait_for_cmd(host, &cmd, 0);
78b1ebe384SJarkko Lavinen 	if (err)
79b1ebe384SJarkko Lavinen 		return err;
80b1ebe384SJarkko Lavinen 
81b1ebe384SJarkko Lavinen 	/*
82b1ebe384SJarkko Lavinen 	 * If the host does not wait while the card signals busy, then we will
83b1ebe384SJarkko Lavinen 	 * will have to wait the sleep/awake timeout.  Note, we cannot use the
84b1ebe384SJarkko Lavinen 	 * SEND_STATUS command to poll the status because that command (and most
85b1ebe384SJarkko Lavinen 	 * others) is invalid while the card sleeps.
86b1ebe384SJarkko Lavinen 	 */
87b1ebe384SJarkko Lavinen 	if (!(host->caps & MMC_CAP_WAIT_WHILE_BUSY))
88b1ebe384SJarkko Lavinen 		mmc_delay(DIV_ROUND_UP(card->ext_csd.sa_timeout, 10000));
89b1ebe384SJarkko Lavinen 
90b1ebe384SJarkko Lavinen 	if (!sleep)
91b1ebe384SJarkko Lavinen 		err = mmc_select_card(card);
92b1ebe384SJarkko Lavinen 
93b1ebe384SJarkko Lavinen 	return err;
94b1ebe384SJarkko Lavinen }
95b1ebe384SJarkko Lavinen 
96da7fbe58SPierre Ossman int mmc_go_idle(struct mmc_host *host)
97da7fbe58SPierre Ossman {
98da7fbe58SPierre Ossman 	int err;
99da7fbe58SPierre Ossman 	struct mmc_command cmd;
100da7fbe58SPierre Ossman 
101af517150SDavid Brownell 	/*
102af517150SDavid Brownell 	 * Non-SPI hosts need to prevent chipselect going active during
103af517150SDavid Brownell 	 * GO_IDLE; that would put chips into SPI mode.  Remind them of
104af517150SDavid Brownell 	 * that in case of hardware that won't pull up DAT3/nCS otherwise.
105af517150SDavid Brownell 	 *
106af517150SDavid Brownell 	 * SPI hosts ignore ios.chip_select; it's managed according to
107af517150SDavid Brownell 	 * rules that must accomodate non-MMC slaves which this layer
108af517150SDavid Brownell 	 * won't even know about.
109af517150SDavid Brownell 	 */
110af517150SDavid Brownell 	if (!mmc_host_is_spi(host)) {
111da7fbe58SPierre Ossman 		mmc_set_chip_select(host, MMC_CS_HIGH);
112da7fbe58SPierre Ossman 		mmc_delay(1);
113af517150SDavid Brownell 	}
114da7fbe58SPierre Ossman 
115da7fbe58SPierre Ossman 	memset(&cmd, 0, sizeof(struct mmc_command));
116da7fbe58SPierre Ossman 
117da7fbe58SPierre Ossman 	cmd.opcode = MMC_GO_IDLE_STATE;
118da7fbe58SPierre Ossman 	cmd.arg = 0;
119af517150SDavid Brownell 	cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_NONE | MMC_CMD_BC;
120da7fbe58SPierre Ossman 
121da7fbe58SPierre Ossman 	err = mmc_wait_for_cmd(host, &cmd, 0);
122da7fbe58SPierre Ossman 
123da7fbe58SPierre Ossman 	mmc_delay(1);
124da7fbe58SPierre Ossman 
125af517150SDavid Brownell 	if (!mmc_host_is_spi(host)) {
126da7fbe58SPierre Ossman 		mmc_set_chip_select(host, MMC_CS_DONTCARE);
127da7fbe58SPierre Ossman 		mmc_delay(1);
128af517150SDavid Brownell 	}
129af517150SDavid Brownell 
130af517150SDavid Brownell 	host->use_spi_crc = 0;
131da7fbe58SPierre Ossman 
132da7fbe58SPierre Ossman 	return err;
133da7fbe58SPierre Ossman }
134da7fbe58SPierre Ossman 
135da7fbe58SPierre Ossman int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
136da7fbe58SPierre Ossman {
137da7fbe58SPierre Ossman 	struct mmc_command cmd;
138da7fbe58SPierre Ossman 	int i, err = 0;
139da7fbe58SPierre Ossman 
140da7fbe58SPierre Ossman 	BUG_ON(!host);
141da7fbe58SPierre Ossman 
142da7fbe58SPierre Ossman 	memset(&cmd, 0, sizeof(struct mmc_command));
143da7fbe58SPierre Ossman 
144da7fbe58SPierre Ossman 	cmd.opcode = MMC_SEND_OP_COND;
145af517150SDavid Brownell 	cmd.arg = mmc_host_is_spi(host) ? 0 : ocr;
146af517150SDavid Brownell 	cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R3 | MMC_CMD_BCR;
147da7fbe58SPierre Ossman 
148da7fbe58SPierre Ossman 	for (i = 100; i; i--) {
149da7fbe58SPierre Ossman 		err = mmc_wait_for_cmd(host, &cmd, 0);
15017b0429dSPierre Ossman 		if (err)
151da7fbe58SPierre Ossman 			break;
152da7fbe58SPierre Ossman 
153af517150SDavid Brownell 		/* if we're just probing, do a single pass */
154af517150SDavid Brownell 		if (ocr == 0)
155da7fbe58SPierre Ossman 			break;
156da7fbe58SPierre Ossman 
157af517150SDavid Brownell 		/* otherwise wait until reset completes */
158af517150SDavid Brownell 		if (mmc_host_is_spi(host)) {
159af517150SDavid Brownell 			if (!(cmd.resp[0] & R1_SPI_IDLE))
160af517150SDavid Brownell 				break;
161af517150SDavid Brownell 		} else {
162af517150SDavid Brownell 			if (cmd.resp[0] & MMC_CARD_BUSY)
163af517150SDavid Brownell 				break;
164af517150SDavid Brownell 		}
165af517150SDavid Brownell 
16617b0429dSPierre Ossman 		err = -ETIMEDOUT;
167da7fbe58SPierre Ossman 
168da7fbe58SPierre Ossman 		mmc_delay(10);
169da7fbe58SPierre Ossman 	}
170da7fbe58SPierre Ossman 
171af517150SDavid Brownell 	if (rocr && !mmc_host_is_spi(host))
172da7fbe58SPierre Ossman 		*rocr = cmd.resp[0];
173da7fbe58SPierre Ossman 
174da7fbe58SPierre Ossman 	return err;
175da7fbe58SPierre Ossman }
176da7fbe58SPierre Ossman 
177da7fbe58SPierre Ossman int mmc_all_send_cid(struct mmc_host *host, u32 *cid)
178da7fbe58SPierre Ossman {
179da7fbe58SPierre Ossman 	int err;
180da7fbe58SPierre Ossman 	struct mmc_command cmd;
181da7fbe58SPierre Ossman 
182da7fbe58SPierre Ossman 	BUG_ON(!host);
183da7fbe58SPierre Ossman 	BUG_ON(!cid);
184da7fbe58SPierre Ossman 
185da7fbe58SPierre Ossman 	memset(&cmd, 0, sizeof(struct mmc_command));
186da7fbe58SPierre Ossman 
187da7fbe58SPierre Ossman 	cmd.opcode = MMC_ALL_SEND_CID;
188da7fbe58SPierre Ossman 	cmd.arg = 0;
189da7fbe58SPierre Ossman 	cmd.flags = MMC_RSP_R2 | MMC_CMD_BCR;
190da7fbe58SPierre Ossman 
191da7fbe58SPierre Ossman 	err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES);
19217b0429dSPierre Ossman 	if (err)
193da7fbe58SPierre Ossman 		return err;
194da7fbe58SPierre Ossman 
195da7fbe58SPierre Ossman 	memcpy(cid, cmd.resp, sizeof(u32) * 4);
196da7fbe58SPierre Ossman 
19717b0429dSPierre Ossman 	return 0;
198da7fbe58SPierre Ossman }
199da7fbe58SPierre Ossman 
200da7fbe58SPierre Ossman int mmc_set_relative_addr(struct mmc_card *card)
201da7fbe58SPierre Ossman {
202da7fbe58SPierre Ossman 	int err;
203da7fbe58SPierre Ossman 	struct mmc_command cmd;
204da7fbe58SPierre Ossman 
205da7fbe58SPierre Ossman 	BUG_ON(!card);
206da7fbe58SPierre Ossman 	BUG_ON(!card->host);
207da7fbe58SPierre Ossman 
208da7fbe58SPierre Ossman 	memset(&cmd, 0, sizeof(struct mmc_command));
209da7fbe58SPierre Ossman 
210da7fbe58SPierre Ossman 	cmd.opcode = MMC_SET_RELATIVE_ADDR;
211da7fbe58SPierre Ossman 	cmd.arg = card->rca << 16;
212da7fbe58SPierre Ossman 	cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
213da7fbe58SPierre Ossman 
214da7fbe58SPierre Ossman 	err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
21517b0429dSPierre Ossman 	if (err)
216da7fbe58SPierre Ossman 		return err;
217da7fbe58SPierre Ossman 
21817b0429dSPierre Ossman 	return 0;
219da7fbe58SPierre Ossman }
220da7fbe58SPierre Ossman 
221af517150SDavid Brownell static int
222af517150SDavid Brownell mmc_send_cxd_native(struct mmc_host *host, u32 arg, u32 *cxd, int opcode)
223da7fbe58SPierre Ossman {
224da7fbe58SPierre Ossman 	int err;
225da7fbe58SPierre Ossman 	struct mmc_command cmd;
226da7fbe58SPierre Ossman 
227af517150SDavid Brownell 	BUG_ON(!host);
228af517150SDavid Brownell 	BUG_ON(!cxd);
229da7fbe58SPierre Ossman 
230da7fbe58SPierre Ossman 	memset(&cmd, 0, sizeof(struct mmc_command));
231da7fbe58SPierre Ossman 
232af517150SDavid Brownell 	cmd.opcode = opcode;
233af517150SDavid Brownell 	cmd.arg = arg;
234da7fbe58SPierre Ossman 	cmd.flags = MMC_RSP_R2 | MMC_CMD_AC;
235da7fbe58SPierre Ossman 
236af517150SDavid Brownell 	err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES);
23717b0429dSPierre Ossman 	if (err)
238da7fbe58SPierre Ossman 		return err;
239da7fbe58SPierre Ossman 
240af517150SDavid Brownell 	memcpy(cxd, cmd.resp, sizeof(u32) * 4);
241da7fbe58SPierre Ossman 
24217b0429dSPierre Ossman 	return 0;
243da7fbe58SPierre Ossman }
244da7fbe58SPierre Ossman 
245af517150SDavid Brownell static int
246af517150SDavid Brownell mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host,
247af517150SDavid Brownell 		u32 opcode, void *buf, unsigned len)
248da7fbe58SPierre Ossman {
249da7fbe58SPierre Ossman 	struct mmc_request mrq;
250da7fbe58SPierre Ossman 	struct mmc_command cmd;
251da7fbe58SPierre Ossman 	struct mmc_data data;
252da7fbe58SPierre Ossman 	struct scatterlist sg;
253af517150SDavid Brownell 	void *data_buf;
254da7fbe58SPierre Ossman 
255af517150SDavid Brownell 	/* dma onto stack is unsafe/nonportable, but callers to this
256af517150SDavid Brownell 	 * routine normally provide temporary on-stack buffers ...
257af517150SDavid Brownell 	 */
258af517150SDavid Brownell 	data_buf = kmalloc(len, GFP_KERNEL);
259af517150SDavid Brownell 	if (data_buf == NULL)
260af517150SDavid Brownell 		return -ENOMEM;
261da7fbe58SPierre Ossman 
262da7fbe58SPierre Ossman 	memset(&mrq, 0, sizeof(struct mmc_request));
263da7fbe58SPierre Ossman 	memset(&cmd, 0, sizeof(struct mmc_command));
264da7fbe58SPierre Ossman 	memset(&data, 0, sizeof(struct mmc_data));
265da7fbe58SPierre Ossman 
266da7fbe58SPierre Ossman 	mrq.cmd = &cmd;
267da7fbe58SPierre Ossman 	mrq.data = &data;
268da7fbe58SPierre Ossman 
269af517150SDavid Brownell 	cmd.opcode = opcode;
270da7fbe58SPierre Ossman 	cmd.arg = 0;
271da7fbe58SPierre Ossman 
272af517150SDavid Brownell 	/* NOTE HACK:  the MMC_RSP_SPI_R1 is always correct here, but we
273af517150SDavid Brownell 	 * rely on callers to never use this with "native" calls for reading
274af517150SDavid Brownell 	 * CSD or CID.  Native versions of those commands use the R2 type,
275af517150SDavid Brownell 	 * not R1 plus a data block.
276af517150SDavid Brownell 	 */
277af517150SDavid Brownell 	cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
278af517150SDavid Brownell 
279af517150SDavid Brownell 	data.blksz = len;
280da7fbe58SPierre Ossman 	data.blocks = 1;
281da7fbe58SPierre Ossman 	data.flags = MMC_DATA_READ;
282da7fbe58SPierre Ossman 	data.sg = &sg;
283da7fbe58SPierre Ossman 	data.sg_len = 1;
284da7fbe58SPierre Ossman 
285af517150SDavid Brownell 	sg_init_one(&sg, data_buf, len);
286da7fbe58SPierre Ossman 
287cda56ac2SAdrian Hunter 	if (opcode == MMC_SEND_CSD || opcode == MMC_SEND_CID) {
2880d3e0460SMatthew Fleming 		/*
2890d3e0460SMatthew Fleming 		 * The spec states that CSR and CID accesses have a timeout
2900d3e0460SMatthew Fleming 		 * of 64 clock cycles.
2910d3e0460SMatthew Fleming 		 */
2920d3e0460SMatthew Fleming 		data.timeout_ns = 0;
2930d3e0460SMatthew Fleming 		data.timeout_clks = 64;
294cda56ac2SAdrian Hunter 	} else
295cda56ac2SAdrian Hunter 		mmc_set_data_timeout(&data, card);
296da7fbe58SPierre Ossman 
297af517150SDavid Brownell 	mmc_wait_for_req(host, &mrq);
298af517150SDavid Brownell 
299af517150SDavid Brownell 	memcpy(buf, data_buf, len);
300af517150SDavid Brownell 	kfree(data_buf);
301da7fbe58SPierre Ossman 
30217b0429dSPierre Ossman 	if (cmd.error)
303da7fbe58SPierre Ossman 		return cmd.error;
30417b0429dSPierre Ossman 	if (data.error)
305da7fbe58SPierre Ossman 		return data.error;
306da7fbe58SPierre Ossman 
30717b0429dSPierre Ossman 	return 0;
308da7fbe58SPierre Ossman }
309da7fbe58SPierre Ossman 
310af517150SDavid Brownell int mmc_send_csd(struct mmc_card *card, u32 *csd)
311af517150SDavid Brownell {
31278e48073SPierre Ossman 	int ret, i;
31378e48073SPierre Ossman 
314af517150SDavid Brownell 	if (!mmc_host_is_spi(card->host))
315af517150SDavid Brownell 		return mmc_send_cxd_native(card->host, card->rca << 16,
316af517150SDavid Brownell 				csd, MMC_SEND_CSD);
317af517150SDavid Brownell 
31878e48073SPierre Ossman 	ret = mmc_send_cxd_data(card, card->host, MMC_SEND_CSD, csd, 16);
31978e48073SPierre Ossman 	if (ret)
32078e48073SPierre Ossman 		return ret;
32178e48073SPierre Ossman 
32278e48073SPierre Ossman 	for (i = 0;i < 4;i++)
32378e48073SPierre Ossman 		csd[i] = be32_to_cpu(csd[i]);
32478e48073SPierre Ossman 
32578e48073SPierre Ossman 	return 0;
326af517150SDavid Brownell }
327af517150SDavid Brownell 
328af517150SDavid Brownell int mmc_send_cid(struct mmc_host *host, u32 *cid)
329af517150SDavid Brownell {
33078e48073SPierre Ossman 	int ret, i;
33178e48073SPierre Ossman 
332af517150SDavid Brownell 	if (!mmc_host_is_spi(host)) {
333af517150SDavid Brownell 		if (!host->card)
334af517150SDavid Brownell 			return -EINVAL;
335af517150SDavid Brownell 		return mmc_send_cxd_native(host, host->card->rca << 16,
336af517150SDavid Brownell 				cid, MMC_SEND_CID);
337af517150SDavid Brownell 	}
338af517150SDavid Brownell 
33978e48073SPierre Ossman 	ret = mmc_send_cxd_data(NULL, host, MMC_SEND_CID, cid, 16);
34078e48073SPierre Ossman 	if (ret)
34178e48073SPierre Ossman 		return ret;
34278e48073SPierre Ossman 
34378e48073SPierre Ossman 	for (i = 0;i < 4;i++)
34478e48073SPierre Ossman 		cid[i] = be32_to_cpu(cid[i]);
34578e48073SPierre Ossman 
34678e48073SPierre Ossman 	return 0;
347af517150SDavid Brownell }
348af517150SDavid Brownell 
349af517150SDavid Brownell int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd)
350af517150SDavid Brownell {
351af517150SDavid Brownell 	return mmc_send_cxd_data(card, card->host, MMC_SEND_EXT_CSD,
352af517150SDavid Brownell 			ext_csd, 512);
353af517150SDavid Brownell }
354af517150SDavid Brownell 
355af517150SDavid Brownell int mmc_spi_read_ocr(struct mmc_host *host, int highcap, u32 *ocrp)
356af517150SDavid Brownell {
357af517150SDavid Brownell 	struct mmc_command cmd;
358af517150SDavid Brownell 	int err;
359af517150SDavid Brownell 
360af517150SDavid Brownell 	memset(&cmd, 0, sizeof(struct mmc_command));
361af517150SDavid Brownell 
362af517150SDavid Brownell 	cmd.opcode = MMC_SPI_READ_OCR;
363af517150SDavid Brownell 	cmd.arg = highcap ? (1 << 30) : 0;
364af517150SDavid Brownell 	cmd.flags = MMC_RSP_SPI_R3;
365af517150SDavid Brownell 
366af517150SDavid Brownell 	err = mmc_wait_for_cmd(host, &cmd, 0);
367af517150SDavid Brownell 
368af517150SDavid Brownell 	*ocrp = cmd.resp[1];
369af517150SDavid Brownell 	return err;
370af517150SDavid Brownell }
371af517150SDavid Brownell 
372af517150SDavid Brownell int mmc_spi_set_crc(struct mmc_host *host, int use_crc)
373af517150SDavid Brownell {
374af517150SDavid Brownell 	struct mmc_command cmd;
375af517150SDavid Brownell 	int err;
376af517150SDavid Brownell 
377af517150SDavid Brownell 	memset(&cmd, 0, sizeof(struct mmc_command));
378af517150SDavid Brownell 
379af517150SDavid Brownell 	cmd.opcode = MMC_SPI_CRC_ON_OFF;
380af517150SDavid Brownell 	cmd.flags = MMC_RSP_SPI_R1;
381af517150SDavid Brownell 	cmd.arg = use_crc;
382af517150SDavid Brownell 
383af517150SDavid Brownell 	err = mmc_wait_for_cmd(host, &cmd, 0);
384af517150SDavid Brownell 	if (!err)
385af517150SDavid Brownell 		host->use_spi_crc = use_crc;
386af517150SDavid Brownell 	return err;
387af517150SDavid Brownell }
388af517150SDavid Brownell 
389da7fbe58SPierre Ossman int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value)
390da7fbe58SPierre Ossman {
391da7fbe58SPierre Ossman 	int err;
392da7fbe58SPierre Ossman 	struct mmc_command cmd;
393ef0b27d4SAdrian Hunter 	u32 status;
394da7fbe58SPierre Ossman 
395da7fbe58SPierre Ossman 	BUG_ON(!card);
396da7fbe58SPierre Ossman 	BUG_ON(!card->host);
397da7fbe58SPierre Ossman 
398da7fbe58SPierre Ossman 	memset(&cmd, 0, sizeof(struct mmc_command));
399da7fbe58SPierre Ossman 
400da7fbe58SPierre Ossman 	cmd.opcode = MMC_SWITCH;
401da7fbe58SPierre Ossman 	cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
402da7fbe58SPierre Ossman 		  (index << 16) |
403da7fbe58SPierre Ossman 		  (value << 8) |
404da7fbe58SPierre Ossman 		  set;
405af517150SDavid Brownell 	cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
406da7fbe58SPierre Ossman 
407da7fbe58SPierre Ossman 	err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
40817b0429dSPierre Ossman 	if (err)
409da7fbe58SPierre Ossman 		return err;
410da7fbe58SPierre Ossman 
411ef0b27d4SAdrian Hunter 	/* Must check status to be sure of no errors */
412ef0b27d4SAdrian Hunter 	do {
413ef0b27d4SAdrian Hunter 		err = mmc_send_status(card, &status);
414ef0b27d4SAdrian Hunter 		if (err)
415ef0b27d4SAdrian Hunter 			return err;
416ef0b27d4SAdrian Hunter 		if (card->host->caps & MMC_CAP_WAIT_WHILE_BUSY)
417ef0b27d4SAdrian Hunter 			break;
418ef0b27d4SAdrian Hunter 		if (mmc_host_is_spi(card->host))
419ef0b27d4SAdrian Hunter 			break;
420ef0b27d4SAdrian Hunter 	} while (R1_CURRENT_STATE(status) == 7);
421ef0b27d4SAdrian Hunter 
422ef0b27d4SAdrian Hunter 	if (mmc_host_is_spi(card->host)) {
423ef0b27d4SAdrian Hunter 		if (status & R1_SPI_ILLEGAL_COMMAND)
424ef0b27d4SAdrian Hunter 			return -EBADMSG;
425ef0b27d4SAdrian Hunter 	} else {
426ef0b27d4SAdrian Hunter 		if (status & 0xFDFFA000)
427ef0b27d4SAdrian Hunter 			printk(KERN_WARNING "%s: unexpected status %#x after "
428ef0b27d4SAdrian Hunter 			       "switch", mmc_hostname(card->host), status);
429ef0b27d4SAdrian Hunter 		if (status & R1_SWITCH_ERROR)
430ef0b27d4SAdrian Hunter 			return -EBADMSG;
431ef0b27d4SAdrian Hunter 	}
432ef0b27d4SAdrian Hunter 
43317b0429dSPierre Ossman 	return 0;
434da7fbe58SPierre Ossman }
435da7fbe58SPierre Ossman 
436da7fbe58SPierre Ossman int mmc_send_status(struct mmc_card *card, u32 *status)
437da7fbe58SPierre Ossman {
438da7fbe58SPierre Ossman 	int err;
439da7fbe58SPierre Ossman 	struct mmc_command cmd;
440da7fbe58SPierre Ossman 
441da7fbe58SPierre Ossman 	BUG_ON(!card);
442da7fbe58SPierre Ossman 	BUG_ON(!card->host);
443da7fbe58SPierre Ossman 
444da7fbe58SPierre Ossman 	memset(&cmd, 0, sizeof(struct mmc_command));
445da7fbe58SPierre Ossman 
446da7fbe58SPierre Ossman 	cmd.opcode = MMC_SEND_STATUS;
447af517150SDavid Brownell 	if (!mmc_host_is_spi(card->host))
448da7fbe58SPierre Ossman 		cmd.arg = card->rca << 16;
449af517150SDavid Brownell 	cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC;
450da7fbe58SPierre Ossman 
451da7fbe58SPierre Ossman 	err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
45217b0429dSPierre Ossman 	if (err)
453da7fbe58SPierre Ossman 		return err;
454da7fbe58SPierre Ossman 
455af517150SDavid Brownell 	/* NOTE: callers are required to understand the difference
456af517150SDavid Brownell 	 * between "native" and SPI format status words!
457af517150SDavid Brownell 	 */
458da7fbe58SPierre Ossman 	if (status)
459da7fbe58SPierre Ossman 		*status = cmd.resp[0];
460da7fbe58SPierre Ossman 
46117b0429dSPierre Ossman 	return 0;
462da7fbe58SPierre Ossman }
463da7fbe58SPierre Ossman 
464