mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-28 09:31:14 +00:00
linux-watchdog 5.6-rc1 tag
-----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.14 (GNU/Linux) iEYEABECAAYFAl48a0YACgkQ+iyteGJfRsoOcQCeMHtMpkUEYQa6X/bMkEnlu9DT bhEAoN0fFm53Y/SVPipe/r1+0JQOkMoI =/D+E -----END PGP SIGNATURE----- Merge tag 'linux-watchdog-5.6-rc1' of git://www.linux-watchdog.org/linux-watchdog Pull watchdog updates from Wim Van Sebroeck: - add IT8786 chipset ID - addition of sam9x60 compatible watchdog - da9062 improvements - fix UAF in reboot notifier handling in watchdog core code - other fixes and small improvements * tag 'linux-watchdog-5.6-rc1' of git://www.linux-watchdog.org/linux-watchdog: watchdog: da9062: make restart handler atomic safe watchdog: mtk_wdt: mt2712: Add reset controller watchdog: mtk_wdt: mt8183: Add reset controller dt-bindings: mediatek: mt2712: Add #reset-cells dt-bindings: mediatek: mt8183: Add #reset-cells dt-bindings: watchdog: da9062: add suspend disable option watchdog: it87_wdt: add IT8786 ID watchdog: dw_wdt: ping watchdog to reset countdown before start watchdog: fix UAF in reboot notifier handling in watchdog core code watchdog: cadence: Skip printing pointer value watchdog: qcom: Use platform_get_irq_optional() for bark irq watchdog: da9062: add power management ops watchdog: make DesignWare watchdog allow users to set bigger timeout value drivers: watchdog: stm32_iwdg: set WDOG_HW_RUNNING at probe watchdog: sama5d4_wdt: addition of sam9x60 compatible watchdog
This commit is contained in:
commit
b34f01f76a
15 changed files with 361 additions and 73 deletions
|
@ -6,6 +6,11 @@ Required properties:
|
||||||
"dlg,da9061-watchdog", "dlg,da9062-watchdog"
|
"dlg,da9061-watchdog", "dlg,da9062-watchdog"
|
||||||
"dlg,da9062-watchdog"
|
"dlg,da9062-watchdog"
|
||||||
|
|
||||||
|
Optional properties:
|
||||||
|
- dlg,use-sw-pm: Add this property to disable the watchdog during suspend.
|
||||||
|
Only use this option if you can't use the watchdog automatic suspend
|
||||||
|
function during a suspend (see register CONTROL_B).
|
||||||
|
|
||||||
Example: DA9062
|
Example: DA9062
|
||||||
|
|
||||||
pmic0: da9062@58 {
|
pmic0: da9062@58 {
|
||||||
|
|
|
@ -4,22 +4,27 @@ Required properties:
|
||||||
|
|
||||||
- compatible should contain:
|
- compatible should contain:
|
||||||
"mediatek,mt2701-wdt", "mediatek,mt6589-wdt": for MT2701
|
"mediatek,mt2701-wdt", "mediatek,mt6589-wdt": for MT2701
|
||||||
|
"mediatek,mt2712-wdt", "mediatek,mt6589-wdt": for MT2712
|
||||||
"mediatek,mt6589-wdt": for MT6589
|
"mediatek,mt6589-wdt": for MT6589
|
||||||
"mediatek,mt6797-wdt", "mediatek,mt6589-wdt": for MT6797
|
"mediatek,mt6797-wdt", "mediatek,mt6589-wdt": for MT6797
|
||||||
"mediatek,mt7622-wdt", "mediatek,mt6589-wdt": for MT7622
|
"mediatek,mt7622-wdt", "mediatek,mt6589-wdt": for MT7622
|
||||||
"mediatek,mt7623-wdt", "mediatek,mt6589-wdt": for MT7623
|
"mediatek,mt7623-wdt", "mediatek,mt6589-wdt": for MT7623
|
||||||
"mediatek,mt7629-wdt", "mediatek,mt6589-wdt": for MT7629
|
"mediatek,mt7629-wdt", "mediatek,mt6589-wdt": for MT7629
|
||||||
|
"mediatek,mt8183-wdt", "mediatek,mt6589-wdt": for MT8183
|
||||||
"mediatek,mt8516-wdt", "mediatek,mt6589-wdt": for MT8516
|
"mediatek,mt8516-wdt", "mediatek,mt6589-wdt": for MT8516
|
||||||
|
|
||||||
- reg : Specifies base physical address and size of the registers.
|
- reg : Specifies base physical address and size of the registers.
|
||||||
|
|
||||||
Optional properties:
|
Optional properties:
|
||||||
- timeout-sec: contains the watchdog timeout in seconds.
|
- timeout-sec: contains the watchdog timeout in seconds.
|
||||||
|
- #reset-cells: Should be 1.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
wdt: watchdog@10000000 {
|
watchdog: watchdog@10007000 {
|
||||||
compatible = "mediatek,mt6589-wdt";
|
compatible = "mediatek,mt8183-wdt",
|
||||||
reg = <0x10000000 0x18>;
|
"mediatek,mt6589-wdt";
|
||||||
|
reg = <0 0x10007000 0 0x100>;
|
||||||
timeout-sec = <10>;
|
timeout-sec = <10>;
|
||||||
|
#reset-cells = <1>;
|
||||||
};
|
};
|
||||||
|
|
|
@ -24,7 +24,10 @@
|
||||||
#define AT91_WDT_MR 0x04 /* Watchdog Mode Register */
|
#define AT91_WDT_MR 0x04 /* Watchdog Mode Register */
|
||||||
#define AT91_WDT_WDV (0xfffUL << 0) /* Counter Value */
|
#define AT91_WDT_WDV (0xfffUL << 0) /* Counter Value */
|
||||||
#define AT91_WDT_SET_WDV(x) ((x) & AT91_WDT_WDV)
|
#define AT91_WDT_SET_WDV(x) ((x) & AT91_WDT_WDV)
|
||||||
|
#define AT91_SAM9X60_PERIODRST BIT(4) /* Period Reset */
|
||||||
|
#define AT91_SAM9X60_RPTHRST BIT(5) /* Minimum Restart Period */
|
||||||
#define AT91_WDT_WDFIEN BIT(12) /* Fault Interrupt Enable */
|
#define AT91_WDT_WDFIEN BIT(12) /* Fault Interrupt Enable */
|
||||||
|
#define AT91_SAM9X60_WDDIS BIT(12) /* Watchdog Disable */
|
||||||
#define AT91_WDT_WDRSTEN BIT(13) /* Reset Processor */
|
#define AT91_WDT_WDRSTEN BIT(13) /* Reset Processor */
|
||||||
#define AT91_WDT_WDRPROC BIT(14) /* Timer Restart */
|
#define AT91_WDT_WDRPROC BIT(14) /* Timer Restart */
|
||||||
#define AT91_WDT_WDDIS BIT(15) /* Watchdog Disable */
|
#define AT91_WDT_WDDIS BIT(15) /* Watchdog Disable */
|
||||||
|
@ -37,4 +40,22 @@
|
||||||
#define AT91_WDT_WDUNF BIT(0) /* Watchdog Underflow */
|
#define AT91_WDT_WDUNF BIT(0) /* Watchdog Underflow */
|
||||||
#define AT91_WDT_WDERR BIT(1) /* Watchdog Error */
|
#define AT91_WDT_WDERR BIT(1) /* Watchdog Error */
|
||||||
|
|
||||||
|
/* Watchdog Timer Value Register */
|
||||||
|
#define AT91_SAM9X60_VR 0x08
|
||||||
|
|
||||||
|
/* Watchdog Window Level Register */
|
||||||
|
#define AT91_SAM9X60_WLR 0x0c
|
||||||
|
/* Watchdog Period Value */
|
||||||
|
#define AT91_SAM9X60_COUNTER (0xfffUL << 0)
|
||||||
|
#define AT91_SAM9X60_SET_COUNTER(x) ((x) & AT91_SAM9X60_COUNTER)
|
||||||
|
|
||||||
|
/* Interrupt Enable Register */
|
||||||
|
#define AT91_SAM9X60_IER 0x14
|
||||||
|
/* Period Interrupt Enable */
|
||||||
|
#define AT91_SAM9X60_PERINT BIT(0)
|
||||||
|
/* Interrupt Disable Register */
|
||||||
|
#define AT91_SAM9X60_IDR 0x18
|
||||||
|
/* Interrupt Status Register */
|
||||||
|
#define AT91_SAM9X60_ISR 0x1c
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -369,9 +369,8 @@ static int cdns_wdt_probe(struct platform_device *pdev)
|
||||||
return ret;
|
return ret;
|
||||||
platform_set_drvdata(pdev, wdt);
|
platform_set_drvdata(pdev, wdt);
|
||||||
|
|
||||||
dev_info(dev, "Xilinx Watchdog Timer at %p with timeout %ds%s\n",
|
dev_info(dev, "Xilinx Watchdog Timer with timeout %ds%s\n",
|
||||||
wdt->regs, cdns_wdt_device->timeout,
|
cdns_wdt_device->timeout, nowayout ? ", nowayout" : "");
|
||||||
nowayout ? ", nowayout" : "");
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
#include <linux/i2c.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/jiffies.h>
|
#include <linux/jiffies.h>
|
||||||
#include <linux/mfd/da9062/registers.h>
|
#include <linux/mfd/da9062/registers.h>
|
||||||
|
@ -147,12 +148,13 @@ static int da9062_wdt_restart(struct watchdog_device *wdd, unsigned long action,
|
||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
struct da9062_watchdog *wdt = watchdog_get_drvdata(wdd);
|
struct da9062_watchdog *wdt = watchdog_get_drvdata(wdd);
|
||||||
|
struct i2c_client *client = to_i2c_client(wdt->hw->dev);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = regmap_write(wdt->hw->regmap,
|
/* Don't use regmap because it is not atomic safe */
|
||||||
DA9062AA_CONTROL_F,
|
ret = i2c_smbus_write_byte_data(client, DA9062AA_CONTROL_F,
|
||||||
DA9062AA_SHUTDOWN_MASK);
|
DA9062AA_SHUTDOWN_MASK);
|
||||||
if (ret)
|
if (ret < 0)
|
||||||
dev_alert(wdt->hw->dev, "Failed to shutdown (err = %d)\n",
|
dev_alert(wdt->hw->dev, "Failed to shutdown (err = %d)\n",
|
||||||
ret);
|
ret);
|
||||||
|
|
||||||
|
@ -212,6 +214,7 @@ static int da9062_wdt_probe(struct platform_device *pdev)
|
||||||
watchdog_set_restart_priority(&wdt->wdtdev, 128);
|
watchdog_set_restart_priority(&wdt->wdtdev, 128);
|
||||||
|
|
||||||
watchdog_set_drvdata(&wdt->wdtdev, wdt);
|
watchdog_set_drvdata(&wdt->wdtdev, wdt);
|
||||||
|
dev_set_drvdata(dev, &wdt->wdtdev);
|
||||||
|
|
||||||
ret = devm_watchdog_register_device(dev, &wdt->wdtdev);
|
ret = devm_watchdog_register_device(dev, &wdt->wdtdev);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
|
@ -220,10 +223,34 @@ static int da9062_wdt_probe(struct platform_device *pdev)
|
||||||
return da9062_wdt_ping(&wdt->wdtdev);
|
return da9062_wdt_ping(&wdt->wdtdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int __maybe_unused da9062_wdt_suspend(struct device *dev)
|
||||||
|
{
|
||||||
|
struct watchdog_device *wdd = dev_get_drvdata(dev);
|
||||||
|
|
||||||
|
if (watchdog_active(wdd))
|
||||||
|
return da9062_wdt_stop(wdd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __maybe_unused da9062_wdt_resume(struct device *dev)
|
||||||
|
{
|
||||||
|
struct watchdog_device *wdd = dev_get_drvdata(dev);
|
||||||
|
|
||||||
|
if (watchdog_active(wdd))
|
||||||
|
return da9062_wdt_start(wdd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SIMPLE_DEV_PM_OPS(da9062_wdt_pm_ops,
|
||||||
|
da9062_wdt_suspend, da9062_wdt_resume);
|
||||||
|
|
||||||
static struct platform_driver da9062_wdt_driver = {
|
static struct platform_driver da9062_wdt_driver = {
|
||||||
.probe = da9062_wdt_probe,
|
.probe = da9062_wdt_probe,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "da9062-watchdog",
|
.name = "da9062-watchdog",
|
||||||
|
.pm = &da9062_wdt_pm_ops,
|
||||||
.of_match_table = da9062_compatible_id_table,
|
.of_match_table = da9062_compatible_id_table,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -114,7 +114,15 @@ static int dw_wdt_set_timeout(struct watchdog_device *wdd, unsigned int top_s)
|
||||||
writel(top_val | top_val << WDOG_TIMEOUT_RANGE_TOPINIT_SHIFT,
|
writel(top_val | top_val << WDOG_TIMEOUT_RANGE_TOPINIT_SHIFT,
|
||||||
dw_wdt->regs + WDOG_TIMEOUT_RANGE_REG_OFFSET);
|
dw_wdt->regs + WDOG_TIMEOUT_RANGE_REG_OFFSET);
|
||||||
|
|
||||||
wdd->timeout = dw_wdt_top_in_seconds(dw_wdt, top_val);
|
/*
|
||||||
|
* In case users set bigger timeout value than HW can support,
|
||||||
|
* kernel(watchdog_dev.c) helps to feed watchdog before
|
||||||
|
* wdd->max_hw_heartbeat_ms
|
||||||
|
*/
|
||||||
|
if (top_s * 1000 <= wdd->max_hw_heartbeat_ms)
|
||||||
|
wdd->timeout = dw_wdt_top_in_seconds(dw_wdt, top_val);
|
||||||
|
else
|
||||||
|
wdd->timeout = top_s;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -135,6 +143,7 @@ static int dw_wdt_start(struct watchdog_device *wdd)
|
||||||
struct dw_wdt *dw_wdt = to_dw_wdt(wdd);
|
struct dw_wdt *dw_wdt = to_dw_wdt(wdd);
|
||||||
|
|
||||||
dw_wdt_set_timeout(wdd, wdd->timeout);
|
dw_wdt_set_timeout(wdd, wdd->timeout);
|
||||||
|
dw_wdt_ping(&dw_wdt->wdd);
|
||||||
dw_wdt_arm_system_reset(dw_wdt);
|
dw_wdt_arm_system_reset(dw_wdt);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -67,6 +67,7 @@
|
||||||
#define IT8726_ID 0x8726 /* the data sheet suggest wrongly 0x8716 */
|
#define IT8726_ID 0x8726 /* the data sheet suggest wrongly 0x8716 */
|
||||||
#define IT8728_ID 0x8728
|
#define IT8728_ID 0x8728
|
||||||
#define IT8783_ID 0x8783
|
#define IT8783_ID 0x8783
|
||||||
|
#define IT8786_ID 0x8786
|
||||||
|
|
||||||
/* GPIO Configuration Registers LDN=0x07 */
|
/* GPIO Configuration Registers LDN=0x07 */
|
||||||
#define WDTCTRL 0x71
|
#define WDTCTRL 0x71
|
||||||
|
@ -294,6 +295,7 @@ static int __init it87_wdt_init(void)
|
||||||
case IT8721_ID:
|
case IT8721_ID:
|
||||||
case IT8728_ID:
|
case IT8728_ID:
|
||||||
case IT8783_ID:
|
case IT8783_ID:
|
||||||
|
case IT8786_ID:
|
||||||
max_units = 65535;
|
max_units = 65535;
|
||||||
break;
|
break;
|
||||||
case IT8705_ID:
|
case IT8705_ID:
|
||||||
|
|
|
@ -9,6 +9,9 @@
|
||||||
* Based on sunxi_wdt.c
|
* Based on sunxi_wdt.c
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <dt-bindings/reset-controller/mt2712-resets.h>
|
||||||
|
#include <dt-bindings/reset-controller/mt8183-resets.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
|
@ -16,10 +19,11 @@
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/moduleparam.h>
|
#include <linux/moduleparam.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
|
#include <linux/of_device.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/reset-controller.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/watchdog.h>
|
#include <linux/watchdog.h>
|
||||||
#include <linux/delay.h>
|
|
||||||
|
|
||||||
#define WDT_MAX_TIMEOUT 31
|
#define WDT_MAX_TIMEOUT 31
|
||||||
#define WDT_MIN_TIMEOUT 1
|
#define WDT_MIN_TIMEOUT 1
|
||||||
|
@ -44,6 +48,9 @@
|
||||||
#define WDT_SWRST 0x14
|
#define WDT_SWRST 0x14
|
||||||
#define WDT_SWRST_KEY 0x1209
|
#define WDT_SWRST_KEY 0x1209
|
||||||
|
|
||||||
|
#define WDT_SWSYSRST 0x18U
|
||||||
|
#define WDT_SWSYS_RST_KEY 0x88000000
|
||||||
|
|
||||||
#define DRV_NAME "mtk-wdt"
|
#define DRV_NAME "mtk-wdt"
|
||||||
#define DRV_VERSION "1.0"
|
#define DRV_VERSION "1.0"
|
||||||
|
|
||||||
|
@ -53,8 +60,94 @@ static unsigned int timeout;
|
||||||
struct mtk_wdt_dev {
|
struct mtk_wdt_dev {
|
||||||
struct watchdog_device wdt_dev;
|
struct watchdog_device wdt_dev;
|
||||||
void __iomem *wdt_base;
|
void __iomem *wdt_base;
|
||||||
|
spinlock_t lock; /* protects WDT_SWSYSRST reg */
|
||||||
|
struct reset_controller_dev rcdev;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct mtk_wdt_data {
|
||||||
|
int toprgu_sw_rst_num;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct mtk_wdt_data mt2712_data = {
|
||||||
|
.toprgu_sw_rst_num = MT2712_TOPRGU_SW_RST_NUM,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct mtk_wdt_data mt8183_data = {
|
||||||
|
.toprgu_sw_rst_num = MT8183_TOPRGU_SW_RST_NUM,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int toprgu_reset_update(struct reset_controller_dev *rcdev,
|
||||||
|
unsigned long id, bool assert)
|
||||||
|
{
|
||||||
|
unsigned int tmp;
|
||||||
|
unsigned long flags;
|
||||||
|
struct mtk_wdt_dev *data =
|
||||||
|
container_of(rcdev, struct mtk_wdt_dev, rcdev);
|
||||||
|
|
||||||
|
spin_lock_irqsave(&data->lock, flags);
|
||||||
|
|
||||||
|
tmp = readl(data->wdt_base + WDT_SWSYSRST);
|
||||||
|
if (assert)
|
||||||
|
tmp |= BIT(id);
|
||||||
|
else
|
||||||
|
tmp &= ~BIT(id);
|
||||||
|
tmp |= WDT_SWSYS_RST_KEY;
|
||||||
|
writel(tmp, data->wdt_base + WDT_SWSYSRST);
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&data->lock, flags);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int toprgu_reset_assert(struct reset_controller_dev *rcdev,
|
||||||
|
unsigned long id)
|
||||||
|
{
|
||||||
|
return toprgu_reset_update(rcdev, id, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int toprgu_reset_deassert(struct reset_controller_dev *rcdev,
|
||||||
|
unsigned long id)
|
||||||
|
{
|
||||||
|
return toprgu_reset_update(rcdev, id, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int toprgu_reset(struct reset_controller_dev *rcdev,
|
||||||
|
unsigned long id)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = toprgu_reset_assert(rcdev, id);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return toprgu_reset_deassert(rcdev, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct reset_control_ops toprgu_reset_ops = {
|
||||||
|
.assert = toprgu_reset_assert,
|
||||||
|
.deassert = toprgu_reset_deassert,
|
||||||
|
.reset = toprgu_reset,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int toprgu_register_reset_controller(struct platform_device *pdev,
|
||||||
|
int rst_num)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct mtk_wdt_dev *mtk_wdt = platform_get_drvdata(pdev);
|
||||||
|
|
||||||
|
spin_lock_init(&mtk_wdt->lock);
|
||||||
|
|
||||||
|
mtk_wdt->rcdev.owner = THIS_MODULE;
|
||||||
|
mtk_wdt->rcdev.nr_resets = rst_num;
|
||||||
|
mtk_wdt->rcdev.ops = &toprgu_reset_ops;
|
||||||
|
mtk_wdt->rcdev.of_node = pdev->dev.of_node;
|
||||||
|
ret = devm_reset_controller_register(&pdev->dev, &mtk_wdt->rcdev);
|
||||||
|
if (ret != 0)
|
||||||
|
dev_err(&pdev->dev,
|
||||||
|
"couldn't register wdt reset controller: %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int mtk_wdt_restart(struct watchdog_device *wdt_dev,
|
static int mtk_wdt_restart(struct watchdog_device *wdt_dev,
|
||||||
unsigned long action, void *data)
|
unsigned long action, void *data)
|
||||||
{
|
{
|
||||||
|
@ -155,6 +248,7 @@ static int mtk_wdt_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct device *dev = &pdev->dev;
|
struct device *dev = &pdev->dev;
|
||||||
struct mtk_wdt_dev *mtk_wdt;
|
struct mtk_wdt_dev *mtk_wdt;
|
||||||
|
const struct mtk_wdt_data *wdt_data;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
mtk_wdt = devm_kzalloc(dev, sizeof(*mtk_wdt), GFP_KERNEL);
|
mtk_wdt = devm_kzalloc(dev, sizeof(*mtk_wdt), GFP_KERNEL);
|
||||||
|
@ -190,6 +284,13 @@ static int mtk_wdt_probe(struct platform_device *pdev)
|
||||||
dev_info(dev, "Watchdog enabled (timeout=%d sec, nowayout=%d)\n",
|
dev_info(dev, "Watchdog enabled (timeout=%d sec, nowayout=%d)\n",
|
||||||
mtk_wdt->wdt_dev.timeout, nowayout);
|
mtk_wdt->wdt_dev.timeout, nowayout);
|
||||||
|
|
||||||
|
wdt_data = of_device_get_match_data(dev);
|
||||||
|
if (wdt_data) {
|
||||||
|
err = toprgu_register_reset_controller(pdev,
|
||||||
|
wdt_data->toprgu_sw_rst_num);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,7 +319,9 @@ static int mtk_wdt_resume(struct device *dev)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static const struct of_device_id mtk_wdt_dt_ids[] = {
|
static const struct of_device_id mtk_wdt_dt_ids[] = {
|
||||||
|
{ .compatible = "mediatek,mt2712-wdt", .data = &mt2712_data },
|
||||||
{ .compatible = "mediatek,mt6589-wdt" },
|
{ .compatible = "mediatek,mt6589-wdt" },
|
||||||
|
{ .compatible = "mediatek,mt8183-wdt", .data = &mt8183_data },
|
||||||
{ /* sentinel */ }
|
{ /* sentinel */ }
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(of, mtk_wdt_dt_ids);
|
MODULE_DEVICE_TABLE(of, mtk_wdt_dt_ids);
|
||||||
|
|
|
@ -246,7 +246,7 @@ static int qcom_wdt_probe(struct platform_device *pdev)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check if there is pretimeout support */
|
/* check if there is pretimeout support */
|
||||||
irq = platform_get_irq(pdev, 0);
|
irq = platform_get_irq_optional(pdev, 0);
|
||||||
if (irq > 0) {
|
if (irq > 0) {
|
||||||
ret = devm_request_irq(dev, irq, qcom_wdt_isr,
|
ret = devm_request_irq(dev, irq, qcom_wdt_isr,
|
||||||
IRQF_TRIGGER_RISING,
|
IRQF_TRIGGER_RISING,
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
/*
|
/*
|
||||||
* Driver for Atmel SAMA5D4 Watchdog Timer
|
* Driver for Atmel SAMA5D4 Watchdog Timer
|
||||||
*
|
*
|
||||||
* Copyright (C) 2015 Atmel Corporation
|
* Copyright (C) 2015-2019 Microchip Technology Inc. and its subsidiaries
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
|
@ -11,6 +11,7 @@
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
|
#include <linux/of_device.h>
|
||||||
#include <linux/of_irq.h>
|
#include <linux/of_irq.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/reboot.h>
|
#include <linux/reboot.h>
|
||||||
|
@ -29,7 +30,10 @@ struct sama5d4_wdt {
|
||||||
struct watchdog_device wdd;
|
struct watchdog_device wdd;
|
||||||
void __iomem *reg_base;
|
void __iomem *reg_base;
|
||||||
u32 mr;
|
u32 mr;
|
||||||
|
u32 ir;
|
||||||
unsigned long last_ping;
|
unsigned long last_ping;
|
||||||
|
bool need_irq;
|
||||||
|
bool sam9x60_support;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int wdt_timeout;
|
static int wdt_timeout;
|
||||||
|
@ -78,7 +82,12 @@ static int sama5d4_wdt_start(struct watchdog_device *wdd)
|
||||||
{
|
{
|
||||||
struct sama5d4_wdt *wdt = watchdog_get_drvdata(wdd);
|
struct sama5d4_wdt *wdt = watchdog_get_drvdata(wdd);
|
||||||
|
|
||||||
wdt->mr &= ~AT91_WDT_WDDIS;
|
if (wdt->sam9x60_support) {
|
||||||
|
writel_relaxed(wdt->ir, wdt->reg_base + AT91_SAM9X60_IER);
|
||||||
|
wdt->mr &= ~AT91_SAM9X60_WDDIS;
|
||||||
|
} else {
|
||||||
|
wdt->mr &= ~AT91_WDT_WDDIS;
|
||||||
|
}
|
||||||
wdt_write(wdt, AT91_WDT_MR, wdt->mr);
|
wdt_write(wdt, AT91_WDT_MR, wdt->mr);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -88,7 +97,12 @@ static int sama5d4_wdt_stop(struct watchdog_device *wdd)
|
||||||
{
|
{
|
||||||
struct sama5d4_wdt *wdt = watchdog_get_drvdata(wdd);
|
struct sama5d4_wdt *wdt = watchdog_get_drvdata(wdd);
|
||||||
|
|
||||||
wdt->mr |= AT91_WDT_WDDIS;
|
if (wdt->sam9x60_support) {
|
||||||
|
writel_relaxed(wdt->ir, wdt->reg_base + AT91_SAM9X60_IDR);
|
||||||
|
wdt->mr |= AT91_SAM9X60_WDDIS;
|
||||||
|
} else {
|
||||||
|
wdt->mr |= AT91_WDT_WDDIS;
|
||||||
|
}
|
||||||
wdt_write(wdt, AT91_WDT_MR, wdt->mr);
|
wdt_write(wdt, AT91_WDT_MR, wdt->mr);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -109,6 +123,14 @@ static int sama5d4_wdt_set_timeout(struct watchdog_device *wdd,
|
||||||
struct sama5d4_wdt *wdt = watchdog_get_drvdata(wdd);
|
struct sama5d4_wdt *wdt = watchdog_get_drvdata(wdd);
|
||||||
u32 value = WDT_SEC2TICKS(timeout);
|
u32 value = WDT_SEC2TICKS(timeout);
|
||||||
|
|
||||||
|
if (wdt->sam9x60_support) {
|
||||||
|
wdt_write(wdt, AT91_SAM9X60_WLR,
|
||||||
|
AT91_SAM9X60_SET_COUNTER(value));
|
||||||
|
|
||||||
|
wdd->timeout = timeout;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
wdt->mr &= ~AT91_WDT_WDV;
|
wdt->mr &= ~AT91_WDT_WDV;
|
||||||
wdt->mr |= AT91_WDT_SET_WDV(value);
|
wdt->mr |= AT91_WDT_SET_WDV(value);
|
||||||
|
|
||||||
|
@ -143,8 +165,14 @@ static const struct watchdog_ops sama5d4_wdt_ops = {
|
||||||
static irqreturn_t sama5d4_wdt_irq_handler(int irq, void *dev_id)
|
static irqreturn_t sama5d4_wdt_irq_handler(int irq, void *dev_id)
|
||||||
{
|
{
|
||||||
struct sama5d4_wdt *wdt = platform_get_drvdata(dev_id);
|
struct sama5d4_wdt *wdt = platform_get_drvdata(dev_id);
|
||||||
|
u32 reg;
|
||||||
|
|
||||||
if (wdt_read(wdt, AT91_WDT_SR)) {
|
if (wdt->sam9x60_support)
|
||||||
|
reg = wdt_read(wdt, AT91_SAM9X60_ISR);
|
||||||
|
else
|
||||||
|
reg = wdt_read(wdt, AT91_WDT_SR);
|
||||||
|
|
||||||
|
if (reg) {
|
||||||
pr_crit("Atmel Watchdog Software Reset\n");
|
pr_crit("Atmel Watchdog Software Reset\n");
|
||||||
emergency_restart();
|
emergency_restart();
|
||||||
pr_crit("Reboot didn't succeed\n");
|
pr_crit("Reboot didn't succeed\n");
|
||||||
|
@ -157,13 +185,14 @@ static int of_sama5d4_wdt_init(struct device_node *np, struct sama5d4_wdt *wdt)
|
||||||
{
|
{
|
||||||
const char *tmp;
|
const char *tmp;
|
||||||
|
|
||||||
wdt->mr = AT91_WDT_WDDIS;
|
if (wdt->sam9x60_support)
|
||||||
|
wdt->mr = AT91_SAM9X60_WDDIS;
|
||||||
|
else
|
||||||
|
wdt->mr = AT91_WDT_WDDIS;
|
||||||
|
|
||||||
if (!of_property_read_string(np, "atmel,watchdog-type", &tmp) &&
|
if (!of_property_read_string(np, "atmel,watchdog-type", &tmp) &&
|
||||||
!strcmp(tmp, "software"))
|
!strcmp(tmp, "software"))
|
||||||
wdt->mr |= AT91_WDT_WDFIEN;
|
wdt->need_irq = true;
|
||||||
else
|
|
||||||
wdt->mr |= AT91_WDT_WDRSTEN;
|
|
||||||
|
|
||||||
if (of_property_read_bool(np, "atmel,idle-halt"))
|
if (of_property_read_bool(np, "atmel,idle-halt"))
|
||||||
wdt->mr |= AT91_WDT_WDIDLEHLT;
|
wdt->mr |= AT91_WDT_WDIDLEHLT;
|
||||||
|
@ -176,21 +205,46 @@ static int of_sama5d4_wdt_init(struct device_node *np, struct sama5d4_wdt *wdt)
|
||||||
|
|
||||||
static int sama5d4_wdt_init(struct sama5d4_wdt *wdt)
|
static int sama5d4_wdt_init(struct sama5d4_wdt *wdt)
|
||||||
{
|
{
|
||||||
u32 reg;
|
u32 reg, val;
|
||||||
|
|
||||||
|
val = WDT_SEC2TICKS(WDT_DEFAULT_TIMEOUT);
|
||||||
/*
|
/*
|
||||||
* When booting and resuming, the bootloader may have changed the
|
* When booting and resuming, the bootloader may have changed the
|
||||||
* watchdog configuration.
|
* watchdog configuration.
|
||||||
* If the watchdog is already running, we can safely update it.
|
* If the watchdog is already running, we can safely update it.
|
||||||
* Else, we have to disable it properly.
|
* Else, we have to disable it properly.
|
||||||
*/
|
*/
|
||||||
if (wdt_enabled) {
|
if (!wdt_enabled) {
|
||||||
wdt_write_nosleep(wdt, AT91_WDT_MR, wdt->mr);
|
|
||||||
} else {
|
|
||||||
reg = wdt_read(wdt, AT91_WDT_MR);
|
reg = wdt_read(wdt, AT91_WDT_MR);
|
||||||
if (!(reg & AT91_WDT_WDDIS))
|
if (wdt->sam9x60_support && (!(reg & AT91_SAM9X60_WDDIS)))
|
||||||
|
wdt_write_nosleep(wdt, AT91_WDT_MR,
|
||||||
|
reg | AT91_SAM9X60_WDDIS);
|
||||||
|
else if (!wdt->sam9x60_support &&
|
||||||
|
(!(reg & AT91_WDT_WDDIS)))
|
||||||
wdt_write_nosleep(wdt, AT91_WDT_MR,
|
wdt_write_nosleep(wdt, AT91_WDT_MR,
|
||||||
reg | AT91_WDT_WDDIS);
|
reg | AT91_WDT_WDDIS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (wdt->sam9x60_support) {
|
||||||
|
if (wdt->need_irq)
|
||||||
|
wdt->ir = AT91_SAM9X60_PERINT;
|
||||||
|
else
|
||||||
|
wdt->mr |= AT91_SAM9X60_PERIODRST;
|
||||||
|
|
||||||
|
wdt_write(wdt, AT91_SAM9X60_IER, wdt->ir);
|
||||||
|
wdt_write(wdt, AT91_SAM9X60_WLR, AT91_SAM9X60_SET_COUNTER(val));
|
||||||
|
} else {
|
||||||
|
wdt->mr |= AT91_WDT_SET_WDD(WDT_SEC2TICKS(MAX_WDT_TIMEOUT));
|
||||||
|
wdt->mr |= AT91_WDT_SET_WDV(val);
|
||||||
|
|
||||||
|
if (wdt->need_irq)
|
||||||
|
wdt->mr |= AT91_WDT_WDFIEN;
|
||||||
|
else
|
||||||
|
wdt->mr |= AT91_WDT_WDRSTEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
wdt_write_nosleep(wdt, AT91_WDT_MR, wdt->mr);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,7 +255,6 @@ static int sama5d4_wdt_probe(struct platform_device *pdev)
|
||||||
struct sama5d4_wdt *wdt;
|
struct sama5d4_wdt *wdt;
|
||||||
void __iomem *regs;
|
void __iomem *regs;
|
||||||
u32 irq = 0;
|
u32 irq = 0;
|
||||||
u32 timeout;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL);
|
wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL);
|
||||||
|
@ -215,6 +268,8 @@ static int sama5d4_wdt_probe(struct platform_device *pdev)
|
||||||
wdd->min_timeout = MIN_WDT_TIMEOUT;
|
wdd->min_timeout = MIN_WDT_TIMEOUT;
|
||||||
wdd->max_timeout = MAX_WDT_TIMEOUT;
|
wdd->max_timeout = MAX_WDT_TIMEOUT;
|
||||||
wdt->last_ping = jiffies;
|
wdt->last_ping = jiffies;
|
||||||
|
wdt->sam9x60_support = of_device_is_compatible(dev->of_node,
|
||||||
|
"microchip,sam9x60-wdt");
|
||||||
|
|
||||||
watchdog_set_drvdata(wdd, wdt);
|
watchdog_set_drvdata(wdd, wdt);
|
||||||
|
|
||||||
|
@ -224,15 +279,19 @@ static int sama5d4_wdt_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
wdt->reg_base = regs;
|
wdt->reg_base = regs;
|
||||||
|
|
||||||
irq = irq_of_parse_and_map(dev->of_node, 0);
|
|
||||||
if (!irq)
|
|
||||||
dev_warn(dev, "failed to get IRQ from DT\n");
|
|
||||||
|
|
||||||
ret = of_sama5d4_wdt_init(dev->of_node, wdt);
|
ret = of_sama5d4_wdt_init(dev->of_node, wdt);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if ((wdt->mr & AT91_WDT_WDFIEN) && irq) {
|
if (wdt->need_irq) {
|
||||||
|
irq = irq_of_parse_and_map(dev->of_node, 0);
|
||||||
|
if (!irq) {
|
||||||
|
dev_warn(dev, "failed to get IRQ from DT\n");
|
||||||
|
wdt->need_irq = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wdt->need_irq) {
|
||||||
ret = devm_request_irq(dev, irq, sama5d4_wdt_irq_handler,
|
ret = devm_request_irq(dev, irq, sama5d4_wdt_irq_handler,
|
||||||
IRQF_SHARED | IRQF_IRQPOLL |
|
IRQF_SHARED | IRQF_IRQPOLL |
|
||||||
IRQF_NO_SUSPEND, pdev->name, pdev);
|
IRQF_NO_SUSPEND, pdev->name, pdev);
|
||||||
|
@ -244,11 +303,6 @@ static int sama5d4_wdt_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
watchdog_init_timeout(wdd, wdt_timeout, dev);
|
watchdog_init_timeout(wdd, wdt_timeout, dev);
|
||||||
|
|
||||||
timeout = WDT_SEC2TICKS(wdd->timeout);
|
|
||||||
|
|
||||||
wdt->mr |= AT91_WDT_SET_WDD(WDT_SEC2TICKS(MAX_WDT_TIMEOUT));
|
|
||||||
wdt->mr |= AT91_WDT_SET_WDV(timeout);
|
|
||||||
|
|
||||||
ret = sama5d4_wdt_init(wdt);
|
ret = sama5d4_wdt_init(wdt);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -269,7 +323,12 @@ static int sama5d4_wdt_probe(struct platform_device *pdev)
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct of_device_id sama5d4_wdt_of_match[] = {
|
static const struct of_device_id sama5d4_wdt_of_match[] = {
|
||||||
{ .compatible = "atmel,sama5d4-wdt", },
|
{
|
||||||
|
.compatible = "atmel,sama5d4-wdt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.compatible = "microchip,sam9x60-wdt",
|
||||||
|
},
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(of, sama5d4_wdt_of_match);
|
MODULE_DEVICE_TABLE(of, sama5d4_wdt_of_match);
|
||||||
|
|
|
@ -262,6 +262,24 @@ static int stm32_iwdg_probe(struct platform_device *pdev)
|
||||||
watchdog_set_nowayout(wdd, WATCHDOG_NOWAYOUT);
|
watchdog_set_nowayout(wdd, WATCHDOG_NOWAYOUT);
|
||||||
watchdog_init_timeout(wdd, 0, dev);
|
watchdog_init_timeout(wdd, 0, dev);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In case of CONFIG_WATCHDOG_HANDLE_BOOT_ENABLED is set
|
||||||
|
* (Means U-Boot/bootloaders leaves the watchdog running)
|
||||||
|
* When we get here we should make a decision to prevent
|
||||||
|
* any side effects before user space daemon will take care of it.
|
||||||
|
* The best option, taking into consideration that there is no
|
||||||
|
* way to read values back from hardware, is to enforce watchdog
|
||||||
|
* being run with deterministic values.
|
||||||
|
*/
|
||||||
|
if (IS_ENABLED(CONFIG_WATCHDOG_HANDLE_BOOT_ENABLED)) {
|
||||||
|
ret = stm32_iwdg_start(wdd);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* Make sure the watchdog is serviced */
|
||||||
|
set_bit(WDOG_HW_RUNNING, &wdd->status);
|
||||||
|
}
|
||||||
|
|
||||||
ret = devm_watchdog_register_device(dev, wdd);
|
ret = devm_watchdog_register_device(dev, wdd);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -147,6 +147,25 @@ int watchdog_init_timeout(struct watchdog_device *wdd,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(watchdog_init_timeout);
|
EXPORT_SYMBOL_GPL(watchdog_init_timeout);
|
||||||
|
|
||||||
|
static int watchdog_reboot_notifier(struct notifier_block *nb,
|
||||||
|
unsigned long code, void *data)
|
||||||
|
{
|
||||||
|
struct watchdog_device *wdd;
|
||||||
|
|
||||||
|
wdd = container_of(nb, struct watchdog_device, reboot_nb);
|
||||||
|
if (code == SYS_DOWN || code == SYS_HALT) {
|
||||||
|
if (watchdog_active(wdd)) {
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = wdd->ops->stop(wdd);
|
||||||
|
if (ret)
|
||||||
|
return NOTIFY_BAD;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NOTIFY_DONE;
|
||||||
|
}
|
||||||
|
|
||||||
static int watchdog_restart_notifier(struct notifier_block *nb,
|
static int watchdog_restart_notifier(struct notifier_block *nb,
|
||||||
unsigned long action, void *data)
|
unsigned long action, void *data)
|
||||||
{
|
{
|
||||||
|
@ -235,6 +254,19 @@ static int __watchdog_register_device(struct watchdog_device *wdd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (test_bit(WDOG_STOP_ON_REBOOT, &wdd->status)) {
|
||||||
|
wdd->reboot_nb.notifier_call = watchdog_reboot_notifier;
|
||||||
|
|
||||||
|
ret = register_reboot_notifier(&wdd->reboot_nb);
|
||||||
|
if (ret) {
|
||||||
|
pr_err("watchdog%d: Cannot register reboot notifier (%d)\n",
|
||||||
|
wdd->id, ret);
|
||||||
|
watchdog_dev_unregister(wdd);
|
||||||
|
ida_simple_remove(&watchdog_ida, id);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (wdd->ops->restart) {
|
if (wdd->ops->restart) {
|
||||||
wdd->restart_nb.notifier_call = watchdog_restart_notifier;
|
wdd->restart_nb.notifier_call = watchdog_restart_notifier;
|
||||||
|
|
||||||
|
@ -289,6 +321,9 @@ static void __watchdog_unregister_device(struct watchdog_device *wdd)
|
||||||
if (wdd->ops->restart)
|
if (wdd->ops->restart)
|
||||||
unregister_restart_handler(&wdd->restart_nb);
|
unregister_restart_handler(&wdd->restart_nb);
|
||||||
|
|
||||||
|
if (test_bit(WDOG_STOP_ON_REBOOT, &wdd->status))
|
||||||
|
unregister_reboot_notifier(&wdd->reboot_nb);
|
||||||
|
|
||||||
watchdog_dev_unregister(wdd);
|
watchdog_dev_unregister(wdd);
|
||||||
ida_simple_remove(&watchdog_ida, wdd->id);
|
ida_simple_remove(&watchdog_ida, wdd->id);
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,6 @@
|
||||||
#include <linux/miscdevice.h> /* For handling misc devices */
|
#include <linux/miscdevice.h> /* For handling misc devices */
|
||||||
#include <linux/module.h> /* For module stuff/... */
|
#include <linux/module.h> /* For module stuff/... */
|
||||||
#include <linux/mutex.h> /* For mutexes */
|
#include <linux/mutex.h> /* For mutexes */
|
||||||
#include <linux/reboot.h> /* For reboot notifier */
|
|
||||||
#include <linux/slab.h> /* For memory functions */
|
#include <linux/slab.h> /* For memory functions */
|
||||||
#include <linux/types.h> /* For standard types (like size_t) */
|
#include <linux/types.h> /* For standard types (like size_t) */
|
||||||
#include <linux/watchdog.h> /* For watchdog specific items */
|
#include <linux/watchdog.h> /* For watchdog specific items */
|
||||||
|
@ -1097,25 +1096,6 @@ static void watchdog_cdev_unregister(struct watchdog_device *wdd)
|
||||||
put_device(&wd_data->dev);
|
put_device(&wd_data->dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int watchdog_reboot_notifier(struct notifier_block *nb,
|
|
||||||
unsigned long code, void *data)
|
|
||||||
{
|
|
||||||
struct watchdog_device *wdd;
|
|
||||||
|
|
||||||
wdd = container_of(nb, struct watchdog_device, reboot_nb);
|
|
||||||
if (code == SYS_DOWN || code == SYS_HALT) {
|
|
||||||
if (watchdog_active(wdd)) {
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = wdd->ops->stop(wdd);
|
|
||||||
if (ret)
|
|
||||||
return NOTIFY_BAD;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NOTIFY_DONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* watchdog_dev_register: register a watchdog device
|
* watchdog_dev_register: register a watchdog device
|
||||||
* @wdd: watchdog device
|
* @wdd: watchdog device
|
||||||
|
@ -1134,22 +1114,8 @@ int watchdog_dev_register(struct watchdog_device *wdd)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ret = watchdog_register_pretimeout(wdd);
|
ret = watchdog_register_pretimeout(wdd);
|
||||||
if (ret) {
|
if (ret)
|
||||||
watchdog_cdev_unregister(wdd);
|
watchdog_cdev_unregister(wdd);
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (test_bit(WDOG_STOP_ON_REBOOT, &wdd->status)) {
|
|
||||||
wdd->reboot_nb.notifier_call = watchdog_reboot_notifier;
|
|
||||||
|
|
||||||
ret = devm_register_reboot_notifier(&wdd->wd_data->dev,
|
|
||||||
&wdd->reboot_nb);
|
|
||||||
if (ret) {
|
|
||||||
pr_err("watchdog%d: Cannot register reboot notifier (%d)\n",
|
|
||||||
wdd->id, ret);
|
|
||||||
watchdog_dev_unregister(wdd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
22
include/dt-bindings/reset-controller/mt2712-resets.h
Normal file
22
include/dt-bindings/reset-controller/mt2712-resets.h
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019 MediaTek Inc.
|
||||||
|
* Author: Yong Liang <yong.liang@mediatek.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _DT_BINDINGS_RESET_CONTROLLER_MT2712
|
||||||
|
#define _DT_BINDINGS_RESET_CONTROLLER_MT2712
|
||||||
|
|
||||||
|
#define MT2712_TOPRGU_INFRA_SW_RST 0
|
||||||
|
#define MT2712_TOPRGU_MM_SW_RST 1
|
||||||
|
#define MT2712_TOPRGU_MFG_SW_RST 2
|
||||||
|
#define MT2712_TOPRGU_VENC_SW_RST 3
|
||||||
|
#define MT2712_TOPRGU_VDEC_SW_RST 4
|
||||||
|
#define MT2712_TOPRGU_IMG_SW_RST 5
|
||||||
|
#define MT2712_TOPRGU_INFRA_AO_SW_RST 8
|
||||||
|
#define MT2712_TOPRGU_USB_SW_RST 9
|
||||||
|
#define MT2712_TOPRGU_APMIXED_SW_RST 10
|
||||||
|
|
||||||
|
#define MT2712_TOPRGU_SW_RST_NUM 11
|
||||||
|
|
||||||
|
#endif /* _DT_BINDINGS_RESET_CONTROLLER_MT2712 */
|
|
@ -78,4 +78,21 @@
|
||||||
#define MT8183_INFRACFG_AO_I2C7_SW_RST 126
|
#define MT8183_INFRACFG_AO_I2C7_SW_RST 126
|
||||||
#define MT8183_INFRACFG_AO_I2C8_SW_RST 127
|
#define MT8183_INFRACFG_AO_I2C8_SW_RST 127
|
||||||
|
|
||||||
|
#define MT8183_INFRACFG_SW_RST_NUM 128
|
||||||
|
|
||||||
|
#define MT8183_TOPRGU_MM_SW_RST 1
|
||||||
|
#define MT8183_TOPRGU_MFG_SW_RST 2
|
||||||
|
#define MT8183_TOPRGU_VENC_SW_RST 3
|
||||||
|
#define MT8183_TOPRGU_VDEC_SW_RST 4
|
||||||
|
#define MT8183_TOPRGU_IMG_SW_RST 5
|
||||||
|
#define MT8183_TOPRGU_MD_SW_RST 7
|
||||||
|
#define MT8183_TOPRGU_CONN_SW_RST 9
|
||||||
|
#define MT8183_TOPRGU_CONN_MCU_SW_RST 12
|
||||||
|
#define MT8183_TOPRGU_IPU0_SW_RST 14
|
||||||
|
#define MT8183_TOPRGU_IPU1_SW_RST 15
|
||||||
|
#define MT8183_TOPRGU_AUDIO_SW_RST 17
|
||||||
|
#define MT8183_TOPRGU_CAMSYS_SW_RST 18
|
||||||
|
|
||||||
|
#define MT8183_TOPRGU_SW_RST_NUM 19
|
||||||
|
|
||||||
#endif /* _DT_BINDINGS_RESET_CONTROLLER_MT8183 */
|
#endif /* _DT_BINDINGS_RESET_CONTROLLER_MT8183 */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue