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

Commit 968cc169 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "mmc: core: hibernation support for mmc cards"

parents 322acbf4 ca899953
Loading
Loading
Loading
Loading
+7 −3
Original line number Diff line number Diff line
@@ -4706,9 +4706,11 @@ static int mmc_pm_notify(struct notifier_block *notify_block,
	int err = 0;

	switch (mode) {
	case PM_RESTORE_PREPARE:
	case PM_HIBERNATION_PREPARE:
		if (host->bus_ops && host->bus_ops->pre_hibernate)
			host->bus_ops->pre_hibernate(host);
	case PM_SUSPEND_PREPARE:
	case PM_RESTORE_PREPARE:
		spin_lock_irqsave(&host->lock, flags);
		host->rescan_disable = 1;
		spin_unlock_irqrestore(&host->lock, flags);
@@ -4740,9 +4742,11 @@ static int mmc_pm_notify(struct notifier_block *notify_block,
		host->pm_flags = 0;
		break;

	case PM_POST_SUSPEND:
	case PM_POST_HIBERNATION:
	case PM_POST_RESTORE:
	case PM_POST_HIBERNATION:
		if (host->bus_ops && host->bus_ops->post_hibernate)
			host->bus_ops->post_hibernate(host);
	case PM_POST_SUSPEND:

		spin_lock_irqsave(&host->lock, flags);
		host->rescan_disable = 0;
+69 −0
Original line number Diff line number Diff line
@@ -3058,6 +3058,73 @@ static int mmc_shutdown(struct mmc_host *host)
	return 0;
}

static int mmc_pre_hibernate(struct mmc_host *host)
{
	int ret = 0;

	mmc_get_card(host->card);
	host->cached_caps2 = host->caps2;

	/*
	 * Increase usage_count of card and host device till
	 * hibernation is over. This will ensure they will not runtime suspend.
	 */
	pm_runtime_get_noresume(mmc_dev(host));
	pm_runtime_get_noresume(&host->card->dev);

	if (!mmc_can_scale_clk(host))
		goto out;
	/*
	 * Suspend clock scaling and mask host capability so that
	 * we will run in max frequency during:
	 *	1. Hibernation preparation and image creation
	 *	2. After finding hibernation image during reboot
	 *	3. Once hibernation image is loaded and till hibernation
	 *	restore is complete.
	 */
	if (host->clk_scaling.enable)
		mmc_suspend_clk_scaling(host);
	host->caps2 &= ~MMC_CAP2_CLK_SCALE;
	host->clk_scaling.state = MMC_LOAD_HIGH;
	ret = mmc_clk_update_freq(host, host->card->clk_scaling_highest,
				host->clk_scaling.state);
	if (ret)
		pr_err("%s: %s: Setting clk frequency to max failed: %d\n",
				mmc_hostname(host), __func__, ret);
out:
	mmc_host_clk_hold(host);
	mmc_put_card(host->card);
	return ret;
}

static int mmc_post_hibernate(struct mmc_host *host)
{
	int ret = 0;

	mmc_get_card(host->card);
	if (!(host->cached_caps2 & MMC_CAP2_CLK_SCALE))
		goto enable_pm;
	/* Enable the clock scaling and set the host capability */
	host->caps2 |= MMC_CAP2_CLK_SCALE;
	if (!host->clk_scaling.enable)
		ret = mmc_resume_clk_scaling(host);
	if (ret)
		pr_err("%s: %s: Resuming clk scaling failed: %d\n",
				mmc_hostname(host), __func__, ret);
enable_pm:
	/*
	 * Reduce usage count of card and host device so that they may
	 * runtime suspend.
	 */
	pm_runtime_put_noidle(&host->card->dev);
	pm_runtime_put_noidle(mmc_dev(host));

	mmc_host_clk_release(host);

	mmc_put_card(host->card);
	return ret;
}

static const struct mmc_bus_ops mmc_ops = {
	.remove = mmc_remove,
	.detect = mmc_detect,
@@ -3069,6 +3136,8 @@ static const struct mmc_bus_ops mmc_ops = {
	.change_bus_speed = mmc_change_bus_speed,
	.reset = mmc_reset,
	.shutdown = mmc_shutdown,
	.pre_hibernate = mmc_pre_hibernate,
	.post_hibernate = mmc_post_hibernate
};

/*
+2 −0
Original line number Diff line number Diff line
@@ -138,6 +138,8 @@ struct mmc_bus_ops {
	int (*shutdown)(struct mmc_host *);
	int (*reset)(struct mmc_host *);
	int (*change_bus_speed)(struct mmc_host *, unsigned long *);
	int (*pre_hibernate)(struct mmc_host *);
	int (*post_hibernate)(struct mmc_host *);
};

struct mmc_card;
+1 −0
Original line number Diff line number Diff line
@@ -454,6 +454,7 @@ struct mmc_host {
#define MMC_CAP_HW_RESET	(1 << 31)	/* Hardware reset */

	u32			caps2;		/* More host capabilities */
	u32			cached_caps2;

#define MMC_CAP2_BOOTPART_NOACC	(1 << 0)	/* Boot partition no access */
#define MMC_CAP2_FULL_PWR_CYCLE	(1 << 2)	/* Can do full power cycle */