Commit | Line | Data |
---|---|---|
da7fbe58 | 1 | /* |
70f10482 | 2 | * linux/drivers/mmc/core/mmc_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 | ||
12 | #include <linux/types.h> | |
da7fbe58 PO |
13 | #include <linux/scatterlist.h> |
14 | ||
15 | #include <linux/mmc/host.h> | |
16 | #include <linux/mmc/card.h> | |
17 | #include <linux/mmc/mmc.h> | |
18 | ||
19 | #include "core.h" | |
20 | #include "mmc_ops.h" | |
21 | ||
22 | static int _mmc_select_card(struct mmc_host *host, struct mmc_card *card) | |
23 | { | |
24 | int err; | |
25 | struct mmc_command cmd; | |
26 | ||
27 | BUG_ON(!host); | |
28 | ||
29 | memset(&cmd, 0, sizeof(struct mmc_command)); | |
30 | ||
31 | cmd.opcode = MMC_SELECT_CARD; | |
32 | ||
33 | if (card) { | |
34 | cmd.arg = card->rca << 16; | |
35 | cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; | |
36 | } else { | |
37 | cmd.arg = 0; | |
38 | cmd.flags = MMC_RSP_NONE | MMC_CMD_AC; | |
39 | } | |
40 | ||
41 | err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES); | |
17b0429d | 42 | if (err) |
da7fbe58 PO |
43 | return err; |
44 | ||
17b0429d | 45 | return 0; |
da7fbe58 PO |
46 | } |
47 | ||
48 | int mmc_select_card(struct mmc_card *card) | |
49 | { | |
50 | BUG_ON(!card); | |
51 | ||
52 | return _mmc_select_card(card->host, card); | |
53 | } | |
54 | ||
55 | int mmc_deselect_cards(struct mmc_host *host) | |
56 | { | |
57 | return _mmc_select_card(host, NULL); | |
58 | } | |
59 | ||
60 | int mmc_go_idle(struct mmc_host *host) | |
61 | { | |
62 | int err; | |
63 | struct mmc_command cmd; | |
64 | ||
af517150 DB |
65 | /* |
66 | * Non-SPI hosts need to prevent chipselect going active during | |
67 | * GO_IDLE; that would put chips into SPI mode. Remind them of | |
68 | * that in case of hardware that won't pull up DAT3/nCS otherwise. | |
69 | * | |
70 | * SPI hosts ignore ios.chip_select; it's managed according to | |
71 | * rules that must accomodate non-MMC slaves which this layer | |
72 | * won't even know about. | |
73 | */ | |
74 | if (!mmc_host_is_spi(host)) { | |
75 | mmc_set_chip_select(host, MMC_CS_HIGH); | |
76 | mmc_delay(1); | |
77 | } | |
da7fbe58 PO |
78 | |
79 | memset(&cmd, 0, sizeof(struct mmc_command)); | |
80 | ||
81 | cmd.opcode = MMC_GO_IDLE_STATE; | |
82 | cmd.arg = 0; | |
af517150 | 83 | cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_NONE | MMC_CMD_BC; |
da7fbe58 PO |
84 | |
85 | err = mmc_wait_for_cmd(host, &cmd, 0); | |
86 | ||
87 | mmc_delay(1); | |
88 | ||
af517150 DB |
89 | if (!mmc_host_is_spi(host)) { |
90 | mmc_set_chip_select(host, MMC_CS_DONTCARE); | |
91 | mmc_delay(1); | |
92 | } | |
da7fbe58 | 93 | |
af517150 | 94 | host->use_spi_crc = 0; |
da7fbe58 PO |
95 | |
96 | return err; | |
97 | } | |
98 | ||
99 | int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr) | |
100 | { | |
101 | struct mmc_command cmd; | |
102 | int i, err = 0; | |
103 | ||
104 | BUG_ON(!host); | |
105 | ||
106 | memset(&cmd, 0, sizeof(struct mmc_command)); | |
107 | ||
108 | cmd.opcode = MMC_SEND_OP_COND; | |
af517150 DB |
109 | cmd.arg = mmc_host_is_spi(host) ? 0 : ocr; |
110 | cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R3 | MMC_CMD_BCR; | |
da7fbe58 PO |
111 | |
112 | for (i = 100; i; i--) { | |
113 | err = mmc_wait_for_cmd(host, &cmd, 0); | |
17b0429d | 114 | if (err) |
da7fbe58 PO |
115 | break; |
116 | ||
af517150 DB |
117 | /* if we're just probing, do a single pass */ |
118 | if (ocr == 0) | |
da7fbe58 PO |
119 | break; |
120 | ||
af517150 DB |
121 | /* otherwise wait until reset completes */ |
122 | if (mmc_host_is_spi(host)) { | |
123 | if (!(cmd.resp[0] & R1_SPI_IDLE)) | |
124 | break; | |
125 | } else { | |
126 | if (cmd.resp[0] & MMC_CARD_BUSY) | |
127 | break; | |
128 | } | |
129 | ||
17b0429d | 130 | err = -ETIMEDOUT; |
da7fbe58 PO |
131 | |
132 | mmc_delay(10); | |
133 | } | |
134 | ||
af517150 | 135 | if (rocr && !mmc_host_is_spi(host)) |
da7fbe58 PO |
136 | *rocr = cmd.resp[0]; |
137 | ||
138 | return err; | |
139 | } | |
140 | ||
141 | int mmc_all_send_cid(struct mmc_host *host, u32 *cid) | |
142 | { | |
143 | int err; | |
144 | struct mmc_command cmd; | |
145 | ||
146 | BUG_ON(!host); | |
147 | BUG_ON(!cid); | |
148 | ||
149 | memset(&cmd, 0, sizeof(struct mmc_command)); | |
150 | ||
151 | cmd.opcode = MMC_ALL_SEND_CID; | |
152 | cmd.arg = 0; | |
153 | cmd.flags = MMC_RSP_R2 | MMC_CMD_BCR; | |
154 | ||
155 | err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES); | |
17b0429d | 156 | if (err) |
da7fbe58 PO |
157 | return err; |
158 | ||
159 | memcpy(cid, cmd.resp, sizeof(u32) * 4); | |
160 | ||
17b0429d | 161 | return 0; |
da7fbe58 PO |
162 | } |
163 | ||
164 | int mmc_set_relative_addr(struct mmc_card *card) | |
165 | { | |
166 | int err; | |
167 | struct mmc_command cmd; | |
168 | ||
169 | BUG_ON(!card); | |
170 | BUG_ON(!card->host); | |
171 | ||
172 | memset(&cmd, 0, sizeof(struct mmc_command)); | |
173 | ||
174 | cmd.opcode = MMC_SET_RELATIVE_ADDR; | |
175 | cmd.arg = card->rca << 16; | |
176 | cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; | |
177 | ||
178 | err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES); | |
17b0429d | 179 | if (err) |
da7fbe58 PO |
180 | return err; |
181 | ||
17b0429d | 182 | return 0; |
da7fbe58 PO |
183 | } |
184 | ||
af517150 DB |
185 | static int |
186 | mmc_send_cxd_native(struct mmc_host *host, u32 arg, u32 *cxd, int opcode) | |
da7fbe58 PO |
187 | { |
188 | int err; | |
189 | struct mmc_command cmd; | |
190 | ||
af517150 DB |
191 | BUG_ON(!host); |
192 | BUG_ON(!cxd); | |
da7fbe58 PO |
193 | |
194 | memset(&cmd, 0, sizeof(struct mmc_command)); | |
195 | ||
af517150 DB |
196 | cmd.opcode = opcode; |
197 | cmd.arg = arg; | |
da7fbe58 PO |
198 | cmd.flags = MMC_RSP_R2 | MMC_CMD_AC; |
199 | ||
af517150 | 200 | err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES); |
17b0429d | 201 | if (err) |
da7fbe58 PO |
202 | return err; |
203 | ||
af517150 | 204 | memcpy(cxd, cmd.resp, sizeof(u32) * 4); |
da7fbe58 | 205 | |
17b0429d | 206 | return 0; |
da7fbe58 PO |
207 | } |
208 | ||
af517150 DB |
209 | static int |
210 | mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host, | |
211 | u32 opcode, void *buf, unsigned len) | |
da7fbe58 PO |
212 | { |
213 | struct mmc_request mrq; | |
214 | struct mmc_command cmd; | |
215 | struct mmc_data data; | |
216 | struct scatterlist sg; | |
af517150 | 217 | void *data_buf; |
da7fbe58 | 218 | |
af517150 DB |
219 | /* dma onto stack is unsafe/nonportable, but callers to this |
220 | * routine normally provide temporary on-stack buffers ... | |
221 | */ | |
222 | data_buf = kmalloc(len, GFP_KERNEL); | |
223 | if (data_buf == NULL) | |
224 | return -ENOMEM; | |
da7fbe58 PO |
225 | |
226 | memset(&mrq, 0, sizeof(struct mmc_request)); | |
227 | memset(&cmd, 0, sizeof(struct mmc_command)); | |
228 | memset(&data, 0, sizeof(struct mmc_data)); | |
229 | ||
230 | mrq.cmd = &cmd; | |
231 | mrq.data = &data; | |
232 | ||
af517150 | 233 | cmd.opcode = opcode; |
da7fbe58 | 234 | cmd.arg = 0; |
da7fbe58 | 235 | |
af517150 DB |
236 | /* NOTE HACK: the MMC_RSP_SPI_R1 is always correct here, but we |
237 | * rely on callers to never use this with "native" calls for reading | |
238 | * CSD or CID. Native versions of those commands use the R2 type, | |
239 | * not R1 plus a data block. | |
240 | */ | |
241 | cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; | |
242 | ||
243 | data.blksz = len; | |
da7fbe58 PO |
244 | data.blocks = 1; |
245 | data.flags = MMC_DATA_READ; | |
246 | data.sg = &sg; | |
247 | data.sg_len = 1; | |
248 | ||
af517150 | 249 | sg_init_one(&sg, data_buf, len); |
da7fbe58 | 250 | |
0d3e0460 MF |
251 | /* |
252 | * The spec states that CSR and CID accesses have a timeout | |
253 | * of 64 clock cycles. | |
254 | */ | |
255 | data.timeout_ns = 0; | |
256 | data.timeout_clks = 64; | |
da7fbe58 | 257 | |
af517150 DB |
258 | mmc_wait_for_req(host, &mrq); |
259 | ||
260 | memcpy(buf, data_buf, len); | |
261 | kfree(data_buf); | |
da7fbe58 | 262 | |
17b0429d | 263 | if (cmd.error) |
da7fbe58 | 264 | return cmd.error; |
17b0429d | 265 | if (data.error) |
da7fbe58 PO |
266 | return data.error; |
267 | ||
17b0429d | 268 | return 0; |
da7fbe58 PO |
269 | } |
270 | ||
af517150 DB |
271 | int mmc_send_csd(struct mmc_card *card, u32 *csd) |
272 | { | |
78e48073 PO |
273 | int ret, i; |
274 | ||
af517150 DB |
275 | if (!mmc_host_is_spi(card->host)) |
276 | return mmc_send_cxd_native(card->host, card->rca << 16, | |
277 | csd, MMC_SEND_CSD); | |
278 | ||
78e48073 PO |
279 | ret = mmc_send_cxd_data(card, card->host, MMC_SEND_CSD, csd, 16); |
280 | if (ret) | |
281 | return ret; | |
282 | ||
283 | for (i = 0;i < 4;i++) | |
284 | csd[i] = be32_to_cpu(csd[i]); | |
285 | ||
286 | return 0; | |
af517150 DB |
287 | } |
288 | ||
289 | int mmc_send_cid(struct mmc_host *host, u32 *cid) | |
290 | { | |
78e48073 PO |
291 | int ret, i; |
292 | ||
af517150 DB |
293 | if (!mmc_host_is_spi(host)) { |
294 | if (!host->card) | |
295 | return -EINVAL; | |
296 | return mmc_send_cxd_native(host, host->card->rca << 16, | |
297 | cid, MMC_SEND_CID); | |
298 | } | |
299 | ||
78e48073 PO |
300 | ret = mmc_send_cxd_data(NULL, host, MMC_SEND_CID, cid, 16); |
301 | if (ret) | |
302 | return ret; | |
303 | ||
304 | for (i = 0;i < 4;i++) | |
305 | cid[i] = be32_to_cpu(cid[i]); | |
306 | ||
307 | return 0; | |
af517150 DB |
308 | } |
309 | ||
310 | int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd) | |
311 | { | |
312 | return mmc_send_cxd_data(card, card->host, MMC_SEND_EXT_CSD, | |
313 | ext_csd, 512); | |
314 | } | |
315 | ||
316 | int mmc_spi_read_ocr(struct mmc_host *host, int highcap, u32 *ocrp) | |
317 | { | |
318 | struct mmc_command cmd; | |
319 | int err; | |
320 | ||
321 | memset(&cmd, 0, sizeof(struct mmc_command)); | |
322 | ||
323 | cmd.opcode = MMC_SPI_READ_OCR; | |
324 | cmd.arg = highcap ? (1 << 30) : 0; | |
325 | cmd.flags = MMC_RSP_SPI_R3; | |
326 | ||
327 | err = mmc_wait_for_cmd(host, &cmd, 0); | |
328 | ||
329 | *ocrp = cmd.resp[1]; | |
330 | return err; | |
331 | } | |
332 | ||
333 | int mmc_spi_set_crc(struct mmc_host *host, int use_crc) | |
334 | { | |
335 | struct mmc_command cmd; | |
336 | int err; | |
337 | ||
338 | memset(&cmd, 0, sizeof(struct mmc_command)); | |
339 | ||
340 | cmd.opcode = MMC_SPI_CRC_ON_OFF; | |
341 | cmd.flags = MMC_RSP_SPI_R1; | |
342 | cmd.arg = use_crc; | |
343 | ||
344 | err = mmc_wait_for_cmd(host, &cmd, 0); | |
345 | if (!err) | |
346 | host->use_spi_crc = use_crc; | |
347 | return err; | |
348 | } | |
349 | ||
da7fbe58 PO |
350 | int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value) |
351 | { | |
352 | int err; | |
353 | struct mmc_command cmd; | |
354 | ||
355 | BUG_ON(!card); | |
356 | BUG_ON(!card->host); | |
357 | ||
358 | memset(&cmd, 0, sizeof(struct mmc_command)); | |
359 | ||
360 | cmd.opcode = MMC_SWITCH; | |
361 | cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | | |
362 | (index << 16) | | |
363 | (value << 8) | | |
364 | set; | |
af517150 | 365 | cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; |
da7fbe58 PO |
366 | |
367 | err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES); | |
17b0429d | 368 | if (err) |
da7fbe58 PO |
369 | return err; |
370 | ||
17b0429d | 371 | return 0; |
da7fbe58 PO |
372 | } |
373 | ||
374 | int mmc_send_status(struct mmc_card *card, u32 *status) | |
375 | { | |
376 | int err; | |
377 | struct mmc_command cmd; | |
378 | ||
379 | BUG_ON(!card); | |
380 | BUG_ON(!card->host); | |
381 | ||
382 | memset(&cmd, 0, sizeof(struct mmc_command)); | |
383 | ||
384 | cmd.opcode = MMC_SEND_STATUS; | |
af517150 DB |
385 | if (!mmc_host_is_spi(card->host)) |
386 | cmd.arg = card->rca << 16; | |
387 | cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC; | |
da7fbe58 PO |
388 | |
389 | err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES); | |
17b0429d | 390 | if (err) |
da7fbe58 PO |
391 | return err; |
392 | ||
af517150 DB |
393 | /* NOTE: callers are required to understand the difference |
394 | * between "native" and SPI format status words! | |
395 | */ | |
da7fbe58 PO |
396 | if (status) |
397 | *status = cmd.resp[0]; | |
398 | ||
17b0429d | 399 | return 0; |
da7fbe58 PO |
400 | } |
401 |