diff mbox series

[v2,4/4] watchdog: cadence_wdt: Support all available prescaler values

Message ID 20190705114522.42565-5-tomas.melin@vaisala.com (mailing list archive)
State Changes Requested
Headers show
Series watchdog: cadence_wdt: Support all available prescaler values | expand

Commit Message

Tomas Melin July 5, 2019, 11:46 a.m. UTC
Cadence watchdog HW supports prescaler values of
8, 64, 512 and 4096.

Add support to select prescaler values of 8 and 64 for lower
input clock frequencies.

Prescaler value is selected to keep timeout resolution of 1 second.
For clock frequencies below 32kHz, 1 second resolution does
no longer hold, thereby returning an error.

Signed-off-by: Tomas Melin <tomas.melin@vaisala.com>
---
 drivers/watchdog/cadence_wdt.c | 18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)

Comments

Guenter Roeck July 8, 2019, 6:14 p.m. UTC | #1
On Fri, Jul 05, 2019 at 11:46:04AM +0000, Melin Tomas wrote:
> Cadence watchdog HW supports prescaler values of
> 8, 64, 512 and 4096.
> 
> Add support to select prescaler values of 8 and 64 for lower
> input clock frequencies.
> 
> Prescaler value is selected to keep timeout resolution of 1 second.
> For clock frequencies below 32kHz, 1 second resolution does
> no longer hold, thereby returning an error.
> 
> Signed-off-by: Tomas Melin <tomas.melin@vaisala.com>
> ---
>  drivers/watchdog/cadence_wdt.c | 18 ++++++++++++++----
>  1 file changed, 14 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/watchdog/cadence_wdt.c b/drivers/watchdog/cadence_wdt.c
> index 4657800d9d8e..39109b5721c1 100644
> --- a/drivers/watchdog/cadence_wdt.c
> +++ b/drivers/watchdog/cadence_wdt.c
> @@ -33,16 +33,17 @@
>  #define CDNS_WDT_COUNTER_VALUE_DIVISOR 0x1000
>  
>  /* Clock prescaler value and selection */
> +#define CDNS_WDT_PRESCALE_8	8
>  #define CDNS_WDT_PRESCALE_64	64
>  #define CDNS_WDT_PRESCALE_512	512
>  #define CDNS_WDT_PRESCALE_4096	4096
> +#define CDNS_WDT_PRESCALE_SELECT_8	0
>  #define CDNS_WDT_PRESCALE_SELECT_64	1
>  #define CDNS_WDT_PRESCALE_SELECT_512	2
>  #define CDNS_WDT_PRESCALE_SELECT_4096	3
>  
> -/* Input clock frequency */
> -#define CDNS_WDT_CLK_10MHZ	10000000
> -#define CDNS_WDT_CLK_75MHZ	75000000
> +/* Base input clock frequency */
> +#define CDNS_WDT_CLK_32KHZ 32768
>  
>  /* Counter maximum value */
>  #define CDNS_WDT_COUNTER_MAX 0xFFF
> @@ -304,7 +305,16 @@ static int cdns_wdt_probe(struct platform_device *pdev)
>  	}
>  
>  	clock_f = clk_get_rate(wdt->clk);
> -	if (clock_f <= CDNS_WDT_CLK_75MHZ) {
> +	if (clock_f < CDNS_WDT_CLK_32KHZ) {
> +		dev_err(&pdev->dev, "cannot find suitable clock prescaler\n");
> +		return -ERANGE;

	/* Math result not representable */

is a bit misleading here. I understand there isn't a good option,
but using math errors isn't it. Just use -EINVAL if you don't have
a better idea. It might also make sense to display the returned
clock frequency.

> +	} else if (clock_f <= CDNS_WDT_CLK_32KHZ * CDNS_WDT_PRESCALE_8) {
> +		wdt->prescaler = CDNS_WDT_PRESCALE_8;
> +		wdt->ctrl_clksel = CDNS_WDT_PRESCALE_SELECT_8;
> +	} else if (clock_f <= CDNS_WDT_CLK_32KHZ * CDNS_WDT_PRESCALE_64) {
> +		wdt->prescaler = CDNS_WDT_PRESCALE_64;
> +		wdt->ctrl_clksel = CDNS_WDT_PRESCALE_SELECT_64;
> +	} else if (clock_f <= CDNS_WDT_CLK_32KHZ * CDNS_WDT_PRESCALE_512) {
>  		wdt->prescaler = CDNS_WDT_PRESCALE_512;
>  		wdt->ctrl_clksel = CDNS_WDT_PRESCALE_SELECT_512;
>  	} else {
diff mbox series

Patch

diff --git a/drivers/watchdog/cadence_wdt.c b/drivers/watchdog/cadence_wdt.c
index 4657800d9d8e..39109b5721c1 100644
--- a/drivers/watchdog/cadence_wdt.c
+++ b/drivers/watchdog/cadence_wdt.c
@@ -33,16 +33,17 @@ 
 #define CDNS_WDT_COUNTER_VALUE_DIVISOR 0x1000
 
 /* Clock prescaler value and selection */
+#define CDNS_WDT_PRESCALE_8	8
 #define CDNS_WDT_PRESCALE_64	64
 #define CDNS_WDT_PRESCALE_512	512
 #define CDNS_WDT_PRESCALE_4096	4096
+#define CDNS_WDT_PRESCALE_SELECT_8	0
 #define CDNS_WDT_PRESCALE_SELECT_64	1
 #define CDNS_WDT_PRESCALE_SELECT_512	2
 #define CDNS_WDT_PRESCALE_SELECT_4096	3
 
-/* Input clock frequency */
-#define CDNS_WDT_CLK_10MHZ	10000000
-#define CDNS_WDT_CLK_75MHZ	75000000
+/* Base input clock frequency */
+#define CDNS_WDT_CLK_32KHZ 32768
 
 /* Counter maximum value */
 #define CDNS_WDT_COUNTER_MAX 0xFFF
@@ -304,7 +305,16 @@  static int cdns_wdt_probe(struct platform_device *pdev)
 	}
 
 	clock_f = clk_get_rate(wdt->clk);
-	if (clock_f <= CDNS_WDT_CLK_75MHZ) {
+	if (clock_f < CDNS_WDT_CLK_32KHZ) {
+		dev_err(&pdev->dev, "cannot find suitable clock prescaler\n");
+		return -ERANGE;
+	} else if (clock_f <= CDNS_WDT_CLK_32KHZ * CDNS_WDT_PRESCALE_8) {
+		wdt->prescaler = CDNS_WDT_PRESCALE_8;
+		wdt->ctrl_clksel = CDNS_WDT_PRESCALE_SELECT_8;
+	} else if (clock_f <= CDNS_WDT_CLK_32KHZ * CDNS_WDT_PRESCALE_64) {
+		wdt->prescaler = CDNS_WDT_PRESCALE_64;
+		wdt->ctrl_clksel = CDNS_WDT_PRESCALE_SELECT_64;
+	} else if (clock_f <= CDNS_WDT_CLK_32KHZ * CDNS_WDT_PRESCALE_512) {
 		wdt->prescaler = CDNS_WDT_PRESCALE_512;
 		wdt->ctrl_clksel = CDNS_WDT_PRESCALE_SELECT_512;
 	} else {