diff options
Diffstat (limited to 'drivers/watchdog')
-rw-r--r-- | drivers/watchdog/Kconfig | 9 | ||||
-rw-r--r-- | drivers/watchdog/Makefile | 1 | ||||
-rw-r--r-- | drivers/watchdog/armada_37xx_wdt.c | 2 | ||||
-rw-r--r-- | drivers/watchdog/bcm7038_wdt.c | 8 | ||||
-rw-r--r-- | drivers/watchdog/booke_wdt.c | 2 | ||||
-rw-r--r-- | drivers/watchdog/dw_wdt.c | 8 | ||||
-rw-r--r-- | drivers/watchdog/f71808e_wdt.c | 4 | ||||
-rw-r--r-- | drivers/watchdog/max77620_wdt.c | 4 | ||||
-rw-r--r-- | drivers/watchdog/mtk_wdt.c | 10 | ||||
-rw-r--r-- | drivers/watchdog/pc87413_wdt.c | 2 | ||||
-rw-r--r-- | drivers/watchdog/pm8916_wdt.c | 41 | ||||
-rw-r--r-- | drivers/watchdog/pseries-wdt.c | 239 | ||||
-rw-r--r-- | drivers/watchdog/realtek_otto_wdt.c | 1 | ||||
-rw-r--r-- | drivers/watchdog/s3c2410_wdt.c | 9 | ||||
-rw-r--r-- | drivers/watchdog/sama5d4_wdt.c | 8 | ||||
-rw-r--r-- | drivers/watchdog/simatic-ipc-wdt.c | 15 | ||||
-rw-r--r-- | drivers/watchdog/sp5100_tco.c | 1 | ||||
-rw-r--r-- | drivers/watchdog/sp805_wdt.c | 5 | ||||
-rw-r--r-- | drivers/watchdog/st_lpc_wdt.c | 9 | ||||
-rw-r--r-- | drivers/watchdog/tegra_wdt.c | 14 | ||||
-rw-r--r-- | drivers/watchdog/wdat_wdt.c | 7 |
21 files changed, 335 insertions, 64 deletions
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 32fd37698932..9295492d24f7 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -1647,6 +1647,7 @@ config SIEMENS_SIMATIC_IPC_WDT tristate "Siemens Simatic IPC Watchdog" depends on SIEMENS_SIMATIC_IPC select WATCHDOG_CORE + select P2SB help This driver adds support for several watchdogs found in Industrial PCs from Siemens. @@ -1962,6 +1963,14 @@ config MEN_A21_WDT # PPC64 Architecture +config PSERIES_WDT + tristate "POWER Architecture Platform Watchdog Timer" + depends on PPC_PSERIES + select WATCHDOG_CORE + help + Driver for virtual watchdog timers provided by PAPR + hypervisors (e.g. PowerVM, KVM). + config WATCHDOG_RTAS tristate "RTAS watchdog" depends on PPC_RTAS diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index c324e9d820e9..cdeb119e6e61 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -187,6 +187,7 @@ obj-$(CONFIG_BOOKE_WDT) += booke_wdt.o obj-$(CONFIG_MEN_A21_WDT) += mena21_wdt.o # PPC64 Architecture +obj-$(CONFIG_PSERIES_WDT) += pseries-wdt.o obj-$(CONFIG_WATCHDOG_RTAS) += wdrtas.o # S390 Architecture diff --git a/drivers/watchdog/armada_37xx_wdt.c b/drivers/watchdog/armada_37xx_wdt.c index 1635f421ef2c..854b1cc723cb 100644 --- a/drivers/watchdog/armada_37xx_wdt.c +++ b/drivers/watchdog/armada_37xx_wdt.c @@ -274,6 +274,8 @@ static int armada_37xx_wdt_probe(struct platform_device *pdev) if (!res) return -ENODEV; dev->reg = devm_ioremap(&pdev->dev, res->start, resource_size(res)); + if (!dev->reg) + return -ENOMEM; /* init clock */ dev->clk = devm_clk_get(&pdev->dev, NULL); diff --git a/drivers/watchdog/bcm7038_wdt.c b/drivers/watchdog/bcm7038_wdt.c index 1ffcf6aca6ae..9388838899ac 100644 --- a/drivers/watchdog/bcm7038_wdt.c +++ b/drivers/watchdog/bcm7038_wdt.c @@ -192,7 +192,6 @@ static int bcm7038_wdt_probe(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM_SLEEP static int bcm7038_wdt_suspend(struct device *dev) { struct bcm7038_watchdog *wdt = dev_get_drvdata(dev); @@ -212,10 +211,9 @@ static int bcm7038_wdt_resume(struct device *dev) return 0; } -#endif -static SIMPLE_DEV_PM_OPS(bcm7038_wdt_pm_ops, bcm7038_wdt_suspend, - bcm7038_wdt_resume); +static DEFINE_SIMPLE_DEV_PM_OPS(bcm7038_wdt_pm_ops, + bcm7038_wdt_suspend, bcm7038_wdt_resume); static const struct of_device_id bcm7038_wdt_match[] = { { .compatible = "brcm,bcm6345-wdt" }, @@ -236,7 +234,7 @@ static struct platform_driver bcm7038_wdt_driver = { .driver = { .name = "bcm7038-wdt", .of_match_table = bcm7038_wdt_match, - .pm = &bcm7038_wdt_pm_ops, + .pm = pm_sleep_ptr(&bcm7038_wdt_pm_ops), } }; module_platform_driver(bcm7038_wdt_driver); diff --git a/drivers/watchdog/booke_wdt.c b/drivers/watchdog/booke_wdt.c index 5e4dc1a0f2c6..75da5cd02615 100644 --- a/drivers/watchdog/booke_wdt.c +++ b/drivers/watchdog/booke_wdt.c @@ -74,7 +74,7 @@ static unsigned long long period_to_sec(unsigned int period) /* * This procedure will find the highest period which will give a timeout * greater than the one required. e.g. for a bus speed of 66666666 and - * and a parameter of 2 secs, then this procedure will return a value of 38. + * a parameter of 2 secs, then this procedure will return a value of 38. */ static unsigned int sec_to_period(unsigned int secs) { diff --git a/drivers/watchdog/dw_wdt.c b/drivers/watchdog/dw_wdt.c index cd578843277e..52962e8d11a6 100644 --- a/drivers/watchdog/dw_wdt.c +++ b/drivers/watchdog/dw_wdt.c @@ -218,7 +218,7 @@ static int dw_wdt_set_timeout(struct watchdog_device *wdd, unsigned int top_s) /* * Set the new value in the watchdog. Some versions of dw_wdt - * have have TOPINIT in the TIMEOUT_RANGE register (as per + * have TOPINIT in the TIMEOUT_RANGE register (as per * CP_WDT_DUAL_TOP in WDT_COMP_PARAMS_1). On those we * effectively get a pat of the watchdog right here. */ @@ -375,7 +375,6 @@ static irqreturn_t dw_wdt_irq(int irq, void *devid) return IRQ_HANDLED; } -#ifdef CONFIG_PM_SLEEP static int dw_wdt_suspend(struct device *dev) { struct dw_wdt *dw_wdt = dev_get_drvdata(dev); @@ -410,9 +409,8 @@ static int dw_wdt_resume(struct device *dev) return 0; } -#endif /* CONFIG_PM_SLEEP */ -static SIMPLE_DEV_PM_OPS(dw_wdt_pm_ops, dw_wdt_suspend, dw_wdt_resume); +static DEFINE_SIMPLE_DEV_PM_OPS(dw_wdt_pm_ops, dw_wdt_suspend, dw_wdt_resume); /* * In case if DW WDT IP core is synthesized with fixed TOP feature disabled the @@ -710,7 +708,7 @@ static struct platform_driver dw_wdt_driver = { .driver = { .name = "dw_wdt", .of_match_table = of_match_ptr(dw_wdt_of_match), - .pm = &dw_wdt_pm_ops, + .pm = pm_sleep_ptr(&dw_wdt_pm_ops), }, }; diff --git a/drivers/watchdog/f71808e_wdt.c b/drivers/watchdog/f71808e_wdt.c index 7f59c680de25..6a16d3d0bb1e 100644 --- a/drivers/watchdog/f71808e_wdt.c +++ b/drivers/watchdog/f71808e_wdt.c @@ -634,7 +634,9 @@ static int __init fintek_wdt_init(void) pdata.type = ret; - platform_driver_register(&fintek_wdt_driver); + ret = platform_driver_register(&fintek_wdt_driver); + if (ret) + return ret; wdt_res.name = "superio port"; wdt_res.flags = IORESOURCE_IO; diff --git a/drivers/watchdog/max77620_wdt.c b/drivers/watchdog/max77620_wdt.c index b76ad6ba0915..33835c0b06de 100644 --- a/drivers/watchdog/max77620_wdt.c +++ b/drivers/watchdog/max77620_wdt.c @@ -6,7 +6,7 @@ * Copyright (C) 2022 Luca Ceresoli * * Author: Laxman Dewangan <ldewangan@nvidia.com> - * Author: Luca Ceresoli <luca@lucaceresoli.net> + * Author: Luca Ceresoli <luca.ceresoli@bootlin.com> */ #include <linux/err.h> @@ -260,5 +260,5 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started " "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>"); -MODULE_AUTHOR("Luca Ceresoli <luca@lucaceresoli.net>"); +MODULE_AUTHOR("Luca Ceresoli <luca.ceresoli@bootlin.com>"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/watchdog/mtk_wdt.c b/drivers/watchdog/mtk_wdt.c index f0d4e3cc7459..e97787536792 100644 --- a/drivers/watchdog/mtk_wdt.c +++ b/drivers/watchdog/mtk_wdt.c @@ -401,7 +401,6 @@ static int mtk_wdt_probe(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM_SLEEP static int mtk_wdt_suspend(struct device *dev) { struct mtk_wdt_dev *mtk_wdt = dev_get_drvdata(dev); @@ -423,7 +422,6 @@ static int mtk_wdt_resume(struct device *dev) return 0; } -#endif static const struct of_device_id mtk_wdt_dt_ids[] = { { .compatible = "mediatek,mt2712-wdt", .data = &mt2712_data }, @@ -437,16 +435,14 @@ static const struct of_device_id mtk_wdt_dt_ids[] = { }; MODULE_DEVICE_TABLE(of, mtk_wdt_dt_ids); -static const struct dev_pm_ops mtk_wdt_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(mtk_wdt_suspend, - mtk_wdt_resume) -}; +static DEFINE_SIMPLE_DEV_PM_OPS(mtk_wdt_pm_ops, + mtk_wdt_suspend, mtk_wdt_resume); static struct platform_driver mtk_wdt_driver = { .probe = mtk_wdt_probe, .driver = { .name = DRV_NAME, - .pm = &mtk_wdt_pm_ops, + .pm = pm_sleep_ptr(&mtk_wdt_pm_ops), .of_match_table = mtk_wdt_dt_ids, }, }; diff --git a/drivers/watchdog/pc87413_wdt.c b/drivers/watchdog/pc87413_wdt.c index 9f9a340427fc..c7f745caf203 100644 --- a/drivers/watchdog/pc87413_wdt.c +++ b/drivers/watchdog/pc87413_wdt.c @@ -442,7 +442,7 @@ static long pc87413_ioctl(struct file *file, unsigned int cmd, } } -/* -- Notifier funtions -----------------------------------------*/ +/* -- Notifier functions -----------------------------------------*/ /** * pc87413_notify_sys: diff --git a/drivers/watchdog/pm8916_wdt.c b/drivers/watchdog/pm8916_wdt.c index 0937b8d33104..f4bfbffaf49c 100644 --- a/drivers/watchdog/pm8916_wdt.c +++ b/drivers/watchdog/pm8916_wdt.c @@ -9,6 +9,12 @@ #include <linux/regmap.h> #include <linux/watchdog.h> +#define PON_POFF_REASON1 0x0c +#define PON_POFF_REASON1_PMIC_WD BIT(2) +#define PON_POFF_REASON2 0x0d +#define PON_POFF_REASON2_UVLO BIT(5) +#define PON_POFF_REASON2_OTST3 BIT(6) + #define PON_INT_RT_STS 0x10 #define PMIC_WD_BARK_STS_BIT BIT(6) @@ -58,9 +64,8 @@ static int pm8916_wdt_ping(struct watchdog_device *wdev) { struct pm8916_wdt *wdt = watchdog_get_drvdata(wdev); - return regmap_update_bits(wdt->regmap, - wdt->baseaddr + PON_PMIC_WD_RESET_PET, - WATCHDOG_PET_BIT, WATCHDOG_PET_BIT); + return regmap_write(wdt->regmap, wdt->baseaddr + PON_PMIC_WD_RESET_PET, + WATCHDOG_PET_BIT); } static int pm8916_wdt_configure_timers(struct watchdog_device *wdev) @@ -111,12 +116,14 @@ static irqreturn_t pm8916_wdt_isr(int irq, void *arg) } static const struct watchdog_info pm8916_wdt_ident = { - .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, + .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE | + WDIOF_OVERHEAT | WDIOF_CARDRESET | WDIOF_POWERUNDER, .identity = "QCOM PM8916 PON WDT", }; static const struct watchdog_info pm8916_wdt_pt_ident = { .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE | + WDIOF_OVERHEAT | WDIOF_CARDRESET | WDIOF_POWERUNDER | WDIOF_PRETIMEOUT, .identity = "QCOM PM8916 PON WDT", }; @@ -135,7 +142,9 @@ static int pm8916_wdt_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct pm8916_wdt *wdt; struct device *parent; + unsigned int val; int err, irq; + u8 poff[2]; wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL); if (!wdt) @@ -176,6 +185,30 @@ static int pm8916_wdt_probe(struct platform_device *pdev) wdt->wdev.info = &pm8916_wdt_ident; } + err = regmap_bulk_read(wdt->regmap, wdt->baseaddr + PON_POFF_REASON1, + &poff, ARRAY_SIZE(poff)); + if (err) { + dev_err(dev, "failed to read POFF reason: %d\n", err); + return err; + } + + dev_dbg(dev, "POFF reason: %#x %#x\n", poff[0], poff[1]); + if (poff[0] & PON_POFF_REASON1_PMIC_WD) + wdt->wdev.bootstatus |= WDIOF_CARDRESET; + if (poff[1] & PON_POFF_REASON2_UVLO) + wdt->wdev.bootstatus |= WDIOF_POWERUNDER; + if (poff[1] & PON_POFF_REASON2_OTST3) + wdt->wdev.bootstatus |= WDIOF_OVERHEAT; + + err = regmap_read(wdt->regmap, wdt->baseaddr + PON_PMIC_WD_RESET_S2_CTL2, + &val); + if (err) { + dev_err(dev, "failed to check if watchdog is active: %d\n", err); + return err; + } + if (val & S2_RESET_EN_BIT) + set_bit(WDOG_HW_RUNNING, &wdt->wdev.status); + /* Configure watchdog to hard-reset mode */ err = regmap_write(wdt->regmap, wdt->baseaddr + PON_PMIC_WD_RESET_S2_CTL, diff --git a/drivers/watchdog/pseries-wdt.c b/drivers/watchdog/pseries-wdt.c new file mode 100644 index 000000000000..7f53b5293409 --- /dev/null +++ b/drivers/watchdog/pseries-wdt.c @@ -0,0 +1,239 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2022 International Business Machines, Inc. + */ + +#include <linux/bitops.h> +#include <linux/kernel.h> +#include <linux/limits.h> +#include <linux/math.h> +#include <linux/mod_devicetable.h> +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/platform_device.h> +#include <linux/time64.h> +#include <linux/watchdog.h> + +#define DRV_NAME "pseries-wdt" + +/* + * H_WATCHDOG Input + * + * R4: "flags": + * + * Bits 48-55: "operation" + */ +#define PSERIES_WDTF_OP_START 0x100UL /* start timer */ +#define PSERIES_WDTF_OP_STOP 0x200UL /* stop timer */ +#define PSERIES_WDTF_OP_QUERY 0x300UL /* query timer capabilities */ + +/* + * Bits 56-63: "timeoutAction" (for "Start Watchdog" only) + */ +#define PSERIES_WDTF_ACTION_HARD_POWEROFF 0x1UL /* poweroff */ +#define PSERIES_WDTF_ACTION_HARD_RESTART 0x2UL /* restart */ +#define PSERIES_WDTF_ACTION_DUMP_RESTART 0x3UL /* dump + restart */ + +/* + * H_WATCHDOG Output + * + * R3: Return code + * + * H_SUCCESS The operation completed. + * + * H_BUSY The hypervisor is too busy; retry the operation. + * + * H_PARAMETER The given "flags" are somehow invalid. Either the + * "operation" or "timeoutAction" is invalid, or a + * reserved bit is set. + * + * H_P2 The given "watchdogNumber" is zero or exceeds the + * supported maximum value. + * + * H_P3 The given "timeoutInMs" is below the supported + * minimum value. + * + * H_NOOP The given "watchdogNumber" is already stopped. + * + * H_HARDWARE The operation failed for ineffable reasons. + * + * H_FUNCTION The H_WATCHDOG hypercall is not supported by this + * hypervisor. + * + * R4: + * + * - For the "Query Watchdog Capabilities" operation, a 64-bit + * structure: + */ +#define PSERIES_WDTQ_MIN_TIMEOUT(cap) (((cap) >> 48) & 0xffff) +#define PSERIES_WDTQ_MAX_NUMBER(cap) (((cap) >> 32) & 0xffff) + +static const unsigned long pseries_wdt_action[] = { + [0] = PSERIES_WDTF_ACTION_HARD_POWEROFF, + [1] = PSERIES_WDTF_ACTION_HARD_RESTART, + [2] = PSERIES_WDTF_ACTION_DUMP_RESTART, +}; + +#define WATCHDOG_ACTION 1 +static unsigned int action = WATCHDOG_ACTION; +module_param(action, uint, 0444); +MODULE_PARM_DESC(action, "Action taken when watchdog expires (default=" + __MODULE_STRING(WATCHDOG_ACTION) ")"); + +static bool nowayout = WATCHDOG_NOWAYOUT; +module_param(nowayout, bool, 0444); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" + __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); + +#define WATCHDOG_TIMEOUT 60 +static unsigned int timeout = WATCHDOG_TIMEOUT; +module_param(timeout, uint, 0444); +MODULE_PARM_DESC(timeout, "Initial watchdog timeout in seconds (default=" + __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); + +struct pseries_wdt { + struct watchdog_device wd; + unsigned long action; + unsigned long num; /* Watchdog numbers are 1-based */ +}; + +static int pseries_wdt_start(struct watchdog_device *wdd) +{ + struct pseries_wdt *pw = watchdog_get_drvdata(wdd); + struct device *dev = wdd->parent; + unsigned long flags, msecs; + long rc; + + flags = pw->action | PSERIES_WDTF_OP_START; + msecs = wdd->timeout * MSEC_PER_SEC; + rc = plpar_hcall_norets(H_WATCHDOG, flags, pw->num, msecs); + if (rc != H_SUCCESS) { + dev_crit(dev, "H_WATCHDOG: %ld: failed to start timer %lu", + rc, pw->num); + return -EIO; + } + return 0; +} + +static int pseries_wdt_stop(struct watchdog_device *wdd) +{ + struct pseries_wdt *pw = watchdog_get_drvdata(wdd); + struct device *dev = wdd->parent; + long rc; + + rc = plpar_hcall_norets(H_WATCHDOG, PSERIES_WDTF_OP_STOP, pw->num); + if (rc != H_SUCCESS && rc != H_NOOP) { + dev_crit(dev, "H_WATCHDOG: %ld: failed to stop timer %lu", + rc, pw->num); + return -EIO; + } + return 0; +} + +static struct watchdog_info pseries_wdt_info = { + .identity = DRV_NAME, + .options = WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT + | WDIOF_PRETIMEOUT, +}; + +static const struct watchdog_ops pseries_wdt_ops = { + .owner = THIS_MODULE, + .start = pseries_wdt_start, + .stop = pseries_wdt_stop, +}; + +static int pseries_wdt_probe(struct platform_device *pdev) +{ + unsigned long ret[PLPAR_HCALL_BUFSIZE] = { 0 }; + struct pseries_wdt *pw; + unsigned long cap; + long msecs, rc; + int err; + + rc = plpar_hcall(H_WATCHDOG, ret, PSERIES_WDTF_OP_QUERY); + if (rc == H_FUNCTION) + return -ENODEV; + if (rc != H_SUCCESS) + return -EIO; + cap = ret[0]; + + pw = devm_kzalloc(&pdev->dev, sizeof(*pw), GFP_KERNEL); + if (!pw) + return -ENOMEM; + + /* + * Assume watchdogNumber 1 for now. If we ever support + * multiple timers we will need to devise a way to choose a + * distinct watchdogNumber for each platform device at device + * registration time. + */ + pw->num = 1; + if (PSERIES_WDTQ_MAX_NUMBER(cap) < pw->num) + return -ENODEV; + + if (action >= ARRAY_SIZE(pseries_wdt_action)) + return -EINVAL; + pw->action = pseries_wdt_action[action]; + + pw->wd.parent = &pdev->dev; + pw->wd.info = &pseries_wdt_info; + pw->wd.ops = &pseries_wdt_ops; + msecs = PSERIES_WDTQ_MIN_TIMEOUT(cap); + pw->wd.min_timeout = DIV_ROUND_UP(msecs, MSEC_PER_SEC); + pw->wd.max_timeout = UINT_MAX / 1000; /* from linux/watchdog.h */ + pw->wd.timeout = timeout; + if (watchdog_init_timeout(&pw->wd, 0, NULL)) + return -EINVAL; + watchdog_set_nowayout(&pw->wd, nowayout); + watchdog_stop_on_reboot(&pw->wd); + watchdog_stop_on_unregister(&pw->wd); + watchdog_set_drvdata(&pw->wd, pw); + + err = devm_watchdog_register_device(&pdev->dev, &pw->wd); + if (err) + return err; + + platform_set_drvdata(pdev, &pw->wd); + + return 0; +} + +static int pseries_wdt_suspend(struct platform_device *pdev, pm_message_t state) +{ + struct watchdog_device *wd = platform_get_drvdata(pdev); + + if (watchdog_active(wd)) + return pseries_wdt_stop(wd); + return 0; +} + +static int pseries_wdt_resume(struct platform_device *pdev) +{ + struct watchdog_device *wd = platform_get_drvdata(pdev); + + if (watchdog_active(wd)) + return pseries_wdt_start(wd); + return 0; +} + +static const struct platform_device_id pseries_wdt_id[] = { + { .name = "pseries-wdt" }, + {} +}; +MODULE_DEVICE_TABLE(platform, pseries_wdt_id); + +static struct platform_driver pseries_wdt_driver = { + .driver = { + .name = DRV_NAME, + }, + .id_table = pseries_wdt_id, + .probe = pseries_wdt_probe, + .resume = pseries_wdt_resume, + .suspend = pseries_wdt_suspend, +}; +module_platform_driver(pseries_wdt_driver); + +MODULE_AUTHOR("Alexey Kardashevskiy"); +MODULE_AUTHOR("Scott Cheloha"); +MODULE_DESCRIPTION("POWER Architecture Platform Watchdog Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/watchdog/realtek_otto_wdt.c b/drivers/watchdog/realtek_otto_wdt.c index 60058a0c3ec4..2a5298c5e8e4 100644 --- a/drivers/watchdog/realtek_otto_wdt.c +++ b/drivers/watchdog/realtek_otto_wdt.c @@ -366,6 +366,7 @@ static const struct of_device_id otto_wdt_ids[] = { { .compatible = "realtek,rtl8380-wdt" }, { .compatible = "realtek,rtl8390-wdt" }, { .compatible = "realtek,rtl9300-wdt" }, + { .compatible = "realtek,rtl9310-wdt" }, { } }; MODULE_DEVICE_TABLE(of, otto_wdt_ids); diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c index 6db22f2e3a4f..95919392927f 100644 --- a/drivers/watchdog/s3c2410_wdt.c +++ b/drivers/watchdog/s3c2410_wdt.c @@ -845,8 +845,6 @@ static void s3c2410wdt_shutdown(struct platform_device *dev) s3c2410wdt_stop(&wdt->wdt_device); } -#ifdef CONFIG_PM_SLEEP - static int s3c2410wdt_suspend(struct device *dev) { int ret; @@ -885,10 +883,9 @@ static int s3c2410wdt_resume(struct device *dev) return 0; } -#endif -static SIMPLE_DEV_PM_OPS(s3c2410wdt_pm_ops, s3c2410wdt_suspend, - s3c2410wdt_resume); +static DEFINE_SIMPLE_DEV_PM_OPS(s3c2410wdt_pm_ops, + s3c2410wdt_suspend, s3c2410wdt_resume); static struct platform_driver s3c2410wdt_driver = { .probe = s3c2410wdt_probe, @@ -897,7 +894,7 @@ static struct platform_driver s3c2410wdt_driver = { .id_table = s3c2410_wdt_ids, .driver = { .name = "s3c2410-wdt", - .pm = &s3c2410wdt_pm_ops, + .pm = pm_sleep_ptr(&s3c2410wdt_pm_ops), .of_match_table = of_match_ptr(s3c2410_wdt_match), }, }; diff --git a/drivers/watchdog/sama5d4_wdt.c b/drivers/watchdog/sama5d4_wdt.c index ec20ad4e534f..aeee934ca51b 100644 --- a/drivers/watchdog/sama5d4_wdt.c +++ b/drivers/watchdog/sama5d4_wdt.c @@ -339,7 +339,6 @@ static const struct of_device_id sama5d4_wdt_of_match[] = { }; MODULE_DEVICE_TABLE(of, sama5d4_wdt_of_match); -#ifdef CONFIG_PM_SLEEP static int sama5d4_wdt_suspend_late(struct device *dev) { struct sama5d4_wdt *wdt = dev_get_drvdata(dev); @@ -366,18 +365,17 @@ static int sama5d4_wdt_resume_early(struct device *dev) return 0; } -#endif static const struct dev_pm_ops sama5d4_wdt_pm_ops = { - SET_LATE_SYSTEM_SLEEP_PM_OPS(sama5d4_wdt_suspend_late, - sama5d4_wdt_resume_early) + LATE_SYSTEM_SLEEP_PM_OPS(sama5d4_wdt_suspend_late, + sama5d4_wdt_resume_early) }; static struct platform_driver sama5d4_wdt_driver = { .probe = sama5d4_wdt_probe, .driver = { .name = "sama5d4_wdt", - .pm = &sama5d4_wdt_pm_ops, + .pm = pm_sleep_ptr(&sama5d4_wdt_pm_ops), .of_match_table = sama5d4_wdt_of_match, } }; diff --git a/drivers/watchdog/simatic-ipc-wdt.c b/drivers/watchdog/simatic-ipc-wdt.c index 8bac793c63fb..6599695dc672 100644 --- a/drivers/watchdog/simatic-ipc-wdt.c +++ b/drivers/watchdog/simatic-ipc-wdt.c @@ -16,6 +16,7 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/pci.h> +#include <linux/platform_data/x86/p2sb.h> #include <linux/platform_data/x86/simatic-ipc-base.h> #include <linux/platform_device.h> #include <linux/sizes.h> @@ -54,9 +55,9 @@ static struct resource io_resource_trigger = DEFINE_RES_IO_NAMED(WD_TRIGGER_IOADR, SZ_1, KBUILD_MODNAME " WD_TRIGGER_IOADR"); -/* the actual start will be discovered with pci, 0 is a placeholder */ +/* the actual start will be discovered with p2sb, 0 is a placeholder */ static struct resource mem_resource = - DEFINE_RES_MEM_NAMED(0, SZ_4, "WD_RESET_BASE_ADR"); + DEFINE_RES_MEM_NAMED(0, 0, "WD_RESET_BASE_ADR"); static u32 wd_timeout_table[] = {2, 4, 6, 8, 16, 32, 48, 64 }; static void __iomem *wd_reset_base_addr; @@ -150,6 +151,7 @@ static int simatic_ipc_wdt_probe(struct platform_device *pdev) struct simatic_ipc_platform *plat = pdev->dev.platform_data; struct device *dev = &pdev->dev; struct resource *res; + int ret; switch (plat->devmode) { case SIMATIC_IPC_DEVICE_227E: @@ -190,15 +192,14 @@ static int simatic_ipc_wdt_probe(struct platform_device *pdev) if (plat->devmode == SIMATIC_IPC_DEVICE_427E) { res = &mem_resource; - /* get GPIO base from PCI */ - res->start = simatic_ipc_get_membase0(PCI_DEVFN(0x1f, 1)); - if (res->start == 0) - return -ENODEV; + ret = p2sb_bar(NULL, 0, res); + if (ret) + return ret; /* do the final address calculation */ res->start = res->start + (GPIO_COMMUNITY0_PORT_ID << 16) + PAD_CFG_DW0_GPP_A_23; - res->end += res->start; + res->end = res->start + SZ_4 - 1; wd_reset_base_addr = devm_ioremap_resource(dev, res); if (IS_ERR(wd_reset_base_addr)) diff --git a/drivers/watchdog/sp5100_tco.c b/drivers/watchdog/sp5100_tco.c index 86ffb58fbc85..ae54dd33e233 100644 --- a/drivers/watchdog/sp5100_tco.c +++ b/drivers/watchdog/sp5100_tco.c @@ -402,6 +402,7 @@ out: iounmap(addr); release_resource(res); + kfree(res); return ret; } diff --git a/drivers/watchdog/sp805_wdt.c b/drivers/watchdog/sp805_wdt.c index f9479a3fe2a6..78ba36689eec 100644 --- a/drivers/watchdog/sp805_wdt.c +++ b/drivers/watchdog/sp805_wdt.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * drivers/char/watchdog/sp805-wdt.c * @@ -341,6 +342,10 @@ static const struct amba_id sp805_wdt_ids[] = { .id = 0x00141805, .mask = 0x00ffffff, }, + { + .id = 0x001bb824, + .mask = 0x00ffffff, + }, { 0, 0 }, }; diff --git a/drivers/watchdog/st_lpc_wdt.c b/drivers/watchdog/st_lpc_wdt.c index 14ab6559c748..39abecdb9dd1 100644 --- a/drivers/watchdog/st_lpc_wdt.c +++ b/drivers/watchdog/st_lpc_wdt.c @@ -248,7 +248,6 @@ static int st_wdog_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM_SLEEP static int st_wdog_suspend(struct device *dev) { struct st_wdog *st_wdog = watchdog_get_drvdata(&st_wdog_dev); @@ -285,16 +284,14 @@ static int st_wdog_resume(struct device *dev) return 0; } -#endif -static SIMPLE_DEV_PM_OPS(st_wdog_pm_ops, - st_wdog_suspend, - st_wdog_resume); +static DEFINE_SIMPLE_DEV_PM_OPS(st_wdog_pm_ops, + st_wdog_suspend, st_wdog_resume); static struct platform_driver st_wdog_driver = { .driver = { .name = "st-lpc-wdt", - .pm = &st_wdog_pm_ops, + .pm = pm_sleep_ptr(&st_wdog_pm_ops), .of_match_table = st_wdog_match, }, .probe = st_wdog_probe, diff --git a/drivers/watchdog/tegra_wdt.c b/drivers/watchdog/tegra_wdt.c index dfe06e506cad..d5de6c0657a5 100644 --- a/drivers/watchdog/tegra_wdt.c +++ b/drivers/watchdog/tegra_wdt.c @@ -230,8 +230,7 @@ static int tegra_wdt_probe(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM_SLEEP -static int tegra_wdt_runtime_suspend(struct device *dev) +static int tegra_wdt_suspend(struct device *dev) { struct tegra_wdt *wdt = dev_get_drvdata(dev); @@ -241,7 +240,7 @@ static int tegra_wdt_runtime_suspend(struct device *dev) return 0; } -static int tegra_wdt_runtime_resume(struct device *dev) +static int tegra_wdt_resume(struct device *dev) { struct tegra_wdt *wdt = dev_get_drvdata(dev); @@ -250,7 +249,6 @@ static int tegra_wdt_runtime_resume(struct device *dev) return 0; } -#endif static const struct of_device_id tegra_wdt_of_match[] = { { .compatible = "nvidia,tegra30-timer", }, @@ -258,16 +256,14 @@ static const struct of_device_id tegra_wdt_of_match[] = { }; MODULE_DEVICE_TABLE(of, tegra_wdt_of_match); -static const struct dev_pm_ops tegra_wdt_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(tegra_wdt_runtime_suspend, - tegra_wdt_runtime_resume) -}; +static DEFINE_SIMPLE_DEV_PM_OPS(tegra_wdt_pm_ops, + tegra_wdt_suspend, tegra_wdt_resume); static struct platform_driver tegra_wdt_driver = { .probe = tegra_wdt_probe, .driver = { .name = "tegra-wdt", - .pm = &tegra_wdt_pm_ops, + .pm = pm_sleep_ptr(&tegra_wdt_pm_ops), .of_match_table = tegra_wdt_of_match, }, }; diff --git a/drivers/watchdog/wdat_wdt.c b/drivers/watchdog/wdat_wdt.c index e6f95e99156d..aeadaa07c891 100644 --- a/drivers/watchdog/wdat_wdt.c +++ b/drivers/watchdog/wdat_wdt.c @@ -467,7 +467,6 @@ static int wdat_wdt_probe(struct platform_device *pdev) return devm_watchdog_register_device(dev, &wdat->wdd); } -#ifdef CONFIG_PM_SLEEP static int wdat_wdt_suspend_noirq(struct device *dev) { struct wdat_wdt *wdat = dev_get_drvdata(dev); @@ -528,18 +527,16 @@ static int wdat_wdt_resume_noirq(struct device *dev) return wdat_wdt_start(&wdat->wdd); } -#endif static const struct dev_pm_ops wdat_wdt_pm_ops = { - SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(wdat_wdt_suspend_noirq, - wdat_wdt_resume_noirq) + NOIRQ_SYSTEM_SLEEP_PM_OPS(wdat_wdt_suspend_noirq, wdat_wdt_resume_noirq) }; static struct platform_driver wdat_wdt_driver = { .probe = wdat_wdt_probe, .driver = { .name = "wdat_wdt", - .pm = &wdat_wdt_pm_ops, + .pm = pm_sleep_ptr(&wdat_wdt_pm_ops), }, }; |