diff options
Diffstat (limited to 'drivers/watchdog/mtk_wdt.c')
| -rw-r--r-- | drivers/watchdog/mtk_wdt.c | 55 |
1 files changed, 54 insertions, 1 deletions
diff --git a/drivers/watchdog/mtk_wdt.c b/drivers/watchdog/mtk_wdt.c index a9c437598e7e..91d110646e16 100644 --- a/drivers/watchdog/mtk_wdt.c +++ b/drivers/watchdog/mtk_wdt.c @@ -10,6 +10,7 @@ */ #include <dt-bindings/reset/mt2712-resets.h> +#include <dt-bindings/reset/mediatek,mt6735-wdt.h> #include <dt-bindings/reset/mediatek,mt6795-resets.h> #include <dt-bindings/reset/mt7986-resets.h> #include <dt-bindings/reset/mt8183-resets.h> @@ -25,7 +26,6 @@ #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/reset-controller.h> #include <linux/types.h> @@ -59,9 +59,13 @@ #define WDT_SWSYSRST 0x18U #define WDT_SWSYS_RST_KEY 0x88000000 +#define WDT_SWSYSRST_EN 0xfc + #define DRV_NAME "mtk-wdt" #define DRV_VERSION "1.0" +#define MT7988_TOPRGU_SW_RST_NUM 24 + static bool nowayout = WATCHDOG_NOWAYOUT; static unsigned int timeout; @@ -72,16 +76,22 @@ struct mtk_wdt_dev { struct reset_controller_dev rcdev; bool disable_wdt_extrst; bool reset_by_toprgu; + bool has_swsysrst_en; }; struct mtk_wdt_data { int toprgu_sw_rst_num; + bool has_swsysrst_en; }; static const struct mtk_wdt_data mt2712_data = { .toprgu_sw_rst_num = MT2712_TOPRGU_SW_RST_NUM, }; +static const struct mtk_wdt_data mt6735_data = { + .toprgu_sw_rst_num = MT6735_TOPRGU_RST_NUM, +}; + static const struct mtk_wdt_data mt6795_data = { .toprgu_sw_rst_num = MT6795_TOPRGU_SW_RST_NUM, }; @@ -90,6 +100,11 @@ static const struct mtk_wdt_data mt7986_data = { .toprgu_sw_rst_num = MT7986_TOPRGU_SW_RST_NUM, }; +static const struct mtk_wdt_data mt7988_data = { + .toprgu_sw_rst_num = MT7988_TOPRGU_SW_RST_NUM, + .has_swsysrst_en = true, +}; + static const struct mtk_wdt_data mt8183_data = { .toprgu_sw_rst_num = MT8183_TOPRGU_SW_RST_NUM, }; @@ -110,6 +125,28 @@ static const struct mtk_wdt_data mt8195_data = { .toprgu_sw_rst_num = MT8195_TOPRGU_SW_RST_NUM, }; +/** + * toprgu_reset_sw_en_unlocked() - enable/disable software control for reset bit + * @data: Pointer to instance of driver data. + * @id: Bit number identifying the reset to be enabled or disabled. + * @enable: If true, enable software control for that bit, disable otherwise. + * + * Context: The caller must hold lock of struct mtk_wdt_dev. + */ +static void toprgu_reset_sw_en_unlocked(struct mtk_wdt_dev *data, + unsigned long id, bool enable) +{ + u32 tmp; + + tmp = readl(data->wdt_base + WDT_SWSYSRST_EN); + if (enable) + tmp |= BIT(id); + else + tmp &= ~BIT(id); + + writel(tmp, data->wdt_base + WDT_SWSYSRST_EN); +} + static int toprgu_reset_update(struct reset_controller_dev *rcdev, unsigned long id, bool assert) { @@ -120,6 +157,9 @@ static int toprgu_reset_update(struct reset_controller_dev *rcdev, spin_lock_irqsave(&data->lock, flags); + if (assert && data->has_swsysrst_en) + toprgu_reset_sw_en_unlocked(data, id, true); + tmp = readl(data->wdt_base + WDT_SWSYSRST); if (assert) tmp |= BIT(id); @@ -128,6 +168,9 @@ static int toprgu_reset_update(struct reset_controller_dev *rcdev, tmp |= WDT_SWSYS_RST_KEY; writel(tmp, data->wdt_base + WDT_SWSYSRST); + if (!assert && data->has_swsysrst_en) + toprgu_reset_sw_en_unlocked(data, id, false); + spin_unlock_irqrestore(&data->lock, flags); return 0; @@ -187,9 +230,15 @@ static int mtk_wdt_restart(struct watchdog_device *wdt_dev, { struct mtk_wdt_dev *mtk_wdt = watchdog_get_drvdata(wdt_dev); void __iomem *wdt_base; + u32 reg; wdt_base = mtk_wdt->wdt_base; + /* Enable reset in order to issue a system reset instead of an IRQ */ + reg = readl(wdt_base + WDT_MODE); + reg &= ~WDT_MODE_IRQ_EN; + writel(reg | WDT_MODE_KEY, wdt_base + WDT_MODE); + while (1) { writel(WDT_SWRST_KEY, wdt_base + WDT_SWRST); mdelay(5); @@ -407,6 +456,8 @@ static int mtk_wdt_probe(struct platform_device *pdev) wdt_data->toprgu_sw_rst_num); if (err) return err; + + mtk_wdt->has_swsysrst_en = wdt_data->has_swsysrst_en; } mtk_wdt->disable_wdt_extrst = @@ -443,8 +494,10 @@ static int mtk_wdt_resume(struct device *dev) static const struct of_device_id mtk_wdt_dt_ids[] = { { .compatible = "mediatek,mt2712-wdt", .data = &mt2712_data }, { .compatible = "mediatek,mt6589-wdt" }, + { .compatible = "mediatek,mt6735-wdt", .data = &mt6735_data }, { .compatible = "mediatek,mt6795-wdt", .data = &mt6795_data }, { .compatible = "mediatek,mt7986-wdt", .data = &mt7986_data }, + { .compatible = "mediatek,mt7988-wdt", .data = &mt7988_data }, { .compatible = "mediatek,mt8183-wdt", .data = &mt8183_data }, { .compatible = "mediatek,mt8186-wdt", .data = &mt8186_data }, { .compatible = "mediatek,mt8188-wdt", .data = &mt8188_data }, |
