Re: [PATCH v8 11/21] clk: tegra: clk-dfll: Add suspend and resume support
From: Dmitry Osipenko
Date: Fri Aug 09 2019 - 14:00:24 EST
09.08.2019 19:39, Sowjanya Komatineni ÐÐÑÐÑ:
>
> On 8/9/19 5:23 AM, Dmitry Osipenko wrote:
>> 09.08.2019 2:46, Sowjanya Komatineni ÐÐÑÐÑ:
>>> 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.
>>>
>>> Signed-off-by: Sowjanya Komatineni <skomatineni@xxxxxxxxxx>
>>> ---
>>> Â drivers/clk/tegra/clk-dfll.cÂÂÂÂÂÂÂÂÂÂÂÂÂÂ | 56 ++++++++++++++++++++++++++++++
>>> Â drivers/clk/tegra/clk-dfll.hÂÂÂÂÂÂÂÂÂÂÂÂÂÂ |Â 2 ++
>>> Â drivers/clk/tegra/clk-tegra124-dfll-fcpu.c |Â 1 +
>>> Â 3 files changed, 59 insertions(+)
>>>
>>> diff --git a/drivers/clk/tegra/clk-dfll.c b/drivers/clk/tegra/clk-dfll.c
>>> index f8688c2ddf1a..eb298a5d7be9 100644
>>> --- a/drivers/clk/tegra/clk-dfll.c
>>> +++ b/drivers/clk/tegra/clk-dfll.c
>>> @@ -1487,6 +1487,7 @@ static int dfll_init(struct tegra_dfll *td)
>>> ÂÂÂÂÂ td->last_unrounded_rate = 0;
>>> Â ÂÂÂÂÂ pm_runtime_enable(td->dev);
>>> +ÂÂÂ pm_runtime_irq_safe(td->dev);
>>> ÂÂÂÂÂ pm_runtime_get_sync(td->dev);
>>> Â ÂÂÂÂÂ dfll_set_mode(td, DFLL_DISABLED);
>>> @@ -1513,6 +1514,61 @@ static int dfll_init(struct tegra_dfll *td)
>>> ÂÂÂÂÂ return ret;
>>> Â }
>>> Â +/**
>>> + * tegra_dfll_suspend - check DFLL is disabled
>>> + * @dev: DFLL device *
>>> + *
>>> + * DFLL clock should be disabled by the CPUFreq driver. So, make
>>> + * sure it is disabled and disable all clocks needed by the DFLL.
>>> + */
>>> +int tegra_dfll_suspend(struct device *dev)
>>> +{
>>> +ÂÂÂ struct tegra_dfll *td = dev_get_drvdata(dev);
>>> +
>>> +ÂÂÂ if (dfll_is_running(td)) {
>>> +ÂÂÂÂÂÂÂ dev_err(td->dev, "dfll is enabled while shouldn't be\n");
>>> +ÂÂÂÂÂÂÂ return -EBUSY;
>>> +ÂÂÂ }
>>> +
>>> +ÂÂÂ reset_control_assert(td->dvco_rst);
>>> +
>>> +ÂÂÂ return 0;
>>> +}
>>> +EXPORT_SYMBOL(tegra_dfll_suspend);
>>> +
>>> +/**
>>> + * tegra_dfll_resume - reinitialize DFLL on resume
>>> + * @dev: DFLL instance
>>> + *
>>> + * DFLL is disabled and reset during suspend and resume.
>>> + * So, reinitialize the DFLL IP block back for use.
>>> + * DFLL clock is enabled later in closed loop mode by CPUFreq
>>> + * driver before switching its clock source to DFLL output.
>>> + */
>>> +int tegra_dfll_resume(struct device *dev)
>>> +{
>>> +ÂÂÂ struct tegra_dfll *td = dev_get_drvdata(dev);
>>> +
>>> +ÂÂÂ reset_control_deassert(td->dvco_rst);
>> This doesn't look right because I assume that DFLL resetting is
>> synchronous and thus clk should be enabled in order for reset to
>> propagate inside hardware.
>>
>>> +ÂÂÂ pm_runtime_get_sync(td->dev);
>> Hence it will be better to remove the above reset_control_deassert() and
>> add here:
>>
>> ÂÂÂÂreset_control_reset(td->dvco_rst);
>
> By the time dfll resume happens, dfll controller clock will already be enabled.
>
> so doing reset de-assert before pm_runtime seems ok.
I don't see what enables the DFLL clock because it should be enabled by the CPUFreq driver
on resume from suspend and resume happens after resuming of the DFLL driver.