Skip to content

Commit a99d744

Browse files
Sowjanya Komatinenithierryreding
authored andcommitted
clk: tegra: clk-dfll: Add suspend and resume support
This patch implements DFLL suspend and resume operation. During system suspend entry, CPU clock will switch CPU to safe clock source of PLLP and disables DFLL clock output. DFLL driver suspend confirms DFLL disable state and errors out on being active. DFLL is re-initialized during the DFLL driver resume as it goes through complete reset during suspend entry. Acked-by: Thierry Reding <[email protected]> Reviewed-by: Dmitry Osipenko <[email protected]> Signed-off-by: Sowjanya Komatineni <[email protected]> Signed-off-by: Thierry Reding <[email protected]>
1 parent f8fd975 commit a99d744

File tree

3 files changed

+59
-0
lines changed

3 files changed

+59
-0
lines changed

drivers/clk/tegra/clk-dfll.c

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1487,6 +1487,7 @@ static int dfll_init(struct tegra_dfll *td)
14871487
td->last_unrounded_rate = 0;
14881488

14891489
pm_runtime_enable(td->dev);
1490+
pm_runtime_irq_safe(td->dev);
14901491
pm_runtime_get_sync(td->dev);
14911492

14921493
dfll_set_mode(td, DFLL_DISABLED);
@@ -1513,6 +1514,61 @@ static int dfll_init(struct tegra_dfll *td)
15131514
return ret;
15141515
}
15151516

1517+
/**
1518+
* tegra_dfll_suspend - check DFLL is disabled
1519+
* @dev: DFLL device *
1520+
*
1521+
* DFLL clock should be disabled by the CPUFreq driver. So, make
1522+
* sure it is disabled and disable all clocks needed by the DFLL.
1523+
*/
1524+
int tegra_dfll_suspend(struct device *dev)
1525+
{
1526+
struct tegra_dfll *td = dev_get_drvdata(dev);
1527+
1528+
if (dfll_is_running(td)) {
1529+
dev_err(td->dev, "DFLL still enabled while suspending\n");
1530+
return -EBUSY;
1531+
}
1532+
1533+
reset_control_assert(td->dvco_rst);
1534+
1535+
return 0;
1536+
}
1537+
EXPORT_SYMBOL(tegra_dfll_suspend);
1538+
1539+
/**
1540+
* tegra_dfll_resume - reinitialize DFLL on resume
1541+
* @dev: DFLL instance
1542+
*
1543+
* DFLL is disabled and reset during suspend and resume.
1544+
* So, reinitialize the DFLL IP block back for use.
1545+
* DFLL clock is enabled later in closed loop mode by CPUFreq
1546+
* driver before switching its clock source to DFLL output.
1547+
*/
1548+
int tegra_dfll_resume(struct device *dev)
1549+
{
1550+
struct tegra_dfll *td = dev_get_drvdata(dev);
1551+
1552+
reset_control_deassert(td->dvco_rst);
1553+
1554+
pm_runtime_get_sync(td->dev);
1555+
1556+
dfll_set_mode(td, DFLL_DISABLED);
1557+
dfll_set_default_params(td);
1558+
1559+
if (td->soc->init_clock_trimmers)
1560+
td->soc->init_clock_trimmers();
1561+
1562+
dfll_set_open_loop_config(td);
1563+
1564+
dfll_init_out_if(td);
1565+
1566+
pm_runtime_put_sync(td->dev);
1567+
1568+
return 0;
1569+
}
1570+
EXPORT_SYMBOL(tegra_dfll_resume);
1571+
15161572
/*
15171573
* DT data fetch
15181574
*/

drivers/clk/tegra/clk-dfll.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,5 +42,7 @@ int tegra_dfll_register(struct platform_device *pdev,
4242
struct tegra_dfll_soc_data *tegra_dfll_unregister(struct platform_device *pdev);
4343
int tegra_dfll_runtime_suspend(struct device *dev);
4444
int tegra_dfll_runtime_resume(struct device *dev);
45+
int tegra_dfll_suspend(struct device *dev);
46+
int tegra_dfll_resume(struct device *dev);
4547

4648
#endif /* __DRIVERS_CLK_TEGRA_CLK_DFLL_H */

drivers/clk/tegra/clk-tegra124-dfll-fcpu.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -631,6 +631,7 @@ static int tegra124_dfll_fcpu_remove(struct platform_device *pdev)
631631
static const struct dev_pm_ops tegra124_dfll_pm_ops = {
632632
SET_RUNTIME_PM_OPS(tegra_dfll_runtime_suspend,
633633
tegra_dfll_runtime_resume, NULL)
634+
SET_SYSTEM_SLEEP_PM_OPS(tegra_dfll_suspend, tegra_dfll_resume)
634635
};
635636

636637
static struct platform_driver tegra124_dfll_fcpu_driver = {

0 commit comments

Comments
 (0)