17768a13c252a97e13a552f88f642962768de1fa4Komal Shah/* 22817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi * omap_wdt.c 37768a13c252a97e13a552f88f642962768de1fa4Komal Shah * 42817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi * Watchdog driver for the TI OMAP 16xx & 24xx/34xx 32KHz (non-secure) watchdog 57768a13c252a97e13a552f88f642962768de1fa4Komal Shah * 67768a13c252a97e13a552f88f642962768de1fa4Komal Shah * Author: MontaVista Software, Inc. 77768a13c252a97e13a552f88f642962768de1fa4Komal Shah * <gdavis@mvista.com> or <source@mvista.com> 87768a13c252a97e13a552f88f642962768de1fa4Komal Shah * 97768a13c252a97e13a552f88f642962768de1fa4Komal Shah * 2003 (c) MontaVista Software, Inc. This file is licensed under the 107768a13c252a97e13a552f88f642962768de1fa4Komal Shah * terms of the GNU General Public License version 2. This program is 117768a13c252a97e13a552f88f642962768de1fa4Komal Shah * licensed "as is" without any warranty of any kind, whether express 127768a13c252a97e13a552f88f642962768de1fa4Komal Shah * or implied. 137768a13c252a97e13a552f88f642962768de1fa4Komal Shah * 147768a13c252a97e13a552f88f642962768de1fa4Komal Shah * History: 157768a13c252a97e13a552f88f642962768de1fa4Komal Shah * 167768a13c252a97e13a552f88f642962768de1fa4Komal Shah * 20030527: George G. Davis <gdavis@mvista.com> 177768a13c252a97e13a552f88f642962768de1fa4Komal Shah * Initially based on linux-2.4.19-rmk7-pxa1/drivers/char/sa1100_wdt.c 187768a13c252a97e13a552f88f642962768de1fa4Komal Shah * (c) Copyright 2000 Oleg Drokin <green@crimea.edu> 1929fa0586de4fe518f122a915b8c6e92d12e8ca7fAlan Cox * Based on SoftDog driver by Alan Cox <alan@lxorguk.ukuu.org.uk> 207768a13c252a97e13a552f88f642962768de1fa4Komal Shah * 217768a13c252a97e13a552f88f642962768de1fa4Komal Shah * Copyright (c) 2004 Texas Instruments. 227768a13c252a97e13a552f88f642962768de1fa4Komal Shah * 1. Modified to support OMAP1610 32-KHz watchdog timer 237768a13c252a97e13a552f88f642962768de1fa4Komal Shah * 2. Ported to 2.6 kernel 247768a13c252a97e13a552f88f642962768de1fa4Komal Shah * 257768a13c252a97e13a552f88f642962768de1fa4Komal Shah * Copyright (c) 2005 David Brownell 267768a13c252a97e13a552f88f642962768de1fa4Komal Shah * Use the driver model and standard identifiers; handle bigger timeouts. 277768a13c252a97e13a552f88f642962768de1fa4Komal Shah */ 287768a13c252a97e13a552f88f642962768de1fa4Komal Shah 2927c766aaacb265d625dc634bf7903f7f9fd0c697Joe Perches#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 3027c766aaacb265d625dc634bf7903f7f9fd0c697Joe Perches 317768a13c252a97e13a552f88f642962768de1fa4Komal Shah#include <linux/module.h> 327768a13c252a97e13a552f88f642962768de1fa4Komal Shah#include <linux/types.h> 337768a13c252a97e13a552f88f642962768de1fa4Komal Shah#include <linux/kernel.h> 347768a13c252a97e13a552f88f642962768de1fa4Komal Shah#include <linux/fs.h> 357768a13c252a97e13a552f88f642962768de1fa4Komal Shah#include <linux/mm.h> 367768a13c252a97e13a552f88f642962768de1fa4Komal Shah#include <linux/miscdevice.h> 377768a13c252a97e13a552f88f642962768de1fa4Komal Shah#include <linux/watchdog.h> 387768a13c252a97e13a552f88f642962768de1fa4Komal Shah#include <linux/reboot.h> 397768a13c252a97e13a552f88f642962768de1fa4Komal Shah#include <linux/init.h> 407768a13c252a97e13a552f88f642962768de1fa4Komal Shah#include <linux/err.h> 417768a13c252a97e13a552f88f642962768de1fa4Komal Shah#include <linux/platform_device.h> 427768a13c252a97e13a552f88f642962768de1fa4Komal Shah#include <linux/moduleparam.h> 431977f032722c27ee3730284582fd3991ad9ac81bJiri Slaby#include <linux/bitops.h> 44089ab0791d127e8ada526c4b4d18b7584be8acf0Wim Van Sebroeck#include <linux/io.h> 4512b9df7d21d0eedfaaee925f8f9c9aafb1cafa2fAlan Cox#include <linux/uaccess.h> 465a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 477ec5ad0f3c1e28b693185c35f768953c5db32291Varadarajan, Charulatha#include <linux/pm_runtime.h> 48a09e64fbc0094e3073dbb09c3b4bfe4ab669244bRussell King#include <mach/hardware.h> 49ce491cf85466c3377228c5a852ea627ec5136956Tony Lindgren#include <plat/prcm.h> 507768a13c252a97e13a552f88f642962768de1fa4Komal Shah 517768a13c252a97e13a552f88f642962768de1fa4Komal Shah#include "omap_wdt.h" 527768a13c252a97e13a552f88f642962768de1fa4Komal Shah 532817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbistatic struct platform_device *omap_wdt_dev; 542817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi 557768a13c252a97e13a552f88f642962768de1fa4Komal Shahstatic unsigned timer_margin; 567768a13c252a97e13a552f88f642962768de1fa4Komal Shahmodule_param(timer_margin, uint, 0); 577768a13c252a97e13a552f88f642962768de1fa4Komal ShahMODULE_PARM_DESC(timer_margin, "initial watchdog timeout (in seconds)"); 587768a13c252a97e13a552f88f642962768de1fa4Komal Shah 597768a13c252a97e13a552f88f642962768de1fa4Komal Shahstatic unsigned int wdt_trgr_pattern = 0x1234; 601334f32938e46fb321c67a652997d33583257249Axel Linstatic DEFINE_SPINLOCK(wdt_lock); 617768a13c252a97e13a552f88f642962768de1fa4Komal Shah 622817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbistruct omap_wdt_dev { 632817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi void __iomem *base; /* physical */ 642817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi struct device *dev; 652817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi int omap_wdt_users; 662817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi struct resource *mem; 672817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi struct miscdevice omap_wdt_miscdev; 682817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi}; 692817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi 702817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbistatic void omap_wdt_ping(struct omap_wdt_dev *wdev) 717768a13c252a97e13a552f88f642962768de1fa4Komal Shah{ 722817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi void __iomem *base = wdev->base; 73b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbi 747768a13c252a97e13a552f88f642962768de1fa4Komal Shah /* wait for posted write to complete */ 759f69e3b0c22200998caa73b23a39c03950b2752dFelipe Balbi while ((__raw_readl(base + OMAP_WATCHDOG_WPS)) & 0x08) 767768a13c252a97e13a552f88f642962768de1fa4Komal Shah cpu_relax(); 77b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbi 787768a13c252a97e13a552f88f642962768de1fa4Komal Shah wdt_trgr_pattern = ~wdt_trgr_pattern; 799f69e3b0c22200998caa73b23a39c03950b2752dFelipe Balbi __raw_writel(wdt_trgr_pattern, (base + OMAP_WATCHDOG_TGR)); 80b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbi 817768a13c252a97e13a552f88f642962768de1fa4Komal Shah /* wait for posted write to complete */ 829f69e3b0c22200998caa73b23a39c03950b2752dFelipe Balbi while ((__raw_readl(base + OMAP_WATCHDOG_WPS)) & 0x08) 837768a13c252a97e13a552f88f642962768de1fa4Komal Shah cpu_relax(); 847768a13c252a97e13a552f88f642962768de1fa4Komal Shah /* reloaded WCRR from WLDR */ 857768a13c252a97e13a552f88f642962768de1fa4Komal Shah} 867768a13c252a97e13a552f88f642962768de1fa4Komal Shah 872817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbistatic void omap_wdt_enable(struct omap_wdt_dev *wdev) 887768a13c252a97e13a552f88f642962768de1fa4Komal Shah{ 89b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbi void __iomem *base = wdev->base; 90b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbi 917768a13c252a97e13a552f88f642962768de1fa4Komal Shah /* Sequence to enable the watchdog */ 929f69e3b0c22200998caa73b23a39c03950b2752dFelipe Balbi __raw_writel(0xBBBB, base + OMAP_WATCHDOG_SPR); 939f69e3b0c22200998caa73b23a39c03950b2752dFelipe Balbi while ((__raw_readl(base + OMAP_WATCHDOG_WPS)) & 0x10) 947768a13c252a97e13a552f88f642962768de1fa4Komal Shah cpu_relax(); 95b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbi 969f69e3b0c22200998caa73b23a39c03950b2752dFelipe Balbi __raw_writel(0x4444, base + OMAP_WATCHDOG_SPR); 979f69e3b0c22200998caa73b23a39c03950b2752dFelipe Balbi while ((__raw_readl(base + OMAP_WATCHDOG_WPS)) & 0x10) 987768a13c252a97e13a552f88f642962768de1fa4Komal Shah cpu_relax(); 997768a13c252a97e13a552f88f642962768de1fa4Komal Shah} 1007768a13c252a97e13a552f88f642962768de1fa4Komal Shah 1012817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbistatic void omap_wdt_disable(struct omap_wdt_dev *wdev) 1027768a13c252a97e13a552f88f642962768de1fa4Komal Shah{ 103b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbi void __iomem *base = wdev->base; 104b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbi 1057768a13c252a97e13a552f88f642962768de1fa4Komal Shah /* sequence required to disable watchdog */ 1069f69e3b0c22200998caa73b23a39c03950b2752dFelipe Balbi __raw_writel(0xAAAA, base + OMAP_WATCHDOG_SPR); /* TIMER_MODE */ 1079f69e3b0c22200998caa73b23a39c03950b2752dFelipe Balbi while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x10) 1087768a13c252a97e13a552f88f642962768de1fa4Komal Shah cpu_relax(); 109b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbi 1109f69e3b0c22200998caa73b23a39c03950b2752dFelipe Balbi __raw_writel(0x5555, base + OMAP_WATCHDOG_SPR); /* TIMER_MODE */ 1119f69e3b0c22200998caa73b23a39c03950b2752dFelipe Balbi while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x10) 1127768a13c252a97e13a552f88f642962768de1fa4Komal Shah cpu_relax(); 1137768a13c252a97e13a552f88f642962768de1fa4Komal Shah} 1147768a13c252a97e13a552f88f642962768de1fa4Komal Shah 1157768a13c252a97e13a552f88f642962768de1fa4Komal Shahstatic void omap_wdt_adjust_timeout(unsigned new_timeout) 1167768a13c252a97e13a552f88f642962768de1fa4Komal Shah{ 1177768a13c252a97e13a552f88f642962768de1fa4Komal Shah if (new_timeout < TIMER_MARGIN_MIN) 1187768a13c252a97e13a552f88f642962768de1fa4Komal Shah new_timeout = TIMER_MARGIN_DEFAULT; 1197768a13c252a97e13a552f88f642962768de1fa4Komal Shah if (new_timeout > TIMER_MARGIN_MAX) 1207768a13c252a97e13a552f88f642962768de1fa4Komal Shah new_timeout = TIMER_MARGIN_MAX; 1217768a13c252a97e13a552f88f642962768de1fa4Komal Shah timer_margin = new_timeout; 1227768a13c252a97e13a552f88f642962768de1fa4Komal Shah} 1237768a13c252a97e13a552f88f642962768de1fa4Komal Shah 1242817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbistatic void omap_wdt_set_timeout(struct omap_wdt_dev *wdev) 1257768a13c252a97e13a552f88f642962768de1fa4Komal Shah{ 1267768a13c252a97e13a552f88f642962768de1fa4Komal Shah u32 pre_margin = GET_WLDR_VAL(timer_margin); 127b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbi void __iomem *base = wdev->base; 1287768a13c252a97e13a552f88f642962768de1fa4Komal Shah 1290503add9d251db22ba2f610fb8d9b7743a9786daPaul Walmsley pm_runtime_get_sync(wdev->dev); 1300503add9d251db22ba2f610fb8d9b7743a9786daPaul Walmsley 1317768a13c252a97e13a552f88f642962768de1fa4Komal Shah /* just count up at 32 KHz */ 1329f69e3b0c22200998caa73b23a39c03950b2752dFelipe Balbi while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x04) 1337768a13c252a97e13a552f88f642962768de1fa4Komal Shah cpu_relax(); 134b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbi 1359f69e3b0c22200998caa73b23a39c03950b2752dFelipe Balbi __raw_writel(pre_margin, base + OMAP_WATCHDOG_LDR); 1369f69e3b0c22200998caa73b23a39c03950b2752dFelipe Balbi while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x04) 1377768a13c252a97e13a552f88f642962768de1fa4Komal Shah cpu_relax(); 1380503add9d251db22ba2f610fb8d9b7743a9786daPaul Walmsley 1390503add9d251db22ba2f610fb8d9b7743a9786daPaul Walmsley pm_runtime_put_sync(wdev->dev); 1407768a13c252a97e13a552f88f642962768de1fa4Komal Shah} 1417768a13c252a97e13a552f88f642962768de1fa4Komal Shah 1427768a13c252a97e13a552f88f642962768de1fa4Komal Shah/* 1437768a13c252a97e13a552f88f642962768de1fa4Komal Shah * Allow only one task to hold it open 1447768a13c252a97e13a552f88f642962768de1fa4Komal Shah */ 1457768a13c252a97e13a552f88f642962768de1fa4Komal Shahstatic int omap_wdt_open(struct inode *inode, struct file *file) 1467768a13c252a97e13a552f88f642962768de1fa4Komal Shah{ 147b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbi struct omap_wdt_dev *wdev = platform_get_drvdata(omap_wdt_dev); 148b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbi void __iomem *base = wdev->base; 149b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbi 1502817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi if (test_and_set_bit(1, (unsigned long *)&(wdev->omap_wdt_users))) 1517768a13c252a97e13a552f88f642962768de1fa4Komal Shah return -EBUSY; 1527768a13c252a97e13a552f88f642962768de1fa4Komal Shah 1537ec5ad0f3c1e28b693185c35f768953c5db32291Varadarajan, Charulatha pm_runtime_get_sync(wdev->dev); 1547768a13c252a97e13a552f88f642962768de1fa4Komal Shah 1557768a13c252a97e13a552f88f642962768de1fa4Komal Shah /* initialize prescaler */ 1569f69e3b0c22200998caa73b23a39c03950b2752dFelipe Balbi while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x01) 1577768a13c252a97e13a552f88f642962768de1fa4Komal Shah cpu_relax(); 158b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbi 1599f69e3b0c22200998caa73b23a39c03950b2752dFelipe Balbi __raw_writel((1 << 5) | (PTV << 2), base + OMAP_WATCHDOG_CNTRL); 1609f69e3b0c22200998caa73b23a39c03950b2752dFelipe Balbi while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x01) 1617768a13c252a97e13a552f88f642962768de1fa4Komal Shah cpu_relax(); 1627768a13c252a97e13a552f88f642962768de1fa4Komal Shah 1632817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi file->private_data = (void *) wdev; 1642817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi 1652817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi omap_wdt_set_timeout(wdev); 166789cd4702bf830416d2e1794495407be42fe95adUlrik Bech Hald omap_wdt_ping(wdev); /* trigger loading of new timeout value */ 1672817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi omap_wdt_enable(wdev); 168b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbi 1690503add9d251db22ba2f610fb8d9b7743a9786daPaul Walmsley pm_runtime_put_sync(wdev->dev); 1700503add9d251db22ba2f610fb8d9b7743a9786daPaul Walmsley 171ec9505a7ecadc0ab8f8e3c4c5fa900d57467e391Wim Van Sebroeck return nonseekable_open(inode, file); 1727768a13c252a97e13a552f88f642962768de1fa4Komal Shah} 1737768a13c252a97e13a552f88f642962768de1fa4Komal Shah 1747768a13c252a97e13a552f88f642962768de1fa4Komal Shahstatic int omap_wdt_release(struct inode *inode, struct file *file) 1757768a13c252a97e13a552f88f642962768de1fa4Komal Shah{ 176b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbi struct omap_wdt_dev *wdev = file->private_data; 177b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbi 1787768a13c252a97e13a552f88f642962768de1fa4Komal Shah /* 1797768a13c252a97e13a552f88f642962768de1fa4Komal Shah * Shut off the timer unless NOWAYOUT is defined. 1807768a13c252a97e13a552f88f642962768de1fa4Komal Shah */ 1817768a13c252a97e13a552f88f642962768de1fa4Komal Shah#ifndef CONFIG_WATCHDOG_NOWAYOUT 1820503add9d251db22ba2f610fb8d9b7743a9786daPaul Walmsley pm_runtime_get_sync(wdev->dev); 1837768a13c252a97e13a552f88f642962768de1fa4Komal Shah 1842817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi omap_wdt_disable(wdev); 1857768a13c252a97e13a552f88f642962768de1fa4Komal Shah 1867ec5ad0f3c1e28b693185c35f768953c5db32291Varadarajan, Charulatha pm_runtime_put_sync(wdev->dev); 1877768a13c252a97e13a552f88f642962768de1fa4Komal Shah#else 18827c766aaacb265d625dc634bf7903f7f9fd0c697Joe Perches pr_crit("Unexpected close, not stopping!\n"); 1897768a13c252a97e13a552f88f642962768de1fa4Komal Shah#endif 1902817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi wdev->omap_wdt_users = 0; 191b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbi 1927768a13c252a97e13a552f88f642962768de1fa4Komal Shah return 0; 1937768a13c252a97e13a552f88f642962768de1fa4Komal Shah} 1947768a13c252a97e13a552f88f642962768de1fa4Komal Shah 19512b9df7d21d0eedfaaee925f8f9c9aafb1cafa2fAlan Coxstatic ssize_t omap_wdt_write(struct file *file, const char __user *data, 1967768a13c252a97e13a552f88f642962768de1fa4Komal Shah size_t len, loff_t *ppos) 1977768a13c252a97e13a552f88f642962768de1fa4Komal Shah{ 198b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbi struct omap_wdt_dev *wdev = file->private_data; 199b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbi 2007768a13c252a97e13a552f88f642962768de1fa4Komal Shah /* Refresh LOAD_TIME. */ 20112b9df7d21d0eedfaaee925f8f9c9aafb1cafa2fAlan Cox if (len) { 2020503add9d251db22ba2f610fb8d9b7743a9786daPaul Walmsley pm_runtime_get_sync(wdev->dev); 20312b9df7d21d0eedfaaee925f8f9c9aafb1cafa2fAlan Cox spin_lock(&wdt_lock); 2042817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi omap_wdt_ping(wdev); 20512b9df7d21d0eedfaaee925f8f9c9aafb1cafa2fAlan Cox spin_unlock(&wdt_lock); 2060503add9d251db22ba2f610fb8d9b7743a9786daPaul Walmsley pm_runtime_put_sync(wdev->dev); 20712b9df7d21d0eedfaaee925f8f9c9aafb1cafa2fAlan Cox } 2087768a13c252a97e13a552f88f642962768de1fa4Komal Shah return len; 2097768a13c252a97e13a552f88f642962768de1fa4Komal Shah} 2107768a13c252a97e13a552f88f642962768de1fa4Komal Shah 21112b9df7d21d0eedfaaee925f8f9c9aafb1cafa2fAlan Coxstatic long omap_wdt_ioctl(struct file *file, unsigned int cmd, 21212b9df7d21d0eedfaaee925f8f9c9aafb1cafa2fAlan Cox unsigned long arg) 2137768a13c252a97e13a552f88f642962768de1fa4Komal Shah{ 2142817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi struct omap_wdt_dev *wdev; 2157768a13c252a97e13a552f88f642962768de1fa4Komal Shah int new_margin; 21612b9df7d21d0eedfaaee925f8f9c9aafb1cafa2fAlan Cox static const struct watchdog_info ident = { 2177768a13c252a97e13a552f88f642962768de1fa4Komal Shah .identity = "OMAP Watchdog", 2187768a13c252a97e13a552f88f642962768de1fa4Komal Shah .options = WDIOF_SETTIMEOUT, 2197768a13c252a97e13a552f88f642962768de1fa4Komal Shah .firmware_version = 0, 2207768a13c252a97e13a552f88f642962768de1fa4Komal Shah }; 221b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbi 2222817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi wdev = file->private_data; 2237768a13c252a97e13a552f88f642962768de1fa4Komal Shah 2247768a13c252a97e13a552f88f642962768de1fa4Komal Shah switch (cmd) { 2257768a13c252a97e13a552f88f642962768de1fa4Komal Shah case WDIOC_GETSUPPORT: 2267768a13c252a97e13a552f88f642962768de1fa4Komal Shah return copy_to_user((struct watchdog_info __user *)arg, &ident, 2277768a13c252a97e13a552f88f642962768de1fa4Komal Shah sizeof(ident)); 2287768a13c252a97e13a552f88f642962768de1fa4Komal Shah case WDIOC_GETSTATUS: 2297768a13c252a97e13a552f88f642962768de1fa4Komal Shah return put_user(0, (int __user *)arg); 2307768a13c252a97e13a552f88f642962768de1fa4Komal Shah case WDIOC_GETBOOTSTATUS: 2317768a13c252a97e13a552f88f642962768de1fa4Komal Shah if (cpu_is_omap16xx()) 2329f69e3b0c22200998caa73b23a39c03950b2752dFelipe Balbi return put_user(__raw_readw(ARM_SYSST), 2337768a13c252a97e13a552f88f642962768de1fa4Komal Shah (int __user *)arg); 2347768a13c252a97e13a552f88f642962768de1fa4Komal Shah if (cpu_is_omap24xx()) 2357768a13c252a97e13a552f88f642962768de1fa4Komal Shah return put_user(omap_prcm_get_reset_sources(), 2367768a13c252a97e13a552f88f642962768de1fa4Komal Shah (int __user *)arg); 237e2bf7c4c22939bd83814d8da40a352d246030b1bShubhrajyoti D return put_user(0, (int __user *)arg); 2387768a13c252a97e13a552f88f642962768de1fa4Komal Shah case WDIOC_KEEPALIVE: 2390503add9d251db22ba2f610fb8d9b7743a9786daPaul Walmsley pm_runtime_get_sync(wdev->dev); 24012b9df7d21d0eedfaaee925f8f9c9aafb1cafa2fAlan Cox spin_lock(&wdt_lock); 2412817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi omap_wdt_ping(wdev); 24212b9df7d21d0eedfaaee925f8f9c9aafb1cafa2fAlan Cox spin_unlock(&wdt_lock); 2430503add9d251db22ba2f610fb8d9b7743a9786daPaul Walmsley pm_runtime_put_sync(wdev->dev); 2447768a13c252a97e13a552f88f642962768de1fa4Komal Shah return 0; 2457768a13c252a97e13a552f88f642962768de1fa4Komal Shah case WDIOC_SETTIMEOUT: 2467768a13c252a97e13a552f88f642962768de1fa4Komal Shah if (get_user(new_margin, (int __user *)arg)) 2477768a13c252a97e13a552f88f642962768de1fa4Komal Shah return -EFAULT; 2487768a13c252a97e13a552f88f642962768de1fa4Komal Shah omap_wdt_adjust_timeout(new_margin); 2497768a13c252a97e13a552f88f642962768de1fa4Komal Shah 2500503add9d251db22ba2f610fb8d9b7743a9786daPaul Walmsley pm_runtime_get_sync(wdev->dev); 25112b9df7d21d0eedfaaee925f8f9c9aafb1cafa2fAlan Cox spin_lock(&wdt_lock); 2522817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi omap_wdt_disable(wdev); 2532817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi omap_wdt_set_timeout(wdev); 2542817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi omap_wdt_enable(wdev); 2557768a13c252a97e13a552f88f642962768de1fa4Komal Shah 2562817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi omap_wdt_ping(wdev); 25712b9df7d21d0eedfaaee925f8f9c9aafb1cafa2fAlan Cox spin_unlock(&wdt_lock); 2580503add9d251db22ba2f610fb8d9b7743a9786daPaul Walmsley pm_runtime_put_sync(wdev->dev); 2597768a13c252a97e13a552f88f642962768de1fa4Komal Shah /* Fall */ 2607768a13c252a97e13a552f88f642962768de1fa4Komal Shah case WDIOC_GETTIMEOUT: 2617768a13c252a97e13a552f88f642962768de1fa4Komal Shah return put_user(timer_margin, (int __user *)arg); 2620c06090c9472db0525cb6fe229c3bea33bbbbb3cWim Van Sebroeck default: 2630c06090c9472db0525cb6fe229c3bea33bbbbb3cWim Van Sebroeck return -ENOTTY; 2647768a13c252a97e13a552f88f642962768de1fa4Komal Shah } 2657768a13c252a97e13a552f88f642962768de1fa4Komal Shah} 2667768a13c252a97e13a552f88f642962768de1fa4Komal Shah 2672b8693c0617e972fc0b2fd1ebf8de97e15b656c3Arjan van de Venstatic const struct file_operations omap_wdt_fops = { 2687768a13c252a97e13a552f88f642962768de1fa4Komal Shah .owner = THIS_MODULE, 2697768a13c252a97e13a552f88f642962768de1fa4Komal Shah .write = omap_wdt_write, 27012b9df7d21d0eedfaaee925f8f9c9aafb1cafa2fAlan Cox .unlocked_ioctl = omap_wdt_ioctl, 2717768a13c252a97e13a552f88f642962768de1fa4Komal Shah .open = omap_wdt_open, 2727768a13c252a97e13a552f88f642962768de1fa4Komal Shah .release = omap_wdt_release, 2736038f373a3dc1f1c26496e60b6c40b164716f07eArnd Bergmann .llseek = no_llseek, 2747768a13c252a97e13a552f88f642962768de1fa4Komal Shah}; 2757768a13c252a97e13a552f88f642962768de1fa4Komal Shah 2760e3912c75f42986c17d955542247bf04c6eef738Uwe Kleine-Königstatic int __devinit omap_wdt_probe(struct platform_device *pdev) 2777768a13c252a97e13a552f88f642962768de1fa4Komal Shah{ 2787768a13c252a97e13a552f88f642962768de1fa4Komal Shah struct resource *res, *mem; 2792817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi struct omap_wdt_dev *wdev; 280b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbi int ret; 2817768a13c252a97e13a552f88f642962768de1fa4Komal Shah 2827768a13c252a97e13a552f88f642962768de1fa4Komal Shah /* reserve static register mappings */ 2837768a13c252a97e13a552f88f642962768de1fa4Komal Shah res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 284b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbi if (!res) { 285b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbi ret = -ENOENT; 286b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbi goto err_get_resource; 287b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbi } 2887768a13c252a97e13a552f88f642962768de1fa4Komal Shah 289b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbi if (omap_wdt_dev) { 290b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbi ret = -EBUSY; 291b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbi goto err_busy; 292b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbi } 2932817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi 294b782a563758ac963c794d9fbaaff494140c28fd6H Hartley Sweeten mem = request_mem_region(res->start, resource_size(res), pdev->name); 295b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbi if (!mem) { 296b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbi ret = -EBUSY; 297b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbi goto err_busy; 298b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbi } 2997768a13c252a97e13a552f88f642962768de1fa4Komal Shah 3002817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi wdev = kzalloc(sizeof(struct omap_wdt_dev), GFP_KERNEL); 3012817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi if (!wdev) { 3022817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi ret = -ENOMEM; 303b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbi goto err_kzalloc; 3042817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi } 305b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbi 3062817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi wdev->omap_wdt_users = 0; 3072817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi wdev->mem = mem; 3087ec5ad0f3c1e28b693185c35f768953c5db32291Varadarajan, Charulatha wdev->dev = &pdev->dev; 3092817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi 310b782a563758ac963c794d9fbaaff494140c28fd6H Hartley Sweeten wdev->base = ioremap(res->start, resource_size(res)); 3119f69e3b0c22200998caa73b23a39c03950b2752dFelipe Balbi if (!wdev->base) { 3129f69e3b0c22200998caa73b23a39c03950b2752dFelipe Balbi ret = -ENOMEM; 313b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbi goto err_ioremap; 3149f69e3b0c22200998caa73b23a39c03950b2752dFelipe Balbi } 3159f69e3b0c22200998caa73b23a39c03950b2752dFelipe Balbi 3162817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi platform_set_drvdata(pdev, wdev); 3177768a13c252a97e13a552f88f642962768de1fa4Komal Shah 3187ec5ad0f3c1e28b693185c35f768953c5db32291Varadarajan, Charulatha pm_runtime_enable(wdev->dev); 3197ec5ad0f3c1e28b693185c35f768953c5db32291Varadarajan, Charulatha pm_runtime_get_sync(wdev->dev); 320789cd4702bf830416d2e1794495407be42fe95adUlrik Bech Hald 3212817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi omap_wdt_disable(wdev); 3227768a13c252a97e13a552f88f642962768de1fa4Komal Shah omap_wdt_adjust_timeout(timer_margin); 3237768a13c252a97e13a552f88f642962768de1fa4Komal Shah 3242817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi wdev->omap_wdt_miscdev.parent = &pdev->dev; 3252817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi wdev->omap_wdt_miscdev.minor = WATCHDOG_MINOR; 3262817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi wdev->omap_wdt_miscdev.name = "watchdog"; 3272817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi wdev->omap_wdt_miscdev.fops = &omap_wdt_fops; 3282817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi 3292817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi ret = misc_register(&(wdev->omap_wdt_miscdev)); 3307768a13c252a97e13a552f88f642962768de1fa4Komal Shah if (ret) 331b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbi goto err_misc; 3327768a13c252a97e13a552f88f642962768de1fa4Komal Shah 3332817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi pr_info("OMAP Watchdog Timer Rev 0x%02x: initial timeout %d sec\n", 3349f69e3b0c22200998caa73b23a39c03950b2752dFelipe Balbi __raw_readl(wdev->base + OMAP_WATCHDOG_REV) & 0xFF, 3352817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi timer_margin); 3367768a13c252a97e13a552f88f642962768de1fa4Komal Shah 3377ec5ad0f3c1e28b693185c35f768953c5db32291Varadarajan, Charulatha pm_runtime_put_sync(wdev->dev); 338789cd4702bf830416d2e1794495407be42fe95adUlrik Bech Hald 3392817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi omap_wdt_dev = pdev; 3402817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi 3417768a13c252a97e13a552f88f642962768de1fa4Komal Shah return 0; 3427768a13c252a97e13a552f88f642962768de1fa4Komal Shah 343b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbierr_misc: 34412c583d8dca3320f36afe51e514dfa709ac0662eShubhrajyoti D pm_runtime_disable(wdev->dev); 345b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbi platform_set_drvdata(pdev, NULL); 346b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbi iounmap(wdev->base); 347b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbi 348b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbierr_ioremap: 349b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbi wdev->base = NULL; 350b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbi kfree(wdev); 351b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbi 352b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbierr_kzalloc: 353b782a563758ac963c794d9fbaaff494140c28fd6H Hartley Sweeten release_mem_region(res->start, resource_size(res)); 354b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbi 355b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbierr_busy: 356b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbierr_get_resource: 357b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbi 3587768a13c252a97e13a552f88f642962768de1fa4Komal Shah return ret; 3597768a13c252a97e13a552f88f642962768de1fa4Komal Shah} 3607768a13c252a97e13a552f88f642962768de1fa4Komal Shah 3617768a13c252a97e13a552f88f642962768de1fa4Komal Shahstatic void omap_wdt_shutdown(struct platform_device *pdev) 3627768a13c252a97e13a552f88f642962768de1fa4Komal Shah{ 363b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbi struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); 3642817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi 3650503add9d251db22ba2f610fb8d9b7743a9786daPaul Walmsley if (wdev->omap_wdt_users) { 3660503add9d251db22ba2f610fb8d9b7743a9786daPaul Walmsley pm_runtime_get_sync(wdev->dev); 3672817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi omap_wdt_disable(wdev); 3680503add9d251db22ba2f610fb8d9b7743a9786daPaul Walmsley pm_runtime_put_sync(wdev->dev); 3690503add9d251db22ba2f610fb8d9b7743a9786daPaul Walmsley } 3707768a13c252a97e13a552f88f642962768de1fa4Komal Shah} 3717768a13c252a97e13a552f88f642962768de1fa4Komal Shah 3720e3912c75f42986c17d955542247bf04c6eef738Uwe Kleine-Königstatic int __devexit omap_wdt_remove(struct platform_device *pdev) 3737768a13c252a97e13a552f88f642962768de1fa4Komal Shah{ 374b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbi struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); 3752817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 3762817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi 37712c583d8dca3320f36afe51e514dfa709ac0662eShubhrajyoti D pm_runtime_disable(wdev->dev); 3782817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi if (!res) 3792817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi return -ENOENT; 3802817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi 3812817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi misc_deregister(&(wdev->omap_wdt_miscdev)); 382b782a563758ac963c794d9fbaaff494140c28fd6H Hartley Sweeten release_mem_region(res->start, resource_size(res)); 3832817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi platform_set_drvdata(pdev, NULL); 384b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbi 3859f69e3b0c22200998caa73b23a39c03950b2752dFelipe Balbi iounmap(wdev->base); 3869f69e3b0c22200998caa73b23a39c03950b2752dFelipe Balbi 3872817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi kfree(wdev); 3882817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi omap_wdt_dev = NULL; 389b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbi 3907768a13c252a97e13a552f88f642962768de1fa4Komal Shah return 0; 3917768a13c252a97e13a552f88f642962768de1fa4Komal Shah} 3927768a13c252a97e13a552f88f642962768de1fa4Komal Shah 3937768a13c252a97e13a552f88f642962768de1fa4Komal Shah#ifdef CONFIG_PM 3947768a13c252a97e13a552f88f642962768de1fa4Komal Shah 3957768a13c252a97e13a552f88f642962768de1fa4Komal Shah/* REVISIT ... not clear this is the best way to handle system suspend; and 3967768a13c252a97e13a552f88f642962768de1fa4Komal Shah * it's very inappropriate for selective device suspend (e.g. suspending this 3977768a13c252a97e13a552f88f642962768de1fa4Komal Shah * through sysfs rather than by stopping the watchdog daemon). Also, this 3987768a13c252a97e13a552f88f642962768de1fa4Komal Shah * may not play well enough with NOWAYOUT... 3997768a13c252a97e13a552f88f642962768de1fa4Komal Shah */ 4007768a13c252a97e13a552f88f642962768de1fa4Komal Shah 4017768a13c252a97e13a552f88f642962768de1fa4Komal Shahstatic int omap_wdt_suspend(struct platform_device *pdev, pm_message_t state) 4027768a13c252a97e13a552f88f642962768de1fa4Komal Shah{ 403b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbi struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); 404b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbi 4050503add9d251db22ba2f610fb8d9b7743a9786daPaul Walmsley if (wdev->omap_wdt_users) { 4060503add9d251db22ba2f610fb8d9b7743a9786daPaul Walmsley pm_runtime_get_sync(wdev->dev); 4072817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi omap_wdt_disable(wdev); 4080503add9d251db22ba2f610fb8d9b7743a9786daPaul Walmsley pm_runtime_put_sync(wdev->dev); 4090503add9d251db22ba2f610fb8d9b7743a9786daPaul Walmsley } 410b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbi 4117768a13c252a97e13a552f88f642962768de1fa4Komal Shah return 0; 4127768a13c252a97e13a552f88f642962768de1fa4Komal Shah} 4137768a13c252a97e13a552f88f642962768de1fa4Komal Shah 4147768a13c252a97e13a552f88f642962768de1fa4Komal Shahstatic int omap_wdt_resume(struct platform_device *pdev) 4157768a13c252a97e13a552f88f642962768de1fa4Komal Shah{ 416b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbi struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); 417b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbi 4182817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi if (wdev->omap_wdt_users) { 4190503add9d251db22ba2f610fb8d9b7743a9786daPaul Walmsley pm_runtime_get_sync(wdev->dev); 4202817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi omap_wdt_enable(wdev); 4212817142f31bfbf26c216bf4f9192540c81b2d071Felipe Balbi omap_wdt_ping(wdev); 4220503add9d251db22ba2f610fb8d9b7743a9786daPaul Walmsley pm_runtime_put_sync(wdev->dev); 4237768a13c252a97e13a552f88f642962768de1fa4Komal Shah } 424b3112180fe0b8dd80053d1d83e6fc421a266e47aFelipe Balbi 4257768a13c252a97e13a552f88f642962768de1fa4Komal Shah return 0; 4267768a13c252a97e13a552f88f642962768de1fa4Komal Shah} 4277768a13c252a97e13a552f88f642962768de1fa4Komal Shah 4287768a13c252a97e13a552f88f642962768de1fa4Komal Shah#else 4297768a13c252a97e13a552f88f642962768de1fa4Komal Shah#define omap_wdt_suspend NULL 4307768a13c252a97e13a552f88f642962768de1fa4Komal Shah#define omap_wdt_resume NULL 4317768a13c252a97e13a552f88f642962768de1fa4Komal Shah#endif 4327768a13c252a97e13a552f88f642962768de1fa4Komal Shah 4337768a13c252a97e13a552f88f642962768de1fa4Komal Shahstatic struct platform_driver omap_wdt_driver = { 4347768a13c252a97e13a552f88f642962768de1fa4Komal Shah .probe = omap_wdt_probe, 4350e3912c75f42986c17d955542247bf04c6eef738Uwe Kleine-König .remove = __devexit_p(omap_wdt_remove), 4367768a13c252a97e13a552f88f642962768de1fa4Komal Shah .shutdown = omap_wdt_shutdown, 4377768a13c252a97e13a552f88f642962768de1fa4Komal Shah .suspend = omap_wdt_suspend, 4387768a13c252a97e13a552f88f642962768de1fa4Komal Shah .resume = omap_wdt_resume, 4397768a13c252a97e13a552f88f642962768de1fa4Komal Shah .driver = { 4407768a13c252a97e13a552f88f642962768de1fa4Komal Shah .owner = THIS_MODULE, 4417768a13c252a97e13a552f88f642962768de1fa4Komal Shah .name = "omap_wdt", 4427768a13c252a97e13a552f88f642962768de1fa4Komal Shah }, 4437768a13c252a97e13a552f88f642962768de1fa4Komal Shah}; 4447768a13c252a97e13a552f88f642962768de1fa4Komal Shah 445b8ec61189f3b4cd9d1b2856342f5d7676151d01cAxel Linmodule_platform_driver(omap_wdt_driver); 4467768a13c252a97e13a552f88f642962768de1fa4Komal Shah 4477768a13c252a97e13a552f88f642962768de1fa4Komal ShahMODULE_AUTHOR("George G. Davis"); 4487768a13c252a97e13a552f88f642962768de1fa4Komal ShahMODULE_LICENSE("GPL"); 4497768a13c252a97e13a552f88f642962768de1fa4Komal ShahMODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); 450f37d193c7c150c40059c7ce5de34e8b28a9cd4aeKay SieversMODULE_ALIAS("platform:omap_wdt"); 451