mbox series

[RESEND,v8,00/10] watchdog: rzg2l_wdt: Add support for RZ/G3S

Message ID 20240410134044.2138310-1-claudiu.beznea.uj@bp.renesas.com
Headers show
Series watchdog: rzg2l_wdt: Add support for RZ/G3S | expand

Message

Claudiu April 10, 2024, 1:40 p.m. UTC
From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>

Hi,

Series adds watchdog support for Renesas RZ/G3S (R9A08G045) SoC.

Patches do the following:
- patch 1/10 makes the driver depend on ARCH_RZG2L || ARCH_R9A09G011
- patch 2/10 makes the driver depend on PM
- patches 3-7/10 adds fixes and cleanups for the watchdog driver
- patch 8/10 adds suspend to RAM to the watchdog driver (to be used by
  RZ/G3S)
- patch 9/10 adapt for power domain support
- patch 10/10 documents the RZ/G3S support

Thank you,
Claudiu Beznea

Changes in v8:
- added patch 9
- collected tags

Changes in v7:
- updated the dependency on patch 2/9

Changes in v6:
- update patch 2/9 description
- fixed the dependency on COMPILE_TEST previously introduced in patch
  2/9

Changes in v5:
- updated description of patch 2/9
- simplify the code in patch 2/9 by using on a new line:
  depends on PM || COMPILE_TEST

Changes in v4:
- added patch "watchdog: rzg2l_wdt: Restrict the driver to ARCH_RZG2L and
  ARCH_R9A09G011"
- collected tags

Changes in v3:
- make driver depend on PM not select it
- drop patches already accepted (patches 1, 10, 11 from v2)
- re-arranged the tags in patch 8/8 as they were messed by b4 am/shazam

Changes in v2:
- added patch "watchdog: rzg2l_wdt: Select PM"
- propagate the return status of rzg2l_wdt_start() to it's callers
  in patch "watchdog: rzg2l_wdt: Use pm_runtime_resume_and_get()" 
- propagate the return status of rzg2l_wdt_stop() to it's callers
  in patch "watchdog: rzg2l_wdt: Check return status of pm_runtime_put()" 
- removed pm_ptr() from patch "watchdog: rzg2l_wdt: Add suspend/resume support"
- s/G2UL/G2L in patch "dt-bindings: watchdog: renesas,wdt: Document RZ/G3S support"
- collected tags

Claudiu Beznea (10):
  watchdog: rzg2l_wdt: Restrict the driver to ARCH_RZG2L and
    ARCH_R9A09G011
  watchdog: rzg2l_wdt: Make the driver depend on PM
  watchdog: rzg2l_wdt: Use pm_runtime_resume_and_get()
  watchdog: rzg2l_wdt: Check return status of pm_runtime_put()
  watchdog: rzg2l_wdt: Remove reset de-assert from probe
  watchdog: rzg2l_wdt: Remove comparison with zero
  watchdog: rzg2l_wdt: Rely on the reset driver for doing proper reset
  watchdog: rzg2l_wdt: Add suspend/resume support
  watchdog: rzg2l_wdt: Power on the PM domain in rzg2l_wdt_restart()
  dt-bindings: watchdog: renesas,wdt: Document RZ/G3S support

 .../bindings/watchdog/renesas,wdt.yaml        |   1 +
 drivers/watchdog/Kconfig                      |   3 +-
 drivers/watchdog/rzg2l_wdt.c                  | 123 +++++++++++-------
 3 files changed, 76 insertions(+), 51 deletions(-)

Comments

Biju Das April 10, 2024, 1:51 p.m. UTC | #1
Hi Claudiu,

> -----Original Message-----
> From: Claudiu <claudiu.beznea@tuxon.dev>
> Sent: Wednesday, April 10, 2024 2:41 PM
> Subject: [PATCH RESEND v8 03/10] watchdog: rzg2l_wdt: Use pm_runtime_resume_and_get()
> 
> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> 
> pm_runtime_get_sync() may return with error. In case it returns with error
> dev->power.usage_count needs to be decremented.
> dev->pm_runtime_resume_and_get()
> takes care of this. Thus use it.
> 
> Along with it the rzg2l_wdt_set_timeout() function was updated to propagate the result of
> rzg2l_wdt_start() to its caller.
> 
> Fixes: 2cbc5cd0b55f ("watchdog: Add Watchdog Timer driver for RZ/G2L")
> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> ---
> 
> Changes in v8:
> - none
> 
> Changes in v7:
> - none
> 
> Changes in v6:
> - none
> 
> Changes in v5:
> - none
> 
> Changes in v4:
> - none
> 
> Changes in v3:
> - none
> 
> Changes in v2:
> - propagate the return code of rzg2l_wdt_start() to it's callers
> 
> 
>  drivers/watchdog/rzg2l_wdt.c | 11 ++++++++---
>  1 file changed, 8 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/watchdog/rzg2l_wdt.c b/drivers/watchdog/rzg2l_wdt.c index
> 1741f98ca67c..d87d4f50180c 100644
> --- a/drivers/watchdog/rzg2l_wdt.c
> +++ b/drivers/watchdog/rzg2l_wdt.c
> @@ -123,8 +123,11 @@ static void rzg2l_wdt_init_timeout(struct watchdog_device *wdev)  static int
> rzg2l_wdt_start(struct watchdog_device *wdev)  {
>  	struct rzg2l_wdt_priv *priv = watchdog_get_drvdata(wdev);
> +	int ret;
> 
> -	pm_runtime_get_sync(wdev->parent);
> +	ret = pm_runtime_resume_and_get(wdev->parent);
> +	if (ret)
> +		return ret;
> 
>  	/* Initialize time out */
>  	rzg2l_wdt_init_timeout(wdev);
> @@ -150,6 +153,8 @@ static int rzg2l_wdt_stop(struct watchdog_device *wdev)
> 
>  static int rzg2l_wdt_set_timeout(struct watchdog_device *wdev, unsigned int timeout)  {
> +	int ret = 0;
> +
>  	wdev->timeout = timeout;
> 
>  	/*
> @@ -159,10 +164,10 @@ static int rzg2l_wdt_set_timeout(struct watchdog_device *wdev, unsigned int
> time
>  	 */
>  	if (watchdog_active(wdev)) {
>  		rzg2l_wdt_stop(wdev);
> -		rzg2l_wdt_start(wdev);
> +		ret = rzg2l_wdt_start(wdev);

This IP won't be able to update WDT settings once you have set it.

But we can update it, if we do a reset assert followed by deassert.
So the previous code looks correct to me.

Current case is if the WDT is active, then start it. Maybe I ma missing something here.

Cheers,
Biju

>  	}
> 
> -	return 0;
> +	return ret;
>  }
> 
>  static int rzg2l_wdt_restart(struct watchdog_device *wdev,
> --
> 2.39.2
Claudiu April 10, 2024, 2:01 p.m. UTC | #2
On 10.04.2024 16:51, Biju Das wrote:
> Hi Claudiu,
> 
>> -----Original Message-----
>> From: Claudiu <claudiu.beznea@tuxon.dev>
>> Sent: Wednesday, April 10, 2024 2:41 PM
>> Subject: [PATCH RESEND v8 03/10] watchdog: rzg2l_wdt: Use pm_runtime_resume_and_get()
>>
>> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>>
>> pm_runtime_get_sync() may return with error. In case it returns with error
>> dev->power.usage_count needs to be decremented.
>> dev->pm_runtime_resume_and_get()
>> takes care of this. Thus use it.
>>
>> Along with it the rzg2l_wdt_set_timeout() function was updated to propagate the result of
>> rzg2l_wdt_start() to its caller.
>>
>> Fixes: 2cbc5cd0b55f ("watchdog: Add Watchdog Timer driver for RZ/G2L")
>> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>> ---
>>
>> Changes in v8:
>> - none
>>
>> Changes in v7:
>> - none
>>
>> Changes in v6:
>> - none
>>
>> Changes in v5:
>> - none
>>
>> Changes in v4:
>> - none
>>
>> Changes in v3:
>> - none
>>
>> Changes in v2:
>> - propagate the return code of rzg2l_wdt_start() to it's callers
>>
>>
>>  drivers/watchdog/rzg2l_wdt.c | 11 ++++++++---
>>  1 file changed, 8 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/watchdog/rzg2l_wdt.c b/drivers/watchdog/rzg2l_wdt.c index
>> 1741f98ca67c..d87d4f50180c 100644
>> --- a/drivers/watchdog/rzg2l_wdt.c
>> +++ b/drivers/watchdog/rzg2l_wdt.c
>> @@ -123,8 +123,11 @@ static void rzg2l_wdt_init_timeout(struct watchdog_device *wdev)  static int
>> rzg2l_wdt_start(struct watchdog_device *wdev)  {
>>  	struct rzg2l_wdt_priv *priv = watchdog_get_drvdata(wdev);
>> +	int ret;
>>
>> -	pm_runtime_get_sync(wdev->parent);
>> +	ret = pm_runtime_resume_and_get(wdev->parent);
>> +	if (ret)
>> +		return ret;
>>
>>  	/* Initialize time out */
>>  	rzg2l_wdt_init_timeout(wdev);
>> @@ -150,6 +153,8 @@ static int rzg2l_wdt_stop(struct watchdog_device *wdev)
>>
>>  static int rzg2l_wdt_set_timeout(struct watchdog_device *wdev, unsigned int timeout)  {
>> +	int ret = 0;
>> +
>>  	wdev->timeout = timeout;
>>
>>  	/*
>> @@ -159,10 +164,10 @@ static int rzg2l_wdt_set_timeout(struct watchdog_device *wdev, unsigned int
>> time
>>  	 */
>>  	if (watchdog_active(wdev)) {
>>  		rzg2l_wdt_stop(wdev);
>> -		rzg2l_wdt_start(wdev);
>> +		ret = rzg2l_wdt_start(wdev);
> 
> This IP won't be able to update WDT settings once you have set it.
> 
> But we can update it, if we do a reset assert followed by deassert.
> So the previous code looks correct to me.
> 
> Current case is if the WDT is active, then start it. Maybe I ma missing something here.
> 

I'm not sure I got you correctly.

This patch keeps the previous functionality, thus, if the watchdog is
active rzg2l_wdt_stop() is called which does a reset assert. Then
rzg2l_wdt_start() is called which does the reset deassert.

Thank you,
Claudiu Beznea

> Cheers,
> Biju
> 
>>  	}
>>
>> -	return 0;
>> +	return ret;
>>  }
>>
>>  static int rzg2l_wdt_restart(struct watchdog_device *wdev,
>> --
>> 2.39.2
>
Biju Das April 10, 2024, 2:05 p.m. UTC | #3
Hi Claudiu,

> -----Original Message-----
> From: claudiu beznea <claudiu.beznea@tuxon.dev>
> Sent: Wednesday, April 10, 2024 3:02 PM
> Subject: Re: [PATCH RESEND v8 03/10] watchdog: rzg2l_wdt: Use pm_runtime_resume_and_get()
> 
> 
> 
> On 10.04.2024 16:51, Biju Das wrote:
> > Hi Claudiu,
> >
> >> -----Original Message-----
> >> From: Claudiu <claudiu.beznea@tuxon.dev>
> >> Sent: Wednesday, April 10, 2024 2:41 PM
> >> Subject: [PATCH RESEND v8 03/10] watchdog: rzg2l_wdt: Use
> >> pm_runtime_resume_and_get()
> >>
> >> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> >>
> >> pm_runtime_get_sync() may return with error. In case it returns with
> >> error
> >> dev->power.usage_count needs to be decremented.
> >> dev->pm_runtime_resume_and_get()
> >> takes care of this. Thus use it.
> >>
> >> Along with it the rzg2l_wdt_set_timeout() function was updated to
> >> propagate the result of
> >> rzg2l_wdt_start() to its caller.
> >>
> >> Fixes: 2cbc5cd0b55f ("watchdog: Add Watchdog Timer driver for
> >> RZ/G2L")
> >> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> >> ---
> >>
> >> Changes in v8:
> >> - none
> >>
> >> Changes in v7:
> >> - none
> >>
> >> Changes in v6:
> >> - none
> >>
> >> Changes in v5:
> >> - none
> >>
> >> Changes in v4:
> >> - none
> >>
> >> Changes in v3:
> >> - none
> >>
> >> Changes in v2:
> >> - propagate the return code of rzg2l_wdt_start() to it's callers
> >>
> >>
> >>  drivers/watchdog/rzg2l_wdt.c | 11 ++++++++---
> >>  1 file changed, 8 insertions(+), 3 deletions(-)
> >>
> >> diff --git a/drivers/watchdog/rzg2l_wdt.c
> >> b/drivers/watchdog/rzg2l_wdt.c index 1741f98ca67c..d87d4f50180c
> >> 100644
> >> --- a/drivers/watchdog/rzg2l_wdt.c
> >> +++ b/drivers/watchdog/rzg2l_wdt.c
> >> @@ -123,8 +123,11 @@ static void rzg2l_wdt_init_timeout(struct
> >> watchdog_device *wdev)  static int rzg2l_wdt_start(struct watchdog_device *wdev)  {
> >>  	struct rzg2l_wdt_priv *priv = watchdog_get_drvdata(wdev);
> >> +	int ret;
> >>
> >> -	pm_runtime_get_sync(wdev->parent);
> >> +	ret = pm_runtime_resume_and_get(wdev->parent);
> >> +	if (ret)
> >> +		return ret;
> >>
> >>  	/* Initialize time out */
> >>  	rzg2l_wdt_init_timeout(wdev);
> >> @@ -150,6 +153,8 @@ static int rzg2l_wdt_stop(struct watchdog_device
> >> *wdev)
> >>
> >>  static int rzg2l_wdt_set_timeout(struct watchdog_device *wdev,
> >> unsigned int timeout)  {
> >> +	int ret = 0;
> >> +
> >>  	wdev->timeout = timeout;
> >>
> >>  	/*
> >> @@ -159,10 +164,10 @@ static int rzg2l_wdt_set_timeout(struct
> >> watchdog_device *wdev, unsigned int time
> >>  	 */
> >>  	if (watchdog_active(wdev)) {
> >>  		rzg2l_wdt_stop(wdev);
> >> -		rzg2l_wdt_start(wdev);
> >> +		ret = rzg2l_wdt_start(wdev);
> >
> > This IP won't be able to update WDT settings once you have set it.
> >
> > But we can update it, if we do a reset assert followed by deassert.
> > So the previous code looks correct to me.
> >
> > Current case is if the WDT is active, then start it. Maybe I ma missing something here.
> >
> 
> I'm not sure I got you correctly.
> 
> This patch keeps the previous functionality, thus, if the watchdog is active rzg2l_wdt_stop() is
> called which does a reset assert. Then
> rzg2l_wdt_start() is called which does the reset deassert.

You are correct. I overlooked and thought you have removed *_stop() as well.
Sorry for the noise.

Cheers,
Biju


> >>  	}
> >>
> >> -	return 0;
> >> +	return ret;
> >>  }
> >>
> >>  static int rzg2l_wdt_restart(struct watchdog_device *wdev,
> >> --
> >> 2.39.2
> >
Biju Das April 10, 2024, 2:54 p.m. UTC | #4
Hi Claudiu,

> -----Original Message-----
> From: claudiu beznea <claudiu.beznea@tuxon.dev>
> Sent: Wednesday, April 10, 2024 3:49 PM
> Subject: Re: [PATCH RESEND v8 03/10] watchdog: rzg2l_wdt: Use pm_runtime_resume_and_get()
> 
> 
> 
> On 10.04.2024 17:13, Biju Das wrote:
> > Hi Claudiu,
> >
> >> -----Original Message-----
> >> From: Claudiu <claudiu.beznea@tuxon.dev>
> >> Sent: Wednesday, April 10, 2024 2:41 PM
> >> Subject: [PATCH RESEND v8 03/10] watchdog: rzg2l_wdt: Use
> >> pm_runtime_resume_and_get()
> >>
> >> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> >>
> >> pm_runtime_get_sync() may return with error. In case it returns with
> >> error
> >> dev->power.usage_count needs to be decremented.
> >> dev->pm_runtime_resume_and_get()
> >> takes care of this. Thus use it.
> >>
> >> Along with it the rzg2l_wdt_set_timeout() function was updated to
> >> propagate the result of
> >> rzg2l_wdt_start() to its caller.
> >>
> >> Fixes: 2cbc5cd0b55f ("watchdog: Add Watchdog Timer driver for
> >> RZ/G2L")
> >> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> >> ---
> >>
> >> Changes in v8:
> >> - none
> >>
> >> Changes in v7:
> >> - none
> >>
> >> Changes in v6:
> >> - none
> >>
> >> Changes in v5:
> >> - none
> >>
> >> Changes in v4:
> >> - none
> >>
> >> Changes in v3:
> >> - none
> >>
> >> Changes in v2:
> >> - propagate the return code of rzg2l_wdt_start() to it's callers
> >>
> >>
> >>  drivers/watchdog/rzg2l_wdt.c | 11 ++++++++---
> >>  1 file changed, 8 insertions(+), 3 deletions(-)
> >>
> >> diff --git a/drivers/watchdog/rzg2l_wdt.c
> >> b/drivers/watchdog/rzg2l_wdt.c index 1741f98ca67c..d87d4f50180c
> >> 100644
> >> --- a/drivers/watchdog/rzg2l_wdt.c
> >> +++ b/drivers/watchdog/rzg2l_wdt.c
> >> @@ -123,8 +123,11 @@ static void rzg2l_wdt_init_timeout(struct
> >> watchdog_device *wdev)  static int rzg2l_wdt_start(struct watchdog_device *wdev)  {
> >>  	struct rzg2l_wdt_priv *priv = watchdog_get_drvdata(wdev);
> >> +	int ret;
> >>
> >> -	pm_runtime_get_sync(wdev->parent);
> >> +	ret = pm_runtime_resume_and_get(wdev->parent);
> >
> > Do we need this change at all?
> 
> I haven't encountered issues w/o this patch, though I've did all my testing (including suspend to
> RAM) with this patch on my tree.
> 
> > If we have balanced usage then
> > this won't be a issue.
> 
> I think we should just use the proper APIs w/o making assumptions.

Currently many subsystems in linux kernel use pm_runtime_get_sync() 
without any error checks and it is fine to use as long as the usage is balanced.

Moreover, currently you are not able to reproduce an error condition
hence checking do we need this change?

Cheers,
Biju

> 
> > Did any unbalanced usage count popup
> > during the testing?
> >
> > Cheers,
> > Biju
> >
> >> +	if (ret)
> >> +		return ret;
> >>
> >>  	/* Initialize time out */
> >>  	rzg2l_wdt_init_timeout(wdev);
> >> @@ -150,6 +153,8 @@ static int rzg2l_wdt_stop(struct watchdog_device
> >> *wdev)
> >>
> >>  static int rzg2l_wdt_set_timeout(struct watchdog_device *wdev,
> >> unsigned int timeout)  {
> >> +	int ret = 0;
> >> +
> >>  	wdev->timeout = timeout;
> >>
> >>  	/*
> >> @@ -159,10 +164,10 @@ static int rzg2l_wdt_set_timeout(struct
> >> watchdog_device *wdev, unsigned int time
> >>  	 */
> >>  	if (watchdog_active(wdev)) {
> >>  		rzg2l_wdt_stop(wdev);
> >> -		rzg2l_wdt_start(wdev);
> >> +		ret = rzg2l_wdt_start(wdev);
> >>  	}
> >>
> >> -	return 0;
> >> +	return ret;
> >>  }
> >>
> >>  static int rzg2l_wdt_restart(struct watchdog_device *wdev,
> >> --
> >> 2.39.2
> >
Guenter Roeck April 10, 2024, 4:38 p.m. UTC | #5
On Wed, Apr 10, 2024 at 04:40:35PM +0300, Claudiu wrote:
> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> 
> The rzg2l_wdt driver is used only by ARCH_RZG2L and ARCH_R9A09G011
> micro-architectures of Renesas. Thus, limit it's usage only to these.
> 
> Suggested-by: Biju Das <biju.das.jz@bp.renesas.com>
> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>

Reviewed-by: Guenter Roeck <linux@roeck-us.net>

> ---
> 
> Changes in v8:
> - none
> 
> Changes in v7:
> - none
> 
> Changes in v6:
> - none
> 
> Changes in v5:
> - none
> 
> Changes in v4:
> - none; this patch is introduced in v4
> 
>  drivers/watchdog/Kconfig | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
> index 6bee137cfbe0..e2439967417a 100644
> --- a/drivers/watchdog/Kconfig
> +++ b/drivers/watchdog/Kconfig
> @@ -920,7 +920,7 @@ config RENESAS_RZN1WDT
>  
>  config RENESAS_RZG2LWDT
>  	tristate "Renesas RZ/G2L WDT Watchdog"
> -	depends on ARCH_RENESAS || COMPILE_TEST
> +	depends on ARCH_RZG2L || ARCH_R9A09G011 || COMPILE_TEST
>  	select WATCHDOG_CORE
>  	help
>  	  This driver adds watchdog support for the integrated watchdogs in the
> -- 
> 2.39.2
>
Guenter Roeck April 10, 2024, 4:39 p.m. UTC | #6
On Wed, Apr 10, 2024 at 04:40:37PM +0300, Claudiu wrote:
> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> 
> pm_runtime_get_sync() may return with error. In case it returns with error
> dev->power.usage_count needs to be decremented. pm_runtime_resume_and_get()
> takes care of this. Thus use it.
> 
> Along with it the rzg2l_wdt_set_timeout() function was updated to
> propagate the result of rzg2l_wdt_start() to its caller.
> 
> Fixes: 2cbc5cd0b55f ("watchdog: Add Watchdog Timer driver for RZ/G2L")
> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>

Reviewed-by: Guenter Roeck <linux@roeck-us.net>

> ---
> 
> Changes in v8:
> - none
> 
> Changes in v7:
> - none
> 
> Changes in v6:
> - none
> 
> Changes in v5:
> - none
> 
> Changes in v4:
> - none
> 
> Changes in v3:
> - none
> 
> Changes in v2:
> - propagate the return code of rzg2l_wdt_start() to it's callers
> 
> 
>  drivers/watchdog/rzg2l_wdt.c | 11 ++++++++---
>  1 file changed, 8 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/watchdog/rzg2l_wdt.c b/drivers/watchdog/rzg2l_wdt.c
> index 1741f98ca67c..d87d4f50180c 100644
> --- a/drivers/watchdog/rzg2l_wdt.c
> +++ b/drivers/watchdog/rzg2l_wdt.c
> @@ -123,8 +123,11 @@ static void rzg2l_wdt_init_timeout(struct watchdog_device *wdev)
>  static int rzg2l_wdt_start(struct watchdog_device *wdev)
>  {
>  	struct rzg2l_wdt_priv *priv = watchdog_get_drvdata(wdev);
> +	int ret;
>  
> -	pm_runtime_get_sync(wdev->parent);
> +	ret = pm_runtime_resume_and_get(wdev->parent);
> +	if (ret)
> +		return ret;
>  
>  	/* Initialize time out */
>  	rzg2l_wdt_init_timeout(wdev);
> @@ -150,6 +153,8 @@ static int rzg2l_wdt_stop(struct watchdog_device *wdev)
>  
>  static int rzg2l_wdt_set_timeout(struct watchdog_device *wdev, unsigned int timeout)
>  {
> +	int ret = 0;
> +
>  	wdev->timeout = timeout;
>  
>  	/*
> @@ -159,10 +164,10 @@ static int rzg2l_wdt_set_timeout(struct watchdog_device *wdev, unsigned int time
>  	 */
>  	if (watchdog_active(wdev)) {
>  		rzg2l_wdt_stop(wdev);
> -		rzg2l_wdt_start(wdev);
> +		ret = rzg2l_wdt_start(wdev);
>  	}
>  
> -	return 0;
> +	return ret;
>  }
>  
>  static int rzg2l_wdt_restart(struct watchdog_device *wdev,
> -- 
> 2.39.2
>
Guenter Roeck April 10, 2024, 4:41 p.m. UTC | #7
On Wed, Apr 10, 2024 at 04:40:39PM +0300, Claudiu wrote:
> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> 
> There is no need to de-assert the reset signal on probe as the watchdog
> is not used prior executing start. Also, the clocks are not enabled in
> probe (pm_runtime_enable() doesn't do that), thus this is another indicator
> that the watchdog wasn't used previously like this. Instead, keep the
> watchdog hardware in its previous state at probe (by default it is in
> reset state), enable it when it is started and move it to reset state
> when it is stopped. This saves some extra power when the watchdog is
> unused.
> 
> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>

Reviewed-by: Guenter Roeck <linux@roeck-us.net>

> ---
> 
> Changes in v8:
> - none
> 
> Changes in v7:
> - none
> 
> Changes in v6:
> - none
> 
> Changes in v5:
> - update patch title
> 
> Changes in v4:
> - none
> 
> Changes in v3:
> - none
> 
> Changes in v2:
> - none
> 
>  drivers/watchdog/rzg2l_wdt.c | 26 +++++++++++++++-----------
>  1 file changed, 15 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/watchdog/rzg2l_wdt.c b/drivers/watchdog/rzg2l_wdt.c
> index 7bce093316c4..93a49fd0c7aa 100644
> --- a/drivers/watchdog/rzg2l_wdt.c
> +++ b/drivers/watchdog/rzg2l_wdt.c
> @@ -129,6 +129,10 @@ static int rzg2l_wdt_start(struct watchdog_device *wdev)
>  	if (ret)
>  		return ret;
>  
> +	ret = reset_control_deassert(priv->rstc);
> +	if (ret)
> +		return ret;
> +
>  	/* Initialize time out */
>  	rzg2l_wdt_init_timeout(wdev);
>  
> @@ -146,7 +150,9 @@ static int rzg2l_wdt_stop(struct watchdog_device *wdev)
>  	struct rzg2l_wdt_priv *priv = watchdog_get_drvdata(wdev);
>  	int ret;
>  
> -	rzg2l_wdt_reset(priv);
> +	ret = reset_control_assert(priv->rstc);
> +	if (ret)
> +		return ret;
>  
>  	ret = pm_runtime_put(wdev->parent);
>  	if (ret < 0)
> @@ -186,6 +192,12 @@ static int rzg2l_wdt_restart(struct watchdog_device *wdev,
>  	clk_prepare_enable(priv->osc_clk);
>  
>  	if (priv->devtype == WDT_RZG2L) {
> +		int ret;
> +
> +		ret = reset_control_deassert(priv->rstc);
> +		if (ret)
> +			return ret;
> +
>  		/* Generate Reset (WDTRSTB) Signal on parity error */
>  		rzg2l_wdt_write(priv, 0, PECR);
>  
> @@ -236,13 +248,11 @@ static const struct watchdog_ops rzg2l_wdt_ops = {
>  	.restart = rzg2l_wdt_restart,
>  };
>  
> -static void rzg2l_wdt_reset_assert_pm_disable(void *data)
> +static void rzg2l_wdt_pm_disable(void *data)
>  {
>  	struct watchdog_device *wdev = data;
> -	struct rzg2l_wdt_priv *priv = watchdog_get_drvdata(wdev);
>  
>  	pm_runtime_disable(wdev->parent);
> -	reset_control_assert(priv->rstc);
>  }
>  
>  static int rzg2l_wdt_probe(struct platform_device *pdev)
> @@ -285,10 +295,6 @@ static int rzg2l_wdt_probe(struct platform_device *pdev)
>  		return dev_err_probe(&pdev->dev, PTR_ERR(priv->rstc),
>  				     "failed to get cpg reset");
>  
> -	ret = reset_control_deassert(priv->rstc);
> -	if (ret)
> -		return dev_err_probe(dev, ret, "failed to deassert");
> -
>  	priv->devtype = (uintptr_t)of_device_get_match_data(dev);
>  
>  	if (priv->devtype == WDT_RZV2M) {
> @@ -309,9 +315,7 @@ static int rzg2l_wdt_probe(struct platform_device *pdev)
>  	priv->wdev.timeout = WDT_DEFAULT_TIMEOUT;
>  
>  	watchdog_set_drvdata(&priv->wdev, priv);
> -	ret = devm_add_action_or_reset(&pdev->dev,
> -				       rzg2l_wdt_reset_assert_pm_disable,
> -				       &priv->wdev);
> +	ret = devm_add_action_or_reset(&pdev->dev, rzg2l_wdt_pm_disable, &priv->wdev);
>  	if (ret < 0)
>  		return ret;
>  
> -- 
> 2.39.2
>
Guenter Roeck April 10, 2024, 4:42 p.m. UTC | #8
On Wed, Apr 10, 2024 at 04:40:41PM +0300, Claudiu wrote:
> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> 
> The reset driver has been adapted in commit da235d2fac21
> ("clk: renesas: rzg2l: Check reset monitor registers") to check the reset
> monitor bits before declaring reset asserts/de-asserts as
> successful/failure operations. With that, there is no need to keep the
> reset workaround for RZ/V2M in place in the watchdog driver.
> 
> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de>

Reviewed-by: Guenter Roeck <linux@roeck-us.net>

> ---
> 
> Changes in v8:
> - none
> 
> Changes in v7:
> - none
> 
> Changes in v6:
> - none
> 
> Changes in v5:
> - none
> 
> Changes in v4:
> - collected tag
> 
> Changes in v3:
> - none
> 
> Changes in v2:
> - none
> 
>  drivers/watchdog/rzg2l_wdt.c | 39 ++++--------------------------------
>  1 file changed, 4 insertions(+), 35 deletions(-)
> 
> diff --git a/drivers/watchdog/rzg2l_wdt.c b/drivers/watchdog/rzg2l_wdt.c
> index 29eb47bcf984..42f1d5d6f07e 100644
> --- a/drivers/watchdog/rzg2l_wdt.c
> +++ b/drivers/watchdog/rzg2l_wdt.c
> @@ -8,7 +8,6 @@
>  #include <linux/clk.h>
>  #include <linux/delay.h>
>  #include <linux/io.h>
> -#include <linux/iopoll.h>
>  #include <linux/kernel.h>
>  #include <linux/module.h>
>  #include <linux/of.h>
> @@ -54,35 +53,11 @@ struct rzg2l_wdt_priv {
>  	struct reset_control *rstc;
>  	unsigned long osc_clk_rate;
>  	unsigned long delay;
> -	unsigned long minimum_assertion_period;
>  	struct clk *pclk;
>  	struct clk *osc_clk;
>  	enum rz_wdt_type devtype;
>  };
>  
> -static int rzg2l_wdt_reset(struct rzg2l_wdt_priv *priv)
> -{
> -	int err, status;
> -
> -	if (priv->devtype == WDT_RZV2M) {
> -		/* WDT needs TYPE-B reset control */
> -		err = reset_control_assert(priv->rstc);
> -		if (err)
> -			return err;
> -		ndelay(priv->minimum_assertion_period);
> -		err = reset_control_deassert(priv->rstc);
> -		if (err)
> -			return err;
> -		err = read_poll_timeout(reset_control_status, status,
> -					status != 1, 0, 1000, false,
> -					priv->rstc);
> -	} else {
> -		err = reset_control_reset(priv->rstc);
> -	}
> -
> -	return err;
> -}
> -
>  static void rzg2l_wdt_wait_delay(struct rzg2l_wdt_priv *priv)
>  {
>  	/* delay timer when change the setting register */
> @@ -187,13 +162,12 @@ static int rzg2l_wdt_restart(struct watchdog_device *wdev,
>  			     unsigned long action, void *data)
>  {
>  	struct rzg2l_wdt_priv *priv = watchdog_get_drvdata(wdev);
> +	int ret;
>  
>  	clk_prepare_enable(priv->pclk);
>  	clk_prepare_enable(priv->osc_clk);
>  
>  	if (priv->devtype == WDT_RZG2L) {
> -		int ret;
> -
>  		ret = reset_control_deassert(priv->rstc);
>  		if (ret)
>  			return ret;
> @@ -205,7 +179,9 @@ static int rzg2l_wdt_restart(struct watchdog_device *wdev,
>  		rzg2l_wdt_write(priv, PEEN_FORCE, PEEN);
>  	} else {
>  		/* RZ/V2M doesn't have parity error registers */
> -		rzg2l_wdt_reset(priv);
> +		ret = reset_control_reset(priv->rstc);
> +		if (ret)
> +			return ret;
>  
>  		wdev->timeout = 0;
>  
> @@ -297,13 +273,6 @@ static int rzg2l_wdt_probe(struct platform_device *pdev)
>  
>  	priv->devtype = (uintptr_t)of_device_get_match_data(dev);
>  
> -	if (priv->devtype == WDT_RZV2M) {
> -		priv->minimum_assertion_period = RZV2M_A_NSEC +
> -			3 * F2CYCLE_NSEC(pclk_rate) + 5 *
> -			max(F2CYCLE_NSEC(priv->osc_clk_rate),
> -			    F2CYCLE_NSEC(pclk_rate));
> -	}
> -
>  	pm_runtime_enable(&pdev->dev);
>  
>  	priv->wdev.info = &rzg2l_wdt_ident;
> -- 
> 2.39.2
>
Guenter Roeck April 10, 2024, 4:43 p.m. UTC | #9
On Wed, Apr 10, 2024 at 04:40:43PM +0300, Claudiu wrote:
> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> 
> The rzg2l_wdt_restart() is called from atomic context. Calling
> pm_runtime_{get_sync, resume_and_get}() or any other runtime PM resume
> APIs is not an option as it may lead to issues as described in commit
> e4cf89596c1f ("watchdog: rzg2l_wdt: Fix 'BUG: Invalid wait context'")
> that removed the pm_runtime_get_sync() and used directly the
> clk_prepare_enable() APIs.
> 
> Starting with RZ/G3S the watchdog could be part of its own software
> controlled power domain (see the initial implementation in Link section).
> In case the watchdog is not used the power domain is off and accessing
> watchdog registers leads to aborts.
> 
> To solve this the patch powers on the power domain using
> dev_pm_genpd_resume() API before enabling its clock. This is not
> sleeping or taking any other locks as the power domain will not be
> registered with GENPD_FLAG_IRQ_SAFE flags.
> 
> Link: https://lore.kernel.org/all/20240208124300.2740313-1-claudiu.beznea.uj@bp.renesas.com
> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>

Reviewed-by: Guenter Roeck <linux@roeck-us.net>

> ---
> 
> Changes in v8:
> - none, this patch is new
> 
>  drivers/watchdog/rzg2l_wdt.c | 12 ++++++++++++
>  1 file changed, 12 insertions(+)
> 
> diff --git a/drivers/watchdog/rzg2l_wdt.c b/drivers/watchdog/rzg2l_wdt.c
> index c8c20cfb97a3..98e5e9914a5d 100644
> --- a/drivers/watchdog/rzg2l_wdt.c
> +++ b/drivers/watchdog/rzg2l_wdt.c
> @@ -12,6 +12,7 @@
>  #include <linux/module.h>
>  #include <linux/of.h>
>  #include <linux/platform_device.h>
> +#include <linux/pm_domain.h>
>  #include <linux/pm_runtime.h>
>  #include <linux/reset.h>
>  #include <linux/units.h>
> @@ -164,6 +165,17 @@ static int rzg2l_wdt_restart(struct watchdog_device *wdev,
>  	struct rzg2l_wdt_priv *priv = watchdog_get_drvdata(wdev);
>  	int ret;
>  
> +	/*
> +	 * The device may be part of a power domain that is currently
> +	 * powered off. We need to power it up before accessing registers.
> +	 * We don't undo the dev_pm_genpd_resume() as the device need to
> +	 * be up for the reboot to happen. Also, as we are in atomic context
> +	 * here there is no need to increment PM runtime usage counter
> +	 * (to make sure pm_runtime_active() doesn't return wrong code).
> +	 */
> +	if (!pm_runtime_active(wdev->parent))
> +		dev_pm_genpd_resume(wdev->parent);
> +
>  	clk_prepare_enable(priv->pclk);
>  	clk_prepare_enable(priv->osc_clk);
>  
> -- 
> 2.39.2
>