diff --git a/arch/arm/include/asm/ti-common/omap_wdt.h b/arch/arm/include/asm/ti-common/omap_wdt.h
index 7d72e3af02b9415f6e7a3b6487c8ab06537bd97a..fbc421b6305e1167d67ae889592119d029f20d38 100644
--- a/arch/arm/include/asm/ti-common/omap_wdt.h
+++ b/arch/arm/include/asm/ti-common/omap_wdt.h
@@ -56,4 +56,9 @@ struct wd_timer {
 	unsigned int wdt_unfr;	/* offset 0x100 */
 };
 
+struct omap3_wdt_priv {
+	struct wd_timer *regs;
+	unsigned int wdt_trgr_pattern;
+};
+
 #endif /* __OMAP_WDT_H__ */
diff --git a/configs/am335x_evm_defconfig b/configs/am335x_evm_defconfig
index ff96f192e02f1eb8615e38d56fa7f40651a02e44..fa6b03060aaedfc1dfead5206f2324514502c0ae 100644
--- a/configs/am335x_evm_defconfig
+++ b/configs/am335x_evm_defconfig
@@ -58,6 +58,8 @@ CONFIG_DM_SPI=y
 CONFIG_OMAP3_SPI=y
 CONFIG_TIMER=y
 CONFIG_OMAP_TIMER=y
+CONFIG_WDT=y
+CONFIG_WDT_OMAP3=y
 CONFIG_USB=y
 CONFIG_DM_USB=y
 CONFIG_DM_USB_GADGET=y
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 1e5d14c4ffb93f217ba9a60e53e792b3b5d39ba5..a66a9bcbe23f898c0e784db5213f2072c58ba34a 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -28,7 +28,6 @@ config OMAP_WATCHDOG
 	bool "TI OMAP watchdog driver"
 	depends on ARCH_OMAP2PLUS
 	select HW_WATCHDOG
-	default y if AM33XX
 	help
 	  Say Y here to enable the OMAP3+ watchdog driver.
 
@@ -113,6 +112,14 @@ config WDT_MTK
 	  The watchdog timer is stopped when initialized.
 	  It performs full SoC reset.
 
+config WDT_OMAP3
+        bool "TI OMAP watchdog timer support"
+        depends on WDT && ARCH_OMAP2PLUS
+        default y if AM33XX
+        help
+	  This enables OMAP3+ watchdog timer driver, which can be
+	  found on some TI chipsets and inline with driver model.
+
 config WDT_ORION
 	bool "Orion watchdog timer support"
 	depends on WDT
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 414ba2430a22e89b22cdaa93b347884ce0dad1a7..955caef815ec8a6931d6ac403f962c38cba35b4f 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -25,6 +25,7 @@ obj-$(CONFIG_WDT_CDNS) += cdns_wdt.o
 obj-$(CONFIG_WDT_MPC8xx) += mpc8xx_wdt.o
 obj-$(CONFIG_WDT_MT7621) += mt7621_wdt.o
 obj-$(CONFIG_WDT_MTK) += mtk_wdt.o
+obj-$(CONFIG_WDT_OMAP3) += omap_wdt.o
 obj-$(CONFIG_WDT_SP805) += sp805_wdt.o
 obj-$(CONFIG_WDT_STM32MP) += stm32mp_wdt.o
 obj-$(CONFIG_WDT_TANGIER) += tangier_wdt.o
diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c
index 343adb00c71bfe92c6cd4f27cca13d43a20c740b..86f7cf1aafd01528273ad742c47a1e55db318e3d 100644
--- a/drivers/watchdog/omap_wdt.c
+++ b/drivers/watchdog/omap_wdt.c
@@ -42,10 +42,14 @@
 #include <asm/io.h>
 #include <asm/processor.h>
 #include <asm/arch/cpu.h>
+#include <wdt.h>
+#include <dm.h>
+#include <errno.h>
 
 /* Hardware timeout in seconds */
 #define WDT_HW_TIMEOUT 60
 
+#if !CONFIG_IS_ENABLED(WDT)
 static unsigned int wdt_trgr_pattern = 0x1234;
 
 void hw_watchdog_reset(void)
@@ -134,3 +138,113 @@ void hw_watchdog_init(void)
 	while ((readl(&wdt->wdtwwps)) & WDT_WWPS_PEND_WSPR)
 		;
 }
+#else
+static int omap3_wdt_reset(struct udevice *dev)
+{
+	struct omap3_wdt_priv *priv = dev_get_priv(dev);
+
+	priv->wdt_trgr_pattern = 0x1234;
+/*
+ * Somebody just triggered watchdog reset and write to WTGR register
+ * is in progress. It is resetting right now, no need to trigger it
+ * again
+ */
+	if ((readl(&priv->regs->wdtwwps)) & WDT_WWPS_PEND_WTGR)
+		return 0;
+
+	priv->wdt_trgr_pattern = ~(priv->wdt_trgr_pattern);
+	writel(priv->wdt_trgr_pattern, &priv->regs->wdtwtgr);
+/*
+ * Don't wait for posted write to complete, i.e. don't check
+ * WDT_WWPS_PEND_WTGR bit in WWPS register. There is no writes to
+ * WTGR register outside of this func, and if entering it
+ * we see WDT_WWPS_PEND_WTGR bit set, it means watchdog reset
+ * was just triggered. This prevents us from wasting time in busy
+ * polling of WDT_WWPS_PEND_WTGR bit.
+ */
+	return 0;
+}
+
+static int omap3_wdt_stop(struct udevice *dev)
+{
+	struct omap3_wdt_priv *priv = dev_get_priv(dev);
+
+/* disable watchdog */
+	writel(0xAAAA, &priv->regs->wdtwspr);
+	while (readl(&priv->regs->wdtwwps) != 0x0)
+		;
+	writel(0x5555, &priv->regs->wdtwspr);
+	while (readl(&priv->regs->wdtwwps) != 0x0)
+		;
+	return 0;
+}
+
+static int omap3_wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags)
+{
+	struct omap3_wdt_priv *priv = dev_get_priv(dev);
+	u32 pre_margin = GET_WLDR_VAL(timeout_ms);
+/*
+ * Make sure the watchdog is disabled. This is unfortunately required
+ * because writing to various registers with the watchdog running has no
+ * effect.
+ */
+	omap3_wdt_stop(dev);
+
+/* initialize prescaler */
+	while (readl(&priv->regs->wdtwwps) & WDT_WWPS_PEND_WCLR)
+		;
+
+	writel(WDT_WCLR_PRE | (PTV << WDT_WCLR_PTV_OFF), &priv->regs->wdtwclr);
+	while (readl(&priv->regs->wdtwwps) & WDT_WWPS_PEND_WCLR)
+		;
+/* just count up at 32 KHz */
+	while (readl(&priv->regs->wdtwwps) & WDT_WWPS_PEND_WLDR)
+		;
+
+	writel(pre_margin, &priv->regs->wdtwldr);
+	while (readl(&priv->regs->wdtwwps) & WDT_WWPS_PEND_WLDR)
+		;
+/* Sequence to enable the watchdog */
+	writel(0xBBBB, &priv->regs->wdtwspr);
+	while ((readl(&priv->regs->wdtwwps)) & WDT_WWPS_PEND_WSPR)
+		;
+
+	writel(0x4444, &priv->regs->wdtwspr);
+	while ((readl(&priv->regs->wdtwwps)) & WDT_WWPS_PEND_WSPR)
+		;
+
+	return 0;
+}
+
+static int omap3_wdt_probe(struct udevice *dev)
+{
+	struct omap3_wdt_priv *priv = dev_get_priv(dev);
+
+	priv->regs = (struct wd_timer *)devfdt_get_addr(dev);
+	if (!priv->regs)
+		return -EINVAL;
+
+	debug("%s: Probing wdt%u\n", __func__, dev->seq);
+	return 0;
+}
+
+static const struct wdt_ops omap3_wdt_ops = {
+	.start = omap3_wdt_start,
+	.stop = omap3_wdt_stop,
+	.reset = omap3_wdt_reset,
+};
+
+static const struct udevice_id omap3_wdt_ids[] = {
+	{ .compatible = "ti,omap3-wdt" },
+	{ }
+};
+
+U_BOOT_DRIVER(omap3_wdt) = {
+	.name = "omap3_wdt",
+	.id = UCLASS_WDT,
+	.of_match = omap3_wdt_ids,
+	.ops = &omap3_wdt_ops,
+	.probe = omap3_wdt_probe,
+	.priv_auto_alloc_size = sizeof(struct omap3_wdt_priv),
+};
+#endif /* !CONFIG_IS_ENABLED(WDT) */