summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ddr/altera/sdram_n5x.c1
-rw-r--r--drivers/ddr/altera/sdram_soc64.c1
-rw-r--r--drivers/i2c/rz_riic.c1
-rw-r--r--drivers/led/led_sw_blink.c1
-rw-r--r--drivers/watchdog/Kconfig16
-rw-r--r--drivers/watchdog/Makefile3
-rw-r--r--drivers/watchdog/davinci_wdt.c131
-rw-r--r--drivers/watchdog/gpio_wdt.c27
8 files changed, 177 insertions, 4 deletions
diff --git a/drivers/ddr/altera/sdram_n5x.c b/drivers/ddr/altera/sdram_n5x.c
index db09986f64b..d1fc93b6bdd 100644
--- a/drivers/ddr/altera/sdram_n5x.c
+++ b/drivers/ddr/altera/sdram_n5x.c
@@ -22,6 +22,7 @@
#include <asm/io.h>
#include <linux/err.h>
#include <linux/sizes.h>
+#include <u-boot/schedule.h>
DECLARE_GLOBAL_DATA_PTR;
diff --git a/drivers/ddr/altera/sdram_soc64.c b/drivers/ddr/altera/sdram_soc64.c
index 9e57c2ecfa4..10a8e64af3d 100644
--- a/drivers/ddr/altera/sdram_soc64.c
+++ b/drivers/ddr/altera/sdram_soc64.c
@@ -24,6 +24,7 @@
#include <asm/io.h>
#include <dm/device_compat.h>
#include <linux/sizes.h>
+#include <u-boot/schedule.h>
#define PGTABLE_OFF 0x4000
diff --git a/drivers/i2c/rz_riic.c b/drivers/i2c/rz_riic.c
index 5f3f8d1b24b..f292c824362 100644
--- a/drivers/i2c/rz_riic.c
+++ b/drivers/i2c/rz_riic.c
@@ -14,6 +14,7 @@
#include <linux/bitops.h>
#include <linux/delay.h>
#include <reset.h>
+#include <u-boot/schedule.h>
#include <wait_bit.h>
#define RIIC_ICCR1 0x00
diff --git a/drivers/led/led_sw_blink.c b/drivers/led/led_sw_blink.c
index 06a43db340c..ee1546d02d4 100644
--- a/drivers/led/led_sw_blink.c
+++ b/drivers/led/led_sw_blink.c
@@ -5,6 +5,7 @@
* Author: Mikhail Kshevetskiy <[email protected]>
*/
+#include <cyclic.h>
#include <dm.h>
#include <led.h>
#include <time.h>
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 90bc5653ee3..0e45f0a0922 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -175,6 +175,13 @@ config WDT_DA9063
help
Enable support for the watchdog timer in Dialog DA9063.
+config WDT_DAVINCI
+ bool "DaVinci watchdog timer support"
+ depends on WDT
+ help
+ Select this to enable the watchdog timer for DaVinci SoCs such as the
+ OMAP-L138.
+
config WDT_GPIO
bool "External gpio watchdog support"
depends on WDT
@@ -184,6 +191,15 @@ config WDT_GPIO
doc/device-tree-bindings/watchdog/gpio-wdt.txt for
information on how to describe the watchdog in device tree.
+config SPL_WDT_GPIO
+ bool "External gpio watchdog support in SPL"
+ depends on SPL_WDT
+ depends on SPL_DM_GPIO
+ depends on SPL_OF_REAL
+ default WDT_GPIO
+ help
+ Support for external watchdog fed by toggling a gpio in SPL.
+
config WDT_MAX6370
bool "MAX6370 watchdog timer support"
depends on WDT
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 51be6ab9abe..0b107c008f7 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -30,8 +30,9 @@ obj-$(CONFIG_WDT_CORTINA) += cortina_wdt.o
obj-$(CONFIG_WDT_ORION) += orion_wdt.o
obj-$(CONFIG_WDT_CDNS) += cdns_wdt.o
obj-$(CONFIG_WDT_DA9063) += da9063-wdt.o
+obj-$(CONFIG_WDT_DAVINCI) += davinci_wdt.o
obj-$(CONFIG_WDT_FTWDT010) += ftwdt010_wdt.o
-obj-$(CONFIG_WDT_GPIO) += gpio_wdt.o
+obj-$(CONFIG_$(SPL_TPL_)WDT_GPIO) += gpio_wdt.o
obj-$(CONFIG_WDT_MAX6370) += max6370_wdt.o
obj-$(CONFIG_WDT_MCF) += mcf_wdt.o
obj-$(CONFIG_WDT_MESON_GXBB) += meson_gxbb_wdt.o
diff --git a/drivers/watchdog/davinci_wdt.c b/drivers/watchdog/davinci_wdt.c
new file mode 100644
index 00000000000..fa8d7842e94
--- /dev/null
+++ b/drivers/watchdog/davinci_wdt.c
@@ -0,0 +1,131 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * DaVinci Watchdog driver
+ *
+ */
+
+#include <asm/io.h>
+#include <clk.h>
+#include <dm.h>
+#include <wdt.h>
+
+/* Control Register */
+#define DAVINCI_WDT_ID 0x00
+#define DAVINCI_WDT_TIM12 0x10
+#define DAVINCI_WDT_TIM34 0x14
+#define DAVINCI_WDT_PRD12 0x18
+#define DAVINCI_WDT_PRD34 0x1C
+#define DAVINCI_WDT_TCR 0x20
+#define DAVINCI_WDT_TGCR 0x24
+#define DAVINCI_WDT_WDTCR 0x28
+
+#define DAVINCI_TCR_CONT_EN BIT(7)
+
+#define DAVINCI_TGCR_PLUSEN BIT(4)
+#define DAVINCI_TGCR_WDT_MODE BIT(3)
+#define DAVINCI_TGCR_TIM34RS BIT(1)
+#define DAVINCI_TGCR_TIM12RS BIT(0)
+
+#define DAVINCI_WDTCR_INVALID_KEY (0x5555 << 16)
+#define DAVINCI_WDTCR_WDKEY0 (0xA5C6 << 16)
+#define DAVINCI_WDTCR_WDKEY1 (0xDA7E << 16)
+#define DAVINCI_WDTCR_WDFLAG BIT(15)
+#define DAVINCI_WDTCR_WDEN BIT(14)
+
+#define DEFAULT_THRESHOLD 0xA03200000
+
+struct davinci_wdt_priv {
+ void __iomem *base;
+ struct clk *ref_clk;
+};
+
+static int davinci_wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags)
+{
+ struct davinci_wdt_priv *priv = dev_get_priv(dev);
+ ulong rate = clk_get_rate(priv->ref_clk);
+ u64 threshold;
+
+ if (!rate)
+ threshold = DEFAULT_THRESHOLD;
+ else
+ threshold = rate * timeout_ms / 1000;
+
+ /* Reset control registers */
+ writel(0, priv->base + DAVINCI_WDT_TCR);
+ writel(0, priv->base + DAVINCI_WDT_TGCR);
+
+ /* Enable watchdog mode and timers */
+ writel(DAVINCI_TGCR_WDT_MODE | DAVINCI_TGCR_TIM12RS | DAVINCI_TGCR_TIM34RS,
+ priv->base + DAVINCI_WDT_TGCR);
+
+ /* Reset counters */
+ writel(0, priv->base + DAVINCI_WDT_TIM12);
+ writel(0, priv->base + DAVINCI_WDT_TIM34);
+
+ /* Set timeout threshold */
+ writel(threshold & 0xFFFFFFFF, priv->base + DAVINCI_WDT_PRD12);
+ writel(threshold >> 32, priv->base + DAVINCI_WDT_PRD34);
+
+ /* Enable counter */
+ writel(DAVINCI_TCR_CONT_EN, priv->base + DAVINCI_WDT_TCR);
+
+ /* Go to watchdog's active state */
+ writel(DAVINCI_WDTCR_WDEN | DAVINCI_WDTCR_WDKEY0, priv->base + DAVINCI_WDT_WDTCR);
+ writel(DAVINCI_WDTCR_WDEN | DAVINCI_WDTCR_WDKEY1, priv->base + DAVINCI_WDT_WDTCR);
+
+ return 0;
+}
+
+static int davinci_wdt_expire_now(struct udevice *dev, ulong flags)
+{
+ struct davinci_wdt_priv *priv = dev_get_priv(dev);
+
+ writel(DAVINCI_WDTCR_INVALID_KEY, priv->base + DAVINCI_WDT_WDTCR);
+
+ return 0;
+}
+
+static int davinci_wdt_restart(struct udevice *dev)
+{
+ struct davinci_wdt_priv *priv = dev_get_priv(dev);
+
+ writel(DAVINCI_WDTCR_WDEN | DAVINCI_WDTCR_WDKEY0, priv->base + DAVINCI_WDT_WDTCR);
+ writel(DAVINCI_WDTCR_WDEN | DAVINCI_WDTCR_WDKEY1, priv->base + DAVINCI_WDT_WDTCR);
+
+ return 0;
+}
+
+static int davinci_wdt_probe(struct udevice *dev)
+{
+ struct davinci_wdt_priv *priv = dev_get_priv(dev);
+
+ priv->base = dev_remap_addr_index(dev, 0);
+ if (!priv->base)
+ return -EFAULT;
+
+ priv->ref_clk = devm_clk_get(dev, "ref");
+ if (IS_ERR(priv->ref_clk))
+ return PTR_ERR(priv->ref_clk);
+
+ return 0;
+}
+
+static const struct wdt_ops davinci_wdt_ops = {
+ .start = davinci_wdt_start,
+ .reset = davinci_wdt_restart,
+ .expire_now = davinci_wdt_expire_now,
+};
+
+static const struct udevice_id davinci_wdt_ids[] = {
+ {.compatible = "ti,davinci-wdt"},
+ {}
+};
+
+U_BOOT_DRIVER(davinci_wdt) = {
+ .name = "davinci_wdt",
+ .id = UCLASS_WDT,
+ .probe = davinci_wdt_probe,
+ .of_match = davinci_wdt_ids,
+ .ops = &davinci_wdt_ops,
+ .priv_auto = sizeof(struct davinci_wdt_priv),
+};
diff --git a/drivers/watchdog/gpio_wdt.c b/drivers/watchdog/gpio_wdt.c
index 2920c2c751f..e889861e917 100644
--- a/drivers/watchdog/gpio_wdt.c
+++ b/drivers/watchdog/gpio_wdt.c
@@ -45,14 +45,32 @@ static int gpio_wdt_start(struct udevice *dev, u64 timeout, ulong flags)
if (priv->always_running)
return 0;
- return -ENOSYS;
+ dm_gpio_set_dir_flags(&priv->gpio, GPIOD_IS_OUT);
+ gpio_wdt_reset(dev);
+
+ return 0;
+}
+
+static int gpio_wdt_stop(struct udevice *dev)
+{
+ struct gpio_wdt_priv *priv = dev_get_priv(dev);
+
+ if (priv->always_running)
+ return -EOPNOTSUPP;
+
+ if (priv->hw_algo == HW_ALGO_TOGGLE)
+ dm_gpio_set_dir_flags(&priv->gpio, GPIOD_IS_IN);
+ else
+ dm_gpio_set_value(&priv->gpio, 1);
+
+ return 0;
}
static int dm_probe(struct udevice *dev)
{
struct gpio_wdt_priv *priv = dev_get_priv(dev);
- int ret;
const char *algo = dev_read_string(dev, "hw_algo");
+ int ret, flags;
if (!algo)
return -EINVAL;
@@ -64,7 +82,9 @@ static int dm_probe(struct udevice *dev)
return -EINVAL;
priv->always_running = dev_read_bool(dev, "always-running");
- ret = gpio_request_by_name(dev, "gpios", 0, &priv->gpio, GPIOD_IS_OUT);
+ flags = priv->always_running || priv->hw_algo == HW_ALGO_LEVEL ?
+ GPIOD_IS_OUT : GPIOD_IS_IN;
+ ret = gpio_request_by_name(dev, "gpios", 0, &priv->gpio, flags);
if (ret < 0) {
dev_err(dev, "Request for wdt gpio failed: %d\n", ret);
return ret;
@@ -78,6 +98,7 @@ static int dm_probe(struct udevice *dev)
static const struct wdt_ops gpio_wdt_ops = {
.start = gpio_wdt_start,
+ .stop = gpio_wdt_stop,
.reset = gpio_wdt_reset,
};