[WATCHDOG] Re-factor ts_wdt to use ts-mcu-core

This commit is contained in:
Stuart Longland 2018-08-27 21:34:32 +10:00
parent 9f8f8c0d88
commit 7ee9473d89
Signed by: stuartl
GPG Key ID: 6AA32EFB18079BAA
2 changed files with 41 additions and 47 deletions

View File

@ -545,6 +545,7 @@ config TS4800_WATCHDOG
config TS_WDT_MICRO
tristate "Technologic Microcontroller Watchdog"
depends on ARM
select MFD_TS_MCU
select WATCHDOG_CORE
help
Hardware driver for the Technologic Systems silabs based

View File

@ -21,16 +21,18 @@
#include <linux/delay.h>
#include <asm/system_misc.h>
#include <linux/mfd/ts-mcu.h>
#define TS_DEFAULT_TIMEOUT 30
static bool nowayout = WATCHDOG_NOWAYOUT;
struct ts_wdt_dev {
struct device *dev;
struct ts_mcu_dev *mcu;
struct delayed_work ping_work;
};
struct i2c_client *client;
static struct ts_wdt_dev *wdev;
/* The WDT expects 3 values:
* 0 (always)
@ -55,53 +57,50 @@ static int ts_wdt_write(u16 deciseconds)
out[0] = 0;
out[1] = (deciseconds & 0xff00) >> 8;
out[2] = deciseconds & 0xff;
dev_dbg(&client->dev, "Writing 0x00, 0x%02x, 0x%02x\n",
dev_dbg(wdev->mcu->dev, "Writing 0x00, 0x%02x, 0x%02x\n",
out[1],
out[2]);
msg.addr = client->addr;
msg.flags = 0;
msg.len = 3;
msg.buf = out;
ret = i2c_transfer(client->adapter, &msg, 1);
ret = ts_mcu_transfer(wdev->mcu, &msg, 1);
if (ret != 1) {
dev_err(&client->dev, "%s: write error, ret=%d\n",
dev_err(wdev->mcu->dev, "%s: write error, ret=%d\n",
__func__, ret);
}
return !ret;
}
/* Watchdog is on by default. We feed every timeout/2 until userspace feeds */
static void ts_wdt_ping_enable(struct ts_wdt_dev *wdev)
static void ts_wdt_ping_enable()
{
dev_dbg(&client->dev, "%s\n", __func__);
dev_dbg(wdev->mcu->dev, "%s\n", __func__);
ts_wdt_write(TS_DEFAULT_TIMEOUT * 10);
schedule_delayed_work(&wdev->ping_work,
round_jiffies_relative(TS_DEFAULT_TIMEOUT * HZ / 2));
}
static void ts_wdt_ping_disable(struct ts_wdt_dev *wdev)
static void ts_wdt_ping_disable()
{
dev_dbg(&client->dev, "%s\n", __func__);
dev_dbg(wdev->mcu->dev, "%s\n", __func__);
ts_wdt_write(TS_DEFAULT_TIMEOUT * 10);
cancel_delayed_work_sync(&wdev->ping_work);
}
static int ts_wdt_start(struct watchdog_device *wdt)
{
struct ts_wdt_dev *wdev = watchdog_get_drvdata(wdt);
dev_dbg(wdev->mcu->dev, "%s\n", __func__);
dev_dbg(wdev->mcu->dev, "Feeding for %d seconds\n", wdt->timeout);
dev_dbg(&client->dev, "%s\n", __func__);
dev_dbg(&client->dev, "Feeding for %d seconds\n", wdt->timeout);
ts_wdt_ping_disable(wdev);
ts_wdt_ping_disable();
return ts_wdt_write(wdt->timeout * 10);
}
static int ts_wdt_stop(struct watchdog_device *wdt)
{
dev_dbg(&client->dev, "%s\n", __func__);
dev_dbg(wdev->mcu->dev, "%s\n", __func__);
return ts_wdt_write(3);
}
@ -110,7 +109,7 @@ static void do_ts_reboot(enum reboot_mode reboot_mode, const char *cmd)
unsigned long flags;
static DEFINE_SPINLOCK(wdt_lock);
dev_dbg(&client->dev, "%s\n", __func__);
dev_dbg(wdev->mcu->dev, "%s\n", __func__);
spin_lock_irqsave(&wdt_lock, flags);
ts_wdt_write(0);
@ -122,7 +121,7 @@ static void do_ts_halt(void)
unsigned long flags;
static DEFINE_SPINLOCK(wdt_lock);
dev_dbg(&client->dev, "%s\n", __func__);
dev_dbg(wdev->mcu->dev, "%s\n", __func__);
spin_lock_irqsave(&wdt_lock, flags);
ts_wdt_write(3);
@ -132,17 +131,15 @@ static void do_ts_halt(void)
static int ts_set_timeout(struct watchdog_device *wdt,
unsigned int timeout)
{
dev_dbg(&client->dev, "%s\n", __func__);
dev_dbg(wdev->mcu->dev, "%s\n", __func__);
wdt->timeout = timeout;
return 0;
}
static void ts_wdt_ping_work(struct work_struct *work)
{
struct ts_wdt_dev *wdev = container_of(to_delayed_work(work),
struct ts_wdt_dev, ping_work);
dev_dbg(&client->dev, "%s\n", __func__);
ts_wdt_ping_enable(wdev);
dev_dbg(wdev->mcu->dev, "%s\n", __func__);
ts_wdt_ping_enable();
}
static struct watchdog_info ts_wdt_ident = {
@ -166,20 +163,24 @@ static struct watchdog_device ts_wdt_wdd = {
.max_timeout = 6553,
};
static int tsreboot_probe(struct i2c_client *c,
const struct i2c_device_id *id)
static int ts_wdt_probe(struct platform_device *pdev)
{
int err;
struct ts_wdt_dev *wdev;
client = c;
struct ts_mcu_dev *mcu = dev_get_drvdata(pdev->dev.parent);
wdev = devm_kzalloc(&client->dev, sizeof(*wdev), GFP_KERNEL);
if (wdev) {
dev_err(&pdev->dev, "Only one instance supported\n");
return -EALREADY;
}
wdev = devm_kzalloc(&pdev->dev, sizeof(*wdev), GFP_KERNEL);
if (!wdev)
return -ENOMEM;
wdev->mcu = mcu;
arm_pm_restart = do_ts_reboot;
pm_power_off = do_ts_halt;
dev_dbg(&client->dev, "%s\n", __func__);
dev_dbg(&pdev->dev, "%s\n", __func__);
watchdog_set_drvdata(&ts_wdt_wdd, wdev);
watchdog_set_nowayout(&ts_wdt_wdd, nowayout);
@ -190,40 +191,32 @@ static int tsreboot_probe(struct i2c_client *c,
if (err)
return err;
ts_wdt_ping_enable(wdev);
ts_wdt_ping_enable();
return 0;
}
static const struct i2c_device_id tsreboot_id[] = {
{ "ts-wdt", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, tsreboot_id);
MODULE_ALIAS("platform:ts-wdt");
static struct i2c_driver ts_reboot_driver = {
static struct platform_driver ts_wdt_driver = {
.driver = {
.name = "ts-wdt",
.owner = THIS_MODULE,
},
.probe = tsreboot_probe,
.id_table = tsreboot_id,
.probe = ts_wdt_probe,
};
static int __init ts_reboot_init(void)
static int __init ts_wdt_init(void)
{
return i2c_add_driver(&ts_reboot_driver);
return platform_driver_register(&ts_wdt_driver);
}
subsys_initcall(ts_reboot_init);
subsys_initcall(ts_wdt_init);
static void __exit ts_reboot_exit(void)
static void __exit ts_wdt_exit(void)
{
i2c_del_driver(&ts_reboot_driver);
platform_driver_unregister(&ts_wdt_driver);
}
module_exit(ts_reboot_exit);
module_exit(ts_wdt_exit);
MODULE_AUTHOR("Mark Featherston <mark@embeddedarm.com>");
MODULE_DESCRIPTION("Technologic Systems watchdog driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:ts-wdt");