xref: /openbmc/linux/drivers/mmc/core/mmc_ops.c (revision c21b37f6)
1 /*
2  *  linux/drivers/mmc/core/mmc_ops.h
3  *
4  *  Copyright 2006-2007 Pierre Ossman
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or (at
9  * your option) any later version.
10  */
11 
12 #include <linux/types.h>
13 #include <asm/scatterlist.h>
14 #include <linux/scatterlist.h>
15 
16 #include <linux/mmc/host.h>
17 #include <linux/mmc/card.h>
18 #include <linux/mmc/mmc.h>
19 
20 #include "core.h"
21 #include "mmc_ops.h"
22 
23 static int _mmc_select_card(struct mmc_host *host, struct mmc_card *card)
24 {
25 	int err;
26 	struct mmc_command cmd;
27 
28 	BUG_ON(!host);
29 
30 	memset(&cmd, 0, sizeof(struct mmc_command));
31 
32 	cmd.opcode = MMC_SELECT_CARD;
33 
34 	if (card) {
35 		cmd.arg = card->rca << 16;
36 		cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
37 	} else {
38 		cmd.arg = 0;
39 		cmd.flags = MMC_RSP_NONE | MMC_CMD_AC;
40 	}
41 
42 	err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES);
43 	if (err != MMC_ERR_NONE)
44 		return err;
45 
46 	return MMC_ERR_NONE;
47 }
48 
49 int mmc_select_card(struct mmc_card *card)
50 {
51 	BUG_ON(!card);
52 
53 	return _mmc_select_card(card->host, card);
54 }
55 
56 int mmc_deselect_cards(struct mmc_host *host)
57 {
58 	return _mmc_select_card(host, NULL);
59 }
60 
61 int mmc_go_idle(struct mmc_host *host)
62 {
63 	int err;
64 	struct mmc_command cmd;
65 
66 	mmc_set_chip_select(host, MMC_CS_HIGH);
67 
68 	mmc_delay(1);
69 
70 	memset(&cmd, 0, sizeof(struct mmc_command));
71 
72 	cmd.opcode = MMC_GO_IDLE_STATE;
73 	cmd.arg = 0;
74 	cmd.flags = MMC_RSP_NONE | MMC_CMD_BC;
75 
76 	err = mmc_wait_for_cmd(host, &cmd, 0);
77 
78 	mmc_delay(1);
79 
80 	mmc_set_chip_select(host, MMC_CS_DONTCARE);
81 
82 	mmc_delay(1);
83 
84 	return err;
85 }
86 
87 int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
88 {
89 	struct mmc_command cmd;
90 	int i, err = 0;
91 
92 	BUG_ON(!host);
93 
94 	memset(&cmd, 0, sizeof(struct mmc_command));
95 
96 	cmd.opcode = MMC_SEND_OP_COND;
97 	cmd.arg = ocr;
98 	cmd.flags = MMC_RSP_R3 | MMC_CMD_BCR;
99 
100 	for (i = 100; i; i--) {
101 		err = mmc_wait_for_cmd(host, &cmd, 0);
102 		if (err != MMC_ERR_NONE)
103 			break;
104 
105 		if (cmd.resp[0] & MMC_CARD_BUSY || ocr == 0)
106 			break;
107 
108 		err = MMC_ERR_TIMEOUT;
109 
110 		mmc_delay(10);
111 	}
112 
113 	if (rocr)
114 		*rocr = cmd.resp[0];
115 
116 	return err;
117 }
118 
119 int mmc_all_send_cid(struct mmc_host *host, u32 *cid)
120 {
121 	int err;
122 	struct mmc_command cmd;
123 
124 	BUG_ON(!host);
125 	BUG_ON(!cid);
126 
127 	memset(&cmd, 0, sizeof(struct mmc_command));
128 
129 	cmd.opcode = MMC_ALL_SEND_CID;
130 	cmd.arg = 0;
131 	cmd.flags = MMC_RSP_R2 | MMC_CMD_BCR;
132 
133 	err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES);
134 	if (err != MMC_ERR_NONE)
135 		return err;
136 
137 	memcpy(cid, cmd.resp, sizeof(u32) * 4);
138 
139 	return MMC_ERR_NONE;
140 }
141 
142 int mmc_set_relative_addr(struct mmc_card *card)
143 {
144 	int err;
145 	struct mmc_command cmd;
146 
147 	BUG_ON(!card);
148 	BUG_ON(!card->host);
149 
150 	memset(&cmd, 0, sizeof(struct mmc_command));
151 
152 	cmd.opcode = MMC_SET_RELATIVE_ADDR;
153 	cmd.arg = card->rca << 16;
154 	cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
155 
156 	err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
157 	if (err != MMC_ERR_NONE)
158 		return err;
159 
160 	return MMC_ERR_NONE;
161 }
162 
163 int mmc_send_csd(struct mmc_card *card, u32 *csd)
164 {
165 	int err;
166 	struct mmc_command cmd;
167 
168 	BUG_ON(!card);
169 	BUG_ON(!card->host);
170 	BUG_ON(!csd);
171 
172 	memset(&cmd, 0, sizeof(struct mmc_command));
173 
174 	cmd.opcode = MMC_SEND_CSD;
175 	cmd.arg = card->rca << 16;
176 	cmd.flags = MMC_RSP_R2 | MMC_CMD_AC;
177 
178 	err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
179 	if (err != MMC_ERR_NONE)
180 		return err;
181 
182 	memcpy(csd, cmd.resp, sizeof(u32) * 4);
183 
184 	return MMC_ERR_NONE;
185 }
186 
187 int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd)
188 {
189 	struct mmc_request mrq;
190 	struct mmc_command cmd;
191 	struct mmc_data data;
192 	struct scatterlist sg;
193 
194 	BUG_ON(!card);
195 	BUG_ON(!card->host);
196 	BUG_ON(!ext_csd);
197 
198 	memset(&mrq, 0, sizeof(struct mmc_request));
199 	memset(&cmd, 0, sizeof(struct mmc_command));
200 	memset(&data, 0, sizeof(struct mmc_data));
201 
202 	mrq.cmd = &cmd;
203 	mrq.data = &data;
204 
205 	cmd.opcode = MMC_SEND_EXT_CSD;
206 	cmd.arg = 0;
207 	cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
208 
209 	data.blksz = 512;
210 	data.blocks = 1;
211 	data.flags = MMC_DATA_READ;
212 	data.sg = &sg;
213 	data.sg_len = 1;
214 
215 	sg_init_one(&sg, ext_csd, 512);
216 
217 	mmc_set_data_timeout(&data, card, 0);
218 
219 	mmc_wait_for_req(card->host, &mrq);
220 
221 	if (cmd.error != MMC_ERR_NONE)
222 		return cmd.error;
223 	if (data.error != MMC_ERR_NONE)
224 		return data.error;
225 
226 	return MMC_ERR_NONE;
227 }
228 
229 int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value)
230 {
231 	int err;
232 	struct mmc_command cmd;
233 
234 	BUG_ON(!card);
235 	BUG_ON(!card->host);
236 
237 	memset(&cmd, 0, sizeof(struct mmc_command));
238 
239 	cmd.opcode = MMC_SWITCH;
240 	cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
241 		  (index << 16) |
242 		  (value << 8) |
243 		  set;
244 	cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
245 
246 	err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
247 	if (err != MMC_ERR_NONE)
248 		return err;
249 
250 	return MMC_ERR_NONE;
251 }
252 
253 int mmc_send_status(struct mmc_card *card, u32 *status)
254 {
255 	int err;
256 	struct mmc_command cmd;
257 
258 	BUG_ON(!card);
259 	BUG_ON(!card->host);
260 
261 	memset(&cmd, 0, sizeof(struct mmc_command));
262 
263 	cmd.opcode = MMC_SEND_STATUS;
264 	cmd.arg = card->rca << 16;
265 	cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
266 
267 	err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
268 	if (err != MMC_ERR_NONE)
269 		return err;
270 
271 	if (status)
272 		*status = cmd.resp[0];
273 
274 	return MMC_ERR_NONE;
275 }
276 
277