#define S3C2410_WTCNT 0x08
#define S3C2410_WTCLRINT 0x0c
-#define S3C2410_WTCNT_MAXCNT 0xffff
+#define S3C2410_WTCNT_MAXCNT_16 0xffff
+#define S3C2410_WTCNT_MAXCNT_32 0xffffffff
#define S3C2410_WTCON_RSTEN BIT(0)
#define S3C2410_WTCON_INTEN BIT(2)
* %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_CNT: WTDAT and WTCNT are 32-bit registers. With these
+ * 32-bit registers, larger values will 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)
#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_CNT BIT(6)
/* These quirks require that we have a PMU register map */
#define QUIRKS_HAVE_PMUREG \
struct notifier_block freq_transition;
const struct s3c2410_wdt_variant *drv_data;
struct regmap *pmureg;
+ u32 max_cnt;
};
static const struct s3c2410_wdt_variant drv_data_s3c2410 = {
{
const unsigned long freq = s3c2410wdt_get_freq(wdt);
const u64 n_max = (u64)(S3C2410_WTCON_PRESCALE_MAX + 1) *
- S3C2410_WTCON_MAXDIV * S3C2410_WTCNT_MAXCNT;
+ S3C2410_WTCON_MAXDIV * wdt->max_cnt;
u64 t_max = div64_ul(n_max, freq);
if (t_max > UINT_MAX)
{
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;
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,
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);
}
}
- 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);
if (IS_ERR(wdt->src_clk))
return dev_err_probe(dev, PTR_ERR(wdt->src_clk), "failed to get source clock\n");
+ if (wdt->drv_data->quirks & QUIRK_HAS_32BIT_CNT)
+ wdt->max_cnt = S3C2410_WTCNT_MAXCNT_32;
+ else
+ wdt->max_cnt = S3C2410_WTCNT_MAXCNT_16;
+
wdt->wdt_device.min_timeout = 1;
wdt->wdt_device.max_timeout = s3c2410wdt_max_timeout(wdt);