diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2024-01-12 13:32:30 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2024-01-12 13:32:30 -0800 |
commit | 61f4c3e6711477b8a347ca5fe89e5e6613e0a147 (patch) | |
tree | ca318abb0ad8cb84c2246f0dac97d69c4dafc60b /drivers/watchdog | |
parent | 5dfec3cf3efbd897d774e3b5c08c2f0deaf9b5ad (diff) | |
parent | 9546b21ea672aa961d5a89ea754214afed013f02 (diff) | |
download | lwn-61f4c3e6711477b8a347ca5fe89e5e6613e0a147.tar.gz lwn-61f4c3e6711477b8a347ca5fe89e5e6613e0a147.zip |
Merge tag 'linux-watchdog-6.8-rc1' of git://www.linux-watchdog.org/linux-watchdog
Pull watchdog updates from Wim Van Sebroeck:
- Add Mediatek MT7988 watchdog
- Add IT8659 watchdog
- watchdog: set cdev owner before adding
- hpwdt: Only claim UNKNOWN NMI if from iLO
- Various other fixes and improvements
* tag 'linux-watchdog-6.8-rc1' of git://www.linux-watchdog.org/linux-watchdog: (30 commits)
watchdog: mlx_wdt: fix all kernel-doc warnings
dt-bindings: watchdog: qcom,pm8916-wdt: add parent spmi node to example
dt-bindings: watchdog: nxp,pnx4008-wdt: convert txt to yaml
dt-bindings: watchdog: qca,ar7130-wdt: convert txt to yaml
dt-bindings: watchdog: intel,keembay: reference common watchdog schema
dt-bindings: watchdog: re-order entries to match coding convention
watchdog: it87_wdt: Keep WDTCTRL bit 3 unmodified for IT8784/IT8786
watchdog: it87_wdt: Add IT8659 ID
watchdog: it87_wdt: Remove redundant max_units setting
watchdog: it87_wdt: add blank line after variable declaration
dt-bindings: wdt: Add ts72xx
dt-bindings: watchdog: dlg,da9062-watchdog: Document DA9063 watchdog
dt-bindings: watchdog: dlg,da9062-watchdog: Add fallback for DA9061 watchdog
watchdog: rti_wdt: Drop runtime pm reference count when watchdog is unused
watchdog: starfive: add lock annotations to fix context imbalances
watchdog: mediatek: mt7988: add wdt support
dt-bindings: watchdog: mediatek,mtk-wdt: add MT7988 watchdog and toprgu
dt-bindings: watchdog: realtek,rtd1295-watchdog: convert txt to yaml
watchdog: bcm2835_wdt: Fix WDIOC_SETTIMEOUT handling
watchdog/hpwdt: Remove unused variable
...
Diffstat (limited to 'drivers/watchdog')
-rw-r--r-- | drivers/watchdog/at91sam9_wdt.c | 12 | ||||
-rw-r--r-- | drivers/watchdog/bcm2835_wdt.c | 3 | ||||
-rw-r--r-- | drivers/watchdog/hpwdt.c | 9 | ||||
-rw-r--r-- | drivers/watchdog/it87_wdt.c | 29 | ||||
-rw-r--r-- | drivers/watchdog/mlx_wdt.c | 4 | ||||
-rw-r--r-- | drivers/watchdog/mtk_wdt.c | 42 | ||||
-rw-r--r-- | drivers/watchdog/rti_wdt.c | 13 | ||||
-rw-r--r-- | drivers/watchdog/starfive-wdt.c | 8 | ||||
-rw-r--r-- | drivers/watchdog/txx9wdt.c | 11 | ||||
-rw-r--r-- | drivers/watchdog/watchdog_dev.c | 3 |
10 files changed, 94 insertions, 40 deletions
diff --git a/drivers/watchdog/at91sam9_wdt.c b/drivers/watchdog/at91sam9_wdt.c index b111b28acb94..2c6474cb858b 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/bcm2835_wdt.c b/drivers/watchdog/bcm2835_wdt.c index 7a855289ff5e..bb001c5d7f17 100644 --- a/drivers/watchdog/bcm2835_wdt.c +++ b/drivers/watchdog/bcm2835_wdt.c @@ -42,6 +42,7 @@ #define SECS_TO_WDOG_TICKS(x) ((x) << 16) #define WDOG_TICKS_TO_SECS(x) ((x) >> 16) +#define WDOG_TICKS_TO_MSECS(x) ((x) * 1000 >> 16) struct bcm2835_wdt { void __iomem *base; @@ -140,7 +141,7 @@ static struct watchdog_device bcm2835_wdt_wdd = { .info = &bcm2835_wdt_info, .ops = &bcm2835_wdt_ops, .min_timeout = 1, - .max_timeout = WDOG_TICKS_TO_SECS(PM_WDOG_TIME_SET), + .max_hw_heartbeat_ms = WDOG_TICKS_TO_MSECS(PM_WDOG_TIME_SET), .timeout = WDOG_TICKS_TO_SECS(PM_WDOG_TIME_SET), }; diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c index f79f932bca14..138dc8d8ca3d 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); @@ -178,10 +177,7 @@ static int hpwdt_pretimeout(unsigned int ulReason, struct pt_regs *regs) "3. OA Forward Progress Log\n" "4. iLO Event Log"; - if (ilo5 && ulReason == NMI_UNKNOWN && !mynmi) - return NMI_DONE; - - if (ilo5 && !pretimeout && !mynmi) + if (ulReason == NMI_UNKNOWN && !mynmi) return NMI_DONE; 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 e888b1bdd1f2..9297a5891912 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); @@ -256,6 +258,7 @@ static struct watchdog_device wdt_dev = { static int __init it87_wdt_init(void) { u8 chip_rev; + u8 ctrl; int rc; rc = superio_enter(); @@ -273,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: @@ -284,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: @@ -315,7 +317,18 @@ static int __init it87_wdt_init(void) superio_select(GPIO); superio_outb(WDT_TOV1, WDTCFG); - superio_outb(0x00, WDTCTRL); + + switch (chip_type) { + case IT8784_ID: + case IT8786_ID: + ctrl = superio_inb(WDTCTRL); + ctrl &= 0x08; + superio_outb(ctrl, WDTCTRL); + break; + default: + superio_outb(0x00, WDTCTRL); + } + superio_exit(); if (timeout < 1 || timeout > max_units * 60) { diff --git a/drivers/watchdog/mlx_wdt.c b/drivers/watchdog/mlx_wdt.c index 667e2c5b3431..5dc69363f06a 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 b2330b16b497..c35f85ce8d69 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/rti_wdt.c b/drivers/watchdog/rti_wdt.c index 8e1be7ba0103..9215793a1c81 100644 --- a/drivers/watchdog/rti_wdt.c +++ b/drivers/watchdog/rti_wdt.c @@ -77,6 +77,11 @@ static int rti_wdt_start(struct watchdog_device *wdd) { u32 timer_margin; struct rti_wdt_device *wdt = watchdog_get_drvdata(wdd); + int ret; + + ret = pm_runtime_resume_and_get(wdd->parent); + if (ret) + return ret; /* set timeout period */ timer_margin = (u64)wdd->timeout * wdt->freq; @@ -343,6 +348,9 @@ static int rti_wdt_probe(struct platform_device *pdev) if (last_ping) watchdog_set_last_hw_keepalive(wdd, last_ping); + if (!watchdog_hw_running(wdd)) + pm_runtime_put_sync(&pdev->dev); + return 0; err_iomap: @@ -357,7 +365,10 @@ static void rti_wdt_remove(struct platform_device *pdev) struct rti_wdt_device *wdt = platform_get_drvdata(pdev); watchdog_unregister_device(&wdt->wdd); - pm_runtime_put(&pdev->dev); + + if (!pm_runtime_suspended(&pdev->dev)) + pm_runtime_put(&pdev->dev); + pm_runtime_disable(&pdev->dev); } diff --git a/drivers/watchdog/starfive-wdt.c b/drivers/watchdog/starfive-wdt.c index 5f501b41faf9..e28ead24c520 100644 --- a/drivers/watchdog/starfive-wdt.c +++ b/drivers/watchdog/starfive-wdt.c @@ -202,12 +202,14 @@ static u32 starfive_wdt_ticks_to_sec(struct starfive_wdt *wdt, u32 ticks) /* Write unlock-key to unlock. Write other value to lock. */ static void starfive_wdt_unlock(struct starfive_wdt *wdt) + __acquires(&wdt->lock) { spin_lock(&wdt->lock); writel(wdt->variant->unlock_key, wdt->base + wdt->variant->unlock); } static void starfive_wdt_lock(struct starfive_wdt *wdt) + __releases(&wdt->lock) { writel(~wdt->variant->unlock_key, wdt->base + wdt->variant->unlock); spin_unlock(&wdt->lock); @@ -504,7 +506,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); @@ -516,8 +518,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) @@ -587,7 +587,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 89a54b6645bd..8d5f67acbff2 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"); diff --git a/drivers/watchdog/watchdog_dev.c b/drivers/watchdog/watchdog_dev.c index 15df74e11a59..e2bd266b1b5b 100644 --- a/drivers/watchdog/watchdog_dev.c +++ b/drivers/watchdog/watchdog_dev.c @@ -1073,6 +1073,7 @@ static int watchdog_cdev_register(struct watchdog_device *wdd) /* Fill in the data structures */ cdev_init(&wd_data->cdev, &watchdog_fops); + wd_data->cdev.owner = wdd->ops->owner; /* Add the device */ err = cdev_device_add(&wd_data->cdev, &wd_data->dev); @@ -1087,8 +1088,6 @@ static int watchdog_cdev_register(struct watchdog_device *wdd) return err; } - wd_data->cdev.owner = wdd->ops->owner; - /* Record time of most recent heartbeat as 'just before now'. */ wd_data->last_hw_keepalive = ktime_sub(ktime_get(), 1); watchdog_set_open_deadline(wd_data); |