aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorPhilip Rakity <prakity@marvell.com>2011-07-06 11:51:32 -0400
committerChris Ball <cjb@laptop.org>2011-07-20 17:21:16 -0400
commitca8e99b32e3863c98ac958617cc157a00bf445b8 (patch)
tree2e8b5d9fc5577ef2c795c9cd4ca40ae21e508699 /drivers
parentee8a43a51c7681f19fe23b6b936e1d8094a8b7d1 (diff)
mmc: core: Set non-default Drive Strength via platform hook
Non default Drive Strength cannot be set automatically. It is a function of the board design and only if there is a specific platform handler can it be set. The platform handler needs to take into account the board design. Pass to the platform code the necessary information. For example: The card and host controller may indicate they support HIGH and LOW drive strength. There is no way to know what should be chosen without specific board knowledge. Setting HIGH may lead to reflections and setting LOW may not suffice. There is no mechanism (like ethernet duplex or speed pulses) to determine what should be done automatically. If no platform handler is defined -- use the default value. Signed-off-by: Philip Rakity <prakity@marvell.com> Reviewed-by: Arindam Nath <arindam.nath@amd.com> Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mmc/core/sd.c68
1 files changed, 39 insertions, 29 deletions
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index ff2774128aa9..633975ff2bb3 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -409,52 +409,62 @@ out:
409 409
410static int sd_select_driver_type(struct mmc_card *card, u8 *status) 410static int sd_select_driver_type(struct mmc_card *card, u8 *status)
411{ 411{
412 int host_drv_type = 0, card_drv_type = 0; 412 int host_drv_type = SD_DRIVER_TYPE_B;
413 int card_drv_type = SD_DRIVER_TYPE_B;
414 int drive_strength;
413 int err; 415 int err;
414 416
415 /* 417 /*
416 * If the host doesn't support any of the Driver Types A,C or D, 418 * If the host doesn't support any of the Driver Types A,C or D,
417 * default Driver Type B is used. 419 * or there is no board specific handler then default Driver
420 * Type B is used.
418 */ 421 */
419 if (!(card->host->caps & (MMC_CAP_DRIVER_TYPE_A | MMC_CAP_DRIVER_TYPE_C 422 if (!(card->host->caps & (MMC_CAP_DRIVER_TYPE_A | MMC_CAP_DRIVER_TYPE_C
420 | MMC_CAP_DRIVER_TYPE_D))) 423 | MMC_CAP_DRIVER_TYPE_D)))
421 return 0; 424 return 0;
422 425
423 if (card->host->caps & MMC_CAP_DRIVER_TYPE_A) { 426 if (!card->host->ops->select_drive_strength)
424 host_drv_type = MMC_SET_DRIVER_TYPE_A; 427 return 0;
425 if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_A) 428
426 card_drv_type = MMC_SET_DRIVER_TYPE_A; 429 if (card->host->caps & MMC_CAP_DRIVER_TYPE_A)
427 else if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_B) 430 host_drv_type |= SD_DRIVER_TYPE_A;
428 card_drv_type = MMC_SET_DRIVER_TYPE_B; 431
429 else if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_C) 432 if (card->host->caps & MMC_CAP_DRIVER_TYPE_C)
430 card_drv_type = MMC_SET_DRIVER_TYPE_C; 433 host_drv_type |= SD_DRIVER_TYPE_C;
431 } else if (card->host->caps & MMC_CAP_DRIVER_TYPE_C) { 434
432 host_drv_type = MMC_SET_DRIVER_TYPE_C; 435 if (card->host->caps & MMC_CAP_DRIVER_TYPE_D)
433 if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_C) 436 host_drv_type |= SD_DRIVER_TYPE_D;
434 card_drv_type = MMC_SET_DRIVER_TYPE_C; 437
435 } else if (!(card->host->caps & MMC_CAP_DRIVER_TYPE_D)) { 438 if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_A)
436 /* 439 card_drv_type |= SD_DRIVER_TYPE_A;
437 * If we are here, that means only the default driver type 440
438 * B is supported by the host. 441 if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_C)
439 */ 442 card_drv_type |= SD_DRIVER_TYPE_C;
440 host_drv_type = MMC_SET_DRIVER_TYPE_B; 443
441 if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_B) 444 if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_D)
442 card_drv_type = MMC_SET_DRIVER_TYPE_B; 445 card_drv_type |= SD_DRIVER_TYPE_D;
443 else if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_C) 446
444 card_drv_type = MMC_SET_DRIVER_TYPE_C; 447 /*
445 } 448 * The drive strength that the hardware can support
449 * depends on the board design. Pass the appropriate
450 * information and let the hardware specific code
451 * return what is possible given the options
452 */
453 drive_strength = card->host->ops->select_drive_strength(
454 card->sw_caps.uhs_max_dtr,
455 host_drv_type, card_drv_type);
446 456
447 err = mmc_sd_switch(card, 1, 2, card_drv_type, status); 457 err = mmc_sd_switch(card, 1, 2, drive_strength, status);
448 if (err) 458 if (err)
449 return err; 459 return err;
450 460
451 if ((status[15] & 0xF) != card_drv_type) { 461 if ((status[15] & 0xF) != drive_strength) {
452 printk(KERN_WARNING "%s: Problem setting driver strength!\n", 462 printk(KERN_WARNING "%s: Problem setting drive strength!\n",
453 mmc_hostname(card->host)); 463 mmc_hostname(card->host));
454 return 0; 464 return 0;
455 } 465 }
456 466
457 mmc_set_driver_type(card->host, host_drv_type); 467 mmc_set_driver_type(card->host, drive_strength);
458 468
459 return 0; 469 return 0;
460} 470}