aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorPierre Ossman <drzeus@drzeus.cx>2007-05-01 10:00:02 -0400
committerPierre Ossman <drzeus@drzeus.cx>2007-05-01 10:00:02 -0400
commit6abaa0c9fec563538f2a28a682af8c89bb9b125c (patch)
tree1da7fb5a0b37bd57b38ca52c77ccc72b099fcbae /drivers
parent89a73cf52ba2ae4402c53487b71ec4475544f139 (diff)
mmc: support unsafe resume of cards
Since many have the system root on MMC/SD we must allow some foot shooting when it comes to resume. We cannot detect if a card is removed and reinserted during suspend, so the safe approach would be to assume it was, avoiding potential filesystem corruption. This will of course not work if you cannot release the card before suspend. This commit adds a compile time option that makes the MMC layer assume the card wasn't touched if it is redetected upon resume. Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mmc/Kconfig2
-rw-r--r--drivers/mmc/core/Kconfig17
-rw-r--r--drivers/mmc/core/core.c29
-rw-r--r--drivers/mmc/core/core.h2
-rw-r--r--drivers/mmc/core/mmc.c289
-rw-r--r--drivers/mmc/core/sd.c318
6 files changed, 444 insertions, 213 deletions
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index c7d64c0187fb..6c97491543db 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -19,6 +19,8 @@ config MMC_DEBUG
19 This is an option for use by developers; most people should 19 This is an option for use by developers; most people should
20 say N here. This enables MMC core and driver debugging. 20 say N here. This enables MMC core and driver debugging.
21 21
22source "drivers/mmc/core/Kconfig"
23
22source "drivers/mmc/card/Kconfig" 24source "drivers/mmc/card/Kconfig"
23 25
24source "drivers/mmc/host/Kconfig" 26source "drivers/mmc/host/Kconfig"
diff --git a/drivers/mmc/core/Kconfig b/drivers/mmc/core/Kconfig
new file mode 100644
index 000000000000..94222b9a15ea
--- /dev/null
+++ b/drivers/mmc/core/Kconfig
@@ -0,0 +1,17 @@
1#
2# MMC core configuration
3#
4
5config MMC_UNSAFE_RESUME
6 bool "Allow unsafe resume (DANGEROUS)"
7 depends on MMC != n
8 help
9 If you say Y here, the MMC layer will assume that all cards
10 stayed in their respective slots during the suspend. The
11 normal behaviour is to remove them at suspend and
12 redetecting them at resume. Breaking this assumption will
13 in most cases result in data corruption.
14
15 This option is usually just for embedded systems which use
16 a MMC/SD card for rootfs. Most people should say N here.
17
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 75333a2461df..72c7cf4a9f9d 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -677,14 +677,19 @@ int mmc_suspend_host(struct mmc_host *host, pm_message_t state)
677 677
678 mmc_bus_get(host); 678 mmc_bus_get(host);
679 if (host->bus_ops && !host->bus_dead) { 679 if (host->bus_ops && !host->bus_dead) {
680 if (host->bus_ops->remove) 680 if (host->bus_ops->suspend)
681 host->bus_ops->remove(host); 681 host->bus_ops->suspend(host);
682 mmc_detach_bus(host); 682 if (!host->bus_ops->resume) {
683 if (host->bus_ops->remove)
684 host->bus_ops->remove(host);
685
686 mmc_claim_host(host);
687 mmc_detach_bus(host);
688 mmc_release_host(host);
689 }
683 } 690 }
684 mmc_bus_put(host); 691 mmc_bus_put(host);
685 692
686 BUG_ON(host->card);
687
688 mmc_power_off(host); 693 mmc_power_off(host);
689 694
690 return 0; 695 return 0;
@@ -698,7 +703,19 @@ EXPORT_SYMBOL(mmc_suspend_host);
698 */ 703 */
699int mmc_resume_host(struct mmc_host *host) 704int mmc_resume_host(struct mmc_host *host)
700{ 705{
701 mmc_rescan(&host->detect.work); 706 mmc_bus_get(host);
707 if (host->bus_ops && !host->bus_dead) {
708 mmc_power_up(host);
709 BUG_ON(!host->bus_ops->resume);
710 host->bus_ops->resume(host);
711 }
712 mmc_bus_put(host);
713
714 /*
715 * We add a slight delay here so that resume can progress
716 * in parallel.
717 */
718 mmc_detect_change(host, 1);
702 719
703 return 0; 720 return 0;
704} 721}
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h
index fad8edc38099..177264d090ac 100644
--- a/drivers/mmc/core/core.h
+++ b/drivers/mmc/core/core.h
@@ -18,6 +18,8 @@
18struct mmc_bus_ops { 18struct mmc_bus_ops {
19 void (*remove)(struct mmc_host *); 19 void (*remove)(struct mmc_host *);
20 void (*detect)(struct mmc_host *); 20 void (*detect)(struct mmc_host *);
21 void (*suspend)(struct mmc_host *);
22 void (*resume)(struct mmc_host *);
21}; 23};
22 24
23void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops); 25void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops);
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 *
234static 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 */
246static 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
272static 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 */
280int mmc_attach_mmc(struct mmc_host *host, u32 ocr) 237static 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
370free_card:
371 if (!oldcard)
372 mmc_remove_card(card);
373err:
374
375 return MMC_ERR_FAILED;
376}
377
378/*
379 * Host is being removed. Free up the current card.
380 */
381static 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 */
393static 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 */
424static 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 */
441static 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
468static 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 */
478int 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
425reclaim_host: 521reclaim_host:
426 mmc_claim_host(host); 522 mmc_claim_host(host);
427free_card: 523 mmc_remove_card(host->card);
428 mmc_remove_card(card);
429 host->card = NULL; 524 host->card = NULL;
430err: 525err:
431 mmc_detach_bus(host); 526 mmc_detach_bus(host);
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index ae54e8eb7fea..6597e778f70e 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -263,55 +263,13 @@ out:
263} 263}
264 264
265/* 265/*
266 * Host is being removed. Free up the current card. 266 * Handle the detection and initialisation of a card.
267 */ 267 *
268static void mmc_sd_remove(struct mmc_host *host) 268 * In the case of a resume, "curcard" will contain the card
269{ 269 * we're trying to reinitialise.
270 BUG_ON(!host);
271 BUG_ON(!host->card);
272
273 mmc_remove_card(host->card);
274 host->card = NULL;
275}
276
277/*
278 * Card detection callback from host.
279 */
280static void mmc_sd_detect(struct mmc_host *host)
281{
282 int err;
283
284 BUG_ON(!host);
285 BUG_ON(!host->card);
286
287 mmc_claim_host(host);
288
289 /*
290 * Just check if our card has been removed.
291 */
292 err = mmc_send_status(host->card, NULL);
293
294 mmc_release_host(host);
295
296 if (err != MMC_ERR_NONE) {
297 mmc_remove_card(host->card);
298 host->card = NULL;
299
300 mmc_claim_host(host);
301 mmc_detach_bus(host);
302 mmc_release_host(host);
303 }
304}
305
306static const struct mmc_bus_ops mmc_sd_ops = {
307 .remove = mmc_sd_remove,
308 .detect = mmc_sd_detect,
309};
310
311/*
312 * Starting point for SD card init.
313 */ 270 */
314int mmc_attach_sd(struct mmc_host *host, u32 ocr) 271static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
272 struct mmc_card *oldcard)
315{ 273{
316 struct mmc_card *card; 274 struct mmc_card *card;
317 int err; 275 int err;
@@ -321,34 +279,6 @@ int mmc_attach_sd(struct mmc_host *host, u32 ocr)
321 BUG_ON(!host); 279 BUG_ON(!host);
322 BUG_ON(!host->claimed); 280 BUG_ON(!host->claimed);
323 281
324 mmc_attach_bus(host, &mmc_sd_ops);
325
326 /*
327 * Sanity check the voltages that the card claims to
328 * support.
329 */
330 if (ocr & 0x7F) {
331 printk(KERN_WARNING "%s: card claims to support voltages "
332 "below the defined range. These will be ignored.\n",
333 mmc_hostname(host));
334 ocr &= ~0x7F;
335 }
336
337 if (ocr & MMC_VDD_165_195) {
338 printk(KERN_WARNING "%s: SD card claims to support the "
339 "incompletely defined 'low voltage range'. This "
340 "will be ignored.\n", mmc_hostname(host));
341 ocr &= ~MMC_VDD_165_195;
342 }
343
344 host->ocr = mmc_select_voltage(host, ocr);
345
346 /*
347 * Can we support the voltage(s) of the card(s)?
348 */
349 if (!host->ocr)
350 goto err;
351
352 /* 282 /*
353 * Since we're changing the OCR value, we seem to 283 * Since we're changing the OCR value, we seem to
354 * need to tell some cards to go back to the idle 284 * need to tell some cards to go back to the idle
@@ -363,11 +293,13 @@ int mmc_attach_sd(struct mmc_host *host, u32 ocr)
363 * of the ocr to indicate that we can handle 293 * of the ocr to indicate that we can handle
364 * block-addressed SDHC cards. 294 * block-addressed SDHC cards.
365 */ 295 */
366 err = mmc_send_if_cond(host, host->ocr); 296 err = mmc_send_if_cond(host, ocr);
367 if (err == MMC_ERR_NONE) 297 if (err == MMC_ERR_NONE)
368 ocr = host->ocr | (1 << 30); 298 ocr |= 1 << 30;
369 299
370 mmc_send_app_op_cond(host, ocr, NULL); 300 err = mmc_send_app_op_cond(host, ocr, NULL);
301 if (err != MMC_ERR_NONE)
302 goto err;
371 303
372 /* 304 /*
373 * Fetch CID from card. 305 * Fetch CID from card.
@@ -376,15 +308,22 @@ int mmc_attach_sd(struct mmc_host *host, u32 ocr)
376 if (err != MMC_ERR_NONE) 308 if (err != MMC_ERR_NONE)
377 goto err; 309 goto err;
378 310
379 /* 311 if (oldcard) {
380 * Allocate card structure. 312 if (memcmp(cid, oldcard->raw_cid, sizeof(cid)) != 0)
381 */ 313 goto err;
382 card = mmc_alloc_card(host);
383 if (IS_ERR(card))
384 goto err;
385 314
386 card->type = MMC_TYPE_SD; 315 card = oldcard;
387 memcpy(card->raw_cid, cid, sizeof(card->raw_cid)); 316 } else {
317 /*
318 * Allocate card structure.
319 */
320 card = mmc_alloc_card(host);
321 if (IS_ERR(card))
322 goto err;
323
324 card->type = MMC_TYPE_SD;
325 memcpy(card->raw_cid, cid, sizeof(card->raw_cid));
326 }
388 327
389 /* 328 /*
390 * Set card RCA. 329 * Set card RCA.
@@ -395,35 +334,42 @@ int mmc_attach_sd(struct mmc_host *host, u32 ocr)
395 334
396 mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL); 335 mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL);
397 336
398 /* 337 if (!oldcard) {
399 * Fetch CSD from card. 338 /*
400 */ 339 * Fetch CSD from card.
401 err = mmc_send_csd(card, card->raw_csd); 340 */
402 if (err != MMC_ERR_NONE) 341 err = mmc_send_csd(card, card->raw_csd);
403 goto free_card; 342 if (err != MMC_ERR_NONE)
343 goto free_card;
404 344
405 mmc_decode_csd(card); 345 mmc_decode_csd(card);
406 mmc_decode_cid(card); 346 mmc_decode_cid(card);
347 }
407 348
408 /* 349 /*
409 * Fetch SCR from card. 350 * Select card, as all following commands rely on that.
410 */ 351 */
411 err = mmc_select_card(card); 352 err = mmc_select_card(card);
412 if (err != MMC_ERR_NONE) 353 if (err != MMC_ERR_NONE)
413 goto free_card; 354 goto free_card;
414 355
415 err = mmc_app_send_scr(card, card->raw_scr); 356 if (!oldcard) {
416 if (err != MMC_ERR_NONE) 357 /*
417 goto free_card; 358 * Fetch SCR from card.
359 */
360 err = mmc_app_send_scr(card, card->raw_scr);
361 if (err != MMC_ERR_NONE)
362 goto free_card;
418 363
419 mmc_decode_scr(card); 364 mmc_decode_scr(card);
420 365
421 /* 366 /*
422 * Fetch switch information from card. 367 * Fetch switch information from card.
423 */ 368 */
424 err = mmc_read_switch(card); 369 err = mmc_read_switch(card);
425 if (err != MMC_ERR_NONE) 370 if (err != MMC_ERR_NONE)
426 goto free_card; 371 goto free_card;
372 }
427 373
428 /* 374 /*
429 * Attempt to change to high-speed (if supported) 375 * Attempt to change to high-speed (if supported)
@@ -458,11 +404,164 @@ int mmc_attach_sd(struct mmc_host *host, u32 ocr)
458 mmc_set_bus_width(host, MMC_BUS_WIDTH_4); 404 mmc_set_bus_width(host, MMC_BUS_WIDTH_4);
459 } 405 }
460 406
461 host->card = card; 407 if (!oldcard)
408 host->card = card;
409
410 return MMC_ERR_NONE;
411
412free_card:
413 if (!oldcard)
414 mmc_remove_card(card);
415err:
416
417 return MMC_ERR_FAILED;
418}
419
420/*
421 * Host is being removed. Free up the current card.
422 */
423static void mmc_sd_remove(struct mmc_host *host)
424{
425 BUG_ON(!host);
426 BUG_ON(!host->card);
427
428 mmc_remove_card(host->card);
429 host->card = NULL;
430}
431
432/*
433 * Card detection callback from host.
434 */
435static void mmc_sd_detect(struct mmc_host *host)
436{
437 int err;
438
439 BUG_ON(!host);
440 BUG_ON(!host->card);
441
442 mmc_claim_host(host);
443
444 /*
445 * Just check if our card has been removed.
446 */
447 err = mmc_send_status(host->card, NULL);
462 448
463 mmc_release_host(host); 449 mmc_release_host(host);
464 450
465 err = mmc_register_card(card); 451 if (err != MMC_ERR_NONE) {
452 mmc_remove_card(host->card);
453 host->card = NULL;
454
455 mmc_claim_host(host);
456 mmc_detach_bus(host);
457 mmc_release_host(host);
458 }
459}
460
461#ifdef CONFIG_MMC_UNSAFE_RESUME
462
463/*
464 * Suspend callback from host.
465 */
466static void mmc_sd_suspend(struct mmc_host *host)
467{
468 BUG_ON(!host);
469 BUG_ON(!host->card);
470
471 mmc_claim_host(host);
472 mmc_deselect_cards(host);
473 host->card->state &= ~MMC_STATE_HIGHSPEED;
474 mmc_release_host(host);
475}
476
477/*
478 * Resume callback from host.
479 *
480 * This function tries to determine if the same card is still present
481 * and, if so, restore all state to it.
482 */
483static void mmc_sd_resume(struct mmc_host *host)
484{
485 int err;
486
487 BUG_ON(!host);
488 BUG_ON(!host->card);
489
490 mmc_claim_host(host);
491
492 err = mmc_sd_init_card(host, host->ocr, host->card);
493 if (err != MMC_ERR_NONE) {
494 mmc_remove_card(host->card);
495 host->card = NULL;
496
497 mmc_detach_bus(host);
498 }
499
500 mmc_release_host(host);
501}
502
503#else
504
505#define mmc_sd_suspend NULL
506#define mmc_sd_resume NULL
507
508#endif
509
510static const struct mmc_bus_ops mmc_sd_ops = {
511 .remove = mmc_sd_remove,
512 .detect = mmc_sd_detect,
513 .suspend = mmc_sd_suspend,
514 .resume = mmc_sd_resume,
515};
516
517/*
518 * Starting point for SD card init.
519 */
520int mmc_attach_sd(struct mmc_host *host, u32 ocr)
521{
522 int err;
523
524 BUG_ON(!host);
525 BUG_ON(!host->claimed);
526
527 mmc_attach_bus(host, &mmc_sd_ops);
528
529 /*
530 * Sanity check the voltages that the card claims to
531 * support.
532 */
533 if (ocr & 0x7F) {
534 printk(KERN_WARNING "%s: card claims to support voltages "
535 "below the defined range. These will be ignored.\n",
536 mmc_hostname(host));
537 ocr &= ~0x7F;
538 }
539
540 if (ocr & MMC_VDD_165_195) {
541 printk(KERN_WARNING "%s: SD card claims to support the "
542 "incompletely defined 'low voltage range'. This "
543 "will be ignored.\n", mmc_hostname(host));
544 ocr &= ~MMC_VDD_165_195;
545 }
546
547 host->ocr = mmc_select_voltage(host, ocr);
548
549 /*
550 * Can we support the voltage(s) of the card(s)?
551 */
552 if (!host->ocr)
553 goto err;
554
555 /*
556 * Detect and init the card.
557 */
558 err = mmc_sd_init_card(host, host->ocr, NULL);
559 if (err != MMC_ERR_NONE)
560 goto err;
561
562 mmc_release_host(host);
563
564 err = mmc_register_card(host->card);
466 if (err) 565 if (err)
467 goto reclaim_host; 566 goto reclaim_host;
468 567
@@ -470,8 +569,7 @@ int mmc_attach_sd(struct mmc_host *host, u32 ocr)
470 569
471reclaim_host: 570reclaim_host:
472 mmc_claim_host(host); 571 mmc_claim_host(host);
473free_card: 572 mmc_remove_card(host->card);
474 mmc_remove_card(card);
475 host->card = NULL; 573 host->card = NULL;
476err: 574err:
477 mmc_detach_bus(host); 575 mmc_detach_bus(host);