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

Commit 0b3bb77c authored by Damian Hobson-Garcia's avatar Damian Hobson-Garcia Committed by Laurent Pinchart
Browse files

fbdev: sh_mobile_meram: Backup/restore device registers on shutdown/resume



Save and reconfigure the MERAM registers when the MERAM is powered down
and restored

Signed-off-by: default avatarDamian Hobson-Garcia <dhobsong@igel.co.jp>
parent 0aa492be
Loading
Loading
Loading
Loading
+71 −0
Original line number Diff line number Diff line
@@ -37,12 +37,31 @@
#define MEQSEL1 0x40
#define MEQSEL2 0x44

static unsigned long common_regs[] = {
	MEVCR1,
	MEQSEL1,
	MEQSEL2,
};
#define CMN_REGS_SIZE ARRAY_SIZE(common_regs)

static unsigned long icb_regs[] = {
	MExxCTL,
	MExxBSIZE,
	MExxMNCF,
	MExxSARA,
	MExxSARB,
	MExxSBSIZE,
};
#define ICB_REGS_SIZE ARRAY_SIZE(icb_regs)

struct sh_mobile_meram_priv {
	void __iomem	*base;
	struct mutex	lock;
	unsigned long	used_icb;
	int		used_meram_cache_regions;
	unsigned long	used_meram_cache[SH_MOBILE_MERAM_ICB_NUM];
	unsigned long	cmn_saved_regs[CMN_REGS_SIZE];
	unsigned long	icb_saved_regs[ICB_REGS_SIZE * SH_MOBILE_MERAM_ICB_NUM];
};

/* settings */
@@ -469,6 +488,57 @@ static int sh_mobile_meram_update(struct sh_mobile_meram_info *pdata,
	return 0;
}

static int sh_mobile_meram_runtime_suspend(struct device *dev)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct sh_mobile_meram_priv *priv = platform_get_drvdata(pdev);
	int k, j;

	for (k = 0; k < CMN_REGS_SIZE; k++)
		priv->cmn_saved_regs[k] = meram_read_reg(priv->base,
			common_regs[k]);

	for (j = 0; j < 32; j++) {
		if (!test_bit(j, &priv->used_icb))
			continue;
		for (k = 0; k < ICB_REGS_SIZE; k++) {
			priv->icb_saved_regs[j * ICB_REGS_SIZE + k] =
				meram_read_icb(priv->base, j, icb_regs[k]);
			/* Reset ICB on resume */
			if (icb_regs[k] == MExxCTL)
				priv->icb_saved_regs[j * ICB_REGS_SIZE + k] =
					0x70;
		}
	}
	return 0;
}

static int sh_mobile_meram_runtime_resume(struct device *dev)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct sh_mobile_meram_priv *priv = platform_get_drvdata(pdev);
	int k, j;

	for (j = 0; j < 32; j++) {
		if (!test_bit(j, &priv->used_icb))
			continue;
		for (k = 0; k < ICB_REGS_SIZE; k++) {
			meram_write_icb(priv->base, j, icb_regs[k],
			priv->icb_saved_regs[j * ICB_REGS_SIZE + k]);
		}
	}

	for (k = 0; k < CMN_REGS_SIZE; k++)
		meram_write_reg(priv->base, common_regs[k],
			priv->cmn_saved_regs[k]);
	return 0;
}

static const struct dev_pm_ops sh_mobile_meram_dev_pm_ops = {
	.runtime_suspend = sh_mobile_meram_runtime_suspend,
	.runtime_resume = sh_mobile_meram_runtime_resume,
};

static struct sh_mobile_meram_ops sh_mobile_meram_ops = {
	.module			= THIS_MODULE,
	.meram_register		= sh_mobile_meram_register,
@@ -557,6 +627,7 @@ static struct platform_driver sh_mobile_meram_driver = {
	.driver	= {
		.name		= "sh_mobile_meram",
		.owner		= THIS_MODULE,
		.pm		= &sh_mobile_meram_dev_pm_ops,
	},
	.probe		= sh_mobile_meram_probe,
	.remove		= sh_mobile_meram_remove,