Skip to content

Commit 1c5ee2a

Browse files
wangxiaoningnxpalexandrebelloni
authored andcommitted
i3c: master: svc: fix i3c suspend/resume issue
When system suspends, if i3c module is powered down, register value will lose. Need to save the key registers before system suspend. So save these registers value in runtime pm suspend, and restore them if these register's value is different with the saved values when runtime pm resume. Signed-off-by: Clark Wang <xiaoning.wang@nxp.com> Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com> Link: https://lore.kernel.org/r/20230517033030.3068085-1-xiaoning.wang@nxp.com Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
1 parent ac9a786 commit 1c5ee2a

1 file changed

Lines changed: 26 additions & 0 deletions

File tree

drivers/i3c/master/svc-i3c-master.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,11 @@ struct svc_i3c_xfer {
145145
struct svc_i3c_cmd cmds[];
146146
};
147147

148+
struct svc_i3c_regs_save {
149+
u32 mconfig;
150+
u32 mdynaddr;
151+
};
152+
148153
/**
149154
* struct svc_i3c_master - Silvaco I3C Master structure
150155
* @base: I3C master controller
@@ -173,6 +178,7 @@ struct svc_i3c_master {
173178
struct i3c_master_controller base;
174179
struct device *dev;
175180
void __iomem *regs;
181+
struct svc_i3c_regs_save saved_regs;
176182
u32 free_slots;
177183
u8 addrs[SVC_I3C_MAX_DEVS];
178184
struct i3c_dev_desc *descs[SVC_I3C_MAX_DEVS];
@@ -1579,10 +1585,28 @@ static void svc_i3c_master_remove(struct platform_device *pdev)
15791585
pm_runtime_disable(&pdev->dev);
15801586
}
15811587

1588+
static void svc_i3c_save_regs(struct svc_i3c_master *master)
1589+
{
1590+
master->saved_regs.mconfig = readl(master->regs + SVC_I3C_MCONFIG);
1591+
master->saved_regs.mdynaddr = readl(master->regs + SVC_I3C_MDYNADDR);
1592+
}
1593+
1594+
static void svc_i3c_restore_regs(struct svc_i3c_master *master)
1595+
{
1596+
if (readl(master->regs + SVC_I3C_MDYNADDR) !=
1597+
master->saved_regs.mdynaddr) {
1598+
writel(master->saved_regs.mconfig,
1599+
master->regs + SVC_I3C_MCONFIG);
1600+
writel(master->saved_regs.mdynaddr,
1601+
master->regs + SVC_I3C_MDYNADDR);
1602+
}
1603+
}
1604+
15821605
static int __maybe_unused svc_i3c_runtime_suspend(struct device *dev)
15831606
{
15841607
struct svc_i3c_master *master = dev_get_drvdata(dev);
15851608

1609+
svc_i3c_save_regs(master);
15861610
svc_i3c_master_unprepare_clks(master);
15871611
pinctrl_pm_select_sleep_state(dev);
15881612

@@ -1596,6 +1620,8 @@ static int __maybe_unused svc_i3c_runtime_resume(struct device *dev)
15961620
pinctrl_pm_select_default_state(dev);
15971621
svc_i3c_master_prepare_clks(master);
15981622

1623+
svc_i3c_restore_regs(master);
1624+
15991625
return 0;
16001626
}
16011627

0 commit comments

Comments
 (0)