diff options
Diffstat (limited to 'drivers/watchdog')
-rw-r--r-- | drivers/watchdog/at91sam9_wdt.c | 12 | ||||
-rw-r--r-- | drivers/watchdog/hpwdt.c | 7 | ||||
-rw-r--r-- | drivers/watchdog/it87_wdt.c | 15 | ||||
-rw-r--r-- | drivers/watchdog/mlx_wdt.c | 4 | ||||
-rw-r--r-- | drivers/watchdog/mtk_wdt.c | 42 | ||||
-rw-r--r-- | drivers/watchdog/s3c2410_wdt.c | 85 | ||||
-rw-r--r-- | drivers/watchdog/starfive-wdt.c | 6 | ||||
-rw-r--r-- | drivers/watchdog/txx9wdt.c | 11 |
8 files changed, 136 insertions, 46 deletions
diff --git a/drivers/watchdog/at91sam9_wdt.c b/drivers/watchdog/at91sam9_wdt.c index b111b28acb..2c6474cb85 100644 --- a/drivers/watchdog/at91sam9_wdt.c +++ b/drivers/watchdog/at91sam9_wdt.c @@ -324,7 +324,7 @@ static inline int of_at91wdt_init(struct device_node *np, struct at91wdt *wdt) } #endif -static int __init at91wdt_probe(struct platform_device *pdev) +static int at91wdt_probe(struct platform_device *pdev) { int err; struct at91wdt *wdt; @@ -372,15 +372,13 @@ static int __init at91wdt_probe(struct platform_device *pdev) return 0; } -static int __exit at91wdt_remove(struct platform_device *pdev) +static void at91wdt_remove(struct platform_device *pdev) { struct at91wdt *wdt = platform_get_drvdata(pdev); watchdog_unregister_device(&wdt->wdd); pr_warn("I quit now, hardware will probably reboot!\n"); del_timer(&wdt->timer); - - return 0; } #if defined(CONFIG_OF) @@ -393,14 +391,14 @@ MODULE_DEVICE_TABLE(of, at91_wdt_dt_ids); #endif static struct platform_driver at91wdt_driver = { - .remove = __exit_p(at91wdt_remove), + .probe = at91wdt_probe, + .remove_new = at91wdt_remove, .driver = { .name = "at91_wdt", .of_match_table = of_match_ptr(at91_wdt_dt_ids), }, }; - -module_platform_driver_probe(at91wdt_driver, at91wdt_probe); +module_platform_driver(at91wdt_driver); MODULE_AUTHOR("Renaud CERRATO <r.cerrato@til-technologies.fr>"); MODULE_DESCRIPTION("Watchdog driver for Atmel AT91SAM9x processors"); diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c index 79ed1626d8..138dc8d8ca 100644 --- a/drivers/watchdog/hpwdt.c +++ b/drivers/watchdog/hpwdt.c @@ -33,7 +33,6 @@ #define DEFAULT_MARGIN 30 #define PRETIMEOUT_SEC 9 -static bool ilo5; static unsigned int soft_margin = DEFAULT_MARGIN; /* in seconds */ static bool nowayout = WATCHDOG_NOWAYOUT; static bool pretimeout = IS_ENABLED(CONFIG_HPWDT_NMI_DECODING); @@ -181,9 +180,6 @@ static int hpwdt_pretimeout(unsigned int ulReason, struct pt_regs *regs) if (ulReason == NMI_UNKNOWN && !mynmi) return NMI_DONE; - if (ilo5 && !pretimeout && !mynmi) - return NMI_DONE; - if (kdumptimeout < 0) hpwdt_stop(); else if (kdumptimeout == 0) @@ -363,9 +359,6 @@ static int hpwdt_init_one(struct pci_dev *dev, pretimeout ? "on" : "off"); dev_info(&dev->dev, "kdumptimeout: %d.\n", kdumptimeout); - if (dev->subsystem_vendor == PCI_VENDOR_ID_HP_3PAR) - ilo5 = true; - return 0; error_wd_register: diff --git a/drivers/watchdog/it87_wdt.c b/drivers/watchdog/it87_wdt.c index 8c1ee072f4..9297a58919 100644 --- a/drivers/watchdog/it87_wdt.c +++ b/drivers/watchdog/it87_wdt.c @@ -13,9 +13,9 @@ * http://www.ite.com.tw/ * * Support of the watchdog timers, which are available on - * IT8607, IT8613, IT8620, IT8622, IT8625, IT8628, IT8655, IT8665, - * IT8686, IT8702, IT8712, IT8716, IT8718, IT8720, IT8721, IT8726, - * IT8728, IT8772, IT8783 and IT8784. + * IT8607, IT8613, IT8620, IT8622, IT8625, IT8628, IT8655, IT8659, + * IT8665, IT8686, IT8702, IT8712, IT8716, IT8718, IT8720, IT8721, + * IT8726, IT8728, IT8772, IT8783, IT8784 and IT8786. */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt @@ -56,6 +56,7 @@ #define IT8625_ID 0x8625 #define IT8628_ID 0x8628 #define IT8655_ID 0x8655 +#define IT8659_ID 0x8659 #define IT8665_ID 0x8665 #define IT8686_ID 0x8686 #define IT8702_ID 0x8702 @@ -146,6 +147,7 @@ static inline void superio_outb(int val, int reg) static inline int superio_inw(int reg) { int val; + outb(reg++, REG); val = inb(VAL) << 8; outb(reg, REG); @@ -274,10 +276,6 @@ static int __init it87_wdt_init(void) case IT8712_ID: max_units = (chip_rev < 8) ? 255 : 65535; break; - case IT8716_ID: - case IT8726_ID: - max_units = 65535; - break; case IT8607_ID: case IT8613_ID: case IT8620_ID: @@ -285,11 +283,14 @@ static int __init it87_wdt_init(void) case IT8625_ID: case IT8628_ID: case IT8655_ID: + case IT8659_ID: case IT8665_ID: case IT8686_ID: + case IT8716_ID: case IT8718_ID: case IT8720_ID: case IT8721_ID: + case IT8726_ID: case IT8728_ID: case IT8772_ID: case IT8783_ID: diff --git a/drivers/watchdog/mlx_wdt.c b/drivers/watchdog/mlx_wdt.c index 667e2c5b34..5dc69363f0 100644 --- a/drivers/watchdog/mlx_wdt.c +++ b/drivers/watchdog/mlx_wdt.c @@ -30,17 +30,15 @@ * struct mlxreg_wdt - wd private data: * * @wdd: watchdog device; - * @device: basic device; * @pdata: data received from platform driver; * @regmap: register map of parent device; - * @timeout: defined timeout in sec.; * @action_idx: index for direct access to action register; * @timeout_idx:index for direct access to TO register; * @tleft_idx: index for direct access to time left register; * @ping_idx: index for direct access to ping register; * @reset_idx: index for direct access to reset cause register; * @regmap_val_sz: size of value in register map; - * @wd_type: watchdog HW type; + * @wdt_type: watchdog HW type; */ struct mlxreg_wdt { struct watchdog_device wdd; diff --git a/drivers/watchdog/mtk_wdt.c b/drivers/watchdog/mtk_wdt.c index b2330b16b4..c35f85ce8d 100644 --- a/drivers/watchdog/mtk_wdt.c +++ b/drivers/watchdog/mtk_wdt.c @@ -58,9 +58,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; @@ -71,10 +75,12 @@ 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 = { @@ -89,6 +95,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, }; @@ -109,6 +120,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) { @@ -119,6 +152,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); @@ -127,6 +163,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; @@ -406,6 +445,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 = @@ -444,6 +485,7 @@ static const struct of_device_id mtk_wdt_dt_ids[] = { { .compatible = "mediatek,mt6589-wdt" }, { .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 }, diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c index 0b4bd883ff..349d30462c 100644 --- a/drivers/watchdog/s3c2410_wdt.c +++ b/drivers/watchdog/s3c2410_wdt.c @@ -9,6 +9,7 @@ * (c) Copyright 1996 Alan Cox <alan@lxorguk.ukuu.org.uk> */ +#include <linux/bits.h> #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/types.h> @@ -34,9 +35,10 @@ #define S3C2410_WTCNT_MAXCNT 0xffff -#define S3C2410_WTCON_RSTEN (1 << 0) -#define S3C2410_WTCON_INTEN (1 << 2) -#define S3C2410_WTCON_ENABLE (1 << 5) +#define S3C2410_WTCON_RSTEN BIT(0) +#define S3C2410_WTCON_INTEN BIT(2) +#define S3C2410_WTCON_ENABLE BIT(5) +#define S3C2410_WTCON_DBGACK_MASK BIT(16) #define S3C2410_WTCON_DIV16 (0 << 3) #define S3C2410_WTCON_DIV32 (1 << 3) @@ -67,6 +69,13 @@ #define EXYNOSAUTOV9_CLUSTER0_WDTRESET_BIT 25 #define EXYNOSAUTOV9_CLUSTER1_WDTRESET_BIT 24 +#define GS_CLUSTER0_NONCPU_OUT 0x1220 +#define GS_CLUSTER1_NONCPU_OUT 0x1420 +#define GS_CLUSTER0_NONCPU_INT_EN 0x1244 +#define GS_CLUSTER1_NONCPU_INT_EN 0x1444 +#define GS_CLUSTER2_NONCPU_INT_EN 0x1644 +#define GS_RST_STAT_REG_OFFSET 0x3B44 + /** * DOC: Quirk flags for different Samsung watchdog IP-cores * @@ -100,12 +109,17 @@ * %QUIRK_HAS_PMU_CNT_EN: PMU block has some register (e.g. CLUSTERx_NONCPU_OUT) * with "watchdog counter enable" bit. That bit should be set to make watchdog * counter running. + * + * %QUIRK_HAS_DBGACK_BIT: WTCON register has DBGACK_MASK bit. Setting the + * DBGACK_MASK bit disables the watchdog outputs when the SoC is in debug mode. + * Debug mode is determined by the DBGACK CPU signal. */ -#define QUIRK_HAS_WTCLRINT_REG (1 << 0) -#define QUIRK_HAS_PMU_MASK_RESET (1 << 1) -#define QUIRK_HAS_PMU_RST_STAT (1 << 2) -#define QUIRK_HAS_PMU_AUTO_DISABLE (1 << 3) -#define QUIRK_HAS_PMU_CNT_EN (1 << 4) +#define QUIRK_HAS_WTCLRINT_REG BIT(0) +#define QUIRK_HAS_PMU_MASK_RESET BIT(1) +#define QUIRK_HAS_PMU_RST_STAT BIT(2) +#define QUIRK_HAS_PMU_AUTO_DISABLE BIT(3) +#define QUIRK_HAS_PMU_CNT_EN BIT(4) +#define QUIRK_HAS_DBGACK_BIT BIT(5) /* These quirks require that we have a PMU register map */ #define QUIRKS_HAVE_PMUREG \ @@ -263,7 +277,35 @@ static const struct s3c2410_wdt_variant drv_data_exynosautov9_cl1 = { QUIRK_HAS_PMU_RST_STAT | QUIRK_HAS_PMU_CNT_EN, }; +static const struct s3c2410_wdt_variant drv_data_gs101_cl0 = { + .mask_reset_reg = GS_CLUSTER0_NONCPU_INT_EN, + .mask_bit = 2, + .mask_reset_inv = true, + .rst_stat_reg = GS_RST_STAT_REG_OFFSET, + .rst_stat_bit = 0, + .cnt_en_reg = GS_CLUSTER0_NONCPU_OUT, + .cnt_en_bit = 8, + .quirks = QUIRK_HAS_PMU_RST_STAT | QUIRK_HAS_PMU_MASK_RESET | + QUIRK_HAS_PMU_CNT_EN | QUIRK_HAS_WTCLRINT_REG | + QUIRK_HAS_DBGACK_BIT, +}; + +static const struct s3c2410_wdt_variant drv_data_gs101_cl1 = { + .mask_reset_reg = GS_CLUSTER1_NONCPU_INT_EN, + .mask_bit = 2, + .mask_reset_inv = true, + .rst_stat_reg = GS_RST_STAT_REG_OFFSET, + .rst_stat_bit = 1, + .cnt_en_reg = GS_CLUSTER1_NONCPU_OUT, + .cnt_en_bit = 7, + .quirks = QUIRK_HAS_PMU_RST_STAT | QUIRK_HAS_PMU_MASK_RESET | + QUIRK_HAS_PMU_CNT_EN | QUIRK_HAS_WTCLRINT_REG | + QUIRK_HAS_DBGACK_BIT, +}; + static const struct of_device_id s3c2410_wdt_match[] = { + { .compatible = "google,gs101-wdt", + .data = &drv_data_gs101_cl0 }, { .compatible = "samsung,s3c2410-wdt", .data = &drv_data_s3c2410 }, { .compatible = "samsung,s3c6410-wdt", @@ -375,6 +417,19 @@ static int s3c2410wdt_enable(struct s3c2410_wdt *wdt, bool en) return 0; } +/* Disable watchdog outputs if CPU is in debug mode */ +static void s3c2410wdt_mask_dbgack(struct s3c2410_wdt *wdt) +{ + unsigned long wtcon; + + if (!(wdt->drv_data->quirks & QUIRK_HAS_DBGACK_BIT)) + return; + + wtcon = readl(wdt->reg_base + S3C2410_WTCON); + wtcon |= S3C2410_WTCON_DBGACK_MASK; + writel(wtcon, wdt->reg_base + S3C2410_WTCON); +} + static int s3c2410wdt_keepalive(struct watchdog_device *wdd) { struct s3c2410_wdt *wdt = watchdog_get_drvdata(wdd); @@ -587,7 +642,8 @@ s3c2410_get_wdt_drv_data(struct platform_device *pdev, struct s3c2410_wdt *wdt) #ifdef CONFIG_OF /* Choose Exynos850/ExynosAutov9 driver data w.r.t. cluster index */ if (variant == &drv_data_exynos850_cl0 || - variant == &drv_data_exynosautov9_cl0) { + variant == &drv_data_exynosautov9_cl0 || + variant == &drv_data_gs101_cl0) { u32 index; int err; @@ -600,9 +656,12 @@ s3c2410_get_wdt_drv_data(struct platform_device *pdev, struct s3c2410_wdt *wdt) case 0: break; case 1: - variant = (variant == &drv_data_exynos850_cl0) ? - &drv_data_exynos850_cl1 : - &drv_data_exynosautov9_cl1; + if (variant == &drv_data_exynos850_cl0) + variant = &drv_data_exynos850_cl1; + else if (variant == &drv_data_exynosautov9_cl0) + variant = &drv_data_exynosautov9_cl1; + else if (variant == &drv_data_gs101_cl0) + variant = &drv_data_gs101_cl1; break; default: return dev_err_probe(dev, -EINVAL, "wrong cluster index: %u\n", index); @@ -700,6 +759,8 @@ static int s3c2410wdt_probe(struct platform_device *pdev) wdt->wdt_device.bootstatus = s3c2410wdt_get_bootstatus(wdt); wdt->wdt_device.parent = dev; + s3c2410wdt_mask_dbgack(wdt); + /* * If "tmr_atboot" param is non-zero, start the watchdog right now. Also * set WDOG_HW_RUNNING bit, so that watchdog core can kick the watchdog. diff --git a/drivers/watchdog/starfive-wdt.c b/drivers/watchdog/starfive-wdt.c index e4b344db38..df68ae4acb 100644 --- a/drivers/watchdog/starfive-wdt.c +++ b/drivers/watchdog/starfive-wdt.c @@ -511,7 +511,7 @@ err_exit: return ret; } -static int starfive_wdt_remove(struct platform_device *pdev) +static void starfive_wdt_remove(struct platform_device *pdev) { struct starfive_wdt *wdt = platform_get_drvdata(pdev); @@ -523,8 +523,6 @@ static int starfive_wdt_remove(struct platform_device *pdev) else /* disable clock without PM */ starfive_wdt_disable_clock(wdt); - - return 0; } static void starfive_wdt_shutdown(struct platform_device *pdev) @@ -594,7 +592,7 @@ MODULE_DEVICE_TABLE(of, starfive_wdt_match); static struct platform_driver starfive_wdt_driver = { .probe = starfive_wdt_probe, - .remove = starfive_wdt_remove, + .remove_new = starfive_wdt_remove, .shutdown = starfive_wdt_shutdown, .driver = { .name = "starfive-wdt", diff --git a/drivers/watchdog/txx9wdt.c b/drivers/watchdog/txx9wdt.c index 89a54b6645..8d5f67acbf 100644 --- a/drivers/watchdog/txx9wdt.c +++ b/drivers/watchdog/txx9wdt.c @@ -98,7 +98,7 @@ static struct watchdog_device txx9wdt = { .ops = &txx9wdt_ops, }; -static int __init txx9wdt_probe(struct platform_device *dev) +static int txx9wdt_probe(struct platform_device *dev) { int ret; @@ -145,12 +145,11 @@ exit: return ret; } -static int __exit txx9wdt_remove(struct platform_device *dev) +static void txx9wdt_remove(struct platform_device *dev) { watchdog_unregister_device(&txx9wdt); clk_disable_unprepare(txx9_imclk); clk_put(txx9_imclk); - return 0; } static void txx9wdt_shutdown(struct platform_device *dev) @@ -159,14 +158,14 @@ static void txx9wdt_shutdown(struct platform_device *dev) } static struct platform_driver txx9wdt_driver = { - .remove = __exit_p(txx9wdt_remove), + .probe = txx9wdt_probe, + .remove_new = txx9wdt_remove, .shutdown = txx9wdt_shutdown, .driver = { .name = "txx9wdt", }, }; - -module_platform_driver_probe(txx9wdt_driver, txx9wdt_probe); +module_platform_driver(txx9wdt_driver); MODULE_DESCRIPTION("TXx9 Watchdog Driver"); MODULE_LICENSE("GPL"); |