[PATCH 2/3] watchdog: mtk_wdt: add support for 16-bit control registers
Boris Lysov
arzamas-16 at mail.ee
Sun Jan 31 18:44:24 EST 2021
Add support for 16-bit control registers.
Some old Mediatek SoCs such as mt6577 use 16-bit I/O operations
for controlling watchdog. This commit redefines read/write
functions and some values in mtk_wdt driver depending on the
16-bit register support flag in kernel configuration.
By default, driver still uses 32-bit values and I/O functions, so
currently supported devices are unaffected.
Signed-off-by: Boris Lysov <arzamas-16 at mail.ee>
---
drivers/watchdog/Kconfig | 9 +++++++++
drivers/watchdog/mtk_wdt.c | 34 ++++++++++++++++++++++++----------
2 files changed, 33 insertions(+), 10 deletions(-)
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 7ff941e71b79..83a4b57ede3f 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -865,6 +865,15 @@ config MEDIATEK_WATCHDOG
To compile this driver as a module, choose M here: the
module will be called mtk_wdt.
+config MEDIATEK_WATCHDOG_16BIT
+ bool "Support 16-bit control registers"
+ depends on MEDIATEK_WATCHDOG=y
+ help
+ Some Mediatek SoCs such as mt6577 have 16-bit registers for
+ controlling watchdog. Newer SoCs usually use 32-bit read/write
+ operations.
+ If in doubt, say N.
+
config DIGICOLOR_WATCHDOG
tristate "Conexant Digicolor SoCs watchdog support"
depends on ARCH_DIGICOLOR || COMPILE_TEST
diff --git a/drivers/watchdog/mtk_wdt.c b/drivers/watchdog/mtk_wdt.c
index d6a6393f609d..0ab3cbcf0d93 100644
--- a/drivers/watchdog/mtk_wdt.c
+++ b/drivers/watchdog/mtk_wdt.c
@@ -43,13 +43,27 @@
#define WDT_MODE_IRQ_EN (1 << 3)
#define WDT_MODE_AUTO_START (1 << 4)
#define WDT_MODE_DUAL_EN (1 << 6)
-#define WDT_MODE_KEY 0x22000000
#define WDT_SWRST 0x14
#define WDT_SWRST_KEY 0x1209
#define WDT_SWSYSRST 0x18U
+
+#ifdef CONFIG_MEDIATEK_WATCHDOG_16BIT
+#define WDT_MODE_KEY 0x2200
+#define WDT_SWSYS_RST_KEY 0x8800
+#define mtk_wdt_read(a) readw(a)
+#define mtk_wdt_write(v, a) writew(v, a)
+#define mtk_wdt_ioread(a) ioread16(a)
+#define mtk_wdt_iowrite(v, a) iowrite16(v, a)
+#else
+#define WDT_MODE_KEY 0x22000000
#define WDT_SWSYS_RST_KEY 0x88000000
+#define mtk_wdt_read(a) readl(a)
+#define mtk_wdt_write(v, a) writel(v, a)
+#define mtk_wdt_ioread(a) ioread32(a)
+#define mtk_wdt_iowrite(v, a) iowrite32(v, a)
+#endif
#define DRV_NAME "mtk-wdt"
#define DRV_VERSION "1.0"
@@ -86,13 +100,13 @@ static int toprgu_reset_update(struct reset_controller_dev *rcdev,
spin_lock_irqsave(&data->lock, flags);
- tmp = readl(data->wdt_base + WDT_SWSYSRST);
+ tmp = mtk_wdt_read(data->wdt_base + WDT_SWSYSRST);
if (assert)
tmp |= BIT(id);
else
tmp &= ~BIT(id);
tmp |= WDT_SWSYS_RST_KEY;
- writel(tmp, data->wdt_base + WDT_SWSYSRST);
+ mtk_wdt_write(tmp, data->wdt_base + WDT_SWSYSRST);
spin_unlock_irqrestore(&data->lock, flags);
@@ -157,7 +171,7 @@ static int mtk_wdt_restart(struct watchdog_device *wdt_dev,
wdt_base = mtk_wdt->wdt_base;
while (1) {
- writel(WDT_SWRST_KEY, wdt_base + WDT_SWRST);
+ mtk_wdt_write(WDT_SWRST_KEY, wdt_base + WDT_SWRST);
mdelay(5);
}
@@ -169,7 +183,7 @@ static int mtk_wdt_ping(struct watchdog_device *wdt_dev)
struct mtk_wdt_dev *mtk_wdt = watchdog_get_drvdata(wdt_dev);
void __iomem *wdt_base = mtk_wdt->wdt_base;
- iowrite32(WDT_RST_RELOAD, wdt_base + WDT_RST);
+ mtk_wdt_iowrite(WDT_RST_RELOAD, wdt_base + WDT_RST);
return 0;
}
@@ -188,7 +202,7 @@ static int mtk_wdt_set_timeout(struct watchdog_device *wdt_dev,
* The clock has 32 KHz
*/
reg = WDT_LENGTH_TIMEOUT(timeout << 6) | WDT_LENGTH_KEY;
- iowrite32(reg, wdt_base + WDT_LENGTH);
+ mtk_wdt_iowrite(reg, wdt_base + WDT_LENGTH);
mtk_wdt_ping(wdt_dev);
@@ -201,10 +215,10 @@ static int mtk_wdt_stop(struct watchdog_device *wdt_dev)
void __iomem *wdt_base = mtk_wdt->wdt_base;
u32 reg;
- reg = readl(wdt_base + WDT_MODE);
+ reg = mtk_wdt_read(wdt_base + WDT_MODE);
reg &= ~WDT_MODE_EN;
reg |= WDT_MODE_KEY;
- iowrite32(reg, wdt_base + WDT_MODE);
+ mtk_wdt_iowrite(reg, wdt_base + WDT_MODE);
return 0;
}
@@ -220,10 +234,10 @@ static int mtk_wdt_start(struct watchdog_device *wdt_dev)
if (ret < 0)
return ret;
- reg = ioread32(wdt_base + WDT_MODE);
+ reg = mtk_wdt_ioread(wdt_base + WDT_MODE);
reg &= ~(WDT_MODE_IRQ_EN | WDT_MODE_DUAL_EN);
reg |= (WDT_MODE_EN | WDT_MODE_KEY);
- iowrite32(reg, wdt_base + WDT_MODE);
+ mtk_wdt_iowrite(reg, wdt_base + WDT_MODE);
return 0;
}
--
2.20.1
More information about the Linux-mediatek
mailing list