Add support for 'fastboot reboot-bootloader'
- Add calls to get and set the MTK_WDT_NONRST2 register, which isn't
cleared on a reset.
- Implement fastboot_set_reboot_flag, using the MTK_WDT_NONRST2 register
to store the flag value at reset time
- Enable MISC_INIT_R and use it to handle the flag, board_init runs before watchdog startup.
Change-Id: I3c18ab3d97b4681775d426d487bf95968ab943d4
diff --git a/board/mediatek/mt8516-coral/mt8516-coral.c b/board/mediatek/mt8516-coral/mt8516-coral.c
index 85b2c4d..4299553 100644
--- a/board/mediatek/mt8516-coral/mt8516-coral.c
+++ b/board/mediatek/mt8516-coral/mt8516-coral.c
@@ -5,6 +5,54 @@
#include <common.h>
#include <dm.h>
+#include "../../../drivers/watchdog/mtk_wdt.h"
+
+#define WDT_DRIVER_NAME "mtk_wdt"
+#define REBOOT_BOOTLOADER_VALUE (1)
+#define REBOOT_BOOTLOADER_MASK (1)
+#define REBOOT_BOOTLOADER_SHIFT (2)
+
+int fastboot_set_reboot_flag(void) {
+ struct udevice *dev;
+ struct uclass *uc;
+ int ret = -ENOSYS;
+
+ ret = uclass_get(UCLASS_WDT, &uc);
+ if (ret)
+ return -ENOSYS;
+
+ uclass_foreach_dev(dev, uc) {
+ if (strncmp(dev->driver->name, WDT_DRIVER_NAME, strlen(WDT_DRIVER_NAME)) == 0) {
+ mtk_wdt_set_nonrst2(dev, REBOOT_BOOTLOADER_MASK << REBOOT_BOOTLOADER_SHIFT,
+ REBOOT_BOOTLOADER_VALUE << REBOOT_BOOTLOADER_SHIFT);
+ return 0;
+ }
+ }
+
+ return -ENOSYS;
+}
+
+int misc_init_r(void) {
+ int ret;
+ struct udevice *dev;
+ struct uclass *uc;
+ int reg_val;
+
+ ret = uclass_get(UCLASS_WDT, &uc);
+ if (ret)
+ return -ENOSYS;
+
+ uclass_foreach_dev(dev, uc) {
+ if (strncmp(dev->driver->name, WDT_DRIVER_NAME, strlen(WDT_DRIVER_NAME)) == 0) {
+ reg_val = mtk_wdt_get_nonrst2(dev);
+ if (reg_val & (REBOOT_BOOTLOADER_VALUE << REBOOT_BOOTLOADER_SHIFT)) {
+ env_set("force_fastboot", "1");
+ mtk_wdt_set_nonrst2(dev, REBOOT_BOOTLOADER_MASK << REBOOT_BOOTLOADER_SHIFT, 0);
+ }
+ }
+ }
+ return 0;
+}
int board_init(void)
{
diff --git a/configs/mt8516_coral_defconfig b/configs/mt8516_coral_defconfig
index 26875c2..bf17444 100644
--- a/configs/mt8516_coral_defconfig
+++ b/configs/mt8516_coral_defconfig
@@ -86,3 +86,4 @@
CONFIG_CMD_EXT4=y
CONFIG_CMD_SETEXPR=y
CONFIG_CMD_SOURCE=y
+CONFIG_MISC_INIT_R=y
\ No newline at end of file
diff --git a/drivers/watchdog/mtk_wdt.c b/drivers/watchdog/mtk_wdt.c
index dafd2b5..64d6df6 100644
--- a/drivers/watchdog/mtk_wdt.c
+++ b/drivers/watchdog/mtk_wdt.c
@@ -17,6 +17,7 @@
#define MTK_WDT_STATUS 0x0c
#define MTK_WDT_INTERVAL 0x10
#define MTK_WDT_SWRST 0x14
+#define MTK_WDT_NONRST2 0x24
#define MTK_WDT_REQ_MODE 0x30
#define MTK_WDT_DEBUG_CTL 0x40
@@ -70,6 +71,17 @@
return 0;
}
+int mtk_wdt_get_nonrst2(struct udevice *dev) {
+ struct mtk_wdt_priv *priv = dev_get_priv(dev);
+ return readl(priv->base + MTK_WDT_NONRST2);
+}
+
+void mtk_wdt_set_nonrst2(struct udevice *dev, ulong mask, ulong value) {
+ struct mtk_wdt_priv *priv = dev_get_priv(dev);
+ int reg_val = readl(priv->base + MTK_WDT_NONRST2);
+ writel((reg_val & ~mask) | value, priv->base + MTK_WDT_NONRST2);
+}
+
static void mtk_wdt_set_timeout(struct udevice *dev, u64 timeout_ms)
{
struct mtk_wdt_priv *priv = dev_get_priv(dev);
diff --git a/drivers/watchdog/mtk_wdt.h b/drivers/watchdog/mtk_wdt.h
new file mode 100644
index 0000000..49de8c6
--- /dev/null
+++ b/drivers/watchdog/mtk_wdt.h
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Watchdog driver for MediaTek SoCs
+ *
+ * Copyright (C) 2020 Google, LLC.
+ */
+#ifndef _MTK_WDT_H
+#define _MTK_WDT_H
+
+void mtk_wdt_set_nonrst2(struct udevice *dev, ulong mask, ulong value);
+int mtk_wdt_get_nonrst2(struct udevice *dev);
+
+#endif // _MTK_WDT_H