Skip to content

Commit b4f30a1

Browse files
ahunter6storulf
authored andcommitted
mmc: core: Allow card drive strength to be different to host
Initialization of UHS-I modes for SD and SDIO cards employs a callback to allow the host driver to choose a drive strength value. Currently that assumes the card drive strength and host driver type must be the same value. Change to let the callback make that decision and return both the card drive strength and host driver type. Signed-off-by: Adrian Hunter <adrian.hunter@intel.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
1 parent 75e8a22 commit b4f30a1

File tree

3 files changed

+33
-46
lines changed

3 files changed

+33
-46
lines changed

drivers/mmc/core/sd.c

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -388,18 +388,9 @@ static int sd_select_driver_type(struct mmc_card *card, u8 *status)
388388
{
389389
int host_drv_type = SD_DRIVER_TYPE_B;
390390
int card_drv_type = SD_DRIVER_TYPE_B;
391-
int drive_strength;
391+
int drive_strength, drv_type;
392392
int err;
393393

394-
/*
395-
* If the host doesn't support any of the Driver Types A,C or D,
396-
* or there is no board specific handler then default Driver
397-
* Type B is used.
398-
*/
399-
if (!(card->host->caps & (MMC_CAP_DRIVER_TYPE_A | MMC_CAP_DRIVER_TYPE_C
400-
| MMC_CAP_DRIVER_TYPE_D)))
401-
return 0;
402-
403394
if (!card->host->ops->select_drive_strength)
404395
return 0;
405396

@@ -430,20 +421,22 @@ static int sd_select_driver_type(struct mmc_card *card, u8 *status)
430421
mmc_host_clk_hold(card->host);
431422
drive_strength = card->host->ops->select_drive_strength(
432423
card->sw_caps.uhs_max_dtr,
433-
host_drv_type, card_drv_type);
424+
host_drv_type, card_drv_type, &drv_type);
434425
mmc_host_clk_release(card->host);
435426

436-
err = mmc_sd_switch(card, 1, 2, drive_strength, status);
437-
if (err)
438-
return err;
439-
440-
if ((status[15] & 0xF) != drive_strength) {
441-
pr_warn("%s: Problem setting drive strength!\n",
442-
mmc_hostname(card->host));
443-
return 0;
427+
if (drive_strength) {
428+
err = mmc_sd_switch(card, 1, 2, drive_strength, status);
429+
if (err)
430+
return err;
431+
if ((status[15] & 0xF) != drive_strength) {
432+
pr_warn("%s: Problem setting drive strength!\n",
433+
mmc_hostname(card->host));
434+
return 0;
435+
}
444436
}
445437

446-
mmc_set_driver_type(card->host, drive_strength);
438+
if (drv_type)
439+
mmc_set_driver_type(card->host, drv_type);
447440

448441
return 0;
449442
}

drivers/mmc/core/sdio.c

Lines changed: 18 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -404,21 +404,10 @@ static void sdio_select_driver_type(struct mmc_card *card)
404404
{
405405
int host_drv_type = SD_DRIVER_TYPE_B;
406406
int card_drv_type = SD_DRIVER_TYPE_B;
407-
int drive_strength;
407+
int drive_strength, drv_type;
408408
unsigned char card_strength;
409409
int err;
410410

411-
/*
412-
* If the host doesn't support any of the Driver Types A,C or D,
413-
* or there is no board specific handler then default Driver
414-
* Type B is used.
415-
*/
416-
if (!(card->host->caps &
417-
(MMC_CAP_DRIVER_TYPE_A |
418-
MMC_CAP_DRIVER_TYPE_C |
419-
MMC_CAP_DRIVER_TYPE_D)))
420-
return;
421-
422411
if (!card->host->ops->select_drive_strength)
423412
return;
424413

@@ -448,23 +437,27 @@ static void sdio_select_driver_type(struct mmc_card *card)
448437
*/
449438
drive_strength = card->host->ops->select_drive_strength(
450439
card->sw_caps.uhs_max_dtr,
451-
host_drv_type, card_drv_type);
440+
host_drv_type, card_drv_type, &drv_type);
452441

453-
/* if error just use default for drive strength B */
454-
err = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_DRIVE_STRENGTH, 0,
455-
&card_strength);
456-
if (err)
457-
return;
442+
if (drive_strength) {
443+
/* if error just use default for drive strength B */
444+
err = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_DRIVE_STRENGTH, 0,
445+
&card_strength);
446+
if (err)
447+
return;
458448

459-
card_strength &= ~(SDIO_DRIVE_DTSx_MASK<<SDIO_DRIVE_DTSx_SHIFT);
460-
card_strength |= host_drive_to_sdio_drive(drive_strength);
449+
card_strength &= ~(SDIO_DRIVE_DTSx_MASK<<SDIO_DRIVE_DTSx_SHIFT);
450+
card_strength |= host_drive_to_sdio_drive(drive_strength);
461451

462-
err = mmc_io_rw_direct(card, 1, 0, SDIO_CCCR_DRIVE_STRENGTH,
463-
card_strength, NULL);
452+
/* if error default to drive strength B */
453+
err = mmc_io_rw_direct(card, 1, 0, SDIO_CCCR_DRIVE_STRENGTH,
454+
card_strength, NULL);
455+
if (err)
456+
return;
457+
}
464458

465-
/* if error default to drive strength B */
466-
if (!err)
467-
mmc_set_driver_type(card->host, drive_strength);
459+
if (drv_type)
460+
mmc_set_driver_type(card->host, drv_type);
468461
}
469462

470463

include/linux/mmc/host.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,8 @@ struct mmc_host_ops {
132132

133133
/* Prepare HS400 target operating frequency depending host driver */
134134
int (*prepare_hs400_tuning)(struct mmc_host *host, struct mmc_ios *ios);
135-
int (*select_drive_strength)(unsigned int max_dtr, int host_drv, int card_drv);
135+
int (*select_drive_strength)(unsigned int max_dtr, int host_drv,
136+
int card_drv, int *drv_type);
136137
void (*hw_reset)(struct mmc_host *host);
137138
void (*card_event)(struct mmc_host *host);
138139

0 commit comments

Comments
 (0)