Skip to content

Commit

Permalink
mmc: sdhci: Introduce new flag SDHCI_USING_RETUNING_TIMER
Browse files Browse the repository at this point in the history
Add a new flag of SDHCI_USING_RETUNING_TIMER to represent if the host
is using a retuning timer for the card inserted.

This flag is set when the host does tuning the first time for the card
and the host's retuning mode is 1. This flag is used afterwards whenever
needs to decide if the host is currently using a retuning timer.

This flag is cleared when the card is removed in sdhci_reinit.

The set/clear of the flag and the start/stop of the retuning timer is
associated with the card's init/remove time, so there is no need to
touch it when the host is to be removed as at that time the card should
have already been removed.

Signed-off-by: Aaron Lu <[email protected]>
Reviewed-by: Girish K S <[email protected]>
Reviewed-by: Philip Rakity <[email protected]>
Signed-off-by: Chris Ball <[email protected]>
  • Loading branch information
Aaron Lu authored and cjb committed Jul 22, 2012
1 parent aa6439d commit 973905f
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 18 deletions.
30 changes: 12 additions & 18 deletions drivers/mmc/host/sdhci.c
Original file line number Diff line number Diff line change
Expand Up @@ -250,8 +250,9 @@ static void sdhci_reinit(struct sdhci_host *host)
* applicable to UHS-I cards. So reset these fields to their initial
* value when card is removed.
*/
if (host->version >= SDHCI_SPEC_300 && host->tuning_count &&
host->tuning_mode == SDHCI_TUNING_MODE_1) {
if (host->flags & SDHCI_USING_RETUNING_TIMER) {
host->flags &= ~SDHCI_USING_RETUNING_TIMER;

del_timer_sync(&host->tuning_timer);
host->flags &= ~SDHCI_NEEDS_RETUNING;
host->mmc->max_blk_count =
Expand Down Expand Up @@ -1873,6 +1874,7 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
*/
if (!(host->flags & SDHCI_NEEDS_RETUNING) && host->tuning_count &&
(host->tuning_mode == SDHCI_TUNING_MODE_1)) {
host->flags |= SDHCI_USING_RETUNING_TIMER;
mod_timer(&host->tuning_timer, jiffies +
host->tuning_count * HZ);
/* Tuning mode 1 limits the maximum data length to 4MB */
Expand All @@ -1890,10 +1892,10 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
* try tuning again at a later time, when the re-tuning timer expires.
* So for these controllers, we return 0. Since there might be other
* controllers who do not have this capability, we return error for
* them.
* them. SDHCI_USING_RETUNING_TIMER means the host is currently using
* a retuning timer to do the retuning for the card.
*/
if (err && host->tuning_count &&
host->tuning_mode == SDHCI_TUNING_MODE_1)
if (err && (host->flags & SDHCI_USING_RETUNING_TIMER))
err = 0;

sdhci_clear_set_irqs(host, SDHCI_INT_DATA_AVAIL, ier);
Expand Down Expand Up @@ -2400,24 +2402,21 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
int sdhci_suspend_host(struct sdhci_host *host)
{
int ret;
bool has_tuning_timer;

if (host->ops->platform_suspend)
host->ops->platform_suspend(host);

sdhci_disable_card_detection(host);

/* Disable tuning since we are suspending */
has_tuning_timer = host->version >= SDHCI_SPEC_300 &&
host->tuning_count && host->tuning_mode == SDHCI_TUNING_MODE_1;
if (has_tuning_timer) {
if (host->flags & SDHCI_USING_RETUNING_TIMER) {
del_timer_sync(&host->tuning_timer);
host->flags &= ~SDHCI_NEEDS_RETUNING;
}

ret = mmc_suspend_host(host->mmc);
if (ret) {
if (has_tuning_timer) {
if (host->flags & SDHCI_USING_RETUNING_TIMER) {
host->flags |= SDHCI_NEEDS_RETUNING;
mod_timer(&host->tuning_timer, jiffies +
host->tuning_count * HZ);
Expand Down Expand Up @@ -2468,8 +2467,7 @@ int sdhci_resume_host(struct sdhci_host *host)
host->ops->platform_resume(host);

/* Set the re-tuning expiration flag */
if ((host->version >= SDHCI_SPEC_300) && host->tuning_count &&
(host->tuning_mode == SDHCI_TUNING_MODE_1))
if (host->flags & SDHCI_USING_RETUNING_TIMER)
host->flags |= SDHCI_NEEDS_RETUNING;

return ret;
Expand Down Expand Up @@ -2508,8 +2506,7 @@ int sdhci_runtime_suspend_host(struct sdhci_host *host)
int ret = 0;

/* Disable tuning since we are suspending */
if (host->version >= SDHCI_SPEC_300 &&
host->tuning_mode == SDHCI_TUNING_MODE_1) {
if (host->flags & SDHCI_USING_RETUNING_TIMER) {
del_timer_sync(&host->tuning_timer);
host->flags &= ~SDHCI_NEEDS_RETUNING;
}
Expand Down Expand Up @@ -2550,8 +2547,7 @@ int sdhci_runtime_resume_host(struct sdhci_host *host)
sdhci_do_enable_preset_value(host, true);

/* Set the re-tuning expiration flag */
if ((host->version >= SDHCI_SPEC_300) && host->tuning_count &&
(host->tuning_mode == SDHCI_TUNING_MODE_1))
if (host->flags & SDHCI_USING_RETUNING_TIMER)
host->flags |= SDHCI_NEEDS_RETUNING;

spin_lock_irqsave(&host->lock, flags);
Expand Down Expand Up @@ -3140,8 +3136,6 @@ void sdhci_remove_host(struct sdhci_host *host, int dead)
free_irq(host->irq, host);

del_timer_sync(&host->timer);
if (host->version >= SDHCI_SPEC_300)
del_timer_sync(&host->tuning_timer);

tasklet_kill(&host->card_tasklet);
tasklet_kill(&host->finish_tasklet);
Expand Down
1 change: 1 addition & 0 deletions include/linux/mmc/sdhci.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ struct sdhci_host {
#define SDHCI_PV_ENABLED (1<<8) /* Preset value enabled */
#define SDHCI_SDIO_IRQ_ENABLED (1<<9) /* SDIO irq enabled */
#define SDHCI_HS200_NEEDS_TUNING (1<<10) /* HS200 needs tuning */
#define SDHCI_USING_RETUNING_TIMER (1<<11) /* Host is using a retuning timer for the card */

unsigned int version; /* SDHCI spec. version */

Expand Down

0 comments on commit 973905f

Please sign in to comment.