[v9,20/22] soc/tegra: pmc: Configure deep sleep control settings
diff mbox series

Message ID 1565984527-5272-21-git-send-email-skomatineni@nvidia.com
State Not Applicable, archived
Headers show
Series
  • SC7 entry and exit support for Tegra210
Related show

Commit Message

Sowjanya Komatineni Aug. 16, 2019, 7:42 p.m. UTC
Tegra210 and prior Tegra chips have deep sleep entry and wakeup related
timings which are platform specific that should be configured before
entering into deep sleep.

Below are the timing specific configurations for deep sleep entry and
wakeup.
- Core rail power-on stabilization timer
- OSC clock stabilization timer after SOC rail power is stabilized.
- Core power off time is the minimum wake delay to keep the system
  in deep sleep state irrespective of any quick wake event.

These values depends on the discharge time of regulators and turn OFF
time of the PMIC to allow the complete system to finish entering into
deep sleep state.

These values vary based on the platform design and are specified
through the device tree.

This patch has implementation to configure these timings which are must
to have for proper deep sleep and wakeup operations.

Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com>
---
 drivers/soc/tegra/pmc.c | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

Comments

Dmitry Osipenko Aug. 19, 2019, 4:48 p.m. UTC | #1
16.08.2019 22:42, Sowjanya Komatineni пишет:
> Tegra210 and prior Tegra chips have deep sleep entry and wakeup related
> timings which are platform specific that should be configured before
> entering into deep sleep.
> 
> Below are the timing specific configurations for deep sleep entry and
> wakeup.
> - Core rail power-on stabilization timer
> - OSC clock stabilization timer after SOC rail power is stabilized.
> - Core power off time is the minimum wake delay to keep the system
>   in deep sleep state irrespective of any quick wake event.
> 
> These values depends on the discharge time of regulators and turn OFF
> time of the PMIC to allow the complete system to finish entering into
> deep sleep state.
> 
> These values vary based on the platform design and are specified
> through the device tree.
> 
> This patch has implementation to configure these timings which are must
> to have for proper deep sleep and wakeup operations.
> 
> Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com>
> ---
>  drivers/soc/tegra/pmc.c | 14 +++++++++++++-
>  1 file changed, 13 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
> index 53ed70773872..710969043668 100644
> --- a/drivers/soc/tegra/pmc.c
> +++ b/drivers/soc/tegra/pmc.c
> @@ -88,6 +88,8 @@
>  
>  #define PMC_CPUPWRGOOD_TIMER		0xc8
>  #define PMC_CPUPWROFF_TIMER		0xcc
> +#define PMC_COREPWRGOOD_TIMER		0x3c
> +#define PMC_COREPWROFF_TIMER		0xe0
>  
>  #define PMC_PWR_DET_VALUE		0xe4
>  
> @@ -2277,7 +2279,7 @@ static const struct tegra_pmc_regs tegra20_pmc_regs = {
>  
>  static void tegra20_pmc_init(struct tegra_pmc *pmc)
>  {
> -	u32 value;
> +	u32 value, osc, pmu, off;
>  
>  	/* Always enable CPU power request */
>  	value = tegra_pmc_readl(pmc, PMC_CNTRL);
> @@ -2303,6 +2305,16 @@ static void tegra20_pmc_init(struct tegra_pmc *pmc)
>  	value = tegra_pmc_readl(pmc, PMC_CNTRL);
>  	value |= PMC_CNTRL_SYSCLK_OE;
>  	tegra_pmc_writel(pmc, value, PMC_CNTRL);
> +
> +	/* program core timings which are applicable only for suspend state */
> +	if (pmc->suspend_mode != TEGRA_SUSPEND_NONE) {
> +		osc = DIV_ROUND_UP(pmc->core_osc_time * 8192, 1000000);
> +		pmu = DIV_ROUND_UP(pmc->core_pmu_time * 32768, 1000000);
> +		off = DIV_ROUND_UP(pmc->core_off_time * 32768, 1000000);
> +		tegra_pmc_writel(pmc, ((osc << 8) & 0xff00) | (pmu & 0xff),
> +				 PMC_COREPWRGOOD_TIMER);
> +		tegra_pmc_writel(pmc, off, PMC_COREPWROFF_TIMER);
> +	}
>  }
>  
>  static void tegra20_pmc_setup_irq_polarity(struct tegra_pmc *pmc,
> 

In the previous version of this patch there were checks for zero values
of the timers with intention to skip programming of the timers if value
is zero. I'm a bit puzzled by the new version, given that SUSPEND_NONE
means that suspending isn't available at all and thus PMC timers won't
be utilized, hence it shouldn't matter what values are programmed for
the counters, isn't it?
Sowjanya Komatineni Aug. 19, 2019, 6:20 p.m. UTC | #2
On 8/19/19 9:48 AM, Dmitry Osipenko wrote:
> 16.08.2019 22:42, Sowjanya Komatineni пишет:
>> Tegra210 and prior Tegra chips have deep sleep entry and wakeup related
>> timings which are platform specific that should be configured before
>> entering into deep sleep.
>>
>> Below are the timing specific configurations for deep sleep entry and
>> wakeup.
>> - Core rail power-on stabilization timer
>> - OSC clock stabilization timer after SOC rail power is stabilized.
>> - Core power off time is the minimum wake delay to keep the system
>>    in deep sleep state irrespective of any quick wake event.
>>
>> These values depends on the discharge time of regulators and turn OFF
>> time of the PMIC to allow the complete system to finish entering into
>> deep sleep state.
>>
>> These values vary based on the platform design and are specified
>> through the device tree.
>>
>> This patch has implementation to configure these timings which are must
>> to have for proper deep sleep and wakeup operations.
>>
>> Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com>
>> ---
>>   drivers/soc/tegra/pmc.c | 14 +++++++++++++-
>>   1 file changed, 13 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
>> index 53ed70773872..710969043668 100644
>> --- a/drivers/soc/tegra/pmc.c
>> +++ b/drivers/soc/tegra/pmc.c
>> @@ -88,6 +88,8 @@
>>   
>>   #define PMC_CPUPWRGOOD_TIMER		0xc8
>>   #define PMC_CPUPWROFF_TIMER		0xcc
>> +#define PMC_COREPWRGOOD_TIMER		0x3c
>> +#define PMC_COREPWROFF_TIMER		0xe0
>>   
>>   #define PMC_PWR_DET_VALUE		0xe4
>>   
>> @@ -2277,7 +2279,7 @@ static const struct tegra_pmc_regs tegra20_pmc_regs = {
>>   
>>   static void tegra20_pmc_init(struct tegra_pmc *pmc)
>>   {
>> -	u32 value;
>> +	u32 value, osc, pmu, off;
>>   
>>   	/* Always enable CPU power request */
>>   	value = tegra_pmc_readl(pmc, PMC_CNTRL);
>> @@ -2303,6 +2305,16 @@ static void tegra20_pmc_init(struct tegra_pmc *pmc)
>>   	value = tegra_pmc_readl(pmc, PMC_CNTRL);
>>   	value |= PMC_CNTRL_SYSCLK_OE;
>>   	tegra_pmc_writel(pmc, value, PMC_CNTRL);
>> +
>> +	/* program core timings which are applicable only for suspend state */
>> +	if (pmc->suspend_mode != TEGRA_SUSPEND_NONE) {
>> +		osc = DIV_ROUND_UP(pmc->core_osc_time * 8192, 1000000);
>> +		pmu = DIV_ROUND_UP(pmc->core_pmu_time * 32768, 1000000);
>> +		off = DIV_ROUND_UP(pmc->core_off_time * 32768, 1000000);
>> +		tegra_pmc_writel(pmc, ((osc << 8) & 0xff00) | (pmu & 0xff),
>> +				 PMC_COREPWRGOOD_TIMER);
>> +		tegra_pmc_writel(pmc, off, PMC_COREPWROFF_TIMER);
>> +	}
>>   }
>>   
>>   static void tegra20_pmc_setup_irq_polarity(struct tegra_pmc *pmc,
>>
> In the previous version of this patch there were checks for zero values
> of the timers with intention to skip programming of the timers if value
> is zero. I'm a bit puzzled by the new version, given that SUSPEND_NONE
> means that suspending isn't available at all and thus PMC timers won't
> be utilized, hence it shouldn't matter what values are programmed for
> the counters, isn't it?

Yes, as I see in documentation we already specify all these timings are 
required properties when suspend mode is used, I updated in this version 
to program core timings only when suspend mode is enabled.
Sowjanya Komatineni Aug. 19, 2019, 7:07 p.m. UTC | #3
On 8/19/19 11:20 AM, Sowjanya Komatineni wrote:
>
> On 8/19/19 9:48 AM, Dmitry Osipenko wrote:
>> 16.08.2019 22:42, Sowjanya Komatineni пишет:
>>> Tegra210 and prior Tegra chips have deep sleep entry and wakeup related
>>> timings which are platform specific that should be configured before
>>> entering into deep sleep.
>>>
>>> Below are the timing specific configurations for deep sleep entry and
>>> wakeup.
>>> - Core rail power-on stabilization timer
>>> - OSC clock stabilization timer after SOC rail power is stabilized.
>>> - Core power off time is the minimum wake delay to keep the system
>>>    in deep sleep state irrespective of any quick wake event.
>>>
>>> These values depends on the discharge time of regulators and turn OFF
>>> time of the PMIC to allow the complete system to finish entering into
>>> deep sleep state.
>>>
>>> These values vary based on the platform design and are specified
>>> through the device tree.
>>>
>>> This patch has implementation to configure these timings which are must
>>> to have for proper deep sleep and wakeup operations.
>>>
>>> Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com>
>>> ---
>>>   drivers/soc/tegra/pmc.c | 14 +++++++++++++-
>>>   1 file changed, 13 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
>>> index 53ed70773872..710969043668 100644
>>> --- a/drivers/soc/tegra/pmc.c
>>> +++ b/drivers/soc/tegra/pmc.c
>>> @@ -88,6 +88,8 @@
>>>     #define PMC_CPUPWRGOOD_TIMER        0xc8
>>>   #define PMC_CPUPWROFF_TIMER        0xcc
>>> +#define PMC_COREPWRGOOD_TIMER        0x3c
>>> +#define PMC_COREPWROFF_TIMER        0xe0
>>>     #define PMC_PWR_DET_VALUE        0xe4
>>>   @@ -2277,7 +2279,7 @@ static const struct tegra_pmc_regs 
>>> tegra20_pmc_regs = {
>>>     static void tegra20_pmc_init(struct tegra_pmc *pmc)
>>>   {
>>> -    u32 value;
>>> +    u32 value, osc, pmu, off;
>>>         /* Always enable CPU power request */
>>>       value = tegra_pmc_readl(pmc, PMC_CNTRL);
>>> @@ -2303,6 +2305,16 @@ static void tegra20_pmc_init(struct tegra_pmc 
>>> *pmc)
>>>       value = tegra_pmc_readl(pmc, PMC_CNTRL);
>>>       value |= PMC_CNTRL_SYSCLK_OE;
>>>       tegra_pmc_writel(pmc, value, PMC_CNTRL);
>>> +
>>> +    /* program core timings which are applicable only for suspend 
>>> state */
>>> +    if (pmc->suspend_mode != TEGRA_SUSPEND_NONE) {
>>> +        osc = DIV_ROUND_UP(pmc->core_osc_time * 8192, 1000000);
>>> +        pmu = DIV_ROUND_UP(pmc->core_pmu_time * 32768, 1000000);
>>> +        off = DIV_ROUND_UP(pmc->core_off_time * 32768, 1000000);
>>> +        tegra_pmc_writel(pmc, ((osc << 8) & 0xff00) | (pmu & 0xff),
>>> +                 PMC_COREPWRGOOD_TIMER);
>>> +        tegra_pmc_writel(pmc, off, PMC_COREPWROFF_TIMER);
>>> +    }
>>>   }
>>>     static void tegra20_pmc_setup_irq_polarity(struct tegra_pmc *pmc,
>>>
>> In the previous version of this patch there were checks for zero values
>> of the timers with intention to skip programming of the timers if value
>> is zero. I'm a bit puzzled by the new version, given that SUSPEND_NONE
>> means that suspending isn't available at all and thus PMC timers won't
>> be utilized, hence it shouldn't matter what values are programmed for
>> the counters, isn't it?
>
> Yes, as I see in documentation we already specify all these timings 
> are required properties when suspend mode is used, I updated in this 
> version to program core timings only when suspend mode is enabled.
>
In other words, core timings are for SC7 entry only. So when SC7/suspend 
mode is not used, these timings doesn't matter.
Dmitry Osipenko Aug. 19, 2019, 7:33 p.m. UTC | #4
19.08.2019 22:07, Sowjanya Komatineni пишет:
> 
> On 8/19/19 11:20 AM, Sowjanya Komatineni wrote:
>>
>> On 8/19/19 9:48 AM, Dmitry Osipenko wrote:
>>> 16.08.2019 22:42, Sowjanya Komatineni пишет:
>>>> Tegra210 and prior Tegra chips have deep sleep entry and wakeup related
>>>> timings which are platform specific that should be configured before
>>>> entering into deep sleep.
>>>>
>>>> Below are the timing specific configurations for deep sleep entry and
>>>> wakeup.
>>>> - Core rail power-on stabilization timer
>>>> - OSC clock stabilization timer after SOC rail power is stabilized.
>>>> - Core power off time is the minimum wake delay to keep the system
>>>>    in deep sleep state irrespective of any quick wake event.
>>>>
>>>> These values depends on the discharge time of regulators and turn OFF
>>>> time of the PMIC to allow the complete system to finish entering into
>>>> deep sleep state.
>>>>
>>>> These values vary based on the platform design and are specified
>>>> through the device tree.
>>>>
>>>> This patch has implementation to configure these timings which are must
>>>> to have for proper deep sleep and wakeup operations.
>>>>
>>>> Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com>
>>>> ---
>>>>   drivers/soc/tegra/pmc.c | 14 +++++++++++++-
>>>>   1 file changed, 13 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
>>>> index 53ed70773872..710969043668 100644
>>>> --- a/drivers/soc/tegra/pmc.c
>>>> +++ b/drivers/soc/tegra/pmc.c
>>>> @@ -88,6 +88,8 @@
>>>>     #define PMC_CPUPWRGOOD_TIMER        0xc8
>>>>   #define PMC_CPUPWROFF_TIMER        0xcc
>>>> +#define PMC_COREPWRGOOD_TIMER        0x3c
>>>> +#define PMC_COREPWROFF_TIMER        0xe0
>>>>     #define PMC_PWR_DET_VALUE        0xe4
>>>>   @@ -2277,7 +2279,7 @@ static const struct tegra_pmc_regs
>>>> tegra20_pmc_regs = {
>>>>     static void tegra20_pmc_init(struct tegra_pmc *pmc)
>>>>   {
>>>> -    u32 value;
>>>> +    u32 value, osc, pmu, off;
>>>>         /* Always enable CPU power request */
>>>>       value = tegra_pmc_readl(pmc, PMC_CNTRL);
>>>> @@ -2303,6 +2305,16 @@ static void tegra20_pmc_init(struct tegra_pmc
>>>> *pmc)
>>>>       value = tegra_pmc_readl(pmc, PMC_CNTRL);
>>>>       value |= PMC_CNTRL_SYSCLK_OE;
>>>>       tegra_pmc_writel(pmc, value, PMC_CNTRL);
>>>> +
>>>> +    /* program core timings which are applicable only for suspend
>>>> state */
>>>> +    if (pmc->suspend_mode != TEGRA_SUSPEND_NONE) {
>>>> +        osc = DIV_ROUND_UP(pmc->core_osc_time * 8192, 1000000);
>>>> +        pmu = DIV_ROUND_UP(pmc->core_pmu_time * 32768, 1000000);
>>>> +        off = DIV_ROUND_UP(pmc->core_off_time * 32768, 1000000);
>>>> +        tegra_pmc_writel(pmc, ((osc << 8) & 0xff00) | (pmu & 0xff),
>>>> +                 PMC_COREPWRGOOD_TIMER);
>>>> +        tegra_pmc_writel(pmc, off, PMC_COREPWROFF_TIMER);
>>>> +    }
>>>>   }
>>>>     static void tegra20_pmc_setup_irq_polarity(struct tegra_pmc *pmc,
>>>>
>>> In the previous version of this patch there were checks for zero values
>>> of the timers with intention to skip programming of the timers if value
>>> is zero. I'm a bit puzzled by the new version, given that SUSPEND_NONE
>>> means that suspending isn't available at all and thus PMC timers won't
>>> be utilized, hence it shouldn't matter what values are programmed for
>>> the counters, isn't it?
>>
>> Yes, as I see in documentation we already specify all these timings
>> are required properties when suspend mode is used, I updated in this
>> version to program core timings only when suspend mode is enabled.
>>
> In other words, core timings are for SC7 entry only. So when SC7/suspend
> mode is not used, these timings doesn't matter.

In this case, it should be a bit more straightforward to always program
the timers unconditionally. But since device-tree binding requires all
the properties to be specified when suspend mode isn't NONE, then the
new variant also makes sense. Either way is good to me, thanks.

Reviewed-by: Dmitry Osipenko <digetx@gmail.com>

Patch
diff mbox series

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index 53ed70773872..710969043668 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -88,6 +88,8 @@ 
 
 #define PMC_CPUPWRGOOD_TIMER		0xc8
 #define PMC_CPUPWROFF_TIMER		0xcc
+#define PMC_COREPWRGOOD_TIMER		0x3c
+#define PMC_COREPWROFF_TIMER		0xe0
 
 #define PMC_PWR_DET_VALUE		0xe4
 
@@ -2277,7 +2279,7 @@  static const struct tegra_pmc_regs tegra20_pmc_regs = {
 
 static void tegra20_pmc_init(struct tegra_pmc *pmc)
 {
-	u32 value;
+	u32 value, osc, pmu, off;
 
 	/* Always enable CPU power request */
 	value = tegra_pmc_readl(pmc, PMC_CNTRL);
@@ -2303,6 +2305,16 @@  static void tegra20_pmc_init(struct tegra_pmc *pmc)
 	value = tegra_pmc_readl(pmc, PMC_CNTRL);
 	value |= PMC_CNTRL_SYSCLK_OE;
 	tegra_pmc_writel(pmc, value, PMC_CNTRL);
+
+	/* program core timings which are applicable only for suspend state */
+	if (pmc->suspend_mode != TEGRA_SUSPEND_NONE) {
+		osc = DIV_ROUND_UP(pmc->core_osc_time * 8192, 1000000);
+		pmu = DIV_ROUND_UP(pmc->core_pmu_time * 32768, 1000000);
+		off = DIV_ROUND_UP(pmc->core_off_time * 32768, 1000000);
+		tegra_pmc_writel(pmc, ((osc << 8) & 0xff00) | (pmu & 0xff),
+				 PMC_COREPWRGOOD_TIMER);
+		tegra_pmc_writel(pmc, off, PMC_COREPWROFF_TIMER);
+	}
 }
 
 static void tegra20_pmc_setup_irq_polarity(struct tegra_pmc *pmc,