mmc: sdhci: Add support for auto-calibration

This patch adds Programmable Delay Line auto-calibration
support if supported by respective hosts.If the host
supports auto-calibration this change would enable
sending CMD19/CMD21 before any read operation.

CRs-Fixed: 516314
Change-Id: I8a0f51206dc0e174519dd71f0c75267a9e08e7f7
Signed-off-by: Asutosh Das <asutoshd@codeaurora.org>
[subhashj@codeaurora.org: fixed minor merge conflict]
Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
This commit is contained in:
Asutosh Das 2013-07-30 19:07:29 +05:30 committed by Subhash Jadavani
parent d453e3e1ff
commit d938b50db5
2 changed files with 41 additions and 0 deletions

View file

@ -30,6 +30,7 @@
#include <linux/mmc/card.h>
#include <linux/mmc/sdio.h>
#include <linux/mmc/slot-gpio.h>
#include <linux/mmc/sdio.h>
#include "sdhci.h"
@ -1522,6 +1523,34 @@ static bool sdhci_check_state(struct sdhci_host *host)
return false;
}
static bool sdhci_check_auto_tuning(struct sdhci_host *host,
struct mmc_command *cmd)
{
if (((cmd->opcode != MMC_READ_SINGLE_BLOCK) &&
(cmd->opcode != MMC_READ_MULTIPLE_BLOCK) &&
(cmd->opcode != SD_IO_RW_EXTENDED)) || (host->clock < 100000000))
return false;
else if (host->mmc->ios.timing == MMC_TIMING_MMC_HS200 ||
host->mmc->ios.timing == MMC_TIMING_UHS_SDR104)
return true;
else
return false;
}
static int sdhci_get_tuning_cmd(struct sdhci_host *host)
{
if (!host->mmc || !host->mmc->card)
return 0;
/*
* If we are here, all conditions have already been true
* and the card can either be an eMMC or SD/SDIO
*/
if (mmc_card_mmc(host->mmc->card))
return MMC_SEND_TUNING_BLOCK_HS200;
else
return MMC_SEND_TUNING_BLOCK;
}
static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
{
struct sdhci_host *host;
@ -1583,6 +1612,15 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
host->mrq->cmd->error = -ENOMEDIUM;
tasklet_schedule(&host->finish_tasklet);
} else {
if (host->ops->config_auto_tuning_cmd) {
if (sdhci_check_auto_tuning(host, mrq->cmd))
host->ops->config_auto_tuning_cmd(host, true,
sdhci_get_tuning_cmd(host));
else
host->ops->config_auto_tuning_cmd(host, false,
sdhci_get_tuning_cmd(host));
}
if (mrq->sbc && !(host->flags & SDHCI_AUTO_CMD23))
sdhci_send_command(host, mrq->sbc);
else

View file

@ -632,6 +632,9 @@ struct sdhci_ops {
void (*card_event)(struct sdhci_host *host);
void (*platform_bus_voting)(struct sdhci_host *host, u32 enable);
void (*check_power_status)(struct sdhci_host *host, u32 req_type);
int (*config_auto_tuning_cmd)(struct sdhci_host *host,
bool enable,
u32 type);
void (*dump_vendor_regs)(struct sdhci_host *host);
void (*voltage_switch)(struct sdhci_host *host);
int (*select_drive_strength)(struct sdhci_host *host,