Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8e19c8cb authored by Adrian Hunter's avatar Adrian Hunter Committed by Veerabhadrarao Badiganti
Browse files

mmc: host: Add facility to support re-tuning



Currently, there is core support for tuning during
initialization. There can also be a need to re-tune
periodically (e.g. sdhci) or to re-tune after the
host controller is powered off (e.g. after PM
runtime suspend / resume) or to re-tune in response
to CRC errors.

The main requirements for re-tuning are:
  - ability to enable / disable re-tuning
  - ability to flag that re-tuning is needed
  - ability to re-tune before any request
  - ability to hold off re-tuning if the card is busy
  - ability to hold off re-tuning if re-tuning is in
  progress
  - ability to run a re-tuning timer

To support those requirements 7 members are added to struct
mmc_host:

  unsigned int		can_retune:1;	/* re-tuning can be used */
  unsigned int		doing_retune:1;	/* re-tuning in progress */
  unsigned int		retune_now:1;   /* do re-tuning at next req */
  int			need_retune;	/* re-tuning is needed */
  int			hold_retune;	/* hold off re-tuning */
  unsigned int		retune_period;  /* re-tuning period in secs */
  struct timer_list	retune_timer;	/* for periodic re-tuning */

need_retune is an integer so it can be set without needing
synchronization. hold_retune is a integer to allow nesting.

Various simple functions are provided to set / clear those
variables.

Subsequent patches take those functions into use.

Signed-off-by: default avatarAdrian Hunter <adrian.hunter@intel.com>
Signed-off-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
Git-commit: dfa13ebbe3340e538b988f5608efd9ff2ca7fc35
Git-repo: git://git.linaro.org/people/ulf.hansson/mmc.git


Change-Id: I82fa292b96ee57f18dd089287940aaca5286a304
Signed-off-by: default avatarVeerabhadrarao Badiganti <vbadigan@codeaurora.org>
parent 4654d9ee
Loading
Loading
Loading
Loading
+68 −0
Original line number Diff line number Diff line
@@ -312,6 +312,73 @@ static inline void mmc_host_clk_sysfs_init(struct mmc_host *host)

#endif

void mmc_retune_enable(struct mmc_host *host)
{
	host->can_retune = 1;
	if (host->retune_period)
		mod_timer(&host->retune_timer,
			  jiffies + host->retune_period * HZ);
}

void mmc_retune_disable(struct mmc_host *host)
{
	host->can_retune = 0;
	del_timer_sync(&host->retune_timer);
	host->retune_now = 0;
	host->need_retune = 0;
}

void mmc_retune_timer_stop(struct mmc_host *host)
{
	del_timer_sync(&host->retune_timer);
}
EXPORT_SYMBOL(mmc_retune_timer_stop);

void mmc_retune_hold(struct mmc_host *host)
{
	if (!host->hold_retune)
		host->retune_now = 1;
	host->hold_retune += 1;
}

void mmc_retune_release(struct mmc_host *host)
{
	if (host->hold_retune)
		host->hold_retune -= 1;
	else
		WARN_ON(1);
}

int mmc_retune(struct mmc_host *host)
{
	int err;

	if (host->retune_now)
		host->retune_now = 0;
	else
		return 0;

	if (!host->need_retune || host->doing_retune || !host->card)
		return 0;

	host->need_retune = 0;

	host->doing_retune = 1;

	err = mmc_execute_tuning(host->card);

	host->doing_retune = 0;

	return err;
}

static void mmc_retune_timer(unsigned long data)
{
	struct mmc_host *host = (struct mmc_host *)data;

	mmc_retune_needed(host);
}

/**
 *	mmc_of_parse() - parse host's device-tree node
 *	@host: host whose node should be parsed.
@@ -527,6 +594,7 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
#ifdef CONFIG_PM
	host->pm_notify.notifier_call = mmc_pm_notify;
#endif
	setup_timer(&host->retune_timer, mmc_retune_timer, (unsigned long)host);

	/*
	 * By default, hosts do not support SGIO or large requests.
+6 −0
Original line number Diff line number Diff line
@@ -15,5 +15,11 @@
int mmc_register_host_class(void);
void mmc_unregister_host_class(void);

void mmc_retune_enable(struct mmc_host *host);
void mmc_retune_disable(struct mmc_host *host);
void mmc_retune_hold(struct mmc_host *host);
void mmc_retune_release(struct mmc_host *host);
int mmc_retune(struct mmc_host *host);

#endif
+23 −0
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@

#include <linux/leds.h>
#include <linux/mutex.h>
#include <linux/timer.h>
#include <linux/sched.h>
#include <linux/device.h>
#include <linux/devfreq.h>
@@ -519,10 +520,18 @@ struct mmc_host {
#ifdef CONFIG_MMC_DEBUG
	unsigned int		removed:1;	/* host is being removed */
#endif
	unsigned int		can_retune:1;	/* re-tuning can be used */
	unsigned int		doing_retune:1;	/* re-tuning in progress */
	unsigned int		retune_now:1;	/* do re-tuning at next req */

	int			rescan_disable;	/* disable card detection */
	int			rescan_entered;	/* used with nonremovable devices */

	int			need_retune;	/* re-tuning is needed */
	int			hold_retune;	/* hold off re-tuning */
	unsigned int		retune_period;	/* re-tuning period in secs */
	struct timer_list	retune_timer;	/* for periodic re-tuning */

	bool			trigger_card_event; /* card_event necessary */

	struct mmc_card		*card;		/* device attached to this host */
@@ -823,4 +832,18 @@ static inline bool mmc_card_hs400(struct mmc_card *card)
	return card->host->ios.timing == MMC_TIMING_MMC_HS400;
}

void mmc_retune_timer_stop(struct mmc_host *host);

static inline void mmc_retune_needed(struct mmc_host *host)
{
	if (host->can_retune)
		host->need_retune = 1;
}

static inline void mmc_retune_recheck(struct mmc_host *host)
{
	if (host->hold_retune <= 1)
		host->retune_now = 1;
}

#endif /* LINUX_MMC_HOST_H */