From patchwork Wed Nov 14 07:16:03 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wenyou Yang X-Patchwork-Id: 1739351 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by patchwork1.kernel.org (Postfix) with ESMTP id 08BFA3FC64 for ; Wed, 14 Nov 2012 07:23:51 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1TYXHU-0002a2-CA; Wed, 14 Nov 2012 07:21:04 +0000 Received: from newsmtp5.atmel.com ([204.2.163.5] helo=sjogate2.atmel.com) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1TYXG7-0002Cj-Q8 for linux-arm-kernel@lists.infradead.org; Wed, 14 Nov 2012 07:19:44 +0000 Received: from penbh01.corp.atmel.com ([10.168.5.31]) by sjogate2.atmel.com (8.13.6/8.13.6) with ESMTP id qAE7E6GH008421; Tue, 13 Nov 2012 23:14:24 -0800 (PST) Received: from penmb01.corp.atmel.com ([10.168.5.33]) by penbh01.corp.atmel.com with Microsoft SMTPSVC(6.0.3790.3959); Wed, 14 Nov 2012 15:19:31 +0800 Received: from shaarm01.corp.atmel.com ([10.217.6.34]) by penmb01.corp.atmel.com with Microsoft SMTPSVC(6.0.3790.3959); Wed, 14 Nov 2012 15:19:30 +0800 From: Wenyou Yang To: linux-arm-kernel@lists.infradead.org Subject: [PATCH 05/11] watchdog/at91sam9_wdt: add to use the watchdog framework Date: Wed, 14 Nov 2012 15:16:03 +0800 Message-Id: <1352877369-19740-6-git-send-email-wenyou.yang@atmel.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1352877369-19740-1-git-send-email-wenyou.yang@atmel.com> References: <1352877369-19740-1-git-send-email-wenyou.yang@atmel.com> X-OriginalArrivalTime: 14 Nov 2012 07:19:31.0525 (UTC) FILETIME=[63FF5F50:01CDC238] X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20121114_021940_328132_21D2897F X-CRM114-Status: GOOD ( 17.62 ) X-Spam-Score: -2.6 (--) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-2.6 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_PASS SPF: sender matches SPF record -0.7 RP_MATCHES_RCVD Envelope sender domain matches handover relay domain -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: linux-watchdog@vger.kernel.org, JM.Lin@atmel.com, nicolas.ferre@atmel.com, linux-kernel@vger.kernel.org, wenyou.yang@atmel.com, wim@iguana.be, plagnioj@jcrosoft.com X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: linux-arm-kernel-bounces@lists.infradead.org Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org For the Watchdog Timer Mode Register can be only written only once, so struct watchdog_info options only support WDIOF_KEEPALIVEPING, not support WDIOF_SETTIMEOUT and WDIOF_MAGICCLOSE. Signed-off-by: Wenyou Yang --- drivers/watchdog/Kconfig | 1 + drivers/watchdog/at91sam9_wdt.c | 90 ++++++++++++++++++++++++++++++++------- 2 files changed, 76 insertions(+), 15 deletions(-) diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index ad1bb93..dda695f 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -114,6 +114,7 @@ config AT91RM9200_WATCHDOG config AT91SAM9X_WATCHDOG tristate "AT91SAM9X / AT91CAP9 watchdog" depends on ARCH_AT91 && !ARCH_AT91RM9200 + select WATCHDOG_CORE help Watchdog timer embedded into AT91SAM9X and AT91CAP9 chips. This will reboot your system when the timeout is reached. diff --git a/drivers/watchdog/at91sam9_wdt.c b/drivers/watchdog/at91sam9_wdt.c index e2d6111..84c2aa7 100644 --- a/drivers/watchdog/at91sam9_wdt.c +++ b/drivers/watchdog/at91sam9_wdt.c @@ -85,6 +85,11 @@ static inline void wdt_write(struct at91wdt_drvdata *driver_data, __raw_writel((val), driver_data->base + field); } +static inline bool watchdog_is_open(struct watchdog_device *wddev) +{ + return test_bit(WDOG_DEV_OPEN, &wddev->status); +} + /* * Reload the watchdog timer. (ie, pat the watchdog) */ @@ -101,9 +106,12 @@ static void at91_ping(unsigned long data) struct watchdog_device *wddev = (struct watchdog_device *)data; struct at91wdt_drvdata *driver_data = watchdog_get_drvdata(wddev); - if (time_before(jiffies, driver_data->next_heartbeat)) - at91_wdt_reset(); + if (time_before(jiffies, driver_data->next_heartbeat)) { + at91_wdt_reset(driver_data); mod_timer(&driver_data->timer, jiffies + WDT_TIMEOUT); + + if (!watchdog_is_open(wddev)) + driver_data->next_heartbeat = jiffies + heartbeat * HZ; } else pr_crit("I will reset your machine !\n"); } @@ -144,17 +152,62 @@ static int at91wdt_enable(struct watchdog_device *wddev, unsigned int timeout) return 0; } -static const struct watchdog_info at91_wdt_info = { +static int at91wdt_start(struct watchdog_device *wddev) +{ + struct at91wdt_drvdata *driver_data = watchdog_get_drvdata(wddev); + + if (driver_data->enabled) + return 0; + else + return -EIO; +} + +static int at91wdt_stop(struct watchdog_device *wddev) +{ + struct at91wdt_drvdata *driver_data = watchdog_get_drvdata(wddev); + + if (driver_data->enabled) + return -EIO; + else + return 0; +} + +static int at91wdt_keepalive(struct watchdog_device *wddev) +{ + struct at91wdt_drvdata *driver_data = watchdog_get_drvdata(wddev); + + if (driver_data->enabled) { + driver_data->next_heartbeat = jiffies + heartbeat * HZ; + return 0; + } else + return -EIO; +} + +/* ......................................................................... */ + +static const struct watchdog_info at91wdt_info = { .identity = DRV_NAME, - .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | - WDIOF_MAGICCLOSE, + .options = WDIOF_KEEPALIVEPING, + .firmware_version = 0, +}; + +static struct watchdog_ops at91wdt_ops = { + .owner = THIS_MODULE, + .start = at91wdt_start, + .stop = at91wdt_stop, + .ping = at91wdt_keepalive, +}; + +static struct watchdog_device at91_wddev = { + .info = &at91wdt_info, + .ops = &at91wdt_ops, }; static int __init at91wdt_probe(struct platform_device *pdev) { struct at91wdt_drvdata *driver_data; - struct resource *r; - int res; + struct resource *res; + int ret; driver_data = devm_kzalloc(&pdev->dev, sizeof(*driver_data), GFP_KERNEL); @@ -163,10 +216,10 @@ static int __init at91wdt_probe(struct platform_device *pdev) return -ENOMEM; } - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!r) + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) return -ENODEV; - driver_data->base = ioremap(r->start, resource_size(r)); + driver_data->base = ioremap(res->start, resource_size(res)); if (!driver_data->base) { dev_err(&pdev->dev, "failed to map registers, aborting.\n"); return -ENOMEM; @@ -174,14 +227,21 @@ static int __init at91wdt_probe(struct platform_device *pdev) watchdog_set_drvdata(&at91_wddev, driver_data); - res = at91wdt_enable(&at91_wddev); - if (res) { + ret = at91wdt_enable(&at91_wddev, ms_to_ticks(WDT_HW_TIMEOUT * 1000)); + if (ret) { dev_err(&pdev->dev, "cannot enable watchdog (%d)\n", ret); return ret; } + ret = watchdog_register_device(&at91_wddev); + if (ret) { + dev_err(&pdev->dev, "cannot register watchdog (%d)\n", ret); + return ret; + } + driver_data->next_heartbeat = jiffies + heartbeat * HZ; - setup_timer(&driver_data->timer, at91_ping, 0); + setup_timer(&driver_data->timer, at91_ping, + (unsigned long)&at91_wddev); mod_timer(&driver_data->timer, jiffies + WDT_TIMEOUT); pr_info("enabled (heartbeat=%d sec, nowayout=%d)\n", @@ -192,9 +252,9 @@ static int __init at91wdt_probe(struct platform_device *pdev) static int __exit at91wdt_remove(struct platform_device *pdev) { - int res; + watchdog_unregister_device(&at91_wddev); - return res; + return 0; } static struct platform_driver at91wdt_driver = {