diff options
Diffstat (limited to 'drivers/mmc/core/mmc.c')
-rw-r--r-- | drivers/mmc/core/mmc.c | 289 |
1 files changed, 192 insertions, 97 deletions
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 47449e870131..619581e49163 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c | |||
@@ -229,55 +229,13 @@ out: | |||
229 | } | 229 | } |
230 | 230 | ||
231 | /* | 231 | /* |
232 | * Host is being removed. Free up the current card. | 232 | * Handle the detection and initialisation of a card. |
233 | */ | 233 | * |
234 | static void mmc_remove(struct mmc_host *host) | 234 | * In the case of a resume, "curcard" will contain the card |
235 | { | 235 | * we're trying to reinitialise. |
236 | BUG_ON(!host); | ||
237 | BUG_ON(!host->card); | ||
238 | |||
239 | mmc_remove_card(host->card); | ||
240 | host->card = NULL; | ||
241 | } | ||
242 | |||
243 | /* | ||
244 | * Card detection callback from host. | ||
245 | */ | ||
246 | static void mmc_detect(struct mmc_host *host) | ||
247 | { | ||
248 | int err; | ||
249 | |||
250 | BUG_ON(!host); | ||
251 | BUG_ON(!host->card); | ||
252 | |||
253 | mmc_claim_host(host); | ||
254 | |||
255 | /* | ||
256 | * Just check if our card has been removed. | ||
257 | */ | ||
258 | err = mmc_send_status(host->card, NULL); | ||
259 | |||
260 | mmc_release_host(host); | ||
261 | |||
262 | if (err != MMC_ERR_NONE) { | ||
263 | mmc_remove_card(host->card); | ||
264 | host->card = NULL; | ||
265 | |||
266 | mmc_claim_host(host); | ||
267 | mmc_detach_bus(host); | ||
268 | mmc_release_host(host); | ||
269 | } | ||
270 | } | ||
271 | |||
272 | static const struct mmc_bus_ops mmc_ops = { | ||
273 | .remove = mmc_remove, | ||
274 | .detect = mmc_detect, | ||
275 | }; | ||
276 | |||
277 | /* | ||
278 | * Starting point for MMC card init. | ||
279 | */ | 236 | */ |
280 | int mmc_attach_mmc(struct mmc_host *host, u32 ocr) | 237 | static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, |
238 | struct mmc_card *oldcard) | ||
281 | { | 239 | { |
282 | struct mmc_card *card; | 240 | struct mmc_card *card; |
283 | int err; | 241 | int err; |
@@ -287,27 +245,6 @@ int mmc_attach_mmc(struct mmc_host *host, u32 ocr) | |||
287 | BUG_ON(!host); | 245 | BUG_ON(!host); |
288 | BUG_ON(!host->claimed); | 246 | BUG_ON(!host->claimed); |
289 | 247 | ||
290 | mmc_attach_bus(host, &mmc_ops); | ||
291 | |||
292 | /* | ||
293 | * Sanity check the voltages that the card claims to | ||
294 | * support. | ||
295 | */ | ||
296 | if (ocr & 0x7F) { | ||
297 | printk(KERN_WARNING "%s: card claims to support voltages " | ||
298 | "below the defined range. These will be ignored.\n", | ||
299 | mmc_hostname(host)); | ||
300 | ocr &= ~0x7F; | ||
301 | } | ||
302 | |||
303 | host->ocr = mmc_select_voltage(host, ocr); | ||
304 | |||
305 | /* | ||
306 | * Can we support the voltage of the card? | ||
307 | */ | ||
308 | if (!host->ocr) | ||
309 | goto err; | ||
310 | |||
311 | /* | 248 | /* |
312 | * Since we're changing the OCR value, we seem to | 249 | * Since we're changing the OCR value, we seem to |
313 | * need to tell some cards to go back to the idle | 250 | * need to tell some cards to go back to the idle |
@@ -317,7 +254,9 @@ int mmc_attach_mmc(struct mmc_host *host, u32 ocr) | |||
317 | mmc_go_idle(host); | 254 | mmc_go_idle(host); |
318 | 255 | ||
319 | /* The extra bit indicates that we support high capacity */ | 256 | /* The extra bit indicates that we support high capacity */ |
320 | mmc_send_op_cond(host, host->ocr | (1 << 30), NULL); | 257 | err = mmc_send_op_cond(host, ocr | (1 << 30), NULL); |
258 | if (err != MMC_ERR_NONE) | ||
259 | goto err; | ||
321 | 260 | ||
322 | /* | 261 | /* |
323 | * Fetch CID from card. | 262 | * Fetch CID from card. |
@@ -326,16 +265,23 @@ int mmc_attach_mmc(struct mmc_host *host, u32 ocr) | |||
326 | if (err != MMC_ERR_NONE) | 265 | if (err != MMC_ERR_NONE) |
327 | goto err; | 266 | goto err; |
328 | 267 | ||
329 | /* | 268 | if (oldcard) { |
330 | * Allocate card structure. | 269 | if (memcmp(cid, oldcard->raw_cid, sizeof(cid)) != 0) |
331 | */ | 270 | goto err; |
332 | card = mmc_alloc_card(host); | 271 | |
333 | if (IS_ERR(card)) | 272 | card = oldcard; |
334 | goto err; | 273 | } else { |
274 | /* | ||
275 | * Allocate card structure. | ||
276 | */ | ||
277 | card = mmc_alloc_card(host); | ||
278 | if (IS_ERR(card)) | ||
279 | goto err; | ||
335 | 280 | ||
336 | card->type = MMC_TYPE_MMC; | 281 | card->type = MMC_TYPE_MMC; |
337 | card->rca = 1; | 282 | card->rca = 1; |
338 | memcpy(card->raw_cid, cid, sizeof(card->raw_cid)); | 283 | memcpy(card->raw_cid, cid, sizeof(card->raw_cid)); |
284 | } | ||
339 | 285 | ||
340 | /* | 286 | /* |
341 | * Set card RCA. | 287 | * Set card RCA. |
@@ -346,15 +292,17 @@ int mmc_attach_mmc(struct mmc_host *host, u32 ocr) | |||
346 | 292 | ||
347 | mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL); | 293 | mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL); |
348 | 294 | ||
349 | /* | 295 | if (!oldcard) { |
350 | * Fetch CSD from card. | 296 | /* |
351 | */ | 297 | * Fetch CSD from card. |
352 | err = mmc_send_csd(card, card->raw_csd); | 298 | */ |
353 | if (err != MMC_ERR_NONE) | 299 | err = mmc_send_csd(card, card->raw_csd); |
354 | goto free_card; | 300 | if (err != MMC_ERR_NONE) |
301 | goto free_card; | ||
355 | 302 | ||
356 | mmc_decode_csd(card); | 303 | mmc_decode_csd(card); |
357 | mmc_decode_cid(card); | 304 | mmc_decode_cid(card); |
305 | } | ||
358 | 306 | ||
359 | /* | 307 | /* |
360 | * Select card, as all following commands rely on that. | 308 | * Select card, as all following commands rely on that. |
@@ -363,12 +311,14 @@ int mmc_attach_mmc(struct mmc_host *host, u32 ocr) | |||
363 | if (err != MMC_ERR_NONE) | 311 | if (err != MMC_ERR_NONE) |
364 | goto free_card; | 312 | goto free_card; |
365 | 313 | ||
366 | /* | 314 | if (!oldcard) { |
367 | * Fetch and process extened CSD. | 315 | /* |
368 | */ | 316 | * Fetch and process extened CSD. |
369 | err = mmc_read_ext_csd(card); | 317 | */ |
370 | if (err != MMC_ERR_NONE) | 318 | err = mmc_read_ext_csd(card); |
371 | goto free_card; | 319 | if (err != MMC_ERR_NONE) |
320 | goto free_card; | ||
321 | } | ||
372 | 322 | ||
373 | /* | 323 | /* |
374 | * Activate high speed (if supported) | 324 | * Activate high speed (if supported) |
@@ -412,11 +362,157 @@ int mmc_attach_mmc(struct mmc_host *host, u32 ocr) | |||
412 | mmc_set_bus_width(card->host, MMC_BUS_WIDTH_4); | 362 | mmc_set_bus_width(card->host, MMC_BUS_WIDTH_4); |
413 | } | 363 | } |
414 | 364 | ||
415 | host->card = card; | 365 | if (!oldcard) |
366 | host->card = card; | ||
367 | |||
368 | return MMC_ERR_NONE; | ||
369 | |||
370 | free_card: | ||
371 | if (!oldcard) | ||
372 | mmc_remove_card(card); | ||
373 | err: | ||
374 | |||
375 | return MMC_ERR_FAILED; | ||
376 | } | ||
377 | |||
378 | /* | ||
379 | * Host is being removed. Free up the current card. | ||
380 | */ | ||
381 | static void mmc_remove(struct mmc_host *host) | ||
382 | { | ||
383 | BUG_ON(!host); | ||
384 | BUG_ON(!host->card); | ||
385 | |||
386 | mmc_remove_card(host->card); | ||
387 | host->card = NULL; | ||
388 | } | ||
389 | |||
390 | /* | ||
391 | * Card detection callback from host. | ||
392 | */ | ||
393 | static void mmc_detect(struct mmc_host *host) | ||
394 | { | ||
395 | int err; | ||
396 | |||
397 | BUG_ON(!host); | ||
398 | BUG_ON(!host->card); | ||
399 | |||
400 | mmc_claim_host(host); | ||
401 | |||
402 | /* | ||
403 | * Just check if our card has been removed. | ||
404 | */ | ||
405 | err = mmc_send_status(host->card, NULL); | ||
406 | |||
407 | mmc_release_host(host); | ||
408 | |||
409 | if (err != MMC_ERR_NONE) { | ||
410 | mmc_remove_card(host->card); | ||
411 | host->card = NULL; | ||
412 | |||
413 | mmc_claim_host(host); | ||
414 | mmc_detach_bus(host); | ||
415 | mmc_release_host(host); | ||
416 | } | ||
417 | } | ||
418 | |||
419 | #ifdef CONFIG_MMC_UNSAFE_RESUME | ||
420 | |||
421 | /* | ||
422 | * Suspend callback from host. | ||
423 | */ | ||
424 | static void mmc_suspend(struct mmc_host *host) | ||
425 | { | ||
426 | BUG_ON(!host); | ||
427 | BUG_ON(!host->card); | ||
416 | 428 | ||
429 | mmc_claim_host(host); | ||
430 | mmc_deselect_cards(host); | ||
431 | host->card->state &= ~MMC_STATE_HIGHSPEED; | ||
417 | mmc_release_host(host); | 432 | mmc_release_host(host); |
433 | } | ||
418 | 434 | ||
419 | err = mmc_register_card(card); | 435 | /* |
436 | * Resume callback from host. | ||
437 | * | ||
438 | * This function tries to determine if the same card is still present | ||
439 | * and, if so, restore all state to it. | ||
440 | */ | ||
441 | static void mmc_resume(struct mmc_host *host) | ||
442 | { | ||
443 | int err; | ||
444 | |||
445 | BUG_ON(!host); | ||
446 | BUG_ON(!host->card); | ||
447 | |||
448 | mmc_claim_host(host); | ||
449 | |||
450 | err = mmc_sd_init_card(host, host->ocr, host->card); | ||
451 | if (err != MMC_ERR_NONE) { | ||
452 | mmc_remove_card(host->card); | ||
453 | host->card = NULL; | ||
454 | |||
455 | mmc_detach_bus(host); | ||
456 | } | ||
457 | |||
458 | mmc_release_host(host); | ||
459 | } | ||
460 | |||
461 | #else | ||
462 | |||
463 | #define mmc_suspend NULL | ||
464 | #define mmc_resume NULL | ||
465 | |||
466 | #endif | ||
467 | |||
468 | static const struct mmc_bus_ops mmc_ops = { | ||
469 | .remove = mmc_remove, | ||
470 | .detect = mmc_detect, | ||
471 | .suspend = mmc_suspend, | ||
472 | .resume = mmc_resume, | ||
473 | }; | ||
474 | |||
475 | /* | ||
476 | * Starting point for MMC card init. | ||
477 | */ | ||
478 | int mmc_attach_mmc(struct mmc_host *host, u32 ocr) | ||
479 | { | ||
480 | int err; | ||
481 | |||
482 | BUG_ON(!host); | ||
483 | BUG_ON(!host->claimed); | ||
484 | |||
485 | mmc_attach_bus(host, &mmc_ops); | ||
486 | |||
487 | /* | ||
488 | * Sanity check the voltages that the card claims to | ||
489 | * support. | ||
490 | */ | ||
491 | if (ocr & 0x7F) { | ||
492 | printk(KERN_WARNING "%s: card claims to support voltages " | ||
493 | "below the defined range. These will be ignored.\n", | ||
494 | mmc_hostname(host)); | ||
495 | ocr &= ~0x7F; | ||
496 | } | ||
497 | |||
498 | host->ocr = mmc_select_voltage(host, ocr); | ||
499 | |||
500 | /* | ||
501 | * Can we support the voltage of the card? | ||
502 | */ | ||
503 | if (!host->ocr) | ||
504 | goto err; | ||
505 | |||
506 | /* | ||
507 | * Detect and init the card. | ||
508 | */ | ||
509 | err = mmc_sd_init_card(host, host->ocr, NULL); | ||
510 | if (err != MMC_ERR_NONE) | ||
511 | goto err; | ||
512 | |||
513 | mmc_release_host(host); | ||
514 | |||
515 | err = mmc_register_card(host->card); | ||
420 | if (err) | 516 | if (err) |
421 | goto reclaim_host; | 517 | goto reclaim_host; |
422 | 518 | ||
@@ -424,8 +520,7 @@ int mmc_attach_mmc(struct mmc_host *host, u32 ocr) | |||
424 | 520 | ||
425 | reclaim_host: | 521 | reclaim_host: |
426 | mmc_claim_host(host); | 522 | mmc_claim_host(host); |
427 | free_card: | 523 | mmc_remove_card(host->card); |
428 | mmc_remove_card(card); | ||
429 | host->card = NULL; | 524 | host->card = NULL; |
430 | err: | 525 | err: |
431 | mmc_detach_bus(host); | 526 | mmc_detach_bus(host); |