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: Damian Hobson-Garcia <dhobsong@igel.co.jp>
This commit is contained in:
parent
0aa492be88
commit
0b3bb77c3a
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue