// SPDX-License-Identifier: GPL-2.0+ /* * intel TCO Watchdog Driver * * (c) Copyright 2006-2011 Wim Van Sebroeck <[email protected]>. * * Neither Wim Van Sebroeck nor Iguana vzw. admit liability nor * provide warranty for any of this software. This material is * provided "AS-IS" and at no charge. * * The TCO watchdog is implemented in the following I/O controller hubs: * (See the intel documentation on http://developer.intel.com.) * document number 290655-003, 290677-014: 82801AA (ICH), 82801AB (ICHO) * document number 290687-002, 298242-027: 82801BA (ICH2) * document number 290733-003, 290739-013: 82801CA (ICH3-S) * document number 290716-001, 290718-007: 82801CAM (ICH3-M) * document number 290744-001, 290745-025: 82801DB (ICH4) * document number 252337-001, 252663-008: 82801DBM (ICH4-M) * document number 273599-001, 273645-002: 82801E (C-ICH) * document number 252516-001, 252517-028: 82801EB (ICH5), 82801ER (ICH5R) * document number 300641-004, 300884-013: 6300ESB * document number 301473-002, 301474-026: 82801F (ICH6) * document number 313082-001, 313075-006: 631xESB, 632xESB * document number 307013-003, 307014-024: 82801G (ICH7) * document number 322896-001, 322897-001: NM10 * document number 313056-003, 313057-017: 82801H (ICH8) * document number 316972-004, 316973-012: 82801I (ICH9) * document number 319973-002, 319974-002: 82801J (ICH10) * document number 322169-001, 322170-003: 5 Series, 3400 Series (PCH) * document number 320066-003, 320257-008: EP80597 (IICH) * document number 324645-001, 324646-001: Cougar Point (CPT) * document number TBD : Patsburg (PBG) * document number TBD : DH89xxCC * document number TBD : Panther Point * document number TBD : Lynx Point * document number TBD : Lynx Point-LP */ /* * Includes, defines, variables, module parameters, ... */ /* Module and version information */ #define DRV_NAME … #define DRV_VERSION … /* Includes */ #include <linux/acpi.h> /* For ACPI support */ #include <linux/bits.h> /* For BIT() */ #include <linux/module.h> /* For module specific items */ #include <linux/moduleparam.h> /* For new moduleparam's */ #include <linux/types.h> /* For standard types (like size_t) */ #include <linux/errno.h> /* For the -ENODEV/... values */ #include <linux/kernel.h> /* For printk/panic/... */ #include <linux/watchdog.h> /* For the watchdog specific items */ #include <linux/init.h> /* For __init/__exit/... */ #include <linux/fs.h> /* For file operations */ #include <linux/platform_device.h> /* For platform_driver framework */ #include <linux/pci.h> /* For pci functions */ #include <linux/ioport.h> /* For io-port access */ #include <linux/spinlock.h> /* For spin_lock/spin_unlock/... */ #include <linux/uaccess.h> /* For copy_to_user/put_user/... */ #include <linux/io.h> /* For inb/outb/... */ #include <linux/platform_data/itco_wdt.h> #include <linux/mfd/intel_pmc_bxt.h> #include "iTCO_vendor.h" /* Address definitions for the TCO */ /* TCO base address */ #define TCOBASE(p) … /* SMI Control and Enable Register */ #define SMI_EN(p) … #define TCO_RLD(p) … #define TCOv1_TMR(p) … #define TCO_DAT_IN(p) … #define TCO_DAT_OUT(p) … #define TCO1_STS(p) … #define TCO2_STS(p) … #define TCO1_CNT(p) … #define TCO2_CNT(p) … #define TCOv2_TMR(p) … /* internal variables */ struct iTCO_wdt_private { … }; /* module parameters */ #define WATCHDOG_TIMEOUT … static int heartbeat = …; /* in seconds */ module_param(heartbeat, int, 0); MODULE_PARM_DESC(…) …; static bool nowayout = … WATCHDOG_NOWAYOUT; module_param(nowayout, bool, 0); MODULE_PARM_DESC(…) …; static int turn_SMI_watchdog_clear_off = …; module_param(turn_SMI_watchdog_clear_off, int, 0); MODULE_PARM_DESC(…) …; /* * Some TCO specific functions */ /* * The iTCO v1 and v2's internal timer is stored as ticks which decrement * every 0.6 seconds. v3's internal timer is stored as seconds (some * datasheets incorrectly state 0.6 seconds). */ static inline unsigned int seconds_to_ticks(struct iTCO_wdt_private *p, int secs) { … } static inline unsigned int ticks_to_seconds(struct iTCO_wdt_private *p, int ticks) { … } static inline u32 no_reboot_bit(struct iTCO_wdt_private *p) { … } static int update_no_reboot_bit_def(void *priv, bool set) { … } static int update_no_reboot_bit_pci(void *priv, bool set) { … } static int update_no_reboot_bit_mem(void *priv, bool set) { … } static int update_no_reboot_bit_cnt(void *priv, bool set) { … } static int update_no_reboot_bit_pmc(void *priv, bool set) { … } static void iTCO_wdt_no_reboot_bit_setup(struct iTCO_wdt_private *p, struct platform_device *pdev, struct itco_wdt_platform_data *pdata) { … } static int iTCO_wdt_start(struct watchdog_device *wd_dev) { … } static int iTCO_wdt_stop(struct watchdog_device *wd_dev) { … } static int iTCO_wdt_ping(struct watchdog_device *wd_dev) { … } static int iTCO_wdt_set_timeout(struct watchdog_device *wd_dev, unsigned int t) { … } static unsigned int iTCO_wdt_get_timeleft(struct watchdog_device *wd_dev) { … } /* Returns true if the watchdog was running */ static bool iTCO_wdt_set_running(struct iTCO_wdt_private *p) { … } /* * Kernel Interfaces */ static struct watchdog_info ident = …; static const struct watchdog_ops iTCO_wdt_ops = …; /* * Init & exit routines */ static int iTCO_wdt_probe(struct platform_device *pdev) { … } /* * Suspend-to-idle requires this, because it stops the ticks and timekeeping, so * the watchdog cannot be pinged while in that state. In ACPI sleep states the * watchdog is stopped by the platform firmware. */ #ifdef CONFIG_ACPI static inline bool __maybe_unused need_suspend(void) { … } #else static inline bool __maybe_unused need_suspend(void) { return true; } #endif static int __maybe_unused iTCO_wdt_suspend_noirq(struct device *dev) { … } static int __maybe_unused iTCO_wdt_resume_noirq(struct device *dev) { … } static const struct dev_pm_ops iTCO_wdt_pm = …; static struct platform_driver iTCO_wdt_driver = …; module_platform_driver(…) …; MODULE_AUTHOR(…) …; MODULE_DESCRIPTION(…) …; MODULE_VERSION(…); MODULE_LICENSE(…) …; MODULE_ALIAS(…) …;