Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 360591
b: refs/heads/master
c: 3d3a6d1
h: refs/heads/master
i:
  360589: c5a93db
  360587: eb8d611
  360583: 1e73fdc
  360575: fb23d2e
v: v3
  • Loading branch information
Aaro Koskinen authored and Wim Van Sebroeck committed Mar 1, 2013
1 parent 8e55c92 commit f59636e
Show file tree
Hide file tree
Showing 4 changed files with 192 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: d1ec74ab5a48d794c5e3671a895d49d162d0f916
refs/heads/master: 3d3a6d18abc66ba38e554fd5cb5991dfa805cd23
12 changes: 12 additions & 0 deletions trunk/drivers/watchdog/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,18 @@ config UX500_WATCHDOG
To compile this driver as a module, choose M here: the
module will be called ux500_wdt.

config RETU_WATCHDOG
tristate "Retu watchdog"
depends on MFD_RETU
select WATCHDOG_CORE
help
Retu watchdog driver for Nokia Internet Tablets (770, N800,
N810). At least on N800 the watchdog cannot be disabled, so
this driver is essential and you should enable it.

To compile this driver as a module, choose M here: the
module will be called retu_wdt.

# AVR32 Architecture

config AT32AP700X_WDT
Expand Down
1 change: 1 addition & 0 deletions trunk/drivers/watchdog/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ obj-$(CONFIG_NUC900_WATCHDOG) += nuc900_wdt.o
obj-$(CONFIG_TS72XX_WATCHDOG) += ts72xx_wdt.o
obj-$(CONFIG_IMX2_WDT) += imx2_wdt.o
obj-$(CONFIG_UX500_WATCHDOG) += ux500_wdt.o
obj-$(CONFIG_RETU_WATCHDOG) += retu_wdt.o

# AVR32 Architecture
obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o
Expand Down
178 changes: 178 additions & 0 deletions trunk/drivers/watchdog/retu_wdt.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
/*
* Retu watchdog driver
*
* Copyright (C) 2004, 2005 Nokia Corporation
*
* Based on code written by Amit Kucheria and Michael Buesch.
* Rewritten by Aaro Koskinen.
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file "COPYING" in the main directory of this
* archive for more details.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/

#include <linux/init.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mfd/retu.h>
#include <linux/watchdog.h>
#include <linux/platform_device.h>

/* Watchdog timer values in seconds */
#define RETU_WDT_MAX_TIMER 63

struct retu_wdt_dev {
struct retu_dev *rdev;
struct device *dev;
struct delayed_work ping_work;
};

/*
* Since Retu watchdog cannot be disabled in hardware, we must kick it
* with a timer until userspace watchdog software takes over. If
* CONFIG_WATCHDOG_NOWAYOUT is set, we never start the feeding.
*/
static void retu_wdt_ping_enable(struct retu_wdt_dev *wdev)
{
retu_write(wdev->rdev, RETU_REG_WATCHDOG, RETU_WDT_MAX_TIMER);
schedule_delayed_work(&wdev->ping_work,
round_jiffies_relative(RETU_WDT_MAX_TIMER * HZ / 2));
}

static void retu_wdt_ping_disable(struct retu_wdt_dev *wdev)
{
retu_write(wdev->rdev, RETU_REG_WATCHDOG, RETU_WDT_MAX_TIMER);
cancel_delayed_work_sync(&wdev->ping_work);
}

static void retu_wdt_ping_work(struct work_struct *work)
{
struct retu_wdt_dev *wdev = container_of(to_delayed_work(work),
struct retu_wdt_dev, ping_work);
retu_wdt_ping_enable(wdev);
}

static int retu_wdt_start(struct watchdog_device *wdog)
{
struct retu_wdt_dev *wdev = watchdog_get_drvdata(wdog);

retu_wdt_ping_disable(wdev);

return retu_write(wdev->rdev, RETU_REG_WATCHDOG, wdog->timeout);
}

static int retu_wdt_stop(struct watchdog_device *wdog)
{
struct retu_wdt_dev *wdev = watchdog_get_drvdata(wdog);

retu_wdt_ping_enable(wdev);

return 0;
}

static int retu_wdt_ping(struct watchdog_device *wdog)
{
struct retu_wdt_dev *wdev = watchdog_get_drvdata(wdog);

return retu_write(wdev->rdev, RETU_REG_WATCHDOG, wdog->timeout);
}

static int retu_wdt_set_timeout(struct watchdog_device *wdog,
unsigned int timeout)
{
struct retu_wdt_dev *wdev = watchdog_get_drvdata(wdog);

wdog->timeout = timeout;
return retu_write(wdev->rdev, RETU_REG_WATCHDOG, wdog->timeout);
}

static const struct watchdog_info retu_wdt_info = {
.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
.identity = "Retu watchdog",
};

static const struct watchdog_ops retu_wdt_ops = {
.owner = THIS_MODULE,
.start = retu_wdt_start,
.stop = retu_wdt_stop,
.ping = retu_wdt_ping,
.set_timeout = retu_wdt_set_timeout,
};

static int retu_wdt_probe(struct platform_device *pdev)
{
struct retu_dev *rdev = dev_get_drvdata(pdev->dev.parent);
bool nowayout = WATCHDOG_NOWAYOUT;
struct watchdog_device *retu_wdt;
struct retu_wdt_dev *wdev;
int ret;

retu_wdt = devm_kzalloc(&pdev->dev, sizeof(*retu_wdt), GFP_KERNEL);
if (!retu_wdt)
return -ENOMEM;

wdev = devm_kzalloc(&pdev->dev, sizeof(*wdev), GFP_KERNEL);
if (!wdev)
return -ENOMEM;

retu_wdt->info = &retu_wdt_info;
retu_wdt->ops = &retu_wdt_ops;
retu_wdt->timeout = RETU_WDT_MAX_TIMER;
retu_wdt->min_timeout = 0;
retu_wdt->max_timeout = RETU_WDT_MAX_TIMER;

watchdog_set_drvdata(retu_wdt, wdev);
watchdog_set_nowayout(retu_wdt, nowayout);

wdev->rdev = rdev;
wdev->dev = &pdev->dev;

INIT_DELAYED_WORK(&wdev->ping_work, retu_wdt_ping_work);

ret = watchdog_register_device(retu_wdt);
if (ret < 0)
return ret;

if (nowayout)
retu_wdt_ping(retu_wdt);
else
retu_wdt_ping_enable(wdev);

platform_set_drvdata(pdev, retu_wdt);

return 0;
}

static int retu_wdt_remove(struct platform_device *pdev)
{
struct watchdog_device *wdog = platform_get_drvdata(pdev);
struct retu_wdt_dev *wdev = watchdog_get_drvdata(wdog);

watchdog_unregister_device(wdog);
cancel_delayed_work_sync(&wdev->ping_work);

return 0;
}

static struct platform_driver retu_wdt_driver = {
.probe = retu_wdt_probe,
.remove = retu_wdt_remove,
.driver = {
.name = "retu-wdt",
},
};
module_platform_driver(retu_wdt_driver);

MODULE_ALIAS("platform:retu-wdt");
MODULE_DESCRIPTION("Retu watchdog");
MODULE_AUTHOR("Amit Kucheria");
MODULE_AUTHOR("Aaro Koskinen <aaro.koskinen@iki.fi>");
MODULE_LICENSE("GPL");

0 comments on commit f59636e

Please sign in to comment.