forked from Minki/linux
clk: mvebu: armada-37xx-periph: add suspend/resume support
Add suspend/resume hooks in Armada 37xx peripheral clocks driver to handle S2RAM operations. One can think that these hooks are useless by comparing the register values before and after a suspend/resume cycle: they will look the same anyway. This is because of some scripts executed by the Cortex-M3 core during ATF operations to init both the clocks and the DDR. These values could be modified by the BL33 stage or by Linux itself and should be preserved. Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com> Signed-off-by: Stephen Boyd <sboyd@kernel.org>
This commit is contained in:
parent
d9d95e78cf
commit
5beb1e60db
@ -57,6 +57,14 @@ struct clk_periph_driver_data {
|
||||
struct clk_hw_onecell_data *hw_data;
|
||||
spinlock_t lock;
|
||||
void __iomem *reg;
|
||||
|
||||
/* Storage registers for suspend/resume operations */
|
||||
u32 tbg_sel;
|
||||
u32 div_sel0;
|
||||
u32 div_sel1;
|
||||
u32 div_sel2;
|
||||
u32 clk_sel;
|
||||
u32 clk_dis;
|
||||
};
|
||||
|
||||
struct clk_double_div {
|
||||
@ -673,6 +681,40 @@ static int armada_3700_add_composite_clk(const struct clk_periph_data *data,
|
||||
return PTR_ERR_OR_ZERO(*hw);
|
||||
}
|
||||
|
||||
static int __maybe_unused armada_3700_periph_clock_suspend(struct device *dev)
|
||||
{
|
||||
struct clk_periph_driver_data *data = dev_get_drvdata(dev);
|
||||
|
||||
data->tbg_sel = readl(data->reg + TBG_SEL);
|
||||
data->div_sel0 = readl(data->reg + DIV_SEL0);
|
||||
data->div_sel1 = readl(data->reg + DIV_SEL1);
|
||||
data->div_sel2 = readl(data->reg + DIV_SEL2);
|
||||
data->clk_sel = readl(data->reg + CLK_SEL);
|
||||
data->clk_dis = readl(data->reg + CLK_DIS);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused armada_3700_periph_clock_resume(struct device *dev)
|
||||
{
|
||||
struct clk_periph_driver_data *data = dev_get_drvdata(dev);
|
||||
|
||||
/* Follow the same order than what the Cortex-M3 does (ATF code) */
|
||||
writel(data->clk_dis, data->reg + CLK_DIS);
|
||||
writel(data->div_sel0, data->reg + DIV_SEL0);
|
||||
writel(data->div_sel1, data->reg + DIV_SEL1);
|
||||
writel(data->div_sel2, data->reg + DIV_SEL2);
|
||||
writel(data->tbg_sel, data->reg + TBG_SEL);
|
||||
writel(data->clk_sel, data->reg + CLK_SEL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops armada_3700_periph_clock_pm_ops = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(armada_3700_periph_clock_suspend,
|
||||
armada_3700_periph_clock_resume)
|
||||
};
|
||||
|
||||
static int armada_3700_periph_clock_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct clk_periph_driver_data *driver_data;
|
||||
@ -748,6 +790,7 @@ static struct platform_driver armada_3700_periph_clock_driver = {
|
||||
.driver = {
|
||||
.name = "marvell-armada-3700-periph-clock",
|
||||
.of_match_table = armada_3700_periph_clock_of_match,
|
||||
.pm = &armada_3700_periph_clock_pm_ops,
|
||||
},
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user