diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c
index f5db18db..38e36c1 100644
--- a/drivers/watchdog/omap_wdt.c
+++ b/drivers/watchdog/omap_wdt.c
@@ -45,6 +45,7 @@
  #include <linux/uaccess.h>
  #include <linux/slab.h>
  #include <linux/pm_runtime.h>
+#include <linux/interrupt.h>
  #include <mach/hardware.h>
  #include <plat/cpu.h>
  #include <plat/prcm.h>
@@ -57,6 +58,10 @@ static unsigned timer_margin;
  module_param(timer_margin, uint, 0);
  MODULE_PARM_DESC(timer_margin, "initial watchdog timeout (in seconds)");

+static int kernelpet = 1;
+module_param(kernelpet, int, 0);
+MODULE_PARM_DESC(kernelpet, "pet watchdog in kernel via irq");
+
  static unsigned int wdt_trgr_pattern = 0x1234;
  static DEFINE_SPINLOCK(wdt_lock);

@@ -66,6 +71,7 @@ struct omap_wdt_dev {
  	int             omap_wdt_users;
  	struct resource *mem;
  	struct miscdevice omap_wdt_miscdev;
+	int irq;
  };

  static void omap_wdt_ping(struct omap_wdt_dev *wdev)
@@ -125,6 +131,7 @@ static void omap_wdt_adjust_timeout(unsigned 
new_timeout)
  static void omap_wdt_set_timeout(struct omap_wdt_dev *wdev)
  {
  	u32 pre_margin = GET_WLDR_VAL(timer_margin);
+	u32 delay_period = GET_WLDR_VAL(timer_margin / 2);
  	void __iomem *base = wdev->base;

  	/* just count up at 32 KHz */
@@ -134,14 +141,29 @@ static void omap_wdt_set_timeout(struct 
omap_wdt_dev *wdev)
  	__raw_writel(pre_margin, base + OMAP_WATCHDOG_LDR);
  	while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x04)
  		cpu_relax();
+
+	/* Set delay interrupt to half the watchdog interval. */
+	while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 1 << 5)
+		cpu_relax();
+	__raw_writel(delay_period, base + OMAP_WATCHDOG_WDLY);
  }

-/*
- *	Allow only one task to hold it open
- */
-static int omap_wdt_open(struct inode *inode, struct file *file)
+static irqreturn_t omap_wdt_interrupt(int irq, void *dev_id)
+{
+	struct omap_wdt_dev *wdev = dev_id;
+	void __iomem *base = wdev->base;
+	u32 i;
+
+	i = __raw_readl(base + OMAP_WATCHDOG_WIRQSTAT);
+	__raw_writel(i, base + OMAP_WATCHDOG_WIRQSTAT);
+
+	omap_wdt_ping(wdev);
+
+	return IRQ_HANDLED;
+}
+
+static int omap_wdt_setup(struct omap_wdt_dev *wdev)
  {
-	struct omap_wdt_dev *wdev = platform_get_drvdata(omap_wdt_dev);
  	void __iomem *base = wdev->base;

  	if (test_and_set_bit(1, (unsigned long *)&(wdev->omap_wdt_users)))
@@ -157,12 +179,31 @@ static int omap_wdt_open(struct inode *inode, 
struct file *file)
  	while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x01)
  		cpu_relax();

-	file->private_data = (void *) wdev;
-
  	omap_wdt_set_timeout(wdev);
  	omap_wdt_ping(wdev); /* trigger loading of new timeout value */
+
+	/* Enable delay interrupt */
+	if (kernelpet && wdev->irq)
+		__raw_writel(0x2, base + OMAP_WATCHDOG_WIRQENSET);
+
  	omap_wdt_enable(wdev);

+	return 0;
+}
+/*
+ *	Allow only one task to hold it open
+ */
+static int omap_wdt_open(struct inode *inode, struct file *file)
+{
+	struct omap_wdt_dev *wdev = platform_get_drvdata(omap_wdt_dev);
+	int ret;
+
+	ret = omap_wdt_setup(wdev);
+
+	if (ret)
+		return ret;
+
+	file->private_data = (void *)wdev;
  	return nonseekable_open(inode, file);
  }

@@ -176,6 +217,10 @@ static int omap_wdt_release(struct inode *inode, 
struct file *file)
  #ifndef CONFIG_WATCHDOG_NOWAYOUT
  	omap_wdt_disable(wdev);

+	/* Disable delay interrupt */
+	if (kernelpet && wdev->irq)
+		__raw_writel(0x2, base + OMAP_WATCHDOG_WIRQENCLR);
+
  	pm_runtime_put_sync(wdev->dev);
  #else
  	pr_crit("Unexpected close, not stopping!\n");
@@ -266,7 +311,7 @@ static const struct file_operations omap_wdt_fops = {

  static int __devinit omap_wdt_probe(struct platform_device *pdev)
  {
-	struct resource *res, *mem;
+	struct resource *res, *mem, *res_irq;
  	struct omap_wdt_dev *wdev;
  	int ret;

@@ -288,6 +333,8 @@ static int __devinit omap_wdt_probe(struct 
platform_device *pdev)
  		goto err_busy;
  	}

+	res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+
  	wdev = kzalloc(sizeof(struct omap_wdt_dev), GFP_KERNEL);
  	if (!wdev) {
  		ret = -ENOMEM;
@@ -304,6 +351,16 @@ static int __devinit omap_wdt_probe(struct 
platform_device *pdev)
  		goto err_ioremap;
  	}

+	if (res_irq) {
+		ret = request_irq(res_irq->start, omap_wdt_interrupt, 0,
+				  dev_name(&pdev->dev), wdev);
+
+		if (ret)
+			goto err_irq;
+
+		wdev->irq = res_irq->start;
+	}
+
  	platform_set_drvdata(pdev, wdev);

  	pm_runtime_enable(wdev->dev);
@@ -329,11 +386,17 @@ static int __devinit omap_wdt_probe(struct 
platform_device *pdev)

  	omap_wdt_dev = pdev;

+	if (kernelpet && wdev->irq)
+		return  omap_wdt_setup(wdev);
+
  	return 0;

  err_misc:
  	pm_runtime_disable(wdev->dev);
  	platform_set_drvdata(pdev, NULL);
+	if (wdev->irq)
+		free_irq(wdev->irq, wdev);
+err_irq:
  	iounmap(wdev->base);

  err_ioremap:
@@ -372,6 +435,9 @@ static int __devexit omap_wdt_remove(struct 
platform_device *pdev)
  	release_mem_region(res->start, resource_size(res));
  	platform_set_drvdata(pdev, NULL);

+	if (wdev->irq)
+		free_irq(wdev->irq, wdev);
+
  	iounmap(wdev->base);

  	kfree(wdev);
diff --git a/drivers/watchdog/omap_wdt.h b/drivers/watchdog/omap_wdt.h
index 09b774c..c9980d3 100644
--- a/drivers/watchdog/omap_wdt.h
+++ b/drivers/watchdog/omap_wdt.h
@@ -38,7 +38,11 @@
  #define OMAP_WATCHDOG_LDR		(0x2c)
  #define OMAP_WATCHDOG_TGR		(0x30)
  #define OMAP_WATCHDOG_WPS		(0x34)
+#define OMAP_WATCHDOG_WDLY		(0x44)
  #define OMAP_WATCHDOG_SPR		(0x48)
+#define OMAP_WATCHDOG_WIRQSTAT		(0x58)
+#define OMAP_WATCHDOG_WIRQENSET		(0x5c)
+#define OMAP_WATCHDOG_WIRQENCLR		(0x60)

  /* Using the prescaler, the OMAP watchdog could go for many
   * months before firing.  These limits work without scaling,
