* [PATCH v4 0/4] Increase max timeout value of s3c2410 watchdog
[not found] <CGME20250724081336epcas2p30ba9afd1e78d9bbb60f44d24d1cf0acb@epcas2p3.samsung.com>
@ 2025-07-24 8:08 ` Sangwook Shin
[not found] ` <CGME20250724081336epcas2p31c2e3cbed1d3a7bf30a9fb664e6cb92b@epcas2p3.samsung.com>
` (3 more replies)
0 siblings, 4 replies; 17+ messages in thread
From: Sangwook Shin @ 2025-07-24 8:08 UTC (permalink / raw)
To: krzk, alim.akhtar, wim, linux, semen.protsenko, khwan.seo,
dongil01.park
Cc: linux-arm-kernel, linux-samsung-soc, linux-watchdog, linux-kernel,
Sangwook Shin
The ExynosAutoV9 and ExynosAutoV920 SoCs have a 32-bit counter register,
but due to code constraints, only 16-bit values could be used.
This series enables these SoCs to use the 32-bit counter.
Additionally, it addresses the issue where the ExynosAutoV9 SoC supports
the DBGACK bit but it was not set.
V3->V4:
- Merge patches [v3 3/5] and [v3 4/5] into one so that Quirk and its consumer
are part of the same patch.
- Link to v3:
https://lore.kernel.org/linux-watchdog/20250714055440.3138135-1-sw617.shin@samsung.com/
https://lore.kernel.org/linux-watchdog/20250515075350.3368635-1-sw617.shin@samsung.com/
V2->V3:
- Correct the incorrect tag information.
- Link to v2:
https://lore.kernel.org/linux-watchdog/20250514094220.1561378-1-sw617.shin@samsung.com/
V1->V2:
- Modify the max_timeout calculation considering overflow
- Separate tha max_timeout calculation into a separate patch
- Add max_cnt in struct s3c2410_wdt
- Set max_cnt once in probe function
- Add patch that uses S3C2410_WTCON_PRESCALE_MAX instead of hardcoded one
- Remove unnecessary inner parentheses
- Link to v1:
https://lore.kernel.org/linux-watchdog/20250513094711.2691059-1-sw617.shin@samsung.com/
Sangwook Shin (4):
watchdog: s3c2410_wdt: Replace hardcoded values with macro definitions
watchdog: s3c2410_wdt: Fix max_timeout being calculated larger
watchdog: s3c2410_wdt: Increase max timeout value of watchdog
watchdog: s3c2410_wdt: exynosautov9: Enable supported features
drivers/watchdog/s3c2410_wdt.c | 37 +++++++++++++++++++++++-----------
1 file changed, 25 insertions(+), 12 deletions(-)
--
2.25.1
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v4 1/4] watchdog: s3c2410_wdt: Replace hardcoded values with macro definitions
[not found] ` <CGME20250724081336epcas2p31c2e3cbed1d3a7bf30a9fb664e6cb92b@epcas2p3.samsung.com>
@ 2025-07-24 8:08 ` Sangwook Shin
0 siblings, 0 replies; 17+ messages in thread
From: Sangwook Shin @ 2025-07-24 8:08 UTC (permalink / raw)
To: krzk, alim.akhtar, wim, linux, semen.protsenko, khwan.seo,
dongil01.park
Cc: linux-arm-kernel, linux-samsung-soc, linux-watchdog, linux-kernel,
Sangwook Shin
Modify the code to utilize macro-defined values instead of hardcoded
values. The value 0x100 in the s3c2410wdt_set_heartbeat function represents
S3C2410_WTCON_PRESCALE_MAX + 1, but it is hardcoded, making its meaning
difficult to understand and reducing code readability.
Reviewed-by: Sam Protsenko <semen.protsenko@linaro.org>
Reviewed-by: Alim Akhtar <alim.akhtar@samsung.com>
Signed-off-by: Sangwook Shin <sw617.shin@samsung.com>
---
drivers/watchdog/s3c2410_wdt.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c
index 40901bdac426..95f7207e390a 100644
--- a/drivers/watchdog/s3c2410_wdt.c
+++ b/drivers/watchdog/s3c2410_wdt.c
@@ -587,7 +587,7 @@ static int s3c2410wdt_set_heartbeat(struct watchdog_device *wdd,
if (count >= 0x10000) {
divisor = DIV_ROUND_UP(count, 0xffff);
- if (divisor > 0x100) {
+ if (divisor > S3C2410_WTCON_PRESCALE_MAX + 1) {
dev_err(wdt->dev, "timeout %d too big\n", timeout);
return -EINVAL;
}
--
2.25.1
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH v4 2/4] watchdog: s3c2410_wdt: Fix max_timeout being calculated larger
[not found] ` <CGME20250724081336epcas2p38e95932ddc5c702e05a6436f05582993@epcas2p3.samsung.com>
@ 2025-07-24 8:08 ` Sangwook Shin
2025-08-02 4:11 ` Sam Protsenko
0 siblings, 1 reply; 17+ messages in thread
From: Sangwook Shin @ 2025-07-24 8:08 UTC (permalink / raw)
To: krzk, alim.akhtar, wim, linux, semen.protsenko, khwan.seo,
dongil01.park
Cc: linux-arm-kernel, linux-samsung-soc, linux-watchdog, linux-kernel,
Sangwook Shin
Fix the issue of max_timeout being calculated larger than actual value.
The calculation result of freq / (S3C2410_WTCON_PRESCALE_MAX + 1) /
S3C2410_WTCON_MAXDIV is smaller than the actual value because the remainder
is discarded during the calculation process. This leads to a larger
calculated value for max_timeout compared to the actual settable value.
A ceiling operation is applied in the calculation process to resolve this.
Reviewed-by: Alim Akhtar <alim.akhtar@samsung.com>
Signed-off-by: Sangwook Shin <sw617.shin@samsung.com>
---
drivers/watchdog/s3c2410_wdt.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c
index 95f7207e390a..31f7e1ec779e 100644
--- a/drivers/watchdog/s3c2410_wdt.c
+++ b/drivers/watchdog/s3c2410_wdt.c
@@ -411,8 +411,8 @@ static inline unsigned int s3c2410wdt_max_timeout(struct s3c2410_wdt *wdt)
{
const unsigned long freq = s3c2410wdt_get_freq(wdt);
- return S3C2410_WTCNT_MAXCNT / (freq / (S3C2410_WTCON_PRESCALE_MAX + 1)
- / S3C2410_WTCON_MAXDIV);
+ return S3C2410_WTCNT_MAXCNT / DIV_ROUND_UP(freq,
+ (S3C2410_WTCON_PRESCALE_MAX + 1) * S3C2410_WTCON_MAXDIV);
}
static int s3c2410wdt_disable_wdt_reset(struct s3c2410_wdt *wdt, bool mask)
--
2.25.1
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH v4 3/4] watchdog: s3c2410_wdt: Increase max timeout value of watchdog
[not found] ` <CGME20250724081337epcas2p31f594b6e9ab87e24c94f11dea4070956@epcas2p3.samsung.com>
@ 2025-07-24 8:08 ` Sangwook Shin
2025-08-02 4:36 ` Sam Protsenko
0 siblings, 1 reply; 17+ messages in thread
From: Sangwook Shin @ 2025-07-24 8:08 UTC (permalink / raw)
To: krzk, alim.akhtar, wim, linux, semen.protsenko, khwan.seo,
dongil01.park
Cc: linux-arm-kernel, linux-samsung-soc, linux-watchdog, linux-kernel,
Sangwook Shin
Increase max_timeout value from 55s to 3664647s (1017h 57min 27s) with
38400000 frequency system if the system has 32-bit WTCNT register.
cat /sys/devices/platform/10060000.watchdog_cl0/watchdog/watchdog0/max_timeout
3664647
[ 0.302473] s3c2410-wdt 10060000.watchdog_cl0: Heartbeat: count=1099394100000, timeout=3664647, freq=300000
[ 0.302479] s3c2410-wdt 10060000.watchdog_cl0: Heartbeat: timeout=3664647, divisor=256, count=1099394100000 (fff8feac)
[ 0.302510] s3c2410-wdt 10060000.watchdog_cl0: starting watchdog timer
[ 0.302722] s3c2410-wdt 10060000.watchdog_cl0: watchdog active, reset enabled, irq disabled
If system has 32-bit WTCNT, add QUIRK_HAS_32BIT_MAXCNT to its quirk flags, then
it will operation with 32-bit counter. If not, with 16-bit counter like previous.
Reviewed-by: Alim Akhtar <alim.akhtar@samsung.com>
Signed-off-by: Sangwook Shin <sw617.shin@samsung.com>
---
drivers/watchdog/s3c2410_wdt.c | 27 +++++++++++++++++++--------
1 file changed, 19 insertions(+), 8 deletions(-)
diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c
index 31f7e1ec779e..184b1ad46ca6 100644
--- a/drivers/watchdog/s3c2410_wdt.c
+++ b/drivers/watchdog/s3c2410_wdt.c
@@ -34,6 +34,7 @@
#define S3C2410_WTCLRINT 0x0c
#define S3C2410_WTCNT_MAXCNT 0xffff
+#define S3C2410_WTCNT_MAXCNT_32 0xffffffff
#define S3C2410_WTCON_RSTEN BIT(0)
#define S3C2410_WTCON_INTEN BIT(2)
@@ -123,6 +124,10 @@
* %QUIRK_HAS_DBGACK_BIT: WTCON register has DBGACK_MASK bit. Setting the
* DBGACK_MASK bit disables the watchdog outputs when the SoC is in debug mode.
* Debug mode is determined by the DBGACK CPU signal.
+ *
+ * %QUIRK_HAS_32BIT_MAXCNT: WTDAT and WTCNT are 32-bit registers. With these
+ * 32-bit registers, larger values to be set, which means that larger timeouts
+ * value can be set.
*/
#define QUIRK_HAS_WTCLRINT_REG BIT(0)
#define QUIRK_HAS_PMU_MASK_RESET BIT(1)
@@ -130,6 +135,7 @@
#define QUIRK_HAS_PMU_AUTO_DISABLE BIT(3)
#define QUIRK_HAS_PMU_CNT_EN BIT(4)
#define QUIRK_HAS_DBGACK_BIT BIT(5)
+#define QUIRK_HAS_32BIT_MAXCNT BIT(6)
/* These quirks require that we have a PMU register map */
#define QUIRKS_HAVE_PMUREG \
@@ -198,6 +204,7 @@ struct s3c2410_wdt {
struct notifier_block freq_transition;
const struct s3c2410_wdt_variant *drv_data;
struct regmap *pmureg;
+ unsigned int max_cnt;
};
static const struct s3c2410_wdt_variant drv_data_s3c2410 = {
@@ -349,7 +356,7 @@ static const struct s3c2410_wdt_variant drv_data_exynosautov920_cl0 = {
.cnt_en_bit = 8,
.quirks = QUIRK_HAS_WTCLRINT_REG | QUIRK_HAS_PMU_MASK_RESET |
QUIRK_HAS_PMU_RST_STAT | QUIRK_HAS_PMU_CNT_EN |
- QUIRK_HAS_DBGACK_BIT,
+ QUIRK_HAS_DBGACK_BIT | QUIRK_HAS_32BIT_MAXCNT,
};
static const struct s3c2410_wdt_variant drv_data_exynosautov920_cl1 = {
@@ -362,7 +369,7 @@ static const struct s3c2410_wdt_variant drv_data_exynosautov920_cl1 = {
.cnt_en_bit = 8,
.quirks = QUIRK_HAS_WTCLRINT_REG | QUIRK_HAS_PMU_MASK_RESET |
QUIRK_HAS_PMU_RST_STAT | QUIRK_HAS_PMU_CNT_EN |
- QUIRK_HAS_DBGACK_BIT,
+ QUIRK_HAS_DBGACK_BIT | QUIRK_HAS_32BIT_MAXCNT,
};
static const struct of_device_id s3c2410_wdt_match[] = {
@@ -411,7 +418,7 @@ static inline unsigned int s3c2410wdt_max_timeout(struct s3c2410_wdt *wdt)
{
const unsigned long freq = s3c2410wdt_get_freq(wdt);
- return S3C2410_WTCNT_MAXCNT / DIV_ROUND_UP(freq,
+ return wdt->max_cnt / DIV_ROUND_UP(freq,
(S3C2410_WTCON_PRESCALE_MAX + 1) * S3C2410_WTCON_MAXDIV);
}
@@ -566,7 +573,7 @@ static int s3c2410wdt_set_heartbeat(struct watchdog_device *wdd,
{
struct s3c2410_wdt *wdt = watchdog_get_drvdata(wdd);
unsigned long freq = s3c2410wdt_get_freq(wdt);
- unsigned int count;
+ unsigned long count;
unsigned int divisor = 1;
unsigned long wtcon;
@@ -576,7 +583,7 @@ static int s3c2410wdt_set_heartbeat(struct watchdog_device *wdd,
freq = DIV_ROUND_UP(freq, 128);
count = timeout * freq;
- dev_dbg(wdt->dev, "Heartbeat: count=%d, timeout=%d, freq=%lu\n",
+ dev_dbg(wdt->dev, "Heartbeat: count=%lu, timeout=%d, freq=%lu\n",
count, timeout, freq);
/* if the count is bigger than the watchdog register,
@@ -584,8 +591,8 @@ static int s3c2410wdt_set_heartbeat(struct watchdog_device *wdd,
actually make this value
*/
- if (count >= 0x10000) {
- divisor = DIV_ROUND_UP(count, 0xffff);
+ if (count > wdt->max_cnt) {
+ divisor = DIV_ROUND_UP(count, wdt->max_cnt);
if (divisor > S3C2410_WTCON_PRESCALE_MAX + 1) {
dev_err(wdt->dev, "timeout %d too big\n", timeout);
@@ -593,7 +600,7 @@ static int s3c2410wdt_set_heartbeat(struct watchdog_device *wdd,
}
}
- dev_dbg(wdt->dev, "Heartbeat: timeout=%d, divisor=%d, count=%d (%08x)\n",
+ dev_dbg(wdt->dev, "Heartbeat: timeout=%d, divisor=%d, count=%lu (%08lx)\n",
timeout, divisor, count, DIV_ROUND_UP(count, divisor));
count = DIV_ROUND_UP(count, divisor);
@@ -801,6 +808,10 @@ static int s3c2410wdt_probe(struct platform_device *pdev)
if (IS_ERR(wdt->src_clk))
return dev_err_probe(dev, PTR_ERR(wdt->src_clk), "failed to get source clock\n");
+ wdt->max_cnt = S3C2410_WTCNT_MAXCNT;
+ if ((wdt->drv_data->quirks & QUIRK_HAS_32BIT_MAXCNT))
+ wdt->max_cnt = S3C2410_WTCNT_MAXCNT_32;
+
wdt->wdt_device.min_timeout = 1;
wdt->wdt_device.max_timeout = s3c2410wdt_max_timeout(wdt);
--
2.25.1
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH v4 4/4] watchdog: s3c2410_wdt: exynosautov9: Enable supported features
[not found] ` <CGME20250724081337epcas2p430db7d7514b8cc05e41001f17b8b0d45@epcas2p4.samsung.com>
@ 2025-07-24 8:08 ` Sangwook Shin
2025-08-02 4:39 ` Sam Protsenko
0 siblings, 1 reply; 17+ messages in thread
From: Sangwook Shin @ 2025-07-24 8:08 UTC (permalink / raw)
To: krzk, alim.akhtar, wim, linux, semen.protsenko, khwan.seo,
dongil01.park
Cc: linux-arm-kernel, linux-samsung-soc, linux-watchdog, linux-kernel,
Sangwook Shin
Enable supported features for ExynosAutov9 SoC.
- QUIRK_HAS_DBGACK_BIT
- QUIRK_HAS_32BIT_MAXCNT
Reviewed-by: Alim Akhtar <alim.akhtar@samsung.com>
Signed-off-by: Sangwook Shin <sw617.shin@samsung.com>
---
drivers/watchdog/s3c2410_wdt.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c
index 184b1ad46ca6..16a845f41e74 100644
--- a/drivers/watchdog/s3c2410_wdt.c
+++ b/drivers/watchdog/s3c2410_wdt.c
@@ -305,7 +305,8 @@ static const struct s3c2410_wdt_variant drv_data_exynosautov9_cl0 = {
.cnt_en_reg = EXYNOS850_CLUSTER0_NONCPU_OUT,
.cnt_en_bit = 7,
.quirks = QUIRK_HAS_WTCLRINT_REG | QUIRK_HAS_PMU_MASK_RESET |
- QUIRK_HAS_PMU_RST_STAT | QUIRK_HAS_PMU_CNT_EN,
+ QUIRK_HAS_PMU_RST_STAT | QUIRK_HAS_PMU_CNT_EN |
+ QUIRK_HAS_DBGACK_BIT | QUIRK_HAS_32BIT_MAXCNT,
};
static const struct s3c2410_wdt_variant drv_data_exynosautov9_cl1 = {
@@ -317,7 +318,8 @@ static const struct s3c2410_wdt_variant drv_data_exynosautov9_cl1 = {
.cnt_en_reg = EXYNOSAUTOV9_CLUSTER1_NONCPU_OUT,
.cnt_en_bit = 7,
.quirks = QUIRK_HAS_WTCLRINT_REG | QUIRK_HAS_PMU_MASK_RESET |
- QUIRK_HAS_PMU_RST_STAT | QUIRK_HAS_PMU_CNT_EN,
+ QUIRK_HAS_PMU_RST_STAT | QUIRK_HAS_PMU_CNT_EN |
+ QUIRK_HAS_DBGACK_BIT | QUIRK_HAS_32BIT_MAXCNT,
};
static const struct s3c2410_wdt_variant drv_data_gs101_cl0 = {
--
2.25.1
^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCH v4 2/4] watchdog: s3c2410_wdt: Fix max_timeout being calculated larger
2025-07-24 8:08 ` [PATCH v4 2/4] watchdog: s3c2410_wdt: Fix max_timeout being calculated larger Sangwook Shin
@ 2025-08-02 4:11 ` Sam Protsenko
2025-08-05 4:22 ` sw617.shin
0 siblings, 1 reply; 17+ messages in thread
From: Sam Protsenko @ 2025-08-02 4:11 UTC (permalink / raw)
To: Sangwook Shin
Cc: krzk, alim.akhtar, wim, linux, khwan.seo, dongil01.park,
linux-arm-kernel, linux-samsung-soc, linux-watchdog, linux-kernel
On Thu, Jul 24, 2025 at 3:13 AM Sangwook Shin <sw617.shin@samsung.com> wrote:
>
> Fix the issue of max_timeout being calculated larger than actual value.
> The calculation result of freq / (S3C2410_WTCON_PRESCALE_MAX + 1) /
> S3C2410_WTCON_MAXDIV is smaller than the actual value because the remainder
> is discarded during the calculation process. This leads to a larger
> calculated value for max_timeout compared to the actual settable value.
> A ceiling operation is applied in the calculation process to resolve this.
>
> Reviewed-by: Alim Akhtar <alim.akhtar@samsung.com>
> Signed-off-by: Sangwook Shin <sw617.shin@samsung.com>
> ---
> drivers/watchdog/s3c2410_wdt.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c
> index 95f7207e390a..31f7e1ec779e 100644
> --- a/drivers/watchdog/s3c2410_wdt.c
> +++ b/drivers/watchdog/s3c2410_wdt.c
> @@ -411,8 +411,8 @@ static inline unsigned int s3c2410wdt_max_timeout(struct s3c2410_wdt *wdt)
> {
> const unsigned long freq = s3c2410wdt_get_freq(wdt);
>
> - return S3C2410_WTCNT_MAXCNT / (freq / (S3C2410_WTCON_PRESCALE_MAX + 1)
> - / S3C2410_WTCON_MAXDIV);
> + return S3C2410_WTCNT_MAXCNT / DIV_ROUND_UP(freq,
> + (S3C2410_WTCON_PRESCALE_MAX + 1) * S3C2410_WTCON_MAXDIV);
> }
>
How about something like this instead?
8<--------------------------------------------------------------------->8
static inline unsigned int s3c2410wdt_max_timeout(unsigned long freq)
{
const u64 div_max = (S3C2410_WTCON_PRESCALE_MAX + 1) *
S3C2410_WTCON_MAXDIV; /* 32768 */
const u64 n_max = S3C2410_WTCNT_MAXCNT * div_max;
u64 t_max = n_max / freq;
if (t_max > UINT_MAX)
t_max = UINT_MAX;
return (unsigned int)t_max;
}
8<--------------------------------------------------------------------->8
This implementation's result:
- is never greater than real timeout, as it loses the decimal part
after integer division in t_max
- much closer to the real timeout value, as it benefits from very
big n_max in the numerator (this is the main trick here)
- prepared for using 32-bit max counter value in your next patch, as
it uses u64 type for calculations
For example, at the clock frequency of 33 kHz:
- real timeout is: 65074.269 sec
- old function returns: 65535 sec
- your function returns: 32767 sec
- the suggested function returns: 65074 sec
I've prepared the test program you can run on your machine to play
with all implementations: [1].
Thanks!
[1] https://gist.github.com/joe-skb7/c2b2290bb0b0572a4018d81fc4ba1f3e
> static int s3c2410wdt_disable_wdt_reset(struct s3c2410_wdt *wdt, bool mask)
> --
> 2.25.1
>
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v4 3/4] watchdog: s3c2410_wdt: Increase max timeout value of watchdog
2025-07-24 8:08 ` [PATCH v4 3/4] watchdog: s3c2410_wdt: Increase max timeout value of watchdog Sangwook Shin
@ 2025-08-02 4:36 ` Sam Protsenko
2025-08-05 4:23 ` sw617.shin
0 siblings, 1 reply; 17+ messages in thread
From: Sam Protsenko @ 2025-08-02 4:36 UTC (permalink / raw)
To: Sangwook Shin
Cc: krzk, alim.akhtar, wim, linux, khwan.seo, dongil01.park,
linux-arm-kernel, linux-samsung-soc, linux-watchdog, linux-kernel
On Thu, Jul 24, 2025 at 3:13 AM Sangwook Shin <sw617.shin@samsung.com> wrote:
>
> Increase max_timeout value from 55s to 3664647s (1017h 57min 27s) with
> 38400000 frequency system if the system has 32-bit WTCNT register.
>
> cat /sys/devices/platform/10060000.watchdog_cl0/watchdog/watchdog0/max_timeout
> 3664647
>
> [ 0.302473] s3c2410-wdt 10060000.watchdog_cl0: Heartbeat: count=1099394100000, timeout=3664647, freq=300000
> [ 0.302479] s3c2410-wdt 10060000.watchdog_cl0: Heartbeat: timeout=3664647, divisor=256, count=1099394100000 (fff8feac)
> [ 0.302510] s3c2410-wdt 10060000.watchdog_cl0: starting watchdog timer
> [ 0.302722] s3c2410-wdt 10060000.watchdog_cl0: watchdog active, reset enabled, irq disabled
>
> If system has 32-bit WTCNT, add QUIRK_HAS_32BIT_MAXCNT to its quirk flags, then
> it will operation with 32-bit counter. If not, with 16-bit counter like previous.
>
> Reviewed-by: Alim Akhtar <alim.akhtar@samsung.com>
> Signed-off-by: Sangwook Shin <sw617.shin@samsung.com>
> ---
Not a strong point, but I'd break this patch into two:
1. Add 32-bit counter feature (without enabling it in exynosautov920
implementation)
2. Enable 32-bit counter feature in exynosautov920
> drivers/watchdog/s3c2410_wdt.c | 27 +++++++++++++++++++--------
> 1 file changed, 19 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c
> index 31f7e1ec779e..184b1ad46ca6 100644
> --- a/drivers/watchdog/s3c2410_wdt.c
> +++ b/drivers/watchdog/s3c2410_wdt.c
> @@ -34,6 +34,7 @@
> #define S3C2410_WTCLRINT 0x0c
>
> #define S3C2410_WTCNT_MAXCNT 0xffff
Suggest renaming this to S3C2410_WTCNT_MAXCNT_16, to emphasize the
fact this value is for 16-bit counters. And for consistency with the
below one.
> +#define S3C2410_WTCNT_MAXCNT_32 0xffffffff
>
> #define S3C2410_WTCON_RSTEN BIT(0)
> #define S3C2410_WTCON_INTEN BIT(2)
> @@ -123,6 +124,10 @@
> * %QUIRK_HAS_DBGACK_BIT: WTCON register has DBGACK_MASK bit. Setting the
> * DBGACK_MASK bit disables the watchdog outputs when the SoC is in debug mode.
> * Debug mode is determined by the DBGACK CPU signal.
> + *
> + * %QUIRK_HAS_32BIT_MAXCNT: WTDAT and WTCNT are 32-bit registers. With these
Why not name it like QUIRK_HAS_32BIT_CNT or QUIRK_HAS_32BIT_COUNTER?
As I understand, the quirk means that the chip has 32-bit counter, so
MAX bit is not really needed?
> + * 32-bit registers, larger values to be set, which means that larger timeouts
Spelling: "to be set" -> "will be set" (or "have to be set").
> + * value can be set.
> */
> #define QUIRK_HAS_WTCLRINT_REG BIT(0)
> #define QUIRK_HAS_PMU_MASK_RESET BIT(1)
> @@ -130,6 +135,7 @@
> #define QUIRK_HAS_PMU_AUTO_DISABLE BIT(3)
> #define QUIRK_HAS_PMU_CNT_EN BIT(4)
> #define QUIRK_HAS_DBGACK_BIT BIT(5)
> +#define QUIRK_HAS_32BIT_MAXCNT BIT(6)
>
> /* These quirks require that we have a PMU register map */
> #define QUIRKS_HAVE_PMUREG \
> @@ -198,6 +204,7 @@ struct s3c2410_wdt {
> struct notifier_block freq_transition;
> const struct s3c2410_wdt_variant *drv_data;
> struct regmap *pmureg;
> + unsigned int max_cnt;
Maybe make it u32? It definitely refers to a 32-bit register value, so
will be more explicit that way. Not a strong opinion though.
> };
>
> static const struct s3c2410_wdt_variant drv_data_s3c2410 = {
> @@ -349,7 +356,7 @@ static const struct s3c2410_wdt_variant drv_data_exynosautov920_cl0 = {
> .cnt_en_bit = 8,
> .quirks = QUIRK_HAS_WTCLRINT_REG | QUIRK_HAS_PMU_MASK_RESET |
> QUIRK_HAS_PMU_RST_STAT | QUIRK_HAS_PMU_CNT_EN |
> - QUIRK_HAS_DBGACK_BIT,
> + QUIRK_HAS_DBGACK_BIT | QUIRK_HAS_32BIT_MAXCNT,
> };
>
> static const struct s3c2410_wdt_variant drv_data_exynosautov920_cl1 = {
> @@ -362,7 +369,7 @@ static const struct s3c2410_wdt_variant drv_data_exynosautov920_cl1 = {
> .cnt_en_bit = 8,
> .quirks = QUIRK_HAS_WTCLRINT_REG | QUIRK_HAS_PMU_MASK_RESET |
> QUIRK_HAS_PMU_RST_STAT | QUIRK_HAS_PMU_CNT_EN |
> - QUIRK_HAS_DBGACK_BIT,
> + QUIRK_HAS_DBGACK_BIT | QUIRK_HAS_32BIT_MAXCNT,
Yeah, I think it would be easier to review and handle further if this
exynosautov920 enablement is extracted into a separate patch.
> };
>
> static const struct of_device_id s3c2410_wdt_match[] = {
> @@ -411,7 +418,7 @@ static inline unsigned int s3c2410wdt_max_timeout(struct s3c2410_wdt *wdt)
> {
> const unsigned long freq = s3c2410wdt_get_freq(wdt);
>
> - return S3C2410_WTCNT_MAXCNT / DIV_ROUND_UP(freq,
> + return wdt->max_cnt / DIV_ROUND_UP(freq,
> (S3C2410_WTCON_PRESCALE_MAX + 1) * S3C2410_WTCON_MAXDIV);
> }
>
> @@ -566,7 +573,7 @@ static int s3c2410wdt_set_heartbeat(struct watchdog_device *wdd,
> {
> struct s3c2410_wdt *wdt = watchdog_get_drvdata(wdd);
> unsigned long freq = s3c2410wdt_get_freq(wdt);
> - unsigned int count;
> + unsigned long count;
> unsigned int divisor = 1;
> unsigned long wtcon;
>
> @@ -576,7 +583,7 @@ static int s3c2410wdt_set_heartbeat(struct watchdog_device *wdd,
> freq = DIV_ROUND_UP(freq, 128);
> count = timeout * freq;
>
> - dev_dbg(wdt->dev, "Heartbeat: count=%d, timeout=%d, freq=%lu\n",
> + dev_dbg(wdt->dev, "Heartbeat: count=%lu, timeout=%d, freq=%lu\n",
> count, timeout, freq);
>
> /* if the count is bigger than the watchdog register,
> @@ -584,8 +591,8 @@ static int s3c2410wdt_set_heartbeat(struct watchdog_device *wdd,
> actually make this value
> */
>
> - if (count >= 0x10000) {
> - divisor = DIV_ROUND_UP(count, 0xffff);
> + if (count > wdt->max_cnt) {
wdt->max_cnt + 1?
> + divisor = DIV_ROUND_UP(count, wdt->max_cnt);
>
> if (divisor > S3C2410_WTCON_PRESCALE_MAX + 1) {
> dev_err(wdt->dev, "timeout %d too big\n", timeout);
> @@ -593,7 +600,7 @@ static int s3c2410wdt_set_heartbeat(struct watchdog_device *wdd,
> }
> }
>
> - dev_dbg(wdt->dev, "Heartbeat: timeout=%d, divisor=%d, count=%d (%08x)\n",
> + dev_dbg(wdt->dev, "Heartbeat: timeout=%d, divisor=%d, count=%lu (%08lx)\n",
> timeout, divisor, count, DIV_ROUND_UP(count, divisor));
>
> count = DIV_ROUND_UP(count, divisor);
> @@ -801,6 +808,10 @@ static int s3c2410wdt_probe(struct platform_device *pdev)
> if (IS_ERR(wdt->src_clk))
> return dev_err_probe(dev, PTR_ERR(wdt->src_clk), "failed to get source clock\n");
>
> + wdt->max_cnt = S3C2410_WTCNT_MAXCNT;
> + if ((wdt->drv_data->quirks & QUIRK_HAS_32BIT_MAXCNT))
Double braces don't seem to be needed.
> + wdt->max_cnt = S3C2410_WTCNT_MAXCNT_32;
> +
Style (minor nitpick): this block can be more explicit, i.e.:
if ((wdt->drv_data->quirks & QUIRK_HAS_32BIT_MAXCNT))
wdt->max_cnt = S3C2410_WTCNT_MAXCNT_32;
else
wdt->max_cnt = S3C2410_WTCNT_MAXCNT;
> wdt->wdt_device.min_timeout = 1;
> wdt->wdt_device.max_timeout = s3c2410wdt_max_timeout(wdt);
>
> --
> 2.25.1
>
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v4 4/4] watchdog: s3c2410_wdt: exynosautov9: Enable supported features
2025-07-24 8:08 ` [PATCH v4 4/4] watchdog: s3c2410_wdt: exynosautov9: Enable supported features Sangwook Shin
@ 2025-08-02 4:39 ` Sam Protsenko
0 siblings, 0 replies; 17+ messages in thread
From: Sam Protsenko @ 2025-08-02 4:39 UTC (permalink / raw)
To: Sangwook Shin
Cc: krzk, alim.akhtar, wim, linux, khwan.seo, dongil01.park,
linux-arm-kernel, linux-samsung-soc, linux-watchdog, linux-kernel
On Thu, Jul 24, 2025 at 3:13 AM Sangwook Shin <sw617.shin@samsung.com> wrote:
>
> Enable supported features for ExynosAutov9 SoC.
> - QUIRK_HAS_DBGACK_BIT
> - QUIRK_HAS_32BIT_MAXCNT
>
> Reviewed-by: Alim Akhtar <alim.akhtar@samsung.com>
> Signed-off-by: Sangwook Shin <sw617.shin@samsung.com>
> ---
Reviewed-by: Sam Protsenko <semen.protsenko@linaro.org>
> drivers/watchdog/s3c2410_wdt.c | 6 ++++--
> 1 file changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c
> index 184b1ad46ca6..16a845f41e74 100644
> --- a/drivers/watchdog/s3c2410_wdt.c
> +++ b/drivers/watchdog/s3c2410_wdt.c
> @@ -305,7 +305,8 @@ static const struct s3c2410_wdt_variant drv_data_exynosautov9_cl0 = {
> .cnt_en_reg = EXYNOS850_CLUSTER0_NONCPU_OUT,
> .cnt_en_bit = 7,
> .quirks = QUIRK_HAS_WTCLRINT_REG | QUIRK_HAS_PMU_MASK_RESET |
> - QUIRK_HAS_PMU_RST_STAT | QUIRK_HAS_PMU_CNT_EN,
> + QUIRK_HAS_PMU_RST_STAT | QUIRK_HAS_PMU_CNT_EN |
> + QUIRK_HAS_DBGACK_BIT | QUIRK_HAS_32BIT_MAXCNT,
> };
>
> static const struct s3c2410_wdt_variant drv_data_exynosautov9_cl1 = {
> @@ -317,7 +318,8 @@ static const struct s3c2410_wdt_variant drv_data_exynosautov9_cl1 = {
> .cnt_en_reg = EXYNOSAUTOV9_CLUSTER1_NONCPU_OUT,
> .cnt_en_bit = 7,
> .quirks = QUIRK_HAS_WTCLRINT_REG | QUIRK_HAS_PMU_MASK_RESET |
> - QUIRK_HAS_PMU_RST_STAT | QUIRK_HAS_PMU_CNT_EN,
> + QUIRK_HAS_PMU_RST_STAT | QUIRK_HAS_PMU_CNT_EN |
> + QUIRK_HAS_DBGACK_BIT | QUIRK_HAS_32BIT_MAXCNT,
> };
>
> static const struct s3c2410_wdt_variant drv_data_gs101_cl0 = {
> --
> 2.25.1
>
^ permalink raw reply [flat|nested] 17+ messages in thread
* RE: [PATCH v4 2/4] watchdog: s3c2410_wdt: Fix max_timeout being calculated larger
2025-08-02 4:11 ` Sam Protsenko
@ 2025-08-05 4:22 ` sw617.shin
2025-08-05 4:47 ` Guenter Roeck
0 siblings, 1 reply; 17+ messages in thread
From: sw617.shin @ 2025-08-05 4:22 UTC (permalink / raw)
To: 'Sam Protsenko'
Cc: krzk, alim.akhtar, wim, linux, khwan.seo, dongil01.park,
linux-arm-kernel, linux-samsung-soc, linux-watchdog, linux-kernel
On Saturday, August 2, 2025 at 1:12 PM Sam Protsenko <semen.protsenko@linaro.org> wrote:
> How about something like this instead?
>
> 8<--------------------------------------------------------------------->8
> static inline unsigned int s3c2410wdt_max_timeout(unsigned long freq) {
> const u64 div_max = (S3C2410_WTCON_PRESCALE_MAX + 1) *
> S3C2410_WTCON_MAXDIV; /* 32768 */
> const u64 n_max = S3C2410_WTCNT_MAXCNT * div_max;
> u64 t_max = n_max / freq;
>
> if (t_max > UINT_MAX)
> t_max = UINT_MAX;
>
> return (unsigned int)t_max;
> }
> 8<--------------------------------------------------------------------->8
>
> This implementation's result:
> - is never greater than real timeout, as it loses the decimal part after
> integer division in t_max
> - much closer to the real timeout value, as it benefits from very big
> n_max in the numerator (this is the main trick here)
> - prepared for using 32-bit max counter value in your next patch, as it
> uses u64 type for calculations
>
> For example, at the clock frequency of 33 kHz:
> - real timeout is: 65074.269 sec
> - old function returns: 65535 sec
> - your function returns: 32767 sec
> - the suggested function returns: 65074 sec
Thank you for your feedback.
I'll make the code changes as follows in the next patch set:
static inline unsigned int s3c2410wdt_max_timeout(struct s3c2410_wdt *wdt)
{
const unsigned long freq = s3c2410wdt_get_freq(wdt);
+ const u64 div_max = (S3C2410_WTCON_PRESCALE_MAX + 1) *
+ S3C2410_WTCON_MAXDIV;
+ const u64 n_max = S3C2410_WTCNT_MAXCNT * div_max;
+ u64 t_max = n_max / freq;
- return S3C2410_WTCNT_MAXCNT / (freq / (S3C2410_WTCON_PRESCALE_MAX + 1)
- / S3C2410_WTCON_MAXDIV);
+ if (t_max > UINT_MAX)
+ t_max = UINT_MAX;
+
+ return (unsigned int)t_max;
}
^ permalink raw reply [flat|nested] 17+ messages in thread
* RE: [PATCH v4 3/4] watchdog: s3c2410_wdt: Increase max timeout value of watchdog
2025-08-02 4:36 ` Sam Protsenko
@ 2025-08-05 4:23 ` sw617.shin
2025-08-05 4:51 ` Sam Protsenko
0 siblings, 1 reply; 17+ messages in thread
From: sw617.shin @ 2025-08-05 4:23 UTC (permalink / raw)
To: 'Sam Protsenko'
Cc: krzk, alim.akhtar, wim, linux, khwan.seo, dongil01.park,
linux-arm-kernel, linux-samsung-soc, linux-watchdog, linux-kernel
On Saturday, August 2, 2025 at 1:37 PM Sam Protsenko <semen.protsenko@linaro.org> wrote:
> Not a strong point, but I'd break this patch into two:
> 1. Add 32-bit counter feature (without enabling it in exynosautov920
> implementation)
> 2. Enable 32-bit counter feature in exynosautov920
>
I'll break this patch into two in the next patch set.
> > #define S3C2410_WTCNT_MAXCNT 0xffff
>
> Suggest renaming this to S3C2410_WTCNT_MAXCNT_16, to emphasize the fact
> this value is for 16-bit counters. And for consistency with the below one.
>
> > +#define S3C2410_WTCNT_MAXCNT_32 0xffffffff
> >
I'll rename this to S3C2410_WTCNT_MAXCNT_16 in the next patch set.
> > + * %QUIRK_HAS_32BIT_MAXCNT: WTDAT and WTCNT are 32-bit registers.
> > + With these
>
> Why not name it like QUIRK_HAS_32BIT_CNT or QUIRK_HAS_32BIT_COUNTER?
> As I understand, the quirk means that the chip has 32-bit counter, so MAX
> bit is not really needed?
>
> > + * 32-bit registers, larger values to be set, which means that larger
> > + timeouts
>
> Spelling: "to be set" -> "will be set" (or "have to be set").
I'll modify this in the next patch set.
> > + unsigned int max_cnt;
>
> Maybe make it u32? It definitely refers to a 32-bit register value, so
> will be more explicit that way. Not a strong opinion though.
>
I'll change this to u32 in the next patch set.
> > };
> >
> > static const struct s3c2410_wdt_variant drv_data_s3c2410 = {
> > @@ -349,7 +356,7 @@ static const struct s3c2410_wdt_variant
> drv_data_exynosautov920_cl0 = {
> > .cnt_en_bit = 8,
> > .quirks = QUIRK_HAS_WTCLRINT_REG | QUIRK_HAS_PMU_MASK_RESET |
> > QUIRK_HAS_PMU_RST_STAT | QUIRK_HAS_PMU_CNT_EN |
> > - QUIRK_HAS_DBGACK_BIT,
> > + QUIRK_HAS_DBGACK_BIT | QUIRK_HAS_32BIT_MAXCNT,
> > };
> >
> > static const struct s3c2410_wdt_variant drv_data_exynosautov920_cl1 = {
> > @@ -362,7 +369,7 @@ static const struct s3c2410_wdt_variant
> drv_data_exynosautov920_cl1 = {
> > .cnt_en_bit = 8,
> > .quirks = QUIRK_HAS_WTCLRINT_REG | QUIRK_HAS_PMU_MASK_RESET |
> > QUIRK_HAS_PMU_RST_STAT | QUIRK_HAS_PMU_CNT_EN |
> > - QUIRK_HAS_DBGACK_BIT,
> > + QUIRK_HAS_DBGACK_BIT | QUIRK_HAS_32BIT_MAXCNT,
>
> Yeah, I think it would be easier to review and handle further if this
> exynosautov920 enablement is extracted into a separate patch.
>
I'll break this patch into two in the next patch set.
> >
> > - if (count >= 0x10000) {
> > - divisor = DIV_ROUND_UP(count, 0xffff);
> > + if (count > wdt->max_cnt) {
>
> wdt->max_cnt + 1?
>
Yes, 0x10000 represented 'wdt->max_cnt + 1.'
Would you like to suggest any revisions?
> > + wdt->max_cnt = S3C2410_WTCNT_MAXCNT;
> > + if ((wdt->drv_data->quirks & QUIRK_HAS_32BIT_MAXCNT))
>
> Double braces don't seem to be needed.
>
> > + wdt->max_cnt = S3C2410_WTCNT_MAXCNT_32;
> > +
>
> Style (minor nitpick): this block can be more explicit, i.e.:
>
> if ((wdt->drv_data->quirks & QUIRK_HAS_32BIT_MAXCNT))
> wdt->max_cnt = S3C2410_WTCNT_MAXCNT_32;
> else
> wdt->max_cnt = S3C2410_WTCNT_MAXCNT;
>
I'll fix these in the next patch set.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v4 2/4] watchdog: s3c2410_wdt: Fix max_timeout being calculated larger
2025-08-05 4:22 ` sw617.shin
@ 2025-08-05 4:47 ` Guenter Roeck
2025-08-05 5:03 ` Sam Protsenko
0 siblings, 1 reply; 17+ messages in thread
From: Guenter Roeck @ 2025-08-05 4:47 UTC (permalink / raw)
To: sw617.shin, 'Sam Protsenko'
Cc: krzk, alim.akhtar, wim, khwan.seo, dongil01.park,
linux-arm-kernel, linux-samsung-soc, linux-watchdog, linux-kernel
On 8/4/25 21:22, sw617.shin@samsung.com wrote:
> On Saturday, August 2, 2025 at 1:12 PM Sam Protsenko <semen.protsenko@linaro.org> wrote:
>
>> How about something like this instead?
>>
>> 8<--------------------------------------------------------------------->8
>> static inline unsigned int s3c2410wdt_max_timeout(unsigned long freq) {
>> const u64 div_max = (S3C2410_WTCON_PRESCALE_MAX + 1) *
>> S3C2410_WTCON_MAXDIV; /* 32768 */
>> const u64 n_max = S3C2410_WTCNT_MAXCNT * div_max;
>> u64 t_max = n_max / freq;
>>
>> if (t_max > UINT_MAX)
>> t_max = UINT_MAX;
>>
>> return (unsigned int)t_max;
>> }
>> 8<--------------------------------------------------------------------->8
>>
>> This implementation's result:
>> - is never greater than real timeout, as it loses the decimal part after
>> integer division in t_max
>> - much closer to the real timeout value, as it benefits from very big
>> n_max in the numerator (this is the main trick here)
>> - prepared for using 32-bit max counter value in your next patch, as it
>> uses u64 type for calculations
>>
>> For example, at the clock frequency of 33 kHz:
>> - real timeout is: 65074.269 sec
>> - old function returns: 65535 sec
>> - your function returns: 32767 sec
>> - the suggested function returns: 65074 sec
>
> Thank you for your feedback.
> I'll make the code changes as follows in the next patch set:
>
> static inline unsigned int s3c2410wdt_max_timeout(struct s3c2410_wdt *wdt)
> {
> const unsigned long freq = s3c2410wdt_get_freq(wdt);
> + const u64 div_max = (S3C2410_WTCON_PRESCALE_MAX + 1) *
> + S3C2410_WTCON_MAXDIV;
> + const u64 n_max = S3C2410_WTCNT_MAXCNT * div_max;
Not sure if splitting this expression adds any value. Why not just the following ?
const u64 n_max = (u64)(S3C2410_WTCON_PRESCALE_MAX + 1) *
S3C2410_WTCON_MAXDIV * S3C2410_WTCNT_MAXCNT;
Or just use a define ?
> + u64 t_max = n_max / freq;
>
Make sure this compiles on 32-bit builds.
> - return S3C2410_WTCNT_MAXCNT / (freq / (S3C2410_WTCON_PRESCALE_MAX + 1)
> - / S3C2410_WTCON_MAXDIV);
> + if (t_max > UINT_MAX)
> + t_max = UINT_MAX;
> +
> + return (unsigned int)t_max;
I am quite sure that this typecast is unnecessary.
Guenter
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v4 3/4] watchdog: s3c2410_wdt: Increase max timeout value of watchdog
2025-08-05 4:23 ` sw617.shin
@ 2025-08-05 4:51 ` Sam Protsenko
0 siblings, 0 replies; 17+ messages in thread
From: Sam Protsenko @ 2025-08-05 4:51 UTC (permalink / raw)
To: sw617.shin
Cc: krzk, alim.akhtar, wim, linux, khwan.seo, dongil01.park,
linux-arm-kernel, linux-samsung-soc, linux-watchdog, linux-kernel
On Mon, Aug 4, 2025 at 11:23 PM <sw617.shin@samsung.com> wrote:
>
> On Saturday, August 2, 2025 at 1:37 PM Sam Protsenko <semen.protsenko@linaro.org> wrote:
> > Not a strong point, but I'd break this patch into two:
> > 1. Add 32-bit counter feature (without enabling it in exynosautov920
> > implementation)
> > 2. Enable 32-bit counter feature in exynosautov920
> >
>
> I'll break this patch into two in the next patch set.
>
> > > #define S3C2410_WTCNT_MAXCNT 0xffff
> >
> > Suggest renaming this to S3C2410_WTCNT_MAXCNT_16, to emphasize the fact
> > this value is for 16-bit counters. And for consistency with the below one.
> >
> > > +#define S3C2410_WTCNT_MAXCNT_32 0xffffffff
> > >
>
> I'll rename this to S3C2410_WTCNT_MAXCNT_16 in the next patch set.
>
> > > + * %QUIRK_HAS_32BIT_MAXCNT: WTDAT and WTCNT are 32-bit registers.
> > > + With these
> >
> > Why not name it like QUIRK_HAS_32BIT_CNT or QUIRK_HAS_32BIT_COUNTER?
> > As I understand, the quirk means that the chip has 32-bit counter, so MAX
> > bit is not really needed?
> >
> > > + * 32-bit registers, larger values to be set, which means that larger
> > > + timeouts
> >
> > Spelling: "to be set" -> "will be set" (or "have to be set").
>
> I'll modify this in the next patch set.
>
> > > + unsigned int max_cnt;
> >
> > Maybe make it u32? It definitely refers to a 32-bit register value, so
> > will be more explicit that way. Not a strong opinion though.
> >
>
> I'll change this to u32 in the next patch set.
>
> > > };
> > >
> > > static const struct s3c2410_wdt_variant drv_data_s3c2410 = {
> > > @@ -349,7 +356,7 @@ static const struct s3c2410_wdt_variant
> > drv_data_exynosautov920_cl0 = {
> > > .cnt_en_bit = 8,
> > > .quirks = QUIRK_HAS_WTCLRINT_REG | QUIRK_HAS_PMU_MASK_RESET |
> > > QUIRK_HAS_PMU_RST_STAT | QUIRK_HAS_PMU_CNT_EN |
> > > - QUIRK_HAS_DBGACK_BIT,
> > > + QUIRK_HAS_DBGACK_BIT | QUIRK_HAS_32BIT_MAXCNT,
> > > };
> > >
> > > static const struct s3c2410_wdt_variant drv_data_exynosautov920_cl1 = {
> > > @@ -362,7 +369,7 @@ static const struct s3c2410_wdt_variant
> > drv_data_exynosautov920_cl1 = {
> > > .cnt_en_bit = 8,
> > > .quirks = QUIRK_HAS_WTCLRINT_REG | QUIRK_HAS_PMU_MASK_RESET |
> > > QUIRK_HAS_PMU_RST_STAT | QUIRK_HAS_PMU_CNT_EN |
> > > - QUIRK_HAS_DBGACK_BIT,
> > > + QUIRK_HAS_DBGACK_BIT | QUIRK_HAS_32BIT_MAXCNT,
> >
> > Yeah, I think it would be easier to review and handle further if this
> > exynosautov920 enablement is extracted into a separate patch.
> >
>
> I'll break this patch into two in the next patch set.
>
> > >
> > > - if (count >= 0x10000) {
> > > - divisor = DIV_ROUND_UP(count, 0xffff);
> > > + if (count > wdt->max_cnt) {
> >
> > wdt->max_cnt + 1?
> >
>
> Yes, 0x10000 represented 'wdt->max_cnt + 1.'
> Would you like to suggest any revisions?
>
Ah, sorry, I didn't notice you also changed >= to just >. All well and
good, no change is needed here!
> > > + wdt->max_cnt = S3C2410_WTCNT_MAXCNT;
> > > + if ((wdt->drv_data->quirks & QUIRK_HAS_32BIT_MAXCNT))
> >
> > Double braces don't seem to be needed.
> >
> > > + wdt->max_cnt = S3C2410_WTCNT_MAXCNT_32;
> > > +
> >
> > Style (minor nitpick): this block can be more explicit, i.e.:
> >
> > if ((wdt->drv_data->quirks & QUIRK_HAS_32BIT_MAXCNT))
> > wdt->max_cnt = S3C2410_WTCNT_MAXCNT_32;
> > else
> > wdt->max_cnt = S3C2410_WTCNT_MAXCNT;
> >
>
> I'll fix these in the next patch set.
>
>
>
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v4 2/4] watchdog: s3c2410_wdt: Fix max_timeout being calculated larger
2025-08-05 4:47 ` Guenter Roeck
@ 2025-08-05 5:03 ` Sam Protsenko
2025-08-05 7:26 ` sw617.shin
0 siblings, 1 reply; 17+ messages in thread
From: Sam Protsenko @ 2025-08-05 5:03 UTC (permalink / raw)
To: Guenter Roeck
Cc: sw617.shin, krzk, alim.akhtar, wim, khwan.seo, dongil01.park,
linux-arm-kernel, linux-samsung-soc, linux-watchdog, linux-kernel
On Mon, Aug 4, 2025 at 11:47 PM Guenter Roeck <linux@roeck-us.net> wrote:
>
> On 8/4/25 21:22, sw617.shin@samsung.com wrote:
> > On Saturday, August 2, 2025 at 1:12 PM Sam Protsenko <semen.protsenko@linaro.org> wrote:
> >
> >> How about something like this instead?
> >>
> >> 8<--------------------------------------------------------------------->8
> >> static inline unsigned int s3c2410wdt_max_timeout(unsigned long freq) {
> >> const u64 div_max = (S3C2410_WTCON_PRESCALE_MAX + 1) *
> >> S3C2410_WTCON_MAXDIV; /* 32768 */
> >> const u64 n_max = S3C2410_WTCNT_MAXCNT * div_max;
> >> u64 t_max = n_max / freq;
> >>
> >> if (t_max > UINT_MAX)
> >> t_max = UINT_MAX;
> >>
> >> return (unsigned int)t_max;
> >> }
> >> 8<--------------------------------------------------------------------->8
> >>
> >> This implementation's result:
> >> - is never greater than real timeout, as it loses the decimal part after
> >> integer division in t_max
> >> - much closer to the real timeout value, as it benefits from very big
> >> n_max in the numerator (this is the main trick here)
> >> - prepared for using 32-bit max counter value in your next patch, as it
> >> uses u64 type for calculations
> >>
> >> For example, at the clock frequency of 33 kHz:
> >> - real timeout is: 65074.269 sec
> >> - old function returns: 65535 sec
> >> - your function returns: 32767 sec
> >> - the suggested function returns: 65074 sec
> >
> > Thank you for your feedback.
> > I'll make the code changes as follows in the next patch set:
> >
> > static inline unsigned int s3c2410wdt_max_timeout(struct s3c2410_wdt *wdt)
> > {
> > const unsigned long freq = s3c2410wdt_get_freq(wdt);
> > + const u64 div_max = (S3C2410_WTCON_PRESCALE_MAX + 1) *
> > + S3C2410_WTCON_MAXDIV;
> > + const u64 n_max = S3C2410_WTCNT_MAXCNT * div_max;
>
> Not sure if splitting this expression adds any value. Why not just the following ?
>
> const u64 n_max = (u64)(S3C2410_WTCON_PRESCALE_MAX + 1) *
> S3C2410_WTCON_MAXDIV * S3C2410_WTCNT_MAXCNT;
>
> Or just use a define ?
>
Oh, that code snippet above is just a suggestion, please treat it as
pseudo-code for this purpose, -- I just wanted to illustrate the idea,
and should've been more clear! Yes, definitely should be revised and
re-tested. And yeah, I agree, one single const or define would be
enough, no need to make it too verbose. Also, the naming may be not
the best, e.g. cnt_max might be better than n_max for example. But
I'll leave it to Sangwook Shin to decide on the implementation, just
wanted to communicate the idea.
> > + u64 t_max = n_max / freq;
> >
>
> Make sure this compiles on 32-bit builds.
>
Can you please elaborate what might be the possible problem -- just
curious? I admit I never though about 32-bit case when writing that
code, but don't see any immediate issues with that too.
> > - return S3C2410_WTCNT_MAXCNT / (freq / (S3C2410_WTCON_PRESCALE_MAX + 1)
> > - / S3C2410_WTCON_MAXDIV);
> > + if (t_max > UINT_MAX)
> > + t_max = UINT_MAX;
> > +
> > + return (unsigned int)t_max;
>
> I am quite sure that this typecast is unnecessary.
>
> Guenter
>
^ permalink raw reply [flat|nested] 17+ messages in thread
* RE: [PATCH v4 2/4] watchdog: s3c2410_wdt: Fix max_timeout being calculated larger
2025-08-05 5:03 ` Sam Protsenko
@ 2025-08-05 7:26 ` sw617.shin
2025-08-05 13:30 ` Guenter Roeck
2025-08-05 22:53 ` Sam Protsenko
0 siblings, 2 replies; 17+ messages in thread
From: sw617.shin @ 2025-08-05 7:26 UTC (permalink / raw)
To: 'Sam Protsenko', 'Guenter Roeck'
Cc: krzk, alim.akhtar, wim, khwan.seo, dongil01.park,
linux-arm-kernel, linux-samsung-soc, linux-watchdog, linux-kernel
On Tuesday, August 5, 2025 at 2:03 PM Sam Protsenko <semen.protsenko@linaro.org> wrote:
>
> > > + u64 t_max = n_max / freq;
> > >
> >
> > Make sure this compiles on 32-bit builds.
> >
>
> Can you please elaborate what might be the possible problem -- just
> curious? I admit I never though about 32-bit case when writing that code,
> but don't see any immediate issues with that too.
>
In my opinion, it seems that Gunter Reck's explanation is correct.
I've found out that the error of "undefined reference to '__aeabi_uldivmod'" may occur when compiling new code on a 32-bit architecture.
If you don't mind, I would like to proceed with maintaining the previous revision below.
From my perspective, this approach appears to be the most reasonable solution for supporting both 32-bit and 64-bit architectures.
@@ -411,8 +411,8 @@ static inline unsigned int s3c2410wdt_max_timeout(struct s3c2410_wdt *wdt)
{
const unsigned long freq = s3c2410wdt_get_freq(wdt);
- return S3C2410_WTCNT_MAXCNT / (freq / (S3C2410_WTCON_PRESCALE_MAX + 1)
- / S3C2410_WTCON_MAXDIV);
+ return S3C2410_WTCNT_MAXCNT / DIV_ROUND_UP(freq,
+ (S3C2410_WTCON_PRESCALE_MAX + 1) * S3C2410_WTCON_MAXDIV);
}
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v4 2/4] watchdog: s3c2410_wdt: Fix max_timeout being calculated larger
2025-08-05 7:26 ` sw617.shin
@ 2025-08-05 13:30 ` Guenter Roeck
2025-08-05 22:53 ` Sam Protsenko
1 sibling, 0 replies; 17+ messages in thread
From: Guenter Roeck @ 2025-08-05 13:30 UTC (permalink / raw)
To: sw617.shin, 'Sam Protsenko'
Cc: krzk, alim.akhtar, wim, khwan.seo, dongil01.park,
linux-arm-kernel, linux-samsung-soc, linux-watchdog, linux-kernel
On 8/5/25 00:26, sw617.shin@samsung.com wrote:
> On Tuesday, August 5, 2025 at 2:03 PM Sam Protsenko <semen.protsenko@linaro.org> wrote:
>
>>
>>>> + u64 t_max = n_max / freq;
>>>>
>>>
>>> Make sure this compiles on 32-bit builds.
>>>
>>
>> Can you please elaborate what might be the possible problem -- just
>> curious? I admit I never though about 32-bit case when writing that code,
>> but don't see any immediate issues with that too.
>>
>
> In my opinion, it seems that Gunter Reck's explanation is correct.
> I've found out that the error of "undefined reference to '__aeabi_uldivmod'" may occur when compiling new code on a 32-bit architecture.
Also see include/linux/math64.h. The functions implemented or declared
in that include file do have a reason to exist.
Guenter
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v4 2/4] watchdog: s3c2410_wdt: Fix max_timeout being calculated larger
2025-08-05 7:26 ` sw617.shin
2025-08-05 13:30 ` Guenter Roeck
@ 2025-08-05 22:53 ` Sam Protsenko
2025-08-06 4:51 ` sw617.shin
1 sibling, 1 reply; 17+ messages in thread
From: Sam Protsenko @ 2025-08-05 22:53 UTC (permalink / raw)
To: sw617.shin
Cc: Guenter Roeck, krzk, alim.akhtar, wim, khwan.seo, dongil01.park,
linux-arm-kernel, linux-samsung-soc, linux-watchdog, linux-kernel
On Tue, Aug 5, 2025 at 2:26 AM <sw617.shin@samsung.com> wrote:
>
> On Tuesday, August 5, 2025 at 2:03 PM Sam Protsenko <semen.protsenko@linaro.org> wrote:
>
> >
> > > > + u64 t_max = n_max / freq;
> > > >
> > >
> > > Make sure this compiles on 32-bit builds.
> > >
> >
> > Can you please elaborate what might be the possible problem -- just
> > curious? I admit I never though about 32-bit case when writing that code,
> > but don't see any immediate issues with that too.
> >
>
> In my opinion, it seems that Gunter Reck's explanation is correct.
> I've found out that the error of "undefined reference to '__aeabi_uldivmod'" may occur when compiling new code on a 32-bit architecture.
Indeed. I was able to reproduce that behavior when building for ARM32 too.
> If you don't mind, I would like to proceed with maintaining the previous revision below.
> From my perspective, this approach appears to be the most reasonable solution for supporting both 32-bit and 64-bit architectures.
>
> @@ -411,8 +411,8 @@ static inline unsigned int s3c2410wdt_max_timeout(struct s3c2410_wdt *wdt)
> {
> const unsigned long freq = s3c2410wdt_get_freq(wdt);
>
> - return S3C2410_WTCNT_MAXCNT / (freq / (S3C2410_WTCON_PRESCALE_MAX + 1)
> - / S3C2410_WTCON_MAXDIV);
> + return S3C2410_WTCNT_MAXCNT / DIV_ROUND_UP(freq,
> + (S3C2410_WTCON_PRESCALE_MAX + 1) * S3C2410_WTCON_MAXDIV);
> }
>
I don't mind, although it's quite easy to fix the code I suggested by
replacing this line:
u64 t_max = n_max / freq;
with this one:
u64 t_max = div64_ul(n_max, freq);
from <math64.h>, as Guenter suggested. But I'm totally fine with your
implementation as well.
^ permalink raw reply [flat|nested] 17+ messages in thread
* RE: [PATCH v4 2/4] watchdog: s3c2410_wdt: Fix max_timeout being calculated larger
2025-08-05 22:53 ` Sam Protsenko
@ 2025-08-06 4:51 ` sw617.shin
0 siblings, 0 replies; 17+ messages in thread
From: sw617.shin @ 2025-08-06 4:51 UTC (permalink / raw)
To: 'Sam Protsenko'
Cc: 'Guenter Roeck', krzk, alim.akhtar, wim, khwan.seo,
dongil01.park, linux-arm-kernel, linux-samsung-soc,
linux-watchdog, linux-kernel
On Wednesday, August 6, 2025 at 7:53 AM Sam Protsenko <semen.protsenko@linaro.org> wrote:
>
> I don't mind, although it's quite easy to fix the code I suggested by
> replacing this line:
>
> u64 t_max = n_max / freq;
>
> with this one:
>
> u64 t_max = div64_ul(n_max, freq);
>
> from <math64.h>, as Guenter suggested. But I'm totally fine with your
> implementation as well.
Sam Protsenko and Guenter Roeck, thank you for your kind advice.
As you mentioned, I will proceed with the following code for the next patch set.
@@ -27,6 +27,7 @@
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
#include <linux/delay.h>
+#include <linux/math64.h>
#define S3C2410_WTCON 0x00
#define S3C2410_WTDAT 0x04
@@ -410,9 +411,13 @@ static inline unsigned long s3c2410wdt_get_freq(struct s3c2410_wdt *wdt)
static inline unsigned int s3c2410wdt_max_timeout(struct s3c2410_wdt *wdt)
{
const unsigned long freq = s3c2410wdt_get_freq(wdt);
+ //(S3C2410_WTCON_PRESCALE_MAX + 1) * S3C2410_WTCON_MAXDIV = 0x8000
+ u64 t_max = div64_ul((u64)S3C2410_WTCNT_MAXCNT * 0x8000, freq);
- return S3C2410_WTCNT_MAXCNT / (freq / (S3C2410_WTCON_PRESCALE_MAX + 1)
- / S3C2410_WTCON_MAXDIV);
+ if (t_max > UINT_MAX)
+ t_max = UINT_MAX;
+
+ return t_max;
}
^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2025-08-06 4:54 UTC | newest]
Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <CGME20250724081336epcas2p30ba9afd1e78d9bbb60f44d24d1cf0acb@epcas2p3.samsung.com>
2025-07-24 8:08 ` [PATCH v4 0/4] Increase max timeout value of s3c2410 watchdog Sangwook Shin
[not found] ` <CGME20250724081336epcas2p31c2e3cbed1d3a7bf30a9fb664e6cb92b@epcas2p3.samsung.com>
2025-07-24 8:08 ` [PATCH v4 1/4] watchdog: s3c2410_wdt: Replace hardcoded values with macro definitions Sangwook Shin
[not found] ` <CGME20250724081336epcas2p38e95932ddc5c702e05a6436f05582993@epcas2p3.samsung.com>
2025-07-24 8:08 ` [PATCH v4 2/4] watchdog: s3c2410_wdt: Fix max_timeout being calculated larger Sangwook Shin
2025-08-02 4:11 ` Sam Protsenko
2025-08-05 4:22 ` sw617.shin
2025-08-05 4:47 ` Guenter Roeck
2025-08-05 5:03 ` Sam Protsenko
2025-08-05 7:26 ` sw617.shin
2025-08-05 13:30 ` Guenter Roeck
2025-08-05 22:53 ` Sam Protsenko
2025-08-06 4:51 ` sw617.shin
[not found] ` <CGME20250724081337epcas2p31f594b6e9ab87e24c94f11dea4070956@epcas2p3.samsung.com>
2025-07-24 8:08 ` [PATCH v4 3/4] watchdog: s3c2410_wdt: Increase max timeout value of watchdog Sangwook Shin
2025-08-02 4:36 ` Sam Protsenko
2025-08-05 4:23 ` sw617.shin
2025-08-05 4:51 ` Sam Protsenko
[not found] ` <CGME20250724081337epcas2p430db7d7514b8cc05e41001f17b8b0d45@epcas2p4.samsung.com>
2025-07-24 8:08 ` [PATCH v4 4/4] watchdog: s3c2410_wdt: exynosautov9: Enable supported features Sangwook Shin
2025-08-02 4:39 ` Sam Protsenko
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).