Re: [PATCH] rtc: abx80x: add basic watchdog support

2018-09-10 Thread kbuild test robot
Hi Jeremy,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on abelloni/rtc-next]
[also build test ERROR on v4.19-rc2 next-20180906]
[if your patch is applied to the wrong git tree, please drop us a note to help 
improve the system]

url:
https://github.com/0day-ci/linux/commits/Jeremy-Gebben/rtc-abx80x-add-basic-watchdog-support/20180910-163501
base:   https://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux.git 
rtc-next
config: i386-randconfig-s3-09101230 (attached as .config)
compiler: gcc-6 (Debian 6.4.0-9) 6.4.0 20171026
reproduce:
# save the attached .config to linux build tree
make ARCH=i386 

All errors (new ones prefixed by >>):

>> ERROR: "watchdog_init_timeout" [drivers/rtc/rtc-abx80x.ko] undefined!
>> ERROR: "devm_watchdog_register_device" [drivers/rtc/rtc-abx80x.ko] undefined!

---
0-DAY kernel test infrastructureOpen Source Technology Center
https://lists.01.org/pipermail/kbuild-all   Intel Corporation


.config.gz
Description: application/gzip


Re: [PATCH] rtc: abx80x: add basic watchdog support

2018-09-10 Thread kbuild test robot
Hi Jeremy,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on abelloni/rtc-next]
[also build test ERROR on v4.19-rc2 next-20180906]
[if your patch is applied to the wrong git tree, please drop us a note to help 
improve the system]

url:
https://github.com/0day-ci/linux/commits/Jeremy-Gebben/rtc-abx80x-add-basic-watchdog-support/20180910-163501
base:   https://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux.git 
rtc-next
config: i386-randconfig-s3-09101230 (attached as .config)
compiler: gcc-6 (Debian 6.4.0-9) 6.4.0 20171026
reproduce:
# save the attached .config to linux build tree
make ARCH=i386 

All errors (new ones prefixed by >>):

>> ERROR: "watchdog_init_timeout" [drivers/rtc/rtc-abx80x.ko] undefined!
>> ERROR: "devm_watchdog_register_device" [drivers/rtc/rtc-abx80x.ko] undefined!

---
0-DAY kernel test infrastructureOpen Source Technology Center
https://lists.01.org/pipermail/kbuild-all   Intel Corporation


.config.gz
Description: application/gzip


Re: [PATCH] rtc: abx80x: add basic watchdog support

2018-09-08 Thread Alexandre Belloni
Hi,

Please Cc the watchdog maintainers. Else, I have very few comments.

On 07/09/2018 09:17:43-0600, Jeremy Gebben wrote:
> The abx804 and abx805 chips have support for a simple watchdog
> function that can trigger an external reset.
> 
> Signed-off-by: Jeremy Gebben 
> ---
>  drivers/rtc/Kconfig  |  11 +++
>  drivers/rtc/rtc-abx80x.c | 160 ---
>  2 files changed, 159 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
> index 7d7be60a2413..4771e3a89721 100644
> --- a/drivers/rtc/Kconfig
> +++ b/drivers/rtc/Kconfig
> @@ -195,6 +195,17 @@ config RTC_DRV_ABX80X
> This driver can also be built as a module. If so, the module
> will be called rtc-abx80x.
>  
> +config RTC_DRV_ABX80X_WDT
> + bool "Abracon ABx80x Watchdog"
> + default y
> + depends on RTC_DRV_ABX80X
> + help
> +   If you say yes here you get watchdog support for Abracon ABX804 and 
> ABX805
> +   clock chips. This watchdog supports timeouts up to 31 seconds with 1 
> second
> +   granularity.
> +
> +  This watchdog device is part of the rtc-abx80x module.
> +

I'm not sure it is worth having a separate config option for that. You
may as well just always include the watchdog support code. However,
doesn't it need to depend on CONFIG_WATCHDOG?

>  config RTC_DRV_AC100
>   tristate "X-Powers AC100"
>   depends on MFD_AC100
> diff --git a/drivers/rtc/rtc-abx80x.c b/drivers/rtc/rtc-abx80x.c
> index 2cefa67a1132..fa558939e944 100644
> --- a/drivers/rtc/rtc-abx80x.c
> +++ b/drivers/rtc/rtc-abx80x.c
> @@ -17,6 +17,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  
>  #define ABX8XX_REG_HTH   0x00
>  #define ABX8XX_REG_SC0x01
> @@ -37,6 +38,7 @@
>  
>  #define ABX8XX_REG_STATUS0x0f
>  #define ABX8XX_STATUS_AF BIT(2)
> +#define ABX8XX_STATUS_WDTBIT(6)
>  
>  #define ABX8XX_REG_CTRL1 0x10
>  #define ABX8XX_CTRL_WRITEBIT(0)
> @@ -61,6 +63,14 @@
>  #define ABX8XX_OSS_OFBIT(1)
>  #define ABX8XX_OSS_OMODE BIT(4)
>  
> +#define ABX8XX_REG_WDT   0x1b
> +#define ABX8XX_WDT_WDS   BIT(7)
> +#define ABX8XX_WDT_BMB_MASK  0x7c
> +#define ABX8XX_WDT_BMB_SHIFT 2
> +#define ABX8XX_WDT_MAX_TIME  (ABX8XX_WDT_BMB_MASK >> ABX8XX_WDT_BMB_SHIFT)
> +#define ABX8XX_WDT_WRB_MASK  0x03
> +#define ABX8XX_WDT_WRB_1HZ   0x02
> +
>  #define ABX8XX_REG_CFG_KEY   0x1f
>  #define ABX8XX_CFG_KEY_OSC   0xa1
>  #define ABX8XX_CFG_KEY_MISC  0x9d
> @@ -80,20 +90,27 @@ enum abx80x_chip {AB0801, AB0803, AB0804, AB0805,
>  struct abx80x_cap {
>   u16 pn;
>   bool has_tc;
> + bool has_wdog;
>  };
>  
>  static struct abx80x_cap abx80x_caps[] = {
>   [AB0801] = {.pn = 0x0801},
>   [AB0803] = {.pn = 0x0803},
> - [AB0804] = {.pn = 0x0804, .has_tc = true},
> - [AB0805] = {.pn = 0x0805, .has_tc = true},
> + [AB0804] = {.pn = 0x0804, .has_tc = true, .has_wdog = true},
> + [AB0805] = {.pn = 0x0805, .has_tc = true, .has_wdog = true},
>   [AB1801] = {.pn = 0x1801},
>   [AB1803] = {.pn = 0x1803},
> - [AB1804] = {.pn = 0x1804, .has_tc = true},
> - [AB1805] = {.pn = 0x1805, .has_tc = true},
> + [AB1804] = {.pn = 0x1804, .has_tc = true, .has_wdog = true},
> + [AB1805] = {.pn = 0x1805, .has_tc = true, .has_wdog = true},
>   [ABX80X] = {.pn = 0}
>  };
>  
> +struct abx80x_priv {
> + struct rtc_device *rtc;
> + struct i2c_client *client;
> + struct watchdog_device wdog;
> +};
> +

To make the watchdog part easier to review, you could separate the
introduction of abx80x_priv in a preliminary patch and then introduce
the watchdog code.

>  static int abx80x_is_rc_mode(struct i2c_client *client)
>  {
>   int flags = 0;
> @@ -218,7 +235,8 @@ static int abx80x_rtc_set_time(struct device *dev, struct 
> rtc_time *tm)
>  static irqreturn_t abx80x_handle_irq(int irq, void *dev_id)
>  {
>   struct i2c_client *client = dev_id;
> - struct rtc_device *rtc = i2c_get_clientdata(client);
> + struct abx80x_priv *priv = i2c_get_clientdata(client);
> + struct rtc_device *rtc = priv->rtc;
>   int status;
>  
>   status = i2c_smbus_read_byte_data(client, ABX8XX_REG_STATUS);
> @@ -228,6 +246,13 @@ static irqreturn_t abx80x_handle_irq(int irq, void 
> *dev_id)
>   if (status & ABX8XX_STATUS_AF)
>   rtc_update_irq(rtc, 1, RTC_AF | RTC_IRQF);
>  
> + /*
> +  * It is unclear if we'll get an interrupt before the external
> +  * reset kicks in.
> +  */
> + if (status & ABX8XX_STATUS_WDT)
> + dev_err(>dev, "watchdog timeout interrupt!\n");
> +

dev_alert maybe?

>   i2c_smbus_write_byte_data(client, ABX8XX_REG_STATUS, 0);
>  
>   return IRQ_HANDLED;
> @@ -529,11 +554,110 @@ static void rtc_calib_remove_sysfs_group(void *_dev)
>   sysfs_remove_group(>kobj, _calib_attr_group);
>  }
>  
> +#ifdef CONFIG_RTC_DRV_ABX80X_WDT
> +
> +static inline 

Re: [PATCH] rtc: abx80x: add basic watchdog support

2018-09-08 Thread Alexandre Belloni
Hi,

Please Cc the watchdog maintainers. Else, I have very few comments.

On 07/09/2018 09:17:43-0600, Jeremy Gebben wrote:
> The abx804 and abx805 chips have support for a simple watchdog
> function that can trigger an external reset.
> 
> Signed-off-by: Jeremy Gebben 
> ---
>  drivers/rtc/Kconfig  |  11 +++
>  drivers/rtc/rtc-abx80x.c | 160 ---
>  2 files changed, 159 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
> index 7d7be60a2413..4771e3a89721 100644
> --- a/drivers/rtc/Kconfig
> +++ b/drivers/rtc/Kconfig
> @@ -195,6 +195,17 @@ config RTC_DRV_ABX80X
> This driver can also be built as a module. If so, the module
> will be called rtc-abx80x.
>  
> +config RTC_DRV_ABX80X_WDT
> + bool "Abracon ABx80x Watchdog"
> + default y
> + depends on RTC_DRV_ABX80X
> + help
> +   If you say yes here you get watchdog support for Abracon ABX804 and 
> ABX805
> +   clock chips. This watchdog supports timeouts up to 31 seconds with 1 
> second
> +   granularity.
> +
> +  This watchdog device is part of the rtc-abx80x module.
> +

I'm not sure it is worth having a separate config option for that. You
may as well just always include the watchdog support code. However,
doesn't it need to depend on CONFIG_WATCHDOG?

>  config RTC_DRV_AC100
>   tristate "X-Powers AC100"
>   depends on MFD_AC100
> diff --git a/drivers/rtc/rtc-abx80x.c b/drivers/rtc/rtc-abx80x.c
> index 2cefa67a1132..fa558939e944 100644
> --- a/drivers/rtc/rtc-abx80x.c
> +++ b/drivers/rtc/rtc-abx80x.c
> @@ -17,6 +17,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  
>  #define ABX8XX_REG_HTH   0x00
>  #define ABX8XX_REG_SC0x01
> @@ -37,6 +38,7 @@
>  
>  #define ABX8XX_REG_STATUS0x0f
>  #define ABX8XX_STATUS_AF BIT(2)
> +#define ABX8XX_STATUS_WDTBIT(6)
>  
>  #define ABX8XX_REG_CTRL1 0x10
>  #define ABX8XX_CTRL_WRITEBIT(0)
> @@ -61,6 +63,14 @@
>  #define ABX8XX_OSS_OFBIT(1)
>  #define ABX8XX_OSS_OMODE BIT(4)
>  
> +#define ABX8XX_REG_WDT   0x1b
> +#define ABX8XX_WDT_WDS   BIT(7)
> +#define ABX8XX_WDT_BMB_MASK  0x7c
> +#define ABX8XX_WDT_BMB_SHIFT 2
> +#define ABX8XX_WDT_MAX_TIME  (ABX8XX_WDT_BMB_MASK >> ABX8XX_WDT_BMB_SHIFT)
> +#define ABX8XX_WDT_WRB_MASK  0x03
> +#define ABX8XX_WDT_WRB_1HZ   0x02
> +
>  #define ABX8XX_REG_CFG_KEY   0x1f
>  #define ABX8XX_CFG_KEY_OSC   0xa1
>  #define ABX8XX_CFG_KEY_MISC  0x9d
> @@ -80,20 +90,27 @@ enum abx80x_chip {AB0801, AB0803, AB0804, AB0805,
>  struct abx80x_cap {
>   u16 pn;
>   bool has_tc;
> + bool has_wdog;
>  };
>  
>  static struct abx80x_cap abx80x_caps[] = {
>   [AB0801] = {.pn = 0x0801},
>   [AB0803] = {.pn = 0x0803},
> - [AB0804] = {.pn = 0x0804, .has_tc = true},
> - [AB0805] = {.pn = 0x0805, .has_tc = true},
> + [AB0804] = {.pn = 0x0804, .has_tc = true, .has_wdog = true},
> + [AB0805] = {.pn = 0x0805, .has_tc = true, .has_wdog = true},
>   [AB1801] = {.pn = 0x1801},
>   [AB1803] = {.pn = 0x1803},
> - [AB1804] = {.pn = 0x1804, .has_tc = true},
> - [AB1805] = {.pn = 0x1805, .has_tc = true},
> + [AB1804] = {.pn = 0x1804, .has_tc = true, .has_wdog = true},
> + [AB1805] = {.pn = 0x1805, .has_tc = true, .has_wdog = true},
>   [ABX80X] = {.pn = 0}
>  };
>  
> +struct abx80x_priv {
> + struct rtc_device *rtc;
> + struct i2c_client *client;
> + struct watchdog_device wdog;
> +};
> +

To make the watchdog part easier to review, you could separate the
introduction of abx80x_priv in a preliminary patch and then introduce
the watchdog code.

>  static int abx80x_is_rc_mode(struct i2c_client *client)
>  {
>   int flags = 0;
> @@ -218,7 +235,8 @@ static int abx80x_rtc_set_time(struct device *dev, struct 
> rtc_time *tm)
>  static irqreturn_t abx80x_handle_irq(int irq, void *dev_id)
>  {
>   struct i2c_client *client = dev_id;
> - struct rtc_device *rtc = i2c_get_clientdata(client);
> + struct abx80x_priv *priv = i2c_get_clientdata(client);
> + struct rtc_device *rtc = priv->rtc;
>   int status;
>  
>   status = i2c_smbus_read_byte_data(client, ABX8XX_REG_STATUS);
> @@ -228,6 +246,13 @@ static irqreturn_t abx80x_handle_irq(int irq, void 
> *dev_id)
>   if (status & ABX8XX_STATUS_AF)
>   rtc_update_irq(rtc, 1, RTC_AF | RTC_IRQF);
>  
> + /*
> +  * It is unclear if we'll get an interrupt before the external
> +  * reset kicks in.
> +  */
> + if (status & ABX8XX_STATUS_WDT)
> + dev_err(>dev, "watchdog timeout interrupt!\n");
> +

dev_alert maybe?

>   i2c_smbus_write_byte_data(client, ABX8XX_REG_STATUS, 0);
>  
>   return IRQ_HANDLED;
> @@ -529,11 +554,110 @@ static void rtc_calib_remove_sysfs_group(void *_dev)
>   sysfs_remove_group(>kobj, _calib_attr_group);
>  }
>  
> +#ifdef CONFIG_RTC_DRV_ABX80X_WDT
> +
> +static inline 

[PATCH] rtc: abx80x: add basic watchdog support

2018-09-07 Thread Jeremy Gebben
The abx804 and abx805 chips have support for a simple watchdog
function that can trigger an external reset.

Signed-off-by: Jeremy Gebben 
---
 drivers/rtc/Kconfig  |  11 +++
 drivers/rtc/rtc-abx80x.c | 160 ---
 2 files changed, 159 insertions(+), 12 deletions(-)

diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 7d7be60a2413..4771e3a89721 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -195,6 +195,17 @@ config RTC_DRV_ABX80X
  This driver can also be built as a module. If so, the module
  will be called rtc-abx80x.
 
+config RTC_DRV_ABX80X_WDT
+   bool "Abracon ABx80x Watchdog"
+   default y
+   depends on RTC_DRV_ABX80X
+   help
+ If you say yes here you get watchdog support for Abracon ABX804 and 
ABX805
+ clock chips. This watchdog supports timeouts up to 31 seconds with 1 
second
+ granularity.
+
+  This watchdog device is part of the rtc-abx80x module.
+
 config RTC_DRV_AC100
tristate "X-Powers AC100"
depends on MFD_AC100
diff --git a/drivers/rtc/rtc-abx80x.c b/drivers/rtc/rtc-abx80x.c
index 2cefa67a1132..fa558939e944 100644
--- a/drivers/rtc/rtc-abx80x.c
+++ b/drivers/rtc/rtc-abx80x.c
@@ -17,6 +17,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #define ABX8XX_REG_HTH 0x00
 #define ABX8XX_REG_SC  0x01
@@ -37,6 +38,7 @@
 
 #define ABX8XX_REG_STATUS  0x0f
 #define ABX8XX_STATUS_AF   BIT(2)
+#define ABX8XX_STATUS_WDT  BIT(6)
 
 #define ABX8XX_REG_CTRL1   0x10
 #define ABX8XX_CTRL_WRITE  BIT(0)
@@ -61,6 +63,14 @@
 #define ABX8XX_OSS_OF  BIT(1)
 #define ABX8XX_OSS_OMODE   BIT(4)
 
+#define ABX8XX_REG_WDT 0x1b
+#define ABX8XX_WDT_WDS BIT(7)
+#define ABX8XX_WDT_BMB_MASK0x7c
+#define ABX8XX_WDT_BMB_SHIFT   2
+#define ABX8XX_WDT_MAX_TIME(ABX8XX_WDT_BMB_MASK >> ABX8XX_WDT_BMB_SHIFT)
+#define ABX8XX_WDT_WRB_MASK0x03
+#define ABX8XX_WDT_WRB_1HZ 0x02
+
 #define ABX8XX_REG_CFG_KEY 0x1f
 #define ABX8XX_CFG_KEY_OSC 0xa1
 #define ABX8XX_CFG_KEY_MISC0x9d
@@ -80,20 +90,27 @@ enum abx80x_chip {AB0801, AB0803, AB0804, AB0805,
 struct abx80x_cap {
u16 pn;
bool has_tc;
+   bool has_wdog;
 };
 
 static struct abx80x_cap abx80x_caps[] = {
[AB0801] = {.pn = 0x0801},
[AB0803] = {.pn = 0x0803},
-   [AB0804] = {.pn = 0x0804, .has_tc = true},
-   [AB0805] = {.pn = 0x0805, .has_tc = true},
+   [AB0804] = {.pn = 0x0804, .has_tc = true, .has_wdog = true},
+   [AB0805] = {.pn = 0x0805, .has_tc = true, .has_wdog = true},
[AB1801] = {.pn = 0x1801},
[AB1803] = {.pn = 0x1803},
-   [AB1804] = {.pn = 0x1804, .has_tc = true},
-   [AB1805] = {.pn = 0x1805, .has_tc = true},
+   [AB1804] = {.pn = 0x1804, .has_tc = true, .has_wdog = true},
+   [AB1805] = {.pn = 0x1805, .has_tc = true, .has_wdog = true},
[ABX80X] = {.pn = 0}
 };
 
+struct abx80x_priv {
+   struct rtc_device *rtc;
+   struct i2c_client *client;
+   struct watchdog_device wdog;
+};
+
 static int abx80x_is_rc_mode(struct i2c_client *client)
 {
int flags = 0;
@@ -218,7 +235,8 @@ static int abx80x_rtc_set_time(struct device *dev, struct 
rtc_time *tm)
 static irqreturn_t abx80x_handle_irq(int irq, void *dev_id)
 {
struct i2c_client *client = dev_id;
-   struct rtc_device *rtc = i2c_get_clientdata(client);
+   struct abx80x_priv *priv = i2c_get_clientdata(client);
+   struct rtc_device *rtc = priv->rtc;
int status;
 
status = i2c_smbus_read_byte_data(client, ABX8XX_REG_STATUS);
@@ -228,6 +246,13 @@ static irqreturn_t abx80x_handle_irq(int irq, void *dev_id)
if (status & ABX8XX_STATUS_AF)
rtc_update_irq(rtc, 1, RTC_AF | RTC_IRQF);
 
+   /*
+* It is unclear if we'll get an interrupt before the external
+* reset kicks in.
+*/
+   if (status & ABX8XX_STATUS_WDT)
+   dev_err(>dev, "watchdog timeout interrupt!\n");
+
i2c_smbus_write_byte_data(client, ABX8XX_REG_STATUS, 0);
 
return IRQ_HANDLED;
@@ -529,11 +554,110 @@ static void rtc_calib_remove_sysfs_group(void *_dev)
sysfs_remove_group(>kobj, _calib_attr_group);
 }
 
+#ifdef CONFIG_RTC_DRV_ABX80X_WDT
+
+static inline u8 timeout_bits(unsigned int timeout)
+{
+   return ((timeout << ABX8XX_WDT_BMB_SHIFT) & ABX8XX_WDT_BMB_MASK) |
+ABX8XX_WDT_WRB_1HZ;
+}
+
+static int __abx80x_wdog_set_timeout(struct watchdog_device *wdog,
+   unsigned int timeout)
+{
+   struct abx80x_priv *priv = watchdog_get_drvdata(wdog);
+   u8 val = ABX8XX_WDT_WDS | timeout_bits(timeout);
+
+   /*
+* Writing any timeout to the WDT register resets the watchdog timer.
+* Writing 0 disables it.
+*/
+   return i2c_smbus_write_byte_data(priv->client, ABX8XX_REG_WDT, val);
+}
+
+static int 

[PATCH] rtc: abx80x: add basic watchdog support

2018-09-07 Thread Jeremy Gebben
The abx804 and abx805 chips have support for a simple watchdog
function that can trigger an external reset.

Signed-off-by: Jeremy Gebben 
---
 drivers/rtc/Kconfig  |  11 +++
 drivers/rtc/rtc-abx80x.c | 160 ---
 2 files changed, 159 insertions(+), 12 deletions(-)

diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 7d7be60a2413..4771e3a89721 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -195,6 +195,17 @@ config RTC_DRV_ABX80X
  This driver can also be built as a module. If so, the module
  will be called rtc-abx80x.
 
+config RTC_DRV_ABX80X_WDT
+   bool "Abracon ABx80x Watchdog"
+   default y
+   depends on RTC_DRV_ABX80X
+   help
+ If you say yes here you get watchdog support for Abracon ABX804 and 
ABX805
+ clock chips. This watchdog supports timeouts up to 31 seconds with 1 
second
+ granularity.
+
+  This watchdog device is part of the rtc-abx80x module.
+
 config RTC_DRV_AC100
tristate "X-Powers AC100"
depends on MFD_AC100
diff --git a/drivers/rtc/rtc-abx80x.c b/drivers/rtc/rtc-abx80x.c
index 2cefa67a1132..fa558939e944 100644
--- a/drivers/rtc/rtc-abx80x.c
+++ b/drivers/rtc/rtc-abx80x.c
@@ -17,6 +17,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #define ABX8XX_REG_HTH 0x00
 #define ABX8XX_REG_SC  0x01
@@ -37,6 +38,7 @@
 
 #define ABX8XX_REG_STATUS  0x0f
 #define ABX8XX_STATUS_AF   BIT(2)
+#define ABX8XX_STATUS_WDT  BIT(6)
 
 #define ABX8XX_REG_CTRL1   0x10
 #define ABX8XX_CTRL_WRITE  BIT(0)
@@ -61,6 +63,14 @@
 #define ABX8XX_OSS_OF  BIT(1)
 #define ABX8XX_OSS_OMODE   BIT(4)
 
+#define ABX8XX_REG_WDT 0x1b
+#define ABX8XX_WDT_WDS BIT(7)
+#define ABX8XX_WDT_BMB_MASK0x7c
+#define ABX8XX_WDT_BMB_SHIFT   2
+#define ABX8XX_WDT_MAX_TIME(ABX8XX_WDT_BMB_MASK >> ABX8XX_WDT_BMB_SHIFT)
+#define ABX8XX_WDT_WRB_MASK0x03
+#define ABX8XX_WDT_WRB_1HZ 0x02
+
 #define ABX8XX_REG_CFG_KEY 0x1f
 #define ABX8XX_CFG_KEY_OSC 0xa1
 #define ABX8XX_CFG_KEY_MISC0x9d
@@ -80,20 +90,27 @@ enum abx80x_chip {AB0801, AB0803, AB0804, AB0805,
 struct abx80x_cap {
u16 pn;
bool has_tc;
+   bool has_wdog;
 };
 
 static struct abx80x_cap abx80x_caps[] = {
[AB0801] = {.pn = 0x0801},
[AB0803] = {.pn = 0x0803},
-   [AB0804] = {.pn = 0x0804, .has_tc = true},
-   [AB0805] = {.pn = 0x0805, .has_tc = true},
+   [AB0804] = {.pn = 0x0804, .has_tc = true, .has_wdog = true},
+   [AB0805] = {.pn = 0x0805, .has_tc = true, .has_wdog = true},
[AB1801] = {.pn = 0x1801},
[AB1803] = {.pn = 0x1803},
-   [AB1804] = {.pn = 0x1804, .has_tc = true},
-   [AB1805] = {.pn = 0x1805, .has_tc = true},
+   [AB1804] = {.pn = 0x1804, .has_tc = true, .has_wdog = true},
+   [AB1805] = {.pn = 0x1805, .has_tc = true, .has_wdog = true},
[ABX80X] = {.pn = 0}
 };
 
+struct abx80x_priv {
+   struct rtc_device *rtc;
+   struct i2c_client *client;
+   struct watchdog_device wdog;
+};
+
 static int abx80x_is_rc_mode(struct i2c_client *client)
 {
int flags = 0;
@@ -218,7 +235,8 @@ static int abx80x_rtc_set_time(struct device *dev, struct 
rtc_time *tm)
 static irqreturn_t abx80x_handle_irq(int irq, void *dev_id)
 {
struct i2c_client *client = dev_id;
-   struct rtc_device *rtc = i2c_get_clientdata(client);
+   struct abx80x_priv *priv = i2c_get_clientdata(client);
+   struct rtc_device *rtc = priv->rtc;
int status;
 
status = i2c_smbus_read_byte_data(client, ABX8XX_REG_STATUS);
@@ -228,6 +246,13 @@ static irqreturn_t abx80x_handle_irq(int irq, void *dev_id)
if (status & ABX8XX_STATUS_AF)
rtc_update_irq(rtc, 1, RTC_AF | RTC_IRQF);
 
+   /*
+* It is unclear if we'll get an interrupt before the external
+* reset kicks in.
+*/
+   if (status & ABX8XX_STATUS_WDT)
+   dev_err(>dev, "watchdog timeout interrupt!\n");
+
i2c_smbus_write_byte_data(client, ABX8XX_REG_STATUS, 0);
 
return IRQ_HANDLED;
@@ -529,11 +554,110 @@ static void rtc_calib_remove_sysfs_group(void *_dev)
sysfs_remove_group(>kobj, _calib_attr_group);
 }
 
+#ifdef CONFIG_RTC_DRV_ABX80X_WDT
+
+static inline u8 timeout_bits(unsigned int timeout)
+{
+   return ((timeout << ABX8XX_WDT_BMB_SHIFT) & ABX8XX_WDT_BMB_MASK) |
+ABX8XX_WDT_WRB_1HZ;
+}
+
+static int __abx80x_wdog_set_timeout(struct watchdog_device *wdog,
+   unsigned int timeout)
+{
+   struct abx80x_priv *priv = watchdog_get_drvdata(wdog);
+   u8 val = ABX8XX_WDT_WDS | timeout_bits(timeout);
+
+   /*
+* Writing any timeout to the WDT register resets the watchdog timer.
+* Writing 0 disables it.
+*/
+   return i2c_smbus_write_byte_data(priv->client, ABX8XX_REG_WDT, val);
+}
+
+static int