Commit | Line | Data |
---|---|---|
da7fbe58 | 1 | /* |
70f10482 | 2 | * linux/drivers/mmc/core/sd_ops.h |
da7fbe58 PO |
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 | ||
4f665cb6 | 12 | #include <linux/slab.h> |
da7fbe58 | 13 | #include <linux/types.h> |
3ef77af1 | 14 | #include <linux/export.h> |
da7fbe58 PO |
15 | #include <linux/scatterlist.h> |
16 | ||
17 | #include <linux/mmc/host.h> | |
18 | #include <linux/mmc/card.h> | |
19 | #include <linux/mmc/mmc.h> | |
20 | #include <linux/mmc/sd.h> | |
21 | ||
22 | #include "core.h" | |
23 | #include "sd_ops.h" | |
24 | ||
cb87ea28 | 25 | int mmc_app_cmd(struct mmc_host *host, struct mmc_card *card) |
39361851 AB |
26 | { |
27 | int err; | |
c7836d15 | 28 | struct mmc_command cmd = {}; |
39361851 | 29 | |
349583d6 SL |
30 | if (WARN_ON(card && card->host != host)) |
31 | return -EINVAL; | |
39361851 AB |
32 | |
33 | cmd.opcode = MMC_APP_CMD; | |
34 | ||
35 | if (card) { | |
36 | cmd.arg = card->rca << 16; | |
af517150 | 37 | cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC; |
39361851 AB |
38 | } else { |
39 | cmd.arg = 0; | |
af517150 | 40 | cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_BCR; |
39361851 AB |
41 | } |
42 | ||
43 | err = mmc_wait_for_cmd(host, &cmd, 0); | |
17b0429d | 44 | if (err) |
39361851 AB |
45 | return err; |
46 | ||
47 | /* Check that card supported application commands */ | |
af517150 | 48 | if (!mmc_host_is_spi(host) && !(cmd.resp[0] & R1_APP_CMD)) |
17b0429d | 49 | return -EOPNOTSUPP; |
39361851 | 50 | |
17b0429d | 51 | return 0; |
39361851 | 52 | } |
cb87ea28 | 53 | EXPORT_SYMBOL_GPL(mmc_app_cmd); |
39361851 | 54 | |
da7fbe58 PO |
55 | /** |
56 | * mmc_wait_for_app_cmd - start an application command and wait for | |
57 | completion | |
58 | * @host: MMC host to start command | |
67a61c48 | 59 | * @card: Card to send MMC_APP_CMD to |
da7fbe58 PO |
60 | * @cmd: MMC command to start |
61 | * @retries: maximum number of retries | |
62 | * | |
63 | * Sends a MMC_APP_CMD, checks the card response, sends the command | |
64 | * in the parameter and waits for it to complete. Return any error | |
65 | * that occurred while the command was executing. Do not attempt to | |
66 | * parse the response. | |
67 | */ | |
68 | int mmc_wait_for_app_cmd(struct mmc_host *host, struct mmc_card *card, | |
69 | struct mmc_command *cmd, int retries) | |
70 | { | |
c7836d15 | 71 | struct mmc_request mrq = {}; |
da7fbe58 PO |
72 | |
73 | int i, err; | |
74 | ||
349583d6 SL |
75 | if (retries < 0) |
76 | retries = MMC_CMD_RETRIES; | |
da7fbe58 | 77 | |
17b0429d | 78 | err = -EIO; |
da7fbe58 PO |
79 | |
80 | /* | |
81 | * We have to resend MMC_APP_CMD for each attempt so | |
82 | * we cannot use the retries field in mmc_command. | |
83 | */ | |
84 | for (i = 0;i <= retries;i++) { | |
da7fbe58 | 85 | err = mmc_app_cmd(host, card); |
af517150 DB |
86 | if (err) { |
87 | /* no point in retrying; no APP commands allowed */ | |
88 | if (mmc_host_is_spi(host)) { | |
89 | if (cmd->resp[0] & R1_SPI_ILLEGAL_COMMAND) | |
90 | break; | |
91 | } | |
da7fbe58 | 92 | continue; |
af517150 | 93 | } |
da7fbe58 PO |
94 | |
95 | memset(&mrq, 0, sizeof(struct mmc_request)); | |
96 | ||
97 | memset(cmd->resp, 0, sizeof(cmd->resp)); | |
98 | cmd->retries = 0; | |
99 | ||
100 | mrq.cmd = cmd; | |
101 | cmd->data = NULL; | |
102 | ||
103 | mmc_wait_for_req(host, &mrq); | |
104 | ||
105 | err = cmd->error; | |
17b0429d | 106 | if (!cmd->error) |
da7fbe58 | 107 | break; |
af517150 DB |
108 | |
109 | /* no point in retrying illegal APP commands */ | |
110 | if (mmc_host_is_spi(host)) { | |
111 | if (cmd->resp[0] & R1_SPI_ILLEGAL_COMMAND) | |
112 | break; | |
113 | } | |
da7fbe58 PO |
114 | } |
115 | ||
116 | return err; | |
117 | } | |
118 | ||
119 | EXPORT_SYMBOL(mmc_wait_for_app_cmd); | |
120 | ||
da7fbe58 PO |
121 | int mmc_app_set_bus_width(struct mmc_card *card, int width) |
122 | { | |
c7836d15 | 123 | struct mmc_command cmd = {}; |
da7fbe58 | 124 | |
da7fbe58 PO |
125 | cmd.opcode = SD_APP_SET_BUS_WIDTH; |
126 | cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; | |
127 | ||
128 | switch (width) { | |
129 | case MMC_BUS_WIDTH_1: | |
130 | cmd.arg = SD_BUS_WIDTH_1; | |
131 | break; | |
132 | case MMC_BUS_WIDTH_4: | |
133 | cmd.arg = SD_BUS_WIDTH_4; | |
134 | break; | |
135 | default: | |
17b0429d | 136 | return -EINVAL; |
da7fbe58 PO |
137 | } |
138 | ||
0899e741 | 139 | return mmc_wait_for_app_cmd(card->host, card, &cmd, MMC_CMD_RETRIES); |
da7fbe58 PO |
140 | } |
141 | ||
142 | int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr) | |
143 | { | |
c7836d15 | 144 | struct mmc_command cmd = {}; |
da7fbe58 PO |
145 | int i, err = 0; |
146 | ||
da7fbe58 | 147 | cmd.opcode = SD_APP_OP_COND; |
af517150 DB |
148 | if (mmc_host_is_spi(host)) |
149 | cmd.arg = ocr & (1 << 30); /* SPI only defines one bit */ | |
150 | else | |
151 | cmd.arg = ocr; | |
152 | cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R3 | MMC_CMD_BCR; | |
da7fbe58 PO |
153 | |
154 | for (i = 100; i; i--) { | |
155 | err = mmc_wait_for_app_cmd(host, NULL, &cmd, MMC_CMD_RETRIES); | |
17b0429d | 156 | if (err) |
da7fbe58 PO |
157 | break; |
158 | ||
af517150 DB |
159 | /* if we're just probing, do a single pass */ |
160 | if (ocr == 0) | |
da7fbe58 PO |
161 | break; |
162 | ||
af517150 DB |
163 | /* otherwise wait until reset completes */ |
164 | if (mmc_host_is_spi(host)) { | |
165 | if (!(cmd.resp[0] & R1_SPI_IDLE)) | |
166 | break; | |
167 | } else { | |
168 | if (cmd.resp[0] & MMC_CARD_BUSY) | |
169 | break; | |
170 | } | |
171 | ||
17b0429d | 172 | err = -ETIMEDOUT; |
da7fbe58 PO |
173 | |
174 | mmc_delay(10); | |
175 | } | |
176 | ||
5e863662 JR |
177 | if (!i) |
178 | pr_err("%s: card never left busy state\n", mmc_hostname(host)); | |
179 | ||
af517150 | 180 | if (rocr && !mmc_host_is_spi(host)) |
da7fbe58 PO |
181 | *rocr = cmd.resp[0]; |
182 | ||
183 | return err; | |
184 | } | |
185 | ||
186 | int mmc_send_if_cond(struct mmc_host *host, u32 ocr) | |
187 | { | |
c7836d15 | 188 | struct mmc_command cmd = {}; |
da7fbe58 PO |
189 | int err; |
190 | static const u8 test_pattern = 0xAA; | |
af517150 | 191 | u8 result_pattern; |
da7fbe58 PO |
192 | |
193 | /* | |
194 | * To support SD 2.0 cards, we must always invoke SD_SEND_IF_COND | |
195 | * before SD_APP_OP_COND. This command will harmlessly fail for | |
196 | * SD 1.0 cards. | |
197 | */ | |
198 | cmd.opcode = SD_SEND_IF_COND; | |
199 | cmd.arg = ((ocr & 0xFF8000) != 0) << 8 | test_pattern; | |
af517150 | 200 | cmd.flags = MMC_RSP_SPI_R7 | MMC_RSP_R7 | MMC_CMD_BCR; |
da7fbe58 PO |
201 | |
202 | err = mmc_wait_for_cmd(host, &cmd, 0); | |
17b0429d | 203 | if (err) |
da7fbe58 PO |
204 | return err; |
205 | ||
af517150 DB |
206 | if (mmc_host_is_spi(host)) |
207 | result_pattern = cmd.resp[1] & 0xFF; | |
208 | else | |
209 | result_pattern = cmd.resp[0] & 0xFF; | |
210 | ||
211 | if (result_pattern != test_pattern) | |
17b0429d | 212 | return -EIO; |
da7fbe58 | 213 | |
17b0429d | 214 | return 0; |
da7fbe58 PO |
215 | } |
216 | ||
217 | int mmc_send_relative_addr(struct mmc_host *host, unsigned int *rca) | |
218 | { | |
219 | int err; | |
c7836d15 | 220 | struct mmc_command cmd = {}; |
da7fbe58 | 221 | |
da7fbe58 PO |
222 | cmd.opcode = SD_SEND_RELATIVE_ADDR; |
223 | cmd.arg = 0; | |
224 | cmd.flags = MMC_RSP_R6 | MMC_CMD_BCR; | |
225 | ||
226 | err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES); | |
17b0429d | 227 | if (err) |
da7fbe58 PO |
228 | return err; |
229 | ||
230 | *rca = cmd.resp[0] >> 16; | |
231 | ||
17b0429d | 232 | return 0; |
da7fbe58 PO |
233 | } |
234 | ||
235 | int mmc_app_send_scr(struct mmc_card *card, u32 *scr) | |
236 | { | |
237 | int err; | |
c7836d15 MY |
238 | struct mmc_request mrq = {}; |
239 | struct mmc_command cmd = {}; | |
240 | struct mmc_data data = {}; | |
da7fbe58 | 241 | struct scatterlist sg; |
4f665cb6 | 242 | void *data_buf; |
da7fbe58 | 243 | |
af517150 DB |
244 | /* NOTE: caller guarantees scr is heap-allocated */ |
245 | ||
da7fbe58 | 246 | err = mmc_app_cmd(card->host, card); |
17b0429d | 247 | if (err) |
da7fbe58 PO |
248 | return err; |
249 | ||
4f665cb6 YS |
250 | /* dma onto stack is unsafe/nonportable, but callers to this |
251 | * routine normally provide temporary on-stack buffers ... | |
252 | */ | |
253 | data_buf = kmalloc(sizeof(card->raw_scr), GFP_KERNEL); | |
254 | if (data_buf == NULL) | |
255 | return -ENOMEM; | |
256 | ||
da7fbe58 PO |
257 | mrq.cmd = &cmd; |
258 | mrq.data = &data; | |
259 | ||
260 | cmd.opcode = SD_APP_SEND_SCR; | |
261 | cmd.arg = 0; | |
af517150 | 262 | cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; |
da7fbe58 PO |
263 | |
264 | data.blksz = 8; | |
265 | data.blocks = 1; | |
266 | data.flags = MMC_DATA_READ; | |
267 | data.sg = &sg; | |
268 | data.sg_len = 1; | |
269 | ||
4f665cb6 | 270 | sg_init_one(&sg, data_buf, 8); |
da7fbe58 | 271 | |
b146d26a | 272 | mmc_set_data_timeout(&data, card); |
da7fbe58 PO |
273 | |
274 | mmc_wait_for_req(card->host, &mrq); | |
275 | ||
4f665cb6 YS |
276 | memcpy(scr, data_buf, sizeof(card->raw_scr)); |
277 | kfree(data_buf); | |
278 | ||
17b0429d | 279 | if (cmd.error) |
da7fbe58 | 280 | return cmd.error; |
17b0429d | 281 | if (data.error) |
da7fbe58 PO |
282 | return data.error; |
283 | ||
1fa8dd14 PO |
284 | scr[0] = be32_to_cpu(scr[0]); |
285 | scr[1] = be32_to_cpu(scr[1]); | |
da7fbe58 | 286 | |
17b0429d | 287 | return 0; |
da7fbe58 PO |
288 | } |
289 | ||
290 | int mmc_sd_switch(struct mmc_card *card, int mode, int group, | |
291 | u8 value, u8 *resp) | |
292 | { | |
c7836d15 MY |
293 | struct mmc_request mrq = {}; |
294 | struct mmc_command cmd = {}; | |
295 | struct mmc_data data = {}; | |
da7fbe58 PO |
296 | struct scatterlist sg; |
297 | ||
af517150 DB |
298 | /* NOTE: caller guarantees resp is heap-allocated */ |
299 | ||
da7fbe58 PO |
300 | mode = !!mode; |
301 | value &= 0xF; | |
302 | ||
da7fbe58 PO |
303 | mrq.cmd = &cmd; |
304 | mrq.data = &data; | |
305 | ||
306 | cmd.opcode = SD_SWITCH; | |
307 | cmd.arg = mode << 31 | 0x00FFFFFF; | |
308 | cmd.arg &= ~(0xF << (group * 4)); | |
309 | cmd.arg |= value << (group * 4); | |
af517150 | 310 | cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; |
da7fbe58 PO |
311 | |
312 | data.blksz = 64; | |
313 | data.blocks = 1; | |
314 | data.flags = MMC_DATA_READ; | |
315 | data.sg = &sg; | |
316 | data.sg_len = 1; | |
317 | ||
318 | sg_init_one(&sg, resp, 64); | |
319 | ||
b146d26a | 320 | mmc_set_data_timeout(&data, card); |
da7fbe58 PO |
321 | |
322 | mmc_wait_for_req(card->host, &mrq); | |
323 | ||
17b0429d | 324 | if (cmd.error) |
da7fbe58 | 325 | return cmd.error; |
17b0429d | 326 | if (data.error) |
da7fbe58 PO |
327 | return data.error; |
328 | ||
17b0429d | 329 | return 0; |
da7fbe58 PO |
330 | } |
331 | ||
dfe86cba AH |
332 | int mmc_app_sd_status(struct mmc_card *card, void *ssr) |
333 | { | |
334 | int err; | |
c7836d15 MY |
335 | struct mmc_request mrq = {}; |
336 | struct mmc_command cmd = {}; | |
337 | struct mmc_data data = {}; | |
dfe86cba AH |
338 | struct scatterlist sg; |
339 | ||
dfe86cba AH |
340 | /* NOTE: caller guarantees ssr is heap-allocated */ |
341 | ||
342 | err = mmc_app_cmd(card->host, card); | |
343 | if (err) | |
344 | return err; | |
345 | ||
dfe86cba AH |
346 | mrq.cmd = &cmd; |
347 | mrq.data = &data; | |
348 | ||
349 | cmd.opcode = SD_APP_SD_STATUS; | |
350 | cmd.arg = 0; | |
351 | cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_ADTC; | |
352 | ||
353 | data.blksz = 64; | |
354 | data.blocks = 1; | |
355 | data.flags = MMC_DATA_READ; | |
356 | data.sg = &sg; | |
357 | data.sg_len = 1; | |
358 | ||
359 | sg_init_one(&sg, ssr, 64); | |
360 | ||
361 | mmc_set_data_timeout(&data, card); | |
362 | ||
363 | mmc_wait_for_req(card->host, &mrq); | |
364 | ||
365 | if (cmd.error) | |
366 | return cmd.error; | |
367 | if (data.error) | |
368 | return data.error; | |
369 | ||
370 | return 0; | |
371 | } |