From bedbef8ad3e75a304af6361af235302bcc61d06b Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Tue, 14 May 2024 06:39:01 +0000 Subject: [PATCH] 修改内核路径 --- kernel/drivers/watchdog/da9062_wdt.c | 93 +++++++++++++++++++++++++++++++++++----------- 1 files changed, 71 insertions(+), 22 deletions(-) diff --git a/kernel/drivers/watchdog/da9062_wdt.c b/kernel/drivers/watchdog/da9062_wdt.c index 132d45d..706fb09 100644 --- a/kernel/drivers/watchdog/da9062_wdt.c +++ b/kernel/drivers/watchdog/da9062_wdt.c @@ -11,10 +11,12 @@ #include <linux/platform_device.h> #include <linux/uaccess.h> #include <linux/slab.h> +#include <linux/i2c.h> #include <linux/delay.h> #include <linux/jiffies.h> #include <linux/mfd/da9062/registers.h> #include <linux/mfd/da9062/core.h> +#include <linux/property.h> #include <linux/regmap.h> #include <linux/of.h> @@ -30,7 +32,17 @@ struct da9062_watchdog { struct da9062 *hw; struct watchdog_device wdtdev; + bool use_sw_pm; }; + +static unsigned int da9062_wdt_read_timeout(struct da9062_watchdog *wdt) +{ + unsigned int val; + + regmap_read(wdt->hw->regmap, DA9062AA_CONTROL_D, &val); + + return wdt_timeout[val & DA9062AA_TWDSCALE_MASK]; +} static unsigned int da9062_wdt_timeout_to_sel(unsigned int secs) { @@ -46,14 +58,9 @@ static int da9062_reset_watchdog_timer(struct da9062_watchdog *wdt) { - int ret; - - ret = regmap_update_bits(wdt->hw->regmap, - DA9062AA_CONTROL_F, - DA9062AA_WATCHDOG_MASK, - DA9062AA_WATCHDOG_MASK); - - return ret; + return regmap_update_bits(wdt->hw->regmap, DA9062AA_CONTROL_F, + DA9062AA_WATCHDOG_MASK, + DA9062AA_WATCHDOG_MASK); } static int da9062_wdt_update_timeout_register(struct da9062_watchdog *wdt, @@ -140,12 +147,13 @@ void *data) { struct da9062_watchdog *wdt = watchdog_get_drvdata(wdd); + struct i2c_client *client = to_i2c_client(wdt->hw->dev); int ret; - ret = regmap_write(wdt->hw->regmap, - DA9062AA_CONTROL_F, - DA9062AA_SHUTDOWN_MASK); - if (ret) + /* Don't use regmap because it is not atomic safe */ + ret = i2c_smbus_write_byte_data(client, DA9062AA_CONTROL_F, + DA9062AA_SHUTDOWN_MASK); + if (ret < 0) dev_alert(wdt->hw->dev, "Failed to shutdown (err = %d)\n", ret); @@ -178,17 +186,20 @@ static int da9062_wdt_probe(struct platform_device *pdev) { - int ret; + struct device *dev = &pdev->dev; + unsigned int timeout; struct da9062 *chip; struct da9062_watchdog *wdt; - chip = dev_get_drvdata(pdev->dev.parent); + chip = dev_get_drvdata(dev->parent); if (!chip) return -EINVAL; - wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL); + wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL); if (!wdt) return -ENOMEM; + + wdt->use_sw_pm = device_property_present(dev, "dlg,use-sw-pm"); wdt->hw = chip; @@ -199,26 +210,64 @@ wdt->wdtdev.min_hw_heartbeat_ms = DA9062_RESET_PROTECTION_MS; wdt->wdtdev.timeout = DA9062_WDG_DEFAULT_TIMEOUT; wdt->wdtdev.status = WATCHDOG_NOWAYOUT_INIT_STATUS; - wdt->wdtdev.parent = &pdev->dev; + wdt->wdtdev.parent = dev; watchdog_set_restart_priority(&wdt->wdtdev, 128); watchdog_set_drvdata(&wdt->wdtdev, wdt); + dev_set_drvdata(dev, &wdt->wdtdev); - ret = devm_watchdog_register_device(&pdev->dev, &wdt->wdtdev); - if (ret < 0) { - dev_err(wdt->hw->dev, - "watchdog registration failed (%d)\n", ret); - return ret; + timeout = da9062_wdt_read_timeout(wdt); + if (timeout) + wdt->wdtdev.timeout = timeout; + + /* Set timeout from DT value if available */ + watchdog_init_timeout(&wdt->wdtdev, 0, dev); + + if (timeout) { + da9062_wdt_set_timeout(&wdt->wdtdev, wdt->wdtdev.timeout); + set_bit(WDOG_HW_RUNNING, &wdt->wdtdev.status); } - return da9062_wdt_ping(&wdt->wdtdev); + return devm_watchdog_register_device(dev, &wdt->wdtdev); } + +static int __maybe_unused da9062_wdt_suspend(struct device *dev) +{ + struct watchdog_device *wdd = dev_get_drvdata(dev); + struct da9062_watchdog *wdt = watchdog_get_drvdata(wdd); + + if (!wdt->use_sw_pm) + return 0; + + 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); + struct da9062_watchdog *wdt = watchdog_get_drvdata(wdd); + + if (!wdt->use_sw_pm) + return 0; + + 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 = { .probe = da9062_wdt_probe, .driver = { .name = "da9062-watchdog", + .pm = &da9062_wdt_pm_ops, .of_match_table = da9062_compatible_id_table, }, }; -- Gitblit v1.6.2