diff options
author | David Brownell <david-b@pacbell.net> | 2007-08-08 12:11:32 -0400 |
---|---|---|
committer | Pierre Ossman <drzeus@drzeus.cx> | 2007-09-23 15:51:30 -0400 |
commit | af51715079e7fb6b290e1881d63d815dc4de5011 (patch) | |
tree | 324e81b2346955f130dda8515f2ad4f4ce97c864 /drivers/mmc/core | |
parent | 7213d175e3b6f6db60f843b72e88857a350e146a (diff) |
MMC core learns about SPI
Teach the MMC/SD/SDIO core about using SPI mode.
- Use mmc_host_is_spi() so enumeration works through SPI signaling
and protocols, not just the native versions.
- Provide the SPI response type flags with each request issued,
including requests from the new lock/unlock code.
- Understand that cmd->resp[0] and mmc_get_status() results for SPI
return different values than for "native" MMC/SD protocol; this
affects resetting, checking card lock status, and some others.
- Understand that some commands act a bit differently ... notably:
* OP_COND command doesn't return the OCR
* APP_CMD status doesn't have an R1_APP_CMD analogue
Those changes required some new and updated primitives:
- Provide utilities to access two SPI-only requests, and one
request that wasn't previously needed:
* mmc_spi_read_ocr() ... SPI only
* mmc_spi_set_crc() ... SPI only (override by module parm)
* mmc_send_cid() ... for use without broadcast mode
- Updated internal routines:
* Previous mmc_send_csd() modified into mmc_send_cxd_native();
it uses native "R2" responses, which include 16 bytes of data.
* Previous mmc_send_ext_csd() becomes new mmc_send_cxd_data()
helper for command-and-data access
* Bugfix to that mmc_send_cxd_data() code: dma-to-stack is
unsafe/nonportable, so kmalloc a bounce buffer instead.
- Modified mmc_send_ext_csd() now uses mmc_send_cxd_data() helper
- Modified mmc_send_csd(), and new mmc_spi_send_cid(), routines use
those helper routines based on whether they're native or SPI
The newest categories of cards supported by the MMC stack aren't expected
to work yet with SPI: MMC or SD cards with over 4GB data, and SDIO.
All those cards support SPI mode, so eventually they should work too.
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
Diffstat (limited to 'drivers/mmc/core')
-rw-r--r-- | drivers/mmc/core/bus.c | 24 | ||||
-rw-r--r-- | drivers/mmc/core/core.c | 28 | ||||
-rw-r--r-- | drivers/mmc/core/core.h | 2 | ||||
-rw-r--r-- | drivers/mmc/core/mmc.c | 50 | ||||
-rw-r--r-- | drivers/mmc/core/mmc_ops.c | 166 | ||||
-rw-r--r-- | drivers/mmc/core/mmc_ops.h | 3 | ||||
-rw-r--r-- | drivers/mmc/core/sd.c | 48 | ||||
-rw-r--r-- | drivers/mmc/core/sd_ops.c | 59 | ||||
-rw-r--r-- | drivers/mmc/core/sdio.c | 29 | ||||
-rw-r--r-- | drivers/mmc/core/sdio_ops.c | 66 |
10 files changed, 372 insertions, 103 deletions
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c index 733ac95331c7..8d6f6014870f 100644 --- a/drivers/mmc/core/bus.c +++ b/drivers/mmc/core/bus.c | |||
@@ -243,10 +243,17 @@ int mmc_add_card(struct mmc_card *card) | |||
243 | break; | 243 | break; |
244 | } | 244 | } |
245 | 245 | ||
246 | printk(KERN_INFO "%s: new %s%s card at address %04x\n", | 246 | if (mmc_host_is_spi(card->host)) { |
247 | mmc_hostname(card->host), | 247 | printk(KERN_INFO "%s: new %s%s card on SPI\n", |
248 | mmc_card_highspeed(card) ? "high speed " : "", | 248 | mmc_hostname(card->host), |
249 | type, card->rca); | 249 | mmc_card_highspeed(card) ? "high speed " : "", |
250 | type); | ||
251 | } else { | ||
252 | printk(KERN_INFO "%s: new %s%s card at address %04x\n", | ||
253 | mmc_hostname(card->host), | ||
254 | mmc_card_highspeed(card) ? "high speed " : "", | ||
255 | type, card->rca); | ||
256 | } | ||
250 | 257 | ||
251 | card->dev.uevent_suppress = 1; | 258 | card->dev.uevent_suppress = 1; |
252 | 259 | ||
@@ -278,8 +285,13 @@ int mmc_add_card(struct mmc_card *card) | |||
278 | void mmc_remove_card(struct mmc_card *card) | 285 | void mmc_remove_card(struct mmc_card *card) |
279 | { | 286 | { |
280 | if (mmc_card_present(card)) { | 287 | if (mmc_card_present(card)) { |
281 | printk(KERN_INFO "%s: card %04x removed\n", | 288 | if (mmc_host_is_spi(card->host)) { |
282 | mmc_hostname(card->host), card->rca); | 289 | printk(KERN_INFO "%s: SPI card removed\n", |
290 | mmc_hostname(card->host)); | ||
291 | } else { | ||
292 | printk(KERN_INFO "%s: card %04x removed\n", | ||
293 | mmc_hostname(card->host), card->rca); | ||
294 | } | ||
283 | 295 | ||
284 | if (card->host->bus_ops->sysfs_remove) | 296 | if (card->host->bus_ops->sysfs_remove) |
285 | card->host->bus_ops->sysfs_remove(card->host, card); | 297 | card->host->bus_ops->sysfs_remove(card->host, card); |
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index bffcaf8df352..bad39442f8fe 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c | |||
@@ -42,6 +42,14 @@ extern int mmc_attach_sdio(struct mmc_host *host, u32 ocr); | |||
42 | static struct workqueue_struct *workqueue; | 42 | static struct workqueue_struct *workqueue; |
43 | 43 | ||
44 | /* | 44 | /* |
45 | * Enabling software CRCs on the data blocks can be a significant (30%) | ||
46 | * performance cost, and for other reasons may not always be desired. | ||
47 | * So we allow it it to be disabled. | ||
48 | */ | ||
49 | int use_spi_crc = 1; | ||
50 | module_param(use_spi_crc, bool, 0); | ||
51 | |||
52 | /* | ||
45 | * Internal function. Schedule delayed work in the MMC work queue. | 53 | * Internal function. Schedule delayed work in the MMC work queue. |
46 | */ | 54 | */ |
47 | static int mmc_schedule_delayed_work(struct delayed_work *work, | 55 | static int mmc_schedule_delayed_work(struct delayed_work *work, |
@@ -71,6 +79,11 @@ void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq) | |||
71 | struct mmc_command *cmd = mrq->cmd; | 79 | struct mmc_command *cmd = mrq->cmd; |
72 | int err = cmd->error; | 80 | int err = cmd->error; |
73 | 81 | ||
82 | if (err && cmd->retries && mmc_host_is_spi(host)) { | ||
83 | if (cmd->resp[0] & R1_SPI_ILLEGAL_COMMAND) | ||
84 | cmd->retries = 0; | ||
85 | } | ||
86 | |||
74 | if (err && cmd->retries) { | 87 | if (err && cmd->retries) { |
75 | pr_debug("%s: req failed (CMD%u): %d, retrying...\n", | 88 | pr_debug("%s: req failed (CMD%u): %d, retrying...\n", |
76 | mmc_hostname(host), cmd->opcode, err); | 89 | mmc_hostname(host), cmd->opcode, err); |
@@ -453,8 +466,13 @@ static void mmc_power_up(struct mmc_host *host) | |||
453 | int bit = fls(host->ocr_avail) - 1; | 466 | int bit = fls(host->ocr_avail) - 1; |
454 | 467 | ||
455 | host->ios.vdd = bit; | 468 | host->ios.vdd = bit; |
456 | host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN; | 469 | if (mmc_host_is_spi(host)) { |
457 | host->ios.chip_select = MMC_CS_DONTCARE; | 470 | host->ios.chip_select = MMC_CS_HIGH; |
471 | host->ios.bus_mode = MMC_BUSMODE_PUSHPULL; | ||
472 | } else { | ||
473 | host->ios.chip_select = MMC_CS_DONTCARE; | ||
474 | host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN; | ||
475 | } | ||
458 | host->ios.power_mode = MMC_POWER_UP; | 476 | host->ios.power_mode = MMC_POWER_UP; |
459 | host->ios.bus_width = MMC_BUS_WIDTH_1; | 477 | host->ios.bus_width = MMC_BUS_WIDTH_1; |
460 | host->ios.timing = MMC_TIMING_LEGACY; | 478 | host->ios.timing = MMC_TIMING_LEGACY; |
@@ -481,8 +499,10 @@ static void mmc_power_off(struct mmc_host *host) | |||
481 | { | 499 | { |
482 | host->ios.clock = 0; | 500 | host->ios.clock = 0; |
483 | host->ios.vdd = 0; | 501 | host->ios.vdd = 0; |
484 | host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN; | 502 | if (!mmc_host_is_spi(host)) { |
485 | host->ios.chip_select = MMC_CS_DONTCARE; | 503 | host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN; |
504 | host->ios.chip_select = MMC_CS_DONTCARE; | ||
505 | } | ||
486 | host->ios.power_mode = MMC_POWER_OFF; | 506 | host->ios.power_mode = MMC_POWER_OFF; |
487 | host->ios.bus_width = MMC_BUS_WIDTH_1; | 507 | host->ios.bus_width = MMC_BUS_WIDTH_1; |
488 | host->ios.timing = MMC_TIMING_LEGACY; | 508 | host->ios.timing = MMC_TIMING_LEGACY; |
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h index bb2774af9ea9..39daf2fb5dc4 100644 --- a/drivers/mmc/core/core.h +++ b/drivers/mmc/core/core.h | |||
@@ -48,5 +48,7 @@ void mmc_rescan(struct work_struct *work); | |||
48 | void mmc_start_host(struct mmc_host *host); | 48 | void mmc_start_host(struct mmc_host *host); |
49 | void mmc_stop_host(struct mmc_host *host); | 49 | void mmc_stop_host(struct mmc_host *host); |
50 | 50 | ||
51 | extern int use_spi_crc; | ||
52 | |||
51 | #endif | 53 | #endif |
52 | 54 | ||
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 6ba458951d24..65fe28860f54 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c | |||
@@ -165,8 +165,6 @@ static int mmc_read_ext_csd(struct mmc_card *card) | |||
165 | 165 | ||
166 | BUG_ON(!card); | 166 | BUG_ON(!card); |
167 | 167 | ||
168 | err = -EIO; | ||
169 | |||
170 | if (card->csd.mmca_vsn < CSD_SPEC_VER_4) | 168 | if (card->csd.mmca_vsn < CSD_SPEC_VER_4) |
171 | return 0; | 169 | return 0; |
172 | 170 | ||
@@ -280,9 +278,21 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, | |||
280 | goto err; | 278 | goto err; |
281 | 279 | ||
282 | /* | 280 | /* |
281 | * For SPI, enable CRC as appropriate. | ||
282 | */ | ||
283 | if (mmc_host_is_spi(host)) { | ||
284 | err = mmc_spi_set_crc(host, use_spi_crc); | ||
285 | if (err) | ||
286 | goto err; | ||
287 | } | ||
288 | |||
289 | /* | ||
283 | * Fetch CID from card. | 290 | * Fetch CID from card. |
284 | */ | 291 | */ |
285 | err = mmc_all_send_cid(host, cid); | 292 | if (mmc_host_is_spi(host)) |
293 | err = mmc_send_cid(host, cid); | ||
294 | else | ||
295 | err = mmc_all_send_cid(host, cid); | ||
286 | if (err) | 296 | if (err) |
287 | goto err; | 297 | goto err; |
288 | 298 | ||
@@ -309,13 +319,15 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, | |||
309 | } | 319 | } |
310 | 320 | ||
311 | /* | 321 | /* |
312 | * Set card RCA. | 322 | * For native busses: set card RCA and quit open drain mode. |
313 | */ | 323 | */ |
314 | err = mmc_set_relative_addr(card); | 324 | if (!mmc_host_is_spi(host)) { |
315 | if (err) | 325 | err = mmc_set_relative_addr(card); |
316 | goto free_card; | 326 | if (err) |
327 | goto free_card; | ||
317 | 328 | ||
318 | mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL); | 329 | mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL); |
330 | } | ||
319 | 331 | ||
320 | if (!oldcard) { | 332 | if (!oldcard) { |
321 | /* | 333 | /* |
@@ -336,13 +348,15 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, | |||
336 | /* | 348 | /* |
337 | * Select card, as all following commands rely on that. | 349 | * Select card, as all following commands rely on that. |
338 | */ | 350 | */ |
339 | err = mmc_select_card(card); | 351 | if (!mmc_host_is_spi(host)) { |
340 | if (err) | 352 | err = mmc_select_card(card); |
341 | goto free_card; | 353 | if (err) |
354 | goto free_card; | ||
355 | } | ||
342 | 356 | ||
343 | if (!oldcard) { | 357 | if (!oldcard) { |
344 | /* | 358 | /* |
345 | * Fetch and process extened CSD. | 359 | * Fetch and process extended CSD. |
346 | */ | 360 | */ |
347 | err = mmc_read_ext_csd(card); | 361 | err = mmc_read_ext_csd(card); |
348 | if (err) | 362 | if (err) |
@@ -502,7 +516,8 @@ static void mmc_suspend(struct mmc_host *host) | |||
502 | BUG_ON(!host->card); | 516 | BUG_ON(!host->card); |
503 | 517 | ||
504 | mmc_claim_host(host); | 518 | mmc_claim_host(host); |
505 | mmc_deselect_cards(host); | 519 | if (!mmc_host_is_spi(host)) |
520 | mmc_deselect_cards(host); | ||
506 | host->card->state &= ~MMC_STATE_HIGHSPEED; | 521 | host->card->state &= ~MMC_STATE_HIGHSPEED; |
507 | mmc_release_host(host); | 522 | mmc_release_host(host); |
508 | } | 523 | } |
@@ -563,6 +578,15 @@ int mmc_attach_mmc(struct mmc_host *host, u32 ocr) | |||
563 | mmc_attach_bus(host, &mmc_ops); | 578 | mmc_attach_bus(host, &mmc_ops); |
564 | 579 | ||
565 | /* | 580 | /* |
581 | * We need to get OCR a different way for SPI. | ||
582 | */ | ||
583 | if (mmc_host_is_spi(host)) { | ||
584 | err = mmc_spi_read_ocr(host, 1, &ocr); | ||
585 | if (err) | ||
586 | goto err; | ||
587 | } | ||
588 | |||
589 | /* | ||
566 | * Sanity check the voltages that the card claims to | 590 | * Sanity check the voltages that the card claims to |
567 | * support. | 591 | * support. |
568 | */ | 592 | */ |
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 39567f91a4b8..bf4bc6adcfef 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c | |||
@@ -63,23 +63,36 @@ int mmc_go_idle(struct mmc_host *host) | |||
63 | int err; | 63 | int err; |
64 | struct mmc_command cmd; | 64 | struct mmc_command cmd; |
65 | 65 | ||
66 | mmc_set_chip_select(host, MMC_CS_HIGH); | 66 | /* |
67 | 67 | * Non-SPI hosts need to prevent chipselect going active during | |
68 | mmc_delay(1); | 68 | * GO_IDLE; that would put chips into SPI mode. Remind them of |
69 | * that in case of hardware that won't pull up DAT3/nCS otherwise. | ||
70 | * | ||
71 | * SPI hosts ignore ios.chip_select; it's managed according to | ||
72 | * rules that must accomodate non-MMC slaves which this layer | ||
73 | * won't even know about. | ||
74 | */ | ||
75 | if (!mmc_host_is_spi(host)) { | ||
76 | mmc_set_chip_select(host, MMC_CS_HIGH); | ||
77 | mmc_delay(1); | ||
78 | } | ||
69 | 79 | ||
70 | memset(&cmd, 0, sizeof(struct mmc_command)); | 80 | memset(&cmd, 0, sizeof(struct mmc_command)); |
71 | 81 | ||
72 | cmd.opcode = MMC_GO_IDLE_STATE; | 82 | cmd.opcode = MMC_GO_IDLE_STATE; |
73 | cmd.arg = 0; | 83 | cmd.arg = 0; |
74 | cmd.flags = MMC_RSP_NONE | MMC_CMD_BC; | 84 | cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_NONE | MMC_CMD_BC; |
75 | 85 | ||
76 | err = mmc_wait_for_cmd(host, &cmd, 0); | 86 | err = mmc_wait_for_cmd(host, &cmd, 0); |
77 | 87 | ||
78 | mmc_delay(1); | 88 | mmc_delay(1); |
79 | 89 | ||
80 | mmc_set_chip_select(host, MMC_CS_DONTCARE); | 90 | if (!mmc_host_is_spi(host)) { |
91 | mmc_set_chip_select(host, MMC_CS_DONTCARE); | ||
92 | mmc_delay(1); | ||
93 | } | ||
81 | 94 | ||
82 | mmc_delay(1); | 95 | host->use_spi_crc = 0; |
83 | 96 | ||
84 | return err; | 97 | return err; |
85 | } | 98 | } |
@@ -94,23 +107,33 @@ int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr) | |||
94 | memset(&cmd, 0, sizeof(struct mmc_command)); | 107 | memset(&cmd, 0, sizeof(struct mmc_command)); |
95 | 108 | ||
96 | cmd.opcode = MMC_SEND_OP_COND; | 109 | cmd.opcode = MMC_SEND_OP_COND; |
97 | cmd.arg = ocr; | 110 | cmd.arg = mmc_host_is_spi(host) ? 0 : ocr; |
98 | cmd.flags = MMC_RSP_R3 | MMC_CMD_BCR; | 111 | cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R3 | MMC_CMD_BCR; |
99 | 112 | ||
100 | for (i = 100; i; i--) { | 113 | for (i = 100; i; i--) { |
101 | err = mmc_wait_for_cmd(host, &cmd, 0); | 114 | err = mmc_wait_for_cmd(host, &cmd, 0); |
102 | if (err) | 115 | if (err) |
103 | break; | 116 | break; |
104 | 117 | ||
105 | if (cmd.resp[0] & MMC_CARD_BUSY || ocr == 0) | 118 | /* if we're just probing, do a single pass */ |
119 | if (ocr == 0) | ||
106 | break; | 120 | break; |
107 | 121 | ||
122 | /* otherwise wait until reset completes */ | ||
123 | if (mmc_host_is_spi(host)) { | ||
124 | if (!(cmd.resp[0] & R1_SPI_IDLE)) | ||
125 | break; | ||
126 | } else { | ||
127 | if (cmd.resp[0] & MMC_CARD_BUSY) | ||
128 | break; | ||
129 | } | ||
130 | |||
108 | err = -ETIMEDOUT; | 131 | err = -ETIMEDOUT; |
109 | 132 | ||
110 | mmc_delay(10); | 133 | mmc_delay(10); |
111 | } | 134 | } |
112 | 135 | ||
113 | if (rocr) | 136 | if (rocr && !mmc_host_is_spi(host)) |
114 | *rocr = cmd.resp[0]; | 137 | *rocr = cmd.resp[0]; |
115 | 138 | ||
116 | return err; | 139 | return err; |
@@ -160,40 +183,46 @@ int mmc_set_relative_addr(struct mmc_card *card) | |||
160 | return 0; | 183 | return 0; |
161 | } | 184 | } |
162 | 185 | ||
163 | int mmc_send_csd(struct mmc_card *card, u32 *csd) | 186 | static int |
187 | mmc_send_cxd_native(struct mmc_host *host, u32 arg, u32 *cxd, int opcode) | ||
164 | { | 188 | { |
165 | int err; | 189 | int err; |
166 | struct mmc_command cmd; | 190 | struct mmc_command cmd; |
167 | 191 | ||
168 | BUG_ON(!card); | 192 | BUG_ON(!host); |
169 | BUG_ON(!card->host); | 193 | BUG_ON(!cxd); |
170 | BUG_ON(!csd); | ||
171 | 194 | ||
172 | memset(&cmd, 0, sizeof(struct mmc_command)); | 195 | memset(&cmd, 0, sizeof(struct mmc_command)); |
173 | 196 | ||
174 | cmd.opcode = MMC_SEND_CSD; | 197 | cmd.opcode = opcode; |
175 | cmd.arg = card->rca << 16; | 198 | cmd.arg = arg; |
176 | cmd.flags = MMC_RSP_R2 | MMC_CMD_AC; | 199 | cmd.flags = MMC_RSP_R2 | MMC_CMD_AC; |
177 | 200 | ||
178 | err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES); | 201 | err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES); |
179 | if (err) | 202 | if (err) |
180 | return err; | 203 | return err; |
181 | 204 | ||
182 | memcpy(csd, cmd.resp, sizeof(u32) * 4); | 205 | memcpy(cxd, cmd.resp, sizeof(u32) * 4); |
183 | 206 | ||
184 | return 0; | 207 | return 0; |
185 | } | 208 | } |
186 | 209 | ||
187 | int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd) | 210 | static int |
211 | mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host, | ||
212 | u32 opcode, void *buf, unsigned len) | ||
188 | { | 213 | { |
189 | struct mmc_request mrq; | 214 | struct mmc_request mrq; |
190 | struct mmc_command cmd; | 215 | struct mmc_command cmd; |
191 | struct mmc_data data; | 216 | struct mmc_data data; |
192 | struct scatterlist sg; | 217 | struct scatterlist sg; |
218 | void *data_buf; | ||
193 | 219 | ||
194 | BUG_ON(!card); | 220 | /* dma onto stack is unsafe/nonportable, but callers to this |
195 | BUG_ON(!card->host); | 221 | * routine normally provide temporary on-stack buffers ... |
196 | BUG_ON(!ext_csd); | 222 | */ |
223 | data_buf = kmalloc(len, GFP_KERNEL); | ||
224 | if (data_buf == NULL) | ||
225 | return -ENOMEM; | ||
197 | 226 | ||
198 | memset(&mrq, 0, sizeof(struct mmc_request)); | 227 | memset(&mrq, 0, sizeof(struct mmc_request)); |
199 | memset(&cmd, 0, sizeof(struct mmc_command)); | 228 | memset(&cmd, 0, sizeof(struct mmc_command)); |
@@ -202,21 +231,31 @@ int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd) | |||
202 | mrq.cmd = &cmd; | 231 | mrq.cmd = &cmd; |
203 | mrq.data = &data; | 232 | mrq.data = &data; |
204 | 233 | ||
205 | cmd.opcode = MMC_SEND_EXT_CSD; | 234 | cmd.opcode = opcode; |
206 | cmd.arg = 0; | 235 | cmd.arg = 0; |
207 | cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; | ||
208 | 236 | ||
209 | data.blksz = 512; | 237 | /* NOTE HACK: the MMC_RSP_SPI_R1 is always correct here, but we |
238 | * rely on callers to never use this with "native" calls for reading | ||
239 | * CSD or CID. Native versions of those commands use the R2 type, | ||
240 | * not R1 plus a data block. | ||
241 | */ | ||
242 | cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; | ||
243 | |||
244 | data.blksz = len; | ||
210 | data.blocks = 1; | 245 | data.blocks = 1; |
211 | data.flags = MMC_DATA_READ; | 246 | data.flags = MMC_DATA_READ; |
212 | data.sg = &sg; | 247 | data.sg = &sg; |
213 | data.sg_len = 1; | 248 | data.sg_len = 1; |
214 | 249 | ||
215 | sg_init_one(&sg, ext_csd, 512); | 250 | sg_init_one(&sg, data_buf, len); |
216 | 251 | ||
217 | mmc_set_data_timeout(&data, card); | 252 | if (card) |
253 | mmc_set_data_timeout(&data, card); | ||
218 | 254 | ||
219 | mmc_wait_for_req(card->host, &mrq); | 255 | mmc_wait_for_req(host, &mrq); |
256 | |||
257 | memcpy(buf, data_buf, len); | ||
258 | kfree(data_buf); | ||
220 | 259 | ||
221 | if (cmd.error) | 260 | if (cmd.error) |
222 | return cmd.error; | 261 | return cmd.error; |
@@ -226,6 +265,67 @@ int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd) | |||
226 | return 0; | 265 | return 0; |
227 | } | 266 | } |
228 | 267 | ||
268 | int mmc_send_csd(struct mmc_card *card, u32 *csd) | ||
269 | { | ||
270 | if (!mmc_host_is_spi(card->host)) | ||
271 | return mmc_send_cxd_native(card->host, card->rca << 16, | ||
272 | csd, MMC_SEND_CSD); | ||
273 | |||
274 | return mmc_send_cxd_data(card, card->host, MMC_SEND_CSD, csd, 16); | ||
275 | } | ||
276 | |||
277 | int mmc_send_cid(struct mmc_host *host, u32 *cid) | ||
278 | { | ||
279 | if (!mmc_host_is_spi(host)) { | ||
280 | if (!host->card) | ||
281 | return -EINVAL; | ||
282 | return mmc_send_cxd_native(host, host->card->rca << 16, | ||
283 | cid, MMC_SEND_CID); | ||
284 | } | ||
285 | |||
286 | return mmc_send_cxd_data(NULL, host, MMC_SEND_CID, cid, 16); | ||
287 | } | ||
288 | |||
289 | int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd) | ||
290 | { | ||
291 | return mmc_send_cxd_data(card, card->host, MMC_SEND_EXT_CSD, | ||
292 | ext_csd, 512); | ||
293 | } | ||
294 | |||
295 | int mmc_spi_read_ocr(struct mmc_host *host, int highcap, u32 *ocrp) | ||
296 | { | ||
297 | struct mmc_command cmd; | ||
298 | int err; | ||
299 | |||
300 | memset(&cmd, 0, sizeof(struct mmc_command)); | ||
301 | |||
302 | cmd.opcode = MMC_SPI_READ_OCR; | ||
303 | cmd.arg = highcap ? (1 << 30) : 0; | ||
304 | cmd.flags = MMC_RSP_SPI_R3; | ||
305 | |||
306 | err = mmc_wait_for_cmd(host, &cmd, 0); | ||
307 | |||
308 | *ocrp = cmd.resp[1]; | ||
309 | return err; | ||
310 | } | ||
311 | |||
312 | int mmc_spi_set_crc(struct mmc_host *host, int use_crc) | ||
313 | { | ||
314 | struct mmc_command cmd; | ||
315 | int err; | ||
316 | |||
317 | memset(&cmd, 0, sizeof(struct mmc_command)); | ||
318 | |||
319 | cmd.opcode = MMC_SPI_CRC_ON_OFF; | ||
320 | cmd.flags = MMC_RSP_SPI_R1; | ||
321 | cmd.arg = use_crc; | ||
322 | |||
323 | err = mmc_wait_for_cmd(host, &cmd, 0); | ||
324 | if (!err) | ||
325 | host->use_spi_crc = use_crc; | ||
326 | return err; | ||
327 | } | ||
328 | |||
229 | int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value) | 329 | int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value) |
230 | { | 330 | { |
231 | int err; | 331 | int err; |
@@ -241,7 +341,7 @@ int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value) | |||
241 | (index << 16) | | 341 | (index << 16) | |
242 | (value << 8) | | 342 | (value << 8) | |
243 | set; | 343 | set; |
244 | cmd.flags = MMC_RSP_R1B | MMC_CMD_AC; | 344 | cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; |
245 | 345 | ||
246 | err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES); | 346 | err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES); |
247 | if (err) | 347 | if (err) |
@@ -261,13 +361,17 @@ int mmc_send_status(struct mmc_card *card, u32 *status) | |||
261 | memset(&cmd, 0, sizeof(struct mmc_command)); | 361 | memset(&cmd, 0, sizeof(struct mmc_command)); |
262 | 362 | ||
263 | cmd.opcode = MMC_SEND_STATUS; | 363 | cmd.opcode = MMC_SEND_STATUS; |
264 | cmd.arg = card->rca << 16; | 364 | if (!mmc_host_is_spi(card->host)) |
265 | cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; | 365 | cmd.arg = card->rca << 16; |
366 | cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC; | ||
266 | 367 | ||
267 | err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES); | 368 | err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES); |
268 | if (err) | 369 | if (err) |
269 | return err; | 370 | return err; |
270 | 371 | ||
372 | /* NOTE: callers are required to understand the difference | ||
373 | * between "native" and SPI format status words! | ||
374 | */ | ||
271 | if (status) | 375 | if (status) |
272 | *status = cmd.resp[0]; | 376 | *status = cmd.resp[0]; |
273 | 377 | ||
diff --git a/drivers/mmc/core/mmc_ops.h b/drivers/mmc/core/mmc_ops.h index 76d09a93c5d6..17854bf7cf0d 100644 --- a/drivers/mmc/core/mmc_ops.h +++ b/drivers/mmc/core/mmc_ops.h | |||
@@ -22,6 +22,9 @@ int mmc_send_csd(struct mmc_card *card, u32 *csd); | |||
22 | int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd); | 22 | int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd); |
23 | int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value); | 23 | int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value); |
24 | int mmc_send_status(struct mmc_card *card, u32 *status); | 24 | int mmc_send_status(struct mmc_card *card, u32 *status); |
25 | int mmc_send_cid(struct mmc_host *host, u32 *cid); | ||
26 | int mmc_spi_read_ocr(struct mmc_host *host, int highcap, u32 *ocrp); | ||
27 | int mmc_spi_set_crc(struct mmc_host *host, int use_crc); | ||
25 | 28 | ||
26 | #endif | 29 | #endif |
27 | 30 | ||
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index c86588fdaae5..d1c1e0f592f1 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c | |||
@@ -323,9 +323,21 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, | |||
323 | goto err; | 323 | goto err; |
324 | 324 | ||
325 | /* | 325 | /* |
326 | * For SPI, enable CRC as appropriate. | ||
327 | */ | ||
328 | if (mmc_host_is_spi(host)) { | ||
329 | err = mmc_spi_set_crc(host, use_spi_crc); | ||
330 | if (err) | ||
331 | goto err; | ||
332 | } | ||
333 | |||
334 | /* | ||
326 | * Fetch CID from card. | 335 | * Fetch CID from card. |
327 | */ | 336 | */ |
328 | err = mmc_all_send_cid(host, cid); | 337 | if (mmc_host_is_spi(host)) |
338 | err = mmc_send_cid(host, cid); | ||
339 | else | ||
340 | err = mmc_all_send_cid(host, cid); | ||
329 | if (err) | 341 | if (err) |
330 | goto err; | 342 | goto err; |
331 | 343 | ||
@@ -351,13 +363,15 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, | |||
351 | } | 363 | } |
352 | 364 | ||
353 | /* | 365 | /* |
354 | * Set card RCA. | 366 | * For native busses: get card RCA and quit open drain mode. |
355 | */ | 367 | */ |
356 | err = mmc_send_relative_addr(host, &card->rca); | 368 | if (!mmc_host_is_spi(host)) { |
357 | if (err) | 369 | err = mmc_send_relative_addr(host, &card->rca); |
358 | goto free_card; | 370 | if (err) |
371 | goto free_card; | ||
359 | 372 | ||
360 | mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL); | 373 | mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL); |
374 | } | ||
361 | 375 | ||
362 | if (!oldcard) { | 376 | if (!oldcard) { |
363 | /* | 377 | /* |
@@ -377,9 +391,11 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, | |||
377 | /* | 391 | /* |
378 | * Select card, as all following commands rely on that. | 392 | * Select card, as all following commands rely on that. |
379 | */ | 393 | */ |
380 | err = mmc_select_card(card); | 394 | if (!mmc_host_is_spi(host)) { |
381 | if (err) | 395 | err = mmc_select_card(card); |
382 | goto free_card; | 396 | if (err) |
397 | goto free_card; | ||
398 | } | ||
383 | 399 | ||
384 | if (!oldcard) { | 400 | if (!oldcard) { |
385 | /* | 401 | /* |
@@ -562,7 +578,8 @@ static void mmc_sd_suspend(struct mmc_host *host) | |||
562 | BUG_ON(!host->card); | 578 | BUG_ON(!host->card); |
563 | 579 | ||
564 | mmc_claim_host(host); | 580 | mmc_claim_host(host); |
565 | mmc_deselect_cards(host); | 581 | if (!mmc_host_is_spi(host)) |
582 | mmc_deselect_cards(host); | ||
566 | host->card->state &= ~MMC_STATE_HIGHSPEED; | 583 | host->card->state &= ~MMC_STATE_HIGHSPEED; |
567 | mmc_release_host(host); | 584 | mmc_release_host(host); |
568 | } | 585 | } |
@@ -623,6 +640,17 @@ int mmc_attach_sd(struct mmc_host *host, u32 ocr) | |||
623 | mmc_attach_bus(host, &mmc_sd_ops); | 640 | mmc_attach_bus(host, &mmc_sd_ops); |
624 | 641 | ||
625 | /* | 642 | /* |
643 | * We need to get OCR a different way for SPI. | ||
644 | */ | ||
645 | if (mmc_host_is_spi(host)) { | ||
646 | mmc_go_idle(host); | ||
647 | |||
648 | err = mmc_spi_read_ocr(host, 0, &ocr); | ||
649 | if (err) | ||
650 | goto err; | ||
651 | } | ||
652 | |||
653 | /* | ||
626 | * Sanity check the voltages that the card claims to | 654 | * Sanity check the voltages that the card claims to |
627 | * support. | 655 | * support. |
628 | */ | 656 | */ |
diff --git a/drivers/mmc/core/sd_ops.c b/drivers/mmc/core/sd_ops.c index 491e0306b1b4..ee4029a24efd 100644 --- a/drivers/mmc/core/sd_ops.c +++ b/drivers/mmc/core/sd_ops.c | |||
@@ -33,10 +33,10 @@ static int mmc_app_cmd(struct mmc_host *host, struct mmc_card *card) | |||
33 | 33 | ||
34 | if (card) { | 34 | if (card) { |
35 | cmd.arg = card->rca << 16; | 35 | cmd.arg = card->rca << 16; |
36 | cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; | 36 | cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC; |
37 | } else { | 37 | } else { |
38 | cmd.arg = 0; | 38 | cmd.arg = 0; |
39 | cmd.flags = MMC_RSP_R1 | MMC_CMD_BCR; | 39 | cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_BCR; |
40 | } | 40 | } |
41 | 41 | ||
42 | err = mmc_wait_for_cmd(host, &cmd, 0); | 42 | err = mmc_wait_for_cmd(host, &cmd, 0); |
@@ -44,7 +44,7 @@ static int mmc_app_cmd(struct mmc_host *host, struct mmc_card *card) | |||
44 | return err; | 44 | return err; |
45 | 45 | ||
46 | /* Check that card supported application commands */ | 46 | /* Check that card supported application commands */ |
47 | if (!(cmd.resp[0] & R1_APP_CMD)) | 47 | if (!mmc_host_is_spi(host) && !(cmd.resp[0] & R1_APP_CMD)) |
48 | return -EOPNOTSUPP; | 48 | return -EOPNOTSUPP; |
49 | 49 | ||
50 | return 0; | 50 | return 0; |
@@ -83,8 +83,14 @@ int mmc_wait_for_app_cmd(struct mmc_host *host, struct mmc_card *card, | |||
83 | memset(&mrq, 0, sizeof(struct mmc_request)); | 83 | memset(&mrq, 0, sizeof(struct mmc_request)); |
84 | 84 | ||
85 | err = mmc_app_cmd(host, card); | 85 | err = mmc_app_cmd(host, card); |
86 | if (err) | 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 | } | ||
87 | continue; | 92 | continue; |
93 | } | ||
88 | 94 | ||
89 | memset(&mrq, 0, sizeof(struct mmc_request)); | 95 | memset(&mrq, 0, sizeof(struct mmc_request)); |
90 | 96 | ||
@@ -99,6 +105,12 @@ int mmc_wait_for_app_cmd(struct mmc_host *host, struct mmc_card *card, | |||
99 | err = cmd->error; | 105 | err = cmd->error; |
100 | if (!cmd->error) | 106 | if (!cmd->error) |
101 | break; | 107 | break; |
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 | } | ||
102 | } | 114 | } |
103 | 115 | ||
104 | return err; | 116 | return err; |
@@ -147,23 +159,36 @@ int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr) | |||
147 | memset(&cmd, 0, sizeof(struct mmc_command)); | 159 | memset(&cmd, 0, sizeof(struct mmc_command)); |
148 | 160 | ||
149 | cmd.opcode = SD_APP_OP_COND; | 161 | cmd.opcode = SD_APP_OP_COND; |
150 | cmd.arg = ocr; | 162 | if (mmc_host_is_spi(host)) |
151 | cmd.flags = MMC_RSP_R3 | MMC_CMD_BCR; | 163 | cmd.arg = ocr & (1 << 30); /* SPI only defines one bit */ |
164 | else | ||
165 | cmd.arg = ocr; | ||
166 | cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R3 | MMC_CMD_BCR; | ||
152 | 167 | ||
153 | for (i = 100; i; i--) { | 168 | for (i = 100; i; i--) { |
154 | err = mmc_wait_for_app_cmd(host, NULL, &cmd, MMC_CMD_RETRIES); | 169 | err = mmc_wait_for_app_cmd(host, NULL, &cmd, MMC_CMD_RETRIES); |
155 | if (err) | 170 | if (err) |
156 | break; | 171 | break; |
157 | 172 | ||
158 | if (cmd.resp[0] & MMC_CARD_BUSY || ocr == 0) | 173 | /* if we're just probing, do a single pass */ |
174 | if (ocr == 0) | ||
159 | break; | 175 | break; |
160 | 176 | ||
177 | /* otherwise wait until reset completes */ | ||
178 | if (mmc_host_is_spi(host)) { | ||
179 | if (!(cmd.resp[0] & R1_SPI_IDLE)) | ||
180 | break; | ||
181 | } else { | ||
182 | if (cmd.resp[0] & MMC_CARD_BUSY) | ||
183 | break; | ||
184 | } | ||
185 | |||
161 | err = -ETIMEDOUT; | 186 | err = -ETIMEDOUT; |
162 | 187 | ||
163 | mmc_delay(10); | 188 | mmc_delay(10); |
164 | } | 189 | } |
165 | 190 | ||
166 | if (rocr) | 191 | if (rocr && !mmc_host_is_spi(host)) |
167 | *rocr = cmd.resp[0]; | 192 | *rocr = cmd.resp[0]; |
168 | 193 | ||
169 | return err; | 194 | return err; |
@@ -174,6 +199,7 @@ int mmc_send_if_cond(struct mmc_host *host, u32 ocr) | |||
174 | struct mmc_command cmd; | 199 | struct mmc_command cmd; |
175 | int err; | 200 | int err; |
176 | static const u8 test_pattern = 0xAA; | 201 | static const u8 test_pattern = 0xAA; |
202 | u8 result_pattern; | ||
177 | 203 | ||
178 | /* | 204 | /* |
179 | * To support SD 2.0 cards, we must always invoke SD_SEND_IF_COND | 205 | * To support SD 2.0 cards, we must always invoke SD_SEND_IF_COND |
@@ -182,13 +208,18 @@ int mmc_send_if_cond(struct mmc_host *host, u32 ocr) | |||
182 | */ | 208 | */ |
183 | cmd.opcode = SD_SEND_IF_COND; | 209 | cmd.opcode = SD_SEND_IF_COND; |
184 | cmd.arg = ((ocr & 0xFF8000) != 0) << 8 | test_pattern; | 210 | cmd.arg = ((ocr & 0xFF8000) != 0) << 8 | test_pattern; |
185 | cmd.flags = MMC_RSP_R7 | MMC_CMD_BCR; | 211 | cmd.flags = MMC_RSP_SPI_R7 | MMC_RSP_R7 | MMC_CMD_BCR; |
186 | 212 | ||
187 | err = mmc_wait_for_cmd(host, &cmd, 0); | 213 | err = mmc_wait_for_cmd(host, &cmd, 0); |
188 | if (err) | 214 | if (err) |
189 | return err; | 215 | return err; |
190 | 216 | ||
191 | if ((cmd.resp[0] & 0xFF) != test_pattern) | 217 | if (mmc_host_is_spi(host)) |
218 | result_pattern = cmd.resp[1] & 0xFF; | ||
219 | else | ||
220 | result_pattern = cmd.resp[0] & 0xFF; | ||
221 | |||
222 | if (result_pattern != test_pattern) | ||
192 | return -EIO; | 223 | return -EIO; |
193 | 224 | ||
194 | return 0; | 225 | return 0; |
@@ -229,6 +260,8 @@ int mmc_app_send_scr(struct mmc_card *card, u32 *scr) | |||
229 | BUG_ON(!card->host); | 260 | BUG_ON(!card->host); |
230 | BUG_ON(!scr); | 261 | BUG_ON(!scr); |
231 | 262 | ||
263 | /* NOTE: caller guarantees scr is heap-allocated */ | ||
264 | |||
232 | err = mmc_app_cmd(card->host, card); | 265 | err = mmc_app_cmd(card->host, card); |
233 | if (err) | 266 | if (err) |
234 | return err; | 267 | return err; |
@@ -242,7 +275,7 @@ int mmc_app_send_scr(struct mmc_card *card, u32 *scr) | |||
242 | 275 | ||
243 | cmd.opcode = SD_APP_SEND_SCR; | 276 | cmd.opcode = SD_APP_SEND_SCR; |
244 | cmd.arg = 0; | 277 | cmd.arg = 0; |
245 | cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; | 278 | cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; |
246 | 279 | ||
247 | data.blksz = 8; | 280 | data.blksz = 8; |
248 | data.blocks = 1; | 281 | data.blocks = 1; |
@@ -278,6 +311,8 @@ int mmc_sd_switch(struct mmc_card *card, int mode, int group, | |||
278 | BUG_ON(!card); | 311 | BUG_ON(!card); |
279 | BUG_ON(!card->host); | 312 | BUG_ON(!card->host); |
280 | 313 | ||
314 | /* NOTE: caller guarantees resp is heap-allocated */ | ||
315 | |||
281 | mode = !!mode; | 316 | mode = !!mode; |
282 | value &= 0xF; | 317 | value &= 0xF; |
283 | 318 | ||
@@ -292,7 +327,7 @@ int mmc_sd_switch(struct mmc_card *card, int mode, int group, | |||
292 | cmd.arg = mode << 31 | 0x00FFFFFF; | 327 | cmd.arg = mode << 31 | 0x00FFFFFF; |
293 | cmd.arg &= ~(0xF << (group * 4)); | 328 | cmd.arg &= ~(0xF << (group * 4)); |
294 | cmd.arg |= value << (group * 4); | 329 | cmd.arg |= value << (group * 4); |
295 | cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; | 330 | cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; |
296 | 331 | ||
297 | data.blksz = 64; | 332 | data.blksz = 64; |
298 | data.blocks = 1; | 333 | data.blocks = 1; |
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index 2f3fb994c383..87a50f456efc 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c | |||
@@ -270,6 +270,15 @@ int mmc_attach_sdio(struct mmc_host *host, u32 ocr) | |||
270 | goto err; | 270 | goto err; |
271 | 271 | ||
272 | /* | 272 | /* |
273 | * For SPI, enable CRC as appropriate. | ||
274 | */ | ||
275 | if (mmc_host_is_spi(host)) { | ||
276 | err = mmc_spi_set_crc(host, use_spi_crc); | ||
277 | if (err) | ||
278 | goto err; | ||
279 | } | ||
280 | |||
281 | /* | ||
273 | * The number of functions on the card is encoded inside | 282 | * The number of functions on the card is encoded inside |
274 | * the ocr. | 283 | * the ocr. |
275 | */ | 284 | */ |
@@ -290,20 +299,24 @@ int mmc_attach_sdio(struct mmc_host *host, u32 ocr) | |||
290 | host->card = card; | 299 | host->card = card; |
291 | 300 | ||
292 | /* | 301 | /* |
293 | * Set card RCA. | 302 | * For native busses: set card RCA and quit open drain mode. |
294 | */ | 303 | */ |
295 | err = mmc_send_relative_addr(host, &card->rca); | 304 | if (!mmc_host_is_spi(host)) { |
296 | if (err) | 305 | err = mmc_send_relative_addr(host, &card->rca); |
297 | goto remove; | 306 | if (err) |
307 | goto remove; | ||
298 | 308 | ||
299 | mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL); | 309 | mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL); |
310 | } | ||
300 | 311 | ||
301 | /* | 312 | /* |
302 | * Select card, as all following commands rely on that. | 313 | * Select card, as all following commands rely on that. |
303 | */ | 314 | */ |
304 | err = mmc_select_card(card); | 315 | if (!mmc_host_is_spi(host)) { |
305 | if (err) | 316 | err = mmc_select_card(card); |
306 | goto remove; | 317 | if (err) |
318 | goto remove; | ||
319 | } | ||
307 | 320 | ||
308 | /* | 321 | /* |
309 | * Read the common registers. | 322 | * Read the common registers. |
diff --git a/drivers/mmc/core/sdio_ops.c b/drivers/mmc/core/sdio_ops.c index 98e20532452a..4d289b275031 100644 --- a/drivers/mmc/core/sdio_ops.c +++ b/drivers/mmc/core/sdio_ops.c | |||
@@ -30,23 +30,39 @@ int mmc_send_io_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr) | |||
30 | 30 | ||
31 | cmd.opcode = SD_IO_SEND_OP_COND; | 31 | cmd.opcode = SD_IO_SEND_OP_COND; |
32 | cmd.arg = ocr; | 32 | cmd.arg = ocr; |
33 | cmd.flags = MMC_RSP_R4 | MMC_CMD_BCR; | 33 | cmd.flags = MMC_RSP_SPI_R4 | MMC_RSP_R4 | MMC_CMD_BCR; |
34 | 34 | ||
35 | for (i = 100; i; i--) { | 35 | for (i = 100; i; i--) { |
36 | err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES); | 36 | err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES); |
37 | if (err) | 37 | if (err) |
38 | break; | 38 | break; |
39 | 39 | ||
40 | if (cmd.resp[0] & MMC_CARD_BUSY || ocr == 0) | 40 | /* if we're just probing, do a single pass */ |
41 | if (ocr == 0) | ||
41 | break; | 42 | break; |
42 | 43 | ||
44 | /* otherwise wait until reset completes */ | ||
45 | if (mmc_host_is_spi(host)) { | ||
46 | /* | ||
47 | * Both R1_SPI_IDLE and MMC_CARD_BUSY indicate | ||
48 | * an initialized card under SPI, but some cards | ||
49 | * (Marvell's) only behave when looking at this | ||
50 | * one. | ||
51 | */ | ||
52 | if (cmd.resp[1] & MMC_CARD_BUSY) | ||
53 | break; | ||
54 | } else { | ||
55 | if (cmd.resp[0] & MMC_CARD_BUSY) | ||
56 | break; | ||
57 | } | ||
58 | |||
43 | err = -ETIMEDOUT; | 59 | err = -ETIMEDOUT; |
44 | 60 | ||
45 | mmc_delay(10); | 61 | mmc_delay(10); |
46 | } | 62 | } |
47 | 63 | ||
48 | if (rocr) | 64 | if (rocr) |
49 | *rocr = cmd.resp[0]; | 65 | *rocr = cmd.resp[mmc_host_is_spi(host) ? 1 : 0]; |
50 | 66 | ||
51 | return err; | 67 | return err; |
52 | } | 68 | } |
@@ -68,21 +84,29 @@ int mmc_io_rw_direct(struct mmc_card *card, int write, unsigned fn, | |||
68 | cmd.arg |= (write && out) ? 0x08000000 : 0x00000000; | 84 | cmd.arg |= (write && out) ? 0x08000000 : 0x00000000; |
69 | cmd.arg |= addr << 9; | 85 | cmd.arg |= addr << 9; |
70 | cmd.arg |= in; | 86 | cmd.arg |= in; |
71 | cmd.flags = MMC_RSP_R5 | MMC_CMD_AC; | 87 | cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_AC; |
72 | 88 | ||
73 | err = mmc_wait_for_cmd(card->host, &cmd, 0); | 89 | err = mmc_wait_for_cmd(card->host, &cmd, 0); |
74 | if (err) | 90 | if (err) |
75 | return err; | 91 | return err; |
76 | 92 | ||
77 | if (cmd.resp[0] & R5_ERROR) | 93 | if (mmc_host_is_spi(card->host)) { |
78 | return -EIO; | 94 | /* host driver already reported errors */ |
79 | if (cmd.resp[0] & R5_FUNCTION_NUMBER) | 95 | } else { |
80 | return -EINVAL; | 96 | if (cmd.resp[0] & R5_ERROR) |
81 | if (cmd.resp[0] & R5_OUT_OF_RANGE) | 97 | return -EIO; |
82 | return -ERANGE; | 98 | if (cmd.resp[0] & R5_FUNCTION_NUMBER) |
99 | return -EINVAL; | ||
100 | if (cmd.resp[0] & R5_OUT_OF_RANGE) | ||
101 | return -ERANGE; | ||
102 | } | ||
83 | 103 | ||
84 | if (out) | 104 | if (out) { |
85 | *out = cmd.resp[0] & 0xFF; | 105 | if (mmc_host_is_spi(card->host)) |
106 | *out = (cmd.resp[0] >> 8) & 0xFF; | ||
107 | else | ||
108 | *out = cmd.resp[0] & 0xFF; | ||
109 | } | ||
86 | 110 | ||
87 | return 0; | 111 | return 0; |
88 | } | 112 | } |
@@ -117,7 +141,7 @@ int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn, | |||
117 | cmd.arg |= (blksz == 512) ? 0 : blksz; /* byte mode */ | 141 | cmd.arg |= (blksz == 512) ? 0 : blksz; /* byte mode */ |
118 | else | 142 | else |
119 | cmd.arg |= 0x08000000 | blocks; /* block mode */ | 143 | cmd.arg |= 0x08000000 | blocks; /* block mode */ |
120 | cmd.flags = MMC_RSP_R5 | MMC_CMD_ADTC; | 144 | cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_ADTC; |
121 | 145 | ||
122 | data.blksz = blksz; | 146 | data.blksz = blksz; |
123 | data.blocks = blocks; | 147 | data.blocks = blocks; |
@@ -136,12 +160,16 @@ int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn, | |||
136 | if (data.error) | 160 | if (data.error) |
137 | return data.error; | 161 | return data.error; |
138 | 162 | ||
139 | if (cmd.resp[0] & R5_ERROR) | 163 | if (mmc_host_is_spi(card->host)) { |
140 | return -EIO; | 164 | /* host driver already reported errors */ |
141 | if (cmd.resp[0] & R5_FUNCTION_NUMBER) | 165 | } else { |
142 | return -EINVAL; | 166 | if (cmd.resp[0] & R5_ERROR) |
143 | if (cmd.resp[0] & R5_OUT_OF_RANGE) | 167 | return -EIO; |
144 | return -ERANGE; | 168 | if (cmd.resp[0] & R5_FUNCTION_NUMBER) |
169 | return -EINVAL; | ||
170 | if (cmd.resp[0] & R5_OUT_OF_RANGE) | ||
171 | return -ERANGE; | ||
172 | } | ||
145 | 173 | ||
146 | return 0; | 174 | return 0; |
147 | } | 175 | } |