Re: [PATCHv2 3/5] watchdog: rti-wdt: add support for window size configuration

2020-07-13 Thread Tero Kristo

On 05/07/2020 17:49, Guenter Roeck wrote:

On 7/3/20 5:04 AM, Tero Kristo wrote:

RTI watchdog can support different open window sizes. Add support for
these and add a new module parameter to configure it. The default open
window size for the driver still remains at 50%.

Also, modify the margin calculation logic a bit for 32k source clock,
instead of adding a margin to every window config, assume the 32k source
clock is running slower.


I'll drop this patch mostly in next rev to get rid of the dynamic config 
for window size and always use 50%. I will just read the window size in 
case someone has started the watchdog beforehand.




Signed-off-by: Tero Kristo 
---
  drivers/watchdog/rti_wdt.c | 112 +++--
  1 file changed, 95 insertions(+), 17 deletions(-)

diff --git a/drivers/watchdog/rti_wdt.c b/drivers/watchdog/rti_wdt.c
index d456dd72d99a..110bfc8d0bb3 100644
--- a/drivers/watchdog/rti_wdt.c
+++ b/drivers/watchdog/rti_wdt.c
@@ -19,7 +19,8 @@
  #include 
  #include 
  
-#define DEFAULT_HEARTBEAT 60

+#define DEFAULT_HEARTBEAT  60
+#define DEFAULT_WINDOWSIZE 50
  
  /* Max heartbeat is calculated at 32kHz source clock */

  #define MAX_HEARTBEAT 1000
@@ -35,9 +36,13 @@
  
  #define RTIWWDRX_NMI	0xa
  
-#define RTIWWDSIZE_50P	0x50

+#define RTIWWDSIZE_50P 0x50
+#define RTIWWDSIZE_25P 0x500
+#define RTIWWDSIZE_12P50x5000
+#define RTIWWDSIZE_6P250x5
+#define RTIWWDSIZE_3P125   0x50
  
-#define WDENABLE_KEY	0xa98559da

+#define WDENABLE_KEY   0xa98559da
  
  #define WDKEY_SEQ0		0xe51a

  #define WDKEY_SEQ10xa35c
@@ -48,7 +53,8 @@
  
  #define DWDST			BIT(1)
  
-static int heartbeat;

+static int heartbeat = DEFAULT_HEARTBEAT;
+static u32 wsize = DEFAULT_WINDOWSIZE;
  
  /*

   * struct to hold data for each WDT device
@@ -62,34 +68,93 @@ struct rti_wdt_device {
struct watchdog_device  wdd;
  };
  
+static int rti_wdt_convert_wsize(void)

+{
+   if (wsize >= 50) {
+   wsize = RTIWWDSIZE_50P;
+   } else if (wsize >= 25) {
+   wsize = RTIWWDSIZE_25P;
+   } else if (wsize > 12) {
+   wsize = RTIWWDSIZE_12P5;
+   } else if (wsize > 6) {
+   wsize = RTIWWDSIZE_6P25;
+   } else if (wsize > 3) {
+   wsize = RTIWWDSIZE_3P125;
+   } else {
+   pr_err("%s: bad windowsize: %d\n", __func__, wsize);


Please do not use pr_ functions. Pass the watchdog device as argument
and use dev_err().

Also, this function modifies the wsize parameter. When called
again, that parameter will have a  totally different meaning, and
the second call to this function will always set the window size
to 50.

On top of all that, window sizes larger than 50 are set to 50,
window sizes between 4 and 49 are adjusted, and window sizes <= 3
are rejected. That is not exactly consistent.

Does this module parameter really add value / make sense ?
What is the use case ? We should not add such complexity without
use case.


I'll ditch the support for this. Just thought that it would be neat 
feature to have this in place because I ended up implementing most of 
this for the attach feature anyways.





+   return -EINVAL;
+   }
+
+   return 0;
+}
+
+static int rti_wdt_setup_hw_hb(struct watchdog_device *wdd)
+{
+   /*
+* RTI only supports a windowed mode, where the watchdog can only
+* be petted during the open window; not too early or not too late.
+* The HW configuration options only allow for the open window size
+* to be 50% or less than that.
+*/
+   switch (wsize) {
+   case RTIWWDSIZE_50P:
+   /* 50% open window => 50% min heartbeat */
+   wdd->min_hw_heartbeat_ms = 500 * heartbeat;
+   break;
+
+   case RTIWWDSIZE_25P:
+   /* 25% open window => 75% min heartbeat */
+   wdd->min_hw_heartbeat_ms = 750 * heartbeat;
+   break;
+
+   case RTIWWDSIZE_12P5:
+   /* 12.5% open window => 87.5% min heartbeat */
+   wdd->min_hw_heartbeat_ms = 875 * heartbeat;
+   break;
+
+   case RTIWWDSIZE_6P25:
+   /* 6.5% open window => 93.5% min heartbeat */
+   wdd->min_hw_heartbeat_ms = 935 * heartbeat;
+   break;
+
+   case RTIWWDSIZE_3P125:
+   /* 3.125% open window => 96.9% min heartbeat */
+   wdd->min_hw_heartbeat_ms = 969 * heartbeat;
+   break;
+
+   default:
+   pr_err("%s: Bad watchdog window size!\n", __func__);


Same here.


+   return -EINVAL;
+   }
+
+   return 0;
+}
+
  static int rti_wdt_start(struct watchdog_device *wdd)
  {
u32 timer_margin;
struct rti_wdt_device *wdt = watchdog_get_drvdata(wdd);
+   int ret;
  
  	/* set timeout period */

-   timer_margin = (u64)wdd->timeout * wdt->

Re: [PATCHv2 3/5] watchdog: rti-wdt: add support for window size configuration

2020-07-05 Thread Guenter Roeck
On 7/3/20 5:04 AM, Tero Kristo wrote:
> RTI watchdog can support different open window sizes. Add support for
> these and add a new module parameter to configure it. The default open
> window size for the driver still remains at 50%.
> 
> Also, modify the margin calculation logic a bit for 32k source clock,
> instead of adding a margin to every window config, assume the 32k source
> clock is running slower.
> 
> Signed-off-by: Tero Kristo 
> ---
>  drivers/watchdog/rti_wdt.c | 112 +++--
>  1 file changed, 95 insertions(+), 17 deletions(-)
> 
> diff --git a/drivers/watchdog/rti_wdt.c b/drivers/watchdog/rti_wdt.c
> index d456dd72d99a..110bfc8d0bb3 100644
> --- a/drivers/watchdog/rti_wdt.c
> +++ b/drivers/watchdog/rti_wdt.c
> @@ -19,7 +19,8 @@
>  #include 
>  #include 
>  
> -#define DEFAULT_HEARTBEAT 60
> +#define DEFAULT_HEARTBEAT60
> +#define DEFAULT_WINDOWSIZE   50
>  
>  /* Max heartbeat is calculated at 32kHz source clock */
>  #define MAX_HEARTBEAT1000
> @@ -35,9 +36,13 @@
>  
>  #define RTIWWDRX_NMI 0xa
>  
> -#define RTIWWDSIZE_50P   0x50
> +#define RTIWWDSIZE_50P   0x50
> +#define RTIWWDSIZE_25P   0x500
> +#define RTIWWDSIZE_12P5  0x5000
> +#define RTIWWDSIZE_6P25  0x5
> +#define RTIWWDSIZE_3P125 0x50
>  
> -#define WDENABLE_KEY 0xa98559da
> +#define WDENABLE_KEY 0xa98559da
>  
>  #define WDKEY_SEQ0   0xe51a
>  #define WDKEY_SEQ1   0xa35c
> @@ -48,7 +53,8 @@
>  
>  #define DWDSTBIT(1)
>  
> -static int heartbeat;
> +static int heartbeat =   DEFAULT_HEARTBEAT;
> +static u32 wsize =   DEFAULT_WINDOWSIZE;
>  
>  /*
>   * struct to hold data for each WDT device
> @@ -62,34 +68,93 @@ struct rti_wdt_device {
>   struct watchdog_device  wdd;
>  };
>  
> +static int rti_wdt_convert_wsize(void)
> +{
> + if (wsize >= 50) {
> + wsize = RTIWWDSIZE_50P;
> + } else if (wsize >= 25) {
> + wsize = RTIWWDSIZE_25P;
> + } else if (wsize > 12) {
> + wsize = RTIWWDSIZE_12P5;
> + } else if (wsize > 6) {
> + wsize = RTIWWDSIZE_6P25;
> + } else if (wsize > 3) {
> + wsize = RTIWWDSIZE_3P125;
> + } else {
> + pr_err("%s: bad windowsize: %d\n", __func__, wsize);

Please do not use pr_ functions. Pass the watchdog device as argument
and use dev_err().

Also, this function modifies the wsize parameter. When called
again, that parameter will have a  totally different meaning, and
the second call to this function will always set the window size
to 50.

On top of all that, window sizes larger than 50 are set to 50,
window sizes between 4 and 49 are adjusted, and window sizes <= 3
are rejected. That is not exactly consistent.

Does this module parameter really add value / make sense ?
What is the use case ? We should not add such complexity without
use case.

> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
> +static int rti_wdt_setup_hw_hb(struct watchdog_device *wdd)
> +{
> + /*
> +  * RTI only supports a windowed mode, where the watchdog can only
> +  * be petted during the open window; not too early or not too late.
> +  * The HW configuration options only allow for the open window size
> +  * to be 50% or less than that.
> +  */
> + switch (wsize) {
> + case RTIWWDSIZE_50P:
> + /* 50% open window => 50% min heartbeat */
> + wdd->min_hw_heartbeat_ms = 500 * heartbeat;
> + break;
> +
> + case RTIWWDSIZE_25P:
> + /* 25% open window => 75% min heartbeat */
> + wdd->min_hw_heartbeat_ms = 750 * heartbeat;
> + break;
> +
> + case RTIWWDSIZE_12P5:
> + /* 12.5% open window => 87.5% min heartbeat */
> + wdd->min_hw_heartbeat_ms = 875 * heartbeat;
> + break;
> +
> + case RTIWWDSIZE_6P25:
> + /* 6.5% open window => 93.5% min heartbeat */
> + wdd->min_hw_heartbeat_ms = 935 * heartbeat;
> + break;
> +
> + case RTIWWDSIZE_3P125:
> + /* 3.125% open window => 96.9% min heartbeat */
> + wdd->min_hw_heartbeat_ms = 969 * heartbeat;
> + break;
> +
> + default:
> + pr_err("%s: Bad watchdog window size!\n", __func__);

Same here.

> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
>  static int rti_wdt_start(struct watchdog_device *wdd)
>  {
>   u32 timer_margin;
>   struct rti_wdt_device *wdt = watchdog_get_drvdata(wdd);
> + int ret;
>  
>   /* set timeout period */
> - timer_margin = (u64)wdd->timeout * wdt->freq;
> + timer_margin = (u64)heartbeat * wdt->freq;
>   timer_margin >>= WDT_PRELOAD_SHIFT;
>   if (timer_margin > WDT_PRELOAD_MAX)
>   timer_margin = WDT_PRELOAD_MAX;
>   writel_relaxed(timer_margin, wdt->base + RTIDWDPRLD);
>  
> - /*

[PATCHv2 3/5] watchdog: rti-wdt: add support for window size configuration

2020-07-03 Thread Tero Kristo
RTI watchdog can support different open window sizes. Add support for
these and add a new module parameter to configure it. The default open
window size for the driver still remains at 50%.

Also, modify the margin calculation logic a bit for 32k source clock,
instead of adding a margin to every window config, assume the 32k source
clock is running slower.

Signed-off-by: Tero Kristo 
---
 drivers/watchdog/rti_wdt.c | 112 +++--
 1 file changed, 95 insertions(+), 17 deletions(-)

diff --git a/drivers/watchdog/rti_wdt.c b/drivers/watchdog/rti_wdt.c
index d456dd72d99a..110bfc8d0bb3 100644
--- a/drivers/watchdog/rti_wdt.c
+++ b/drivers/watchdog/rti_wdt.c
@@ -19,7 +19,8 @@
 #include 
 #include 
 
-#define DEFAULT_HEARTBEAT 60
+#define DEFAULT_HEARTBEAT  60
+#define DEFAULT_WINDOWSIZE 50
 
 /* Max heartbeat is calculated at 32kHz source clock */
 #define MAX_HEARTBEAT  1000
@@ -35,9 +36,13 @@
 
 #define RTIWWDRX_NMI   0xa
 
-#define RTIWWDSIZE_50P 0x50
+#define RTIWWDSIZE_50P 0x50
+#define RTIWWDSIZE_25P 0x500
+#define RTIWWDSIZE_12P50x5000
+#define RTIWWDSIZE_6P250x5
+#define RTIWWDSIZE_3P125   0x50
 
-#define WDENABLE_KEY   0xa98559da
+#define WDENABLE_KEY   0xa98559da
 
 #define WDKEY_SEQ0 0xe51a
 #define WDKEY_SEQ1 0xa35c
@@ -48,7 +53,8 @@
 
 #define DWDST  BIT(1)
 
-static int heartbeat;
+static int heartbeat = DEFAULT_HEARTBEAT;
+static u32 wsize = DEFAULT_WINDOWSIZE;
 
 /*
  * struct to hold data for each WDT device
@@ -62,34 +68,93 @@ struct rti_wdt_device {
struct watchdog_device  wdd;
 };
 
+static int rti_wdt_convert_wsize(void)
+{
+   if (wsize >= 50) {
+   wsize = RTIWWDSIZE_50P;
+   } else if (wsize >= 25) {
+   wsize = RTIWWDSIZE_25P;
+   } else if (wsize > 12) {
+   wsize = RTIWWDSIZE_12P5;
+   } else if (wsize > 6) {
+   wsize = RTIWWDSIZE_6P25;
+   } else if (wsize > 3) {
+   wsize = RTIWWDSIZE_3P125;
+   } else {
+   pr_err("%s: bad windowsize: %d\n", __func__, wsize);
+   return -EINVAL;
+   }
+
+   return 0;
+}
+
+static int rti_wdt_setup_hw_hb(struct watchdog_device *wdd)
+{
+   /*
+* RTI only supports a windowed mode, where the watchdog can only
+* be petted during the open window; not too early or not too late.
+* The HW configuration options only allow for the open window size
+* to be 50% or less than that.
+*/
+   switch (wsize) {
+   case RTIWWDSIZE_50P:
+   /* 50% open window => 50% min heartbeat */
+   wdd->min_hw_heartbeat_ms = 500 * heartbeat;
+   break;
+
+   case RTIWWDSIZE_25P:
+   /* 25% open window => 75% min heartbeat */
+   wdd->min_hw_heartbeat_ms = 750 * heartbeat;
+   break;
+
+   case RTIWWDSIZE_12P5:
+   /* 12.5% open window => 87.5% min heartbeat */
+   wdd->min_hw_heartbeat_ms = 875 * heartbeat;
+   break;
+
+   case RTIWWDSIZE_6P25:
+   /* 6.5% open window => 93.5% min heartbeat */
+   wdd->min_hw_heartbeat_ms = 935 * heartbeat;
+   break;
+
+   case RTIWWDSIZE_3P125:
+   /* 3.125% open window => 96.9% min heartbeat */
+   wdd->min_hw_heartbeat_ms = 969 * heartbeat;
+   break;
+
+   default:
+   pr_err("%s: Bad watchdog window size!\n", __func__);
+   return -EINVAL;
+   }
+
+   return 0;
+}
+
 static int rti_wdt_start(struct watchdog_device *wdd)
 {
u32 timer_margin;
struct rti_wdt_device *wdt = watchdog_get_drvdata(wdd);
+   int ret;
 
/* set timeout period */
-   timer_margin = (u64)wdd->timeout * wdt->freq;
+   timer_margin = (u64)heartbeat * wdt->freq;
timer_margin >>= WDT_PRELOAD_SHIFT;
if (timer_margin > WDT_PRELOAD_MAX)
timer_margin = WDT_PRELOAD_MAX;
writel_relaxed(timer_margin, wdt->base + RTIDWDPRLD);
 
-   /*
-* RTI only supports a windowed mode, where the watchdog can only
-* be petted during the open window; not too early or not too late.
-* The HW configuration options only allow for the open window size
-* to be 50% or less than that; we obviouly want to configure the open
-* window as large as possible so we select the 50% option. To avoid
-* any glitches, we accommodate 5% safety margin also, so we setup
-* the min_hw_hearbeat at 55% of the timeout period.
-*/
-   wdd->min_hw_heartbeat_ms = 11 * wdd->timeout * 1000 / 20;
+   ret = rti_wdt_convert_wsize();
+   if (ret)
+   return ret;
+
+   ret = rti_wdt_setup_hw_hb(wdd);
+   if (ret)
+   return ret;
 
/* Generate NMI when wdt expires */