diff options
Diffstat (limited to 'drivers/mmc/core/mmc.c')
-rw-r--r-- | drivers/mmc/core/mmc.c | 134 |
1 files changed, 90 insertions, 44 deletions
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 21d7f48e1d4e..65fe28860f54 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c | |||
@@ -161,13 +161,12 @@ static int mmc_read_ext_csd(struct mmc_card *card) | |||
161 | { | 161 | { |
162 | int err; | 162 | int err; |
163 | u8 *ext_csd; | 163 | u8 *ext_csd; |
164 | unsigned int ext_csd_struct; | ||
164 | 165 | ||
165 | BUG_ON(!card); | 166 | BUG_ON(!card); |
166 | 167 | ||
167 | err = MMC_ERR_FAILED; | ||
168 | |||
169 | if (card->csd.mmca_vsn < CSD_SPEC_VER_4) | 168 | if (card->csd.mmca_vsn < CSD_SPEC_VER_4) |
170 | return MMC_ERR_NONE; | 169 | return 0; |
171 | 170 | ||
172 | /* | 171 | /* |
173 | * As the ext_csd is so large and mostly unused, we don't store the | 172 | * As the ext_csd is so large and mostly unused, we don't store the |
@@ -176,13 +175,19 @@ static int mmc_read_ext_csd(struct mmc_card *card) | |||
176 | ext_csd = kmalloc(512, GFP_KERNEL); | 175 | ext_csd = kmalloc(512, GFP_KERNEL); |
177 | if (!ext_csd) { | 176 | if (!ext_csd) { |
178 | printk(KERN_ERR "%s: could not allocate a buffer to " | 177 | printk(KERN_ERR "%s: could not allocate a buffer to " |
179 | "receive the ext_csd. mmc v4 cards will be " | 178 | "receive the ext_csd.\n", mmc_hostname(card->host)); |
180 | "treated as v3.\n", mmc_hostname(card->host)); | 179 | return -ENOMEM; |
181 | return MMC_ERR_FAILED; | ||
182 | } | 180 | } |
183 | 181 | ||
184 | err = mmc_send_ext_csd(card, ext_csd); | 182 | err = mmc_send_ext_csd(card, ext_csd); |
185 | if (err != MMC_ERR_NONE) { | 183 | if (err) { |
184 | /* | ||
185 | * We all hosts that cannot perform the command | ||
186 | * to fail more gracefully | ||
187 | */ | ||
188 | if (err != -EINVAL) | ||
189 | goto out; | ||
190 | |||
186 | /* | 191 | /* |
187 | * High capacity cards should have this "magic" size | 192 | * High capacity cards should have this "magic" size |
188 | * stored in their CSD. | 193 | * stored in their CSD. |
@@ -197,18 +202,29 @@ static int mmc_read_ext_csd(struct mmc_card *card) | |||
197 | "EXT_CSD, performance might " | 202 | "EXT_CSD, performance might " |
198 | "suffer.\n", | 203 | "suffer.\n", |
199 | mmc_hostname(card->host)); | 204 | mmc_hostname(card->host)); |
200 | err = MMC_ERR_NONE; | 205 | err = 0; |
201 | } | 206 | } |
207 | |||
202 | goto out; | 208 | goto out; |
203 | } | 209 | } |
204 | 210 | ||
205 | card->ext_csd.sectors = | 211 | ext_csd_struct = ext_csd[EXT_CSD_REV]; |
206 | ext_csd[EXT_CSD_SEC_CNT + 0] << 0 | | 212 | if (ext_csd_struct > 2) { |
207 | ext_csd[EXT_CSD_SEC_CNT + 1] << 8 | | 213 | printk(KERN_ERR "%s: unrecognised EXT_CSD structure " |
208 | ext_csd[EXT_CSD_SEC_CNT + 2] << 16 | | 214 | "version %d\n", mmc_hostname(card->host), |
209 | ext_csd[EXT_CSD_SEC_CNT + 3] << 24; | 215 | ext_csd_struct); |
210 | if (card->ext_csd.sectors) | 216 | return -EINVAL; |
211 | mmc_card_set_blockaddr(card); | 217 | } |
218 | |||
219 | if (ext_csd_struct >= 2) { | ||
220 | card->ext_csd.sectors = | ||
221 | ext_csd[EXT_CSD_SEC_CNT + 0] << 0 | | ||
222 | ext_csd[EXT_CSD_SEC_CNT + 1] << 8 | | ||
223 | ext_csd[EXT_CSD_SEC_CNT + 2] << 16 | | ||
224 | ext_csd[EXT_CSD_SEC_CNT + 3] << 24; | ||
225 | if (card->ext_csd.sectors) | ||
226 | mmc_card_set_blockaddr(card); | ||
227 | } | ||
212 | 228 | ||
213 | switch (ext_csd[EXT_CSD_CARD_TYPE]) { | 229 | switch (ext_csd[EXT_CSD_CARD_TYPE]) { |
214 | case EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26: | 230 | case EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26: |
@@ -246,7 +262,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, | |||
246 | unsigned int max_dtr; | 262 | unsigned int max_dtr; |
247 | 263 | ||
248 | BUG_ON(!host); | 264 | BUG_ON(!host); |
249 | BUG_ON(!host->claimed); | 265 | WARN_ON(!host->claimed); |
250 | 266 | ||
251 | /* | 267 | /* |
252 | * Since we're changing the OCR value, we seem to | 268 | * Since we're changing the OCR value, we seem to |
@@ -258,19 +274,33 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, | |||
258 | 274 | ||
259 | /* The extra bit indicates that we support high capacity */ | 275 | /* The extra bit indicates that we support high capacity */ |
260 | err = mmc_send_op_cond(host, ocr | (1 << 30), NULL); | 276 | err = mmc_send_op_cond(host, ocr | (1 << 30), NULL); |
261 | if (err != MMC_ERR_NONE) | 277 | if (err) |
262 | goto err; | 278 | goto err; |
263 | 279 | ||
264 | /* | 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 | /* | ||
265 | * Fetch CID from card. | 290 | * Fetch CID from card. |
266 | */ | 291 | */ |
267 | err = mmc_all_send_cid(host, cid); | 292 | if (mmc_host_is_spi(host)) |
268 | if (err != MMC_ERR_NONE) | 293 | err = mmc_send_cid(host, cid); |
294 | else | ||
295 | err = mmc_all_send_cid(host, cid); | ||
296 | if (err) | ||
269 | goto err; | 297 | goto err; |
270 | 298 | ||
271 | if (oldcard) { | 299 | if (oldcard) { |
272 | if (memcmp(cid, oldcard->raw_cid, sizeof(cid)) != 0) | 300 | if (memcmp(cid, oldcard->raw_cid, sizeof(cid)) != 0) { |
301 | err = -ENOENT; | ||
273 | goto err; | 302 | goto err; |
303 | } | ||
274 | 304 | ||
275 | card = oldcard; | 305 | card = oldcard; |
276 | } else { | 306 | } else { |
@@ -278,8 +308,10 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, | |||
278 | * Allocate card structure. | 308 | * Allocate card structure. |
279 | */ | 309 | */ |
280 | card = mmc_alloc_card(host); | 310 | card = mmc_alloc_card(host); |
281 | if (IS_ERR(card)) | 311 | if (IS_ERR(card)) { |
312 | err = PTR_ERR(card); | ||
282 | goto err; | 313 | goto err; |
314 | } | ||
283 | 315 | ||
284 | card->type = MMC_TYPE_MMC; | 316 | card->type = MMC_TYPE_MMC; |
285 | card->rca = 1; | 317 | card->rca = 1; |
@@ -287,43 +319,47 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, | |||
287 | } | 319 | } |
288 | 320 | ||
289 | /* | 321 | /* |
290 | * Set card RCA. | 322 | * For native busses: set card RCA and quit open drain mode. |
291 | */ | 323 | */ |
292 | err = mmc_set_relative_addr(card); | 324 | if (!mmc_host_is_spi(host)) { |
293 | if (err != MMC_ERR_NONE) | 325 | err = mmc_set_relative_addr(card); |
294 | goto free_card; | 326 | if (err) |
327 | goto free_card; | ||
295 | 328 | ||
296 | mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL); | 329 | mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL); |
330 | } | ||
297 | 331 | ||
298 | if (!oldcard) { | 332 | if (!oldcard) { |
299 | /* | 333 | /* |
300 | * Fetch CSD from card. | 334 | * Fetch CSD from card. |
301 | */ | 335 | */ |
302 | err = mmc_send_csd(card, card->raw_csd); | 336 | err = mmc_send_csd(card, card->raw_csd); |
303 | if (err != MMC_ERR_NONE) | 337 | if (err) |
304 | goto free_card; | 338 | goto free_card; |
305 | 339 | ||
306 | err = mmc_decode_csd(card); | 340 | err = mmc_decode_csd(card); |
307 | if (err < 0) | 341 | if (err) |
308 | goto free_card; | 342 | goto free_card; |
309 | err = mmc_decode_cid(card); | 343 | err = mmc_decode_cid(card); |
310 | if (err < 0) | 344 | if (err) |
311 | goto free_card; | 345 | goto free_card; |
312 | } | 346 | } |
313 | 347 | ||
314 | /* | 348 | /* |
315 | * Select card, as all following commands rely on that. | 349 | * Select card, as all following commands rely on that. |
316 | */ | 350 | */ |
317 | err = mmc_select_card(card); | 351 | if (!mmc_host_is_spi(host)) { |
318 | if (err != MMC_ERR_NONE) | 352 | err = mmc_select_card(card); |
319 | goto free_card; | 353 | if (err) |
354 | goto free_card; | ||
355 | } | ||
320 | 356 | ||
321 | if (!oldcard) { | 357 | if (!oldcard) { |
322 | /* | 358 | /* |
323 | * Fetch and process extened CSD. | 359 | * Fetch and process extended CSD. |
324 | */ | 360 | */ |
325 | err = mmc_read_ext_csd(card); | 361 | err = mmc_read_ext_csd(card); |
326 | if (err != MMC_ERR_NONE) | 362 | if (err) |
327 | goto free_card; | 363 | goto free_card; |
328 | } | 364 | } |
329 | 365 | ||
@@ -334,7 +370,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, | |||
334 | (host->caps & MMC_CAP_MMC_HIGHSPEED)) { | 370 | (host->caps & MMC_CAP_MMC_HIGHSPEED)) { |
335 | err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, | 371 | err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, |
336 | EXT_CSD_HS_TIMING, 1); | 372 | EXT_CSD_HS_TIMING, 1); |
337 | if (err != MMC_ERR_NONE) | 373 | if (err) |
338 | goto free_card; | 374 | goto free_card; |
339 | 375 | ||
340 | mmc_card_set_highspeed(card); | 376 | mmc_card_set_highspeed(card); |
@@ -363,7 +399,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, | |||
363 | (host->caps & MMC_CAP_4_BIT_DATA)) { | 399 | (host->caps & MMC_CAP_4_BIT_DATA)) { |
364 | err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, | 400 | err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, |
365 | EXT_CSD_BUS_WIDTH, EXT_CSD_BUS_WIDTH_4); | 401 | EXT_CSD_BUS_WIDTH, EXT_CSD_BUS_WIDTH_4); |
366 | if (err != MMC_ERR_NONE) | 402 | if (err) |
367 | goto free_card; | 403 | goto free_card; |
368 | 404 | ||
369 | mmc_set_bus_width(card->host, MMC_BUS_WIDTH_4); | 405 | mmc_set_bus_width(card->host, MMC_BUS_WIDTH_4); |
@@ -372,14 +408,14 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, | |||
372 | if (!oldcard) | 408 | if (!oldcard) |
373 | host->card = card; | 409 | host->card = card; |
374 | 410 | ||
375 | return MMC_ERR_NONE; | 411 | return 0; |
376 | 412 | ||
377 | free_card: | 413 | free_card: |
378 | if (!oldcard) | 414 | if (!oldcard) |
379 | mmc_remove_card(card); | 415 | mmc_remove_card(card); |
380 | err: | 416 | err: |
381 | 417 | ||
382 | return MMC_ERR_FAILED; | 418 | return err; |
383 | } | 419 | } |
384 | 420 | ||
385 | /* | 421 | /* |
@@ -413,7 +449,7 @@ static void mmc_detect(struct mmc_host *host) | |||
413 | 449 | ||
414 | mmc_release_host(host); | 450 | mmc_release_host(host); |
415 | 451 | ||
416 | if (err != MMC_ERR_NONE) { | 452 | if (err) { |
417 | mmc_remove(host); | 453 | mmc_remove(host); |
418 | 454 | ||
419 | mmc_claim_host(host); | 455 | mmc_claim_host(host); |
@@ -480,7 +516,8 @@ static void mmc_suspend(struct mmc_host *host) | |||
480 | BUG_ON(!host->card); | 516 | BUG_ON(!host->card); |
481 | 517 | ||
482 | mmc_claim_host(host); | 518 | mmc_claim_host(host); |
483 | mmc_deselect_cards(host); | 519 | if (!mmc_host_is_spi(host)) |
520 | mmc_deselect_cards(host); | ||
484 | host->card->state &= ~MMC_STATE_HIGHSPEED; | 521 | host->card->state &= ~MMC_STATE_HIGHSPEED; |
485 | mmc_release_host(host); | 522 | mmc_release_host(host); |
486 | } | 523 | } |
@@ -502,7 +539,7 @@ static void mmc_resume(struct mmc_host *host) | |||
502 | err = mmc_init_card(host, host->ocr, host->card); | 539 | err = mmc_init_card(host, host->ocr, host->card); |
503 | mmc_release_host(host); | 540 | mmc_release_host(host); |
504 | 541 | ||
505 | if (err != MMC_ERR_NONE) { | 542 | if (err) { |
506 | mmc_remove(host); | 543 | mmc_remove(host); |
507 | 544 | ||
508 | mmc_claim_host(host); | 545 | mmc_claim_host(host); |
@@ -536,11 +573,20 @@ int mmc_attach_mmc(struct mmc_host *host, u32 ocr) | |||
536 | int err; | 573 | int err; |
537 | 574 | ||
538 | BUG_ON(!host); | 575 | BUG_ON(!host); |
539 | BUG_ON(!host->claimed); | 576 | WARN_ON(!host->claimed); |
540 | 577 | ||
541 | mmc_attach_bus(host, &mmc_ops); | 578 | mmc_attach_bus(host, &mmc_ops); |
542 | 579 | ||
543 | /* | 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 | /* | ||
544 | * Sanity check the voltages that the card claims to | 590 | * Sanity check the voltages that the card claims to |
545 | * support. | 591 | * support. |
546 | */ | 592 | */ |
@@ -565,7 +611,7 @@ int mmc_attach_mmc(struct mmc_host *host, u32 ocr) | |||
565 | * Detect and init the card. | 611 | * Detect and init the card. |
566 | */ | 612 | */ |
567 | err = mmc_init_card(host, host->ocr, NULL); | 613 | err = mmc_init_card(host, host->ocr, NULL); |
568 | if (err != MMC_ERR_NONE) | 614 | if (err) |
569 | goto err; | 615 | goto err; |
570 | 616 | ||
571 | mmc_release_host(host); | 617 | mmc_release_host(host); |
@@ -587,6 +633,6 @@ err: | |||
587 | printk(KERN_ERR "%s: error %d whilst initialising MMC card\n", | 633 | printk(KERN_ERR "%s: error %d whilst initialising MMC card\n", |
588 | mmc_hostname(host), err); | 634 | mmc_hostname(host), err); |
589 | 635 | ||
590 | return 0; | 636 | return err; |
591 | } | 637 | } |
592 | 638 | ||