txx9wdt.c revision 8dc244f7deac4c0e95ce0ffd26f494bb6e1534c0
16f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto/* 26f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto * txx9wdt: A Hardware Watchdog Driver for TXx9 SoCs 36f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto * 46f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto * Copyright (C) 2007 Atsushi Nemoto <anemo@mba.ocn.ne.jp> 56f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto * 66f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto * This program is free software; you can redistribute it and/or modify 76f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto * it under the terms of the GNU General Public License version 2 as 86f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto * published by the Free Software Foundation. 96f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto */ 106f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto#include <linux/module.h> 116f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto#include <linux/moduleparam.h> 126f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto#include <linux/types.h> 136f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto#include <linux/miscdevice.h> 146f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto#include <linux/watchdog.h> 156f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto#include <linux/fs.h> 166f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto#include <linux/reboot.h> 176f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto#include <linux/init.h> 186f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto#include <linux/uaccess.h> 196f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto#include <linux/platform_device.h> 206f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto#include <linux/clk.h> 216f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto#include <linux/err.h> 226f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto#include <linux/io.h> 236f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto#include <asm/txx9tmr.h> 246f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 256f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto#define TIMER_MARGIN 60 /* Default is 60 seconds */ 266f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 276f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemotostatic int timeout = TIMER_MARGIN; /* in seconds */ 286f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemotomodule_param(timeout, int, 0); 296f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi NemotoMODULE_PARM_DESC(timeout, 306f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto "Watchdog timeout in seconds. " 316f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto "(0<timeout<((2^" __MODULE_STRING(TXX9_TIMER_BITS) ")/(IMCLK/256)), " 326f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto "default=" __MODULE_STRING(TIMER_MARGIN) ")"); 336f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 346f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemotostatic int nowayout = WATCHDOG_NOWAYOUT; 356f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemotomodule_param(nowayout, int, 0); 366f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi NemotoMODULE_PARM_DESC(nowayout, 376f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto "Watchdog cannot be stopped once started " 386f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 396f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 406f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto#define WD_TIMER_CCD 7 /* 1/256 */ 416f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto#define WD_TIMER_CLK (clk_get_rate(txx9_imclk) / (2 << WD_TIMER_CCD)) 426f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto#define WD_MAX_TIMEOUT ((0xffffffff >> (32 - TXX9_TIMER_BITS)) / WD_TIMER_CLK) 436f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 446f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemotostatic unsigned long txx9wdt_alive; 456f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemotostatic int expect_close; 466f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemotostatic struct txx9_tmr_reg __iomem *txx9wdt_reg; 476f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemotostatic struct clk *txx9_imclk; 488dc244f7deac4c0e95ce0ffd26f494bb6e1534c0Alan Coxstatic DECLARE_LOCK(txx9_lock); 496f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 506f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemotostatic void txx9wdt_ping(void) 516f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto{ 528dc244f7deac4c0e95ce0ffd26f494bb6e1534c0Alan Cox spin_lock(&txx9_lock); 536f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto __raw_writel(TXx9_TMWTMR_TWIE | TXx9_TMWTMR_TWC, &txx9wdt_reg->wtmr); 548dc244f7deac4c0e95ce0ffd26f494bb6e1534c0Alan Cox spin_unlock(&txx9_lock); 556f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto} 566f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 576f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemotostatic void txx9wdt_start(void) 586f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto{ 598dc244f7deac4c0e95ce0ffd26f494bb6e1534c0Alan Cox spin_lock(&txx9_lock); 606f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto __raw_writel(WD_TIMER_CLK * timeout, &txx9wdt_reg->cpra); 616f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto __raw_writel(WD_TIMER_CCD, &txx9wdt_reg->ccdr); 626f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto __raw_writel(0, &txx9wdt_reg->tisr); /* clear pending interrupt */ 636f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto __raw_writel(TXx9_TMTCR_TCE | TXx9_TMTCR_CCDE | TXx9_TMTCR_TMODE_WDOG, 646f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto &txx9wdt_reg->tcr); 656f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto __raw_writel(TXx9_TMWTMR_TWIE | TXx9_TMWTMR_TWC, &txx9wdt_reg->wtmr); 668dc244f7deac4c0e95ce0ffd26f494bb6e1534c0Alan Cox spin_unlock(&txx9_lock); 676f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto} 686f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 696f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemotostatic void txx9wdt_stop(void) 706f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto{ 718dc244f7deac4c0e95ce0ffd26f494bb6e1534c0Alan Cox spin_lock(&txx9_lock); 726f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto __raw_writel(TXx9_TMWTMR_WDIS, &txx9wdt_reg->wtmr); 736f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto __raw_writel(__raw_readl(&txx9wdt_reg->tcr) & ~TXx9_TMTCR_TCE, 746f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto &txx9wdt_reg->tcr); 758dc244f7deac4c0e95ce0ffd26f494bb6e1534c0Alan Cox spin_unlock(&txx9_lock); 766f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto} 776f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 786f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemotostatic int txx9wdt_open(struct inode *inode, struct file *file) 796f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto{ 806f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto if (test_and_set_bit(0, &txx9wdt_alive)) 816f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto return -EBUSY; 826f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 836f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto if (__raw_readl(&txx9wdt_reg->tcr) & TXx9_TMTCR_TCE) { 846f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto clear_bit(0, &txx9wdt_alive); 856f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto return -EBUSY; 866f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto } 876f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 886f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto if (nowayout) 896f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto __module_get(THIS_MODULE); 906f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 916f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto txx9wdt_start(); 926f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto return nonseekable_open(inode, file); 936f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto} 946f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 956f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemotostatic int txx9wdt_release(struct inode *inode, struct file *file) 966f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto{ 976f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto if (expect_close) 986f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto txx9wdt_stop(); 996f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto else { 1006f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto printk(KERN_CRIT "txx9wdt: " 1016f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto "Unexpected close, not stopping watchdog!\n"); 1026f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto txx9wdt_ping(); 1036f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto } 1046f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto clear_bit(0, &txx9wdt_alive); 1056f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto expect_close = 0; 1066f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto return 0; 1076f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto} 1086f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 1096f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemotostatic ssize_t txx9wdt_write(struct file *file, const char __user *data, 1106f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto size_t len, loff_t *ppos) 1116f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto{ 1126f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto if (len) { 1136f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto if (!nowayout) { 1146f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto size_t i; 1156f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 1166f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto expect_close = 0; 1176f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto for (i = 0; i != len; i++) { 1186f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto char c; 1196f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto if (get_user(c, data + i)) 1206f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto return -EFAULT; 1216f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto if (c == 'V') 1226f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto expect_close = 1; 1236f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto } 1246f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto } 1256f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto txx9wdt_ping(); 1266f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto } 1276f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto return len; 1286f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto} 1296f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 1308dc244f7deac4c0e95ce0ffd26f494bb6e1534c0Alan Coxstatic long txx9wdt_ioctl(struct file *file, unsigned int cmd, 1318dc244f7deac4c0e95ce0ffd26f494bb6e1534c0Alan Cox unsigned long arg) 1326f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto{ 1336f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto void __user *argp = (void __user *)arg; 1346f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto int __user *p = argp; 1356f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto int new_timeout; 1368dc244f7deac4c0e95ce0ffd26f494bb6e1534c0Alan Cox static const struct watchdog_info ident = { 1376f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto .options = WDIOF_SETTIMEOUT | 1386f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto WDIOF_KEEPALIVEPING | 1396f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto WDIOF_MAGICCLOSE, 1406f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto .firmware_version = 0, 1416f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto .identity = "Hardware Watchdog for TXx9", 1426f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto }; 1436f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 1446f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto switch (cmd) { 1456f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto default: 1466f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto return -ENOTTY; 1476f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto case WDIOC_GETSUPPORT: 1486f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; 1496f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto case WDIOC_GETSTATUS: 1506f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto case WDIOC_GETBOOTSTATUS: 1516f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto return put_user(0, p); 1526f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto case WDIOC_KEEPALIVE: 1536f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto txx9wdt_ping(); 1546f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto return 0; 1556f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto case WDIOC_SETTIMEOUT: 1566f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto if (get_user(new_timeout, p)) 1576f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto return -EFAULT; 1586f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto if (new_timeout < 1 || new_timeout > WD_MAX_TIMEOUT) 1596f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto return -EINVAL; 1606f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto timeout = new_timeout; 1616f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto txx9wdt_stop(); 1626f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto txx9wdt_start(); 1636f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto /* Fall */ 1646f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto case WDIOC_GETTIMEOUT: 1656f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto return put_user(timeout, p); 1666f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto } 1676f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto} 1686f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 1696f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemotostatic int txx9wdt_notify_sys(struct notifier_block *this, unsigned long code, 1706f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto void *unused) 1716f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto{ 1726f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto if (code == SYS_DOWN || code == SYS_HALT) 1736f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto txx9wdt_stop(); 1746f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto return NOTIFY_DONE; 1756f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto} 1766f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 1776f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemotostatic const struct file_operations txx9wdt_fops = { 1788dc244f7deac4c0e95ce0ffd26f494bb6e1534c0Alan Cox .owner = THIS_MODULE, 1798dc244f7deac4c0e95ce0ffd26f494bb6e1534c0Alan Cox .llseek = no_llseek, 1808dc244f7deac4c0e95ce0ffd26f494bb6e1534c0Alan Cox .write = txx9wdt_write, 1818dc244f7deac4c0e95ce0ffd26f494bb6e1534c0Alan Cox .unlocked_ioctl = txx9wdt_ioctl, 1828dc244f7deac4c0e95ce0ffd26f494bb6e1534c0Alan Cox .open = txx9wdt_open, 1838dc244f7deac4c0e95ce0ffd26f494bb6e1534c0Alan Cox .release = txx9wdt_release, 1846f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto}; 1856f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 1866f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemotostatic struct miscdevice txx9wdt_miscdev = { 1878dc244f7deac4c0e95ce0ffd26f494bb6e1534c0Alan Cox .minor = WATCHDOG_MINOR, 1888dc244f7deac4c0e95ce0ffd26f494bb6e1534c0Alan Cox .name = "watchdog", 1898dc244f7deac4c0e95ce0ffd26f494bb6e1534c0Alan Cox .fops = &txx9wdt_fops, 1906f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto}; 1916f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 1926f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemotostatic struct notifier_block txx9wdt_notifier = { 1936f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto .notifier_call = txx9wdt_notify_sys 1946f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto}; 1956f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 1966f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemotostatic int __init txx9wdt_probe(struct platform_device *dev) 1976f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto{ 1986f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto struct resource *res; 1996f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto int ret; 2006f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 2016f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto txx9_imclk = clk_get(NULL, "imbus_clk"); 2026f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto if (IS_ERR(txx9_imclk)) { 2036f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto ret = PTR_ERR(txx9_imclk); 2046f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto txx9_imclk = NULL; 2056f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto goto exit; 2066f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto } 2076f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto ret = clk_enable(txx9_imclk); 2086f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto if (ret) { 2096f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto clk_put(txx9_imclk); 2106f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto txx9_imclk = NULL; 2116f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto goto exit; 2126f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto } 2136f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 2146f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto res = platform_get_resource(dev, IORESOURCE_MEM, 0); 2156f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto if (!res) 2166f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto goto exit_busy; 2176f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto if (!devm_request_mem_region(&dev->dev, 2186f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto res->start, res->end - res->start + 1, 2196f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto "txx9wdt")) 2206f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto goto exit_busy; 2216f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto txx9wdt_reg = devm_ioremap(&dev->dev, 2226f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto res->start, res->end - res->start + 1); 2236f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto if (!txx9wdt_reg) 2246f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto goto exit_busy; 2256f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 2266f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto ret = register_reboot_notifier(&txx9wdt_notifier); 2276f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto if (ret) 2286f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto goto exit; 2296f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 2306f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto ret = misc_register(&txx9wdt_miscdev); 2316f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto if (ret) { 2326f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto unregister_reboot_notifier(&txx9wdt_notifier); 2336f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto goto exit; 2346f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto } 2356f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 2366f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto printk(KERN_INFO "Hardware Watchdog Timer for TXx9: " 2376f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto "timeout=%d sec (max %ld) (nowayout= %d)\n", 2386f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto timeout, WD_MAX_TIMEOUT, nowayout); 2396f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 2406f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto return 0; 2416f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemotoexit_busy: 2426f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto ret = -EBUSY; 2436f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemotoexit: 2446f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto if (txx9_imclk) { 2456f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto clk_disable(txx9_imclk); 2466f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto clk_put(txx9_imclk); 2476f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto } 2486f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto return ret; 2496f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto} 2506f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 2516f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemotostatic int __exit txx9wdt_remove(struct platform_device *dev) 2526f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto{ 2536f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto misc_deregister(&txx9wdt_miscdev); 2546f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto unregister_reboot_notifier(&txx9wdt_notifier); 2556f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto clk_disable(txx9_imclk); 2566f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto clk_put(txx9_imclk); 2576f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto return 0; 2586f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto} 2596f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 2606f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemotostatic struct platform_driver txx9wdt_driver = { 2616f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto .remove = __exit_p(txx9wdt_remove), 2626f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto .driver = { 2636f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto .name = "txx9wdt", 2646f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto .owner = THIS_MODULE, 2656f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto }, 2666f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto}; 2676f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 2686f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemotostatic int __init watchdog_init(void) 2696f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto{ 2706f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto return platform_driver_probe(&txx9wdt_driver, txx9wdt_probe); 2716f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto} 2726f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 2736f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemotostatic void __exit watchdog_exit(void) 2746f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto{ 2756f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto platform_driver_unregister(&txx9wdt_driver); 2766f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto} 2776f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 2786f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemotomodule_init(watchdog_init); 2796f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemotomodule_exit(watchdog_exit); 2806f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 2816f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi NemotoMODULE_DESCRIPTION("TXx9 Watchdog Driver"); 2826f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi NemotoMODULE_LICENSE("GPL"); 2836f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi NemotoMODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); 284f37d193c7c150c40059c7ce5de34e8b28a9cd4aeKay SieversMODULE_ALIAS("platform:txx9wdt"); 285