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/init.h> 176f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto#include <linux/uaccess.h> 186f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto#include <linux/platform_device.h> 196f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto#include <linux/clk.h> 206f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto#include <linux/err.h> 216f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto#include <linux/io.h> 226f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto#include <asm/txx9tmr.h> 236f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 246f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto#define TIMER_MARGIN 60 /* Default is 60 seconds */ 256f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 266f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemotostatic int timeout = TIMER_MARGIN; /* in seconds */ 276f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemotomodule_param(timeout, int, 0); 286f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi NemotoMODULE_PARM_DESC(timeout, 296f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto "Watchdog timeout in seconds. " 306f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto "(0<timeout<((2^" __MODULE_STRING(TXX9_TIMER_BITS) ")/(IMCLK/256)), " 316f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto "default=" __MODULE_STRING(TIMER_MARGIN) ")"); 326f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 336f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemotostatic int nowayout = WATCHDOG_NOWAYOUT; 346f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemotomodule_param(nowayout, int, 0); 356f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi NemotoMODULE_PARM_DESC(nowayout, 366f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto "Watchdog cannot be stopped once started " 376f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 386f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 396f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto#define WD_TIMER_CCD 7 /* 1/256 */ 406f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto#define WD_TIMER_CLK (clk_get_rate(txx9_imclk) / (2 << WD_TIMER_CCD)) 416f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto#define WD_MAX_TIMEOUT ((0xffffffff >> (32 - TXX9_TIMER_BITS)) / WD_TIMER_CLK) 426f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 436f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemotostatic unsigned long txx9wdt_alive; 446f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemotostatic int expect_close; 456f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemotostatic struct txx9_tmr_reg __iomem *txx9wdt_reg; 466f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemotostatic struct clk *txx9_imclk; 47f8494e061799905dc2eb787c148cfbfb134b928fAdrian Bunkstatic DEFINE_SPINLOCK(txx9_lock); 486f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 496f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemotostatic void txx9wdt_ping(void) 506f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto{ 518dc244f7deac4c0e95ce0ffd26f494bb6e1534c0Alan Cox spin_lock(&txx9_lock); 526f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto __raw_writel(TXx9_TMWTMR_TWIE | TXx9_TMWTMR_TWC, &txx9wdt_reg->wtmr); 538dc244f7deac4c0e95ce0ffd26f494bb6e1534c0Alan Cox spin_unlock(&txx9_lock); 546f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto} 556f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 566f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemotostatic void txx9wdt_start(void) 576f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto{ 588dc244f7deac4c0e95ce0ffd26f494bb6e1534c0Alan Cox spin_lock(&txx9_lock); 596f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto __raw_writel(WD_TIMER_CLK * timeout, &txx9wdt_reg->cpra); 606f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto __raw_writel(WD_TIMER_CCD, &txx9wdt_reg->ccdr); 616f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto __raw_writel(0, &txx9wdt_reg->tisr); /* clear pending interrupt */ 626f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto __raw_writel(TXx9_TMTCR_TCE | TXx9_TMTCR_CCDE | TXx9_TMTCR_TMODE_WDOG, 636f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto &txx9wdt_reg->tcr); 646f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto __raw_writel(TXx9_TMWTMR_TWIE | TXx9_TMWTMR_TWC, &txx9wdt_reg->wtmr); 658dc244f7deac4c0e95ce0ffd26f494bb6e1534c0Alan Cox spin_unlock(&txx9_lock); 666f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto} 676f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 686f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemotostatic void txx9wdt_stop(void) 696f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto{ 708dc244f7deac4c0e95ce0ffd26f494bb6e1534c0Alan Cox spin_lock(&txx9_lock); 716f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto __raw_writel(TXx9_TMWTMR_WDIS, &txx9wdt_reg->wtmr); 726f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto __raw_writel(__raw_readl(&txx9wdt_reg->tcr) & ~TXx9_TMTCR_TCE, 736f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto &txx9wdt_reg->tcr); 748dc244f7deac4c0e95ce0ffd26f494bb6e1534c0Alan Cox spin_unlock(&txx9_lock); 756f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto} 766f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 776f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemotostatic int txx9wdt_open(struct inode *inode, struct file *file) 786f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto{ 796f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto if (test_and_set_bit(0, &txx9wdt_alive)) 806f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto return -EBUSY; 816f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 826f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto if (__raw_readl(&txx9wdt_reg->tcr) & TXx9_TMTCR_TCE) { 836f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto clear_bit(0, &txx9wdt_alive); 846f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto return -EBUSY; 856f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto } 866f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 876f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto if (nowayout) 886f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto __module_get(THIS_MODULE); 896f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 906f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto txx9wdt_start(); 916f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto return nonseekable_open(inode, file); 926f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto} 936f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 946f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemotostatic int txx9wdt_release(struct inode *inode, struct file *file) 956f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto{ 966f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto if (expect_close) 976f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto txx9wdt_stop(); 986f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto else { 996f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto printk(KERN_CRIT "txx9wdt: " 1006f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto "Unexpected close, not stopping watchdog!\n"); 1016f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto txx9wdt_ping(); 1026f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto } 1036f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto clear_bit(0, &txx9wdt_alive); 1046f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto expect_close = 0; 1056f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto return 0; 1066f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto} 1076f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 1086f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemotostatic ssize_t txx9wdt_write(struct file *file, const char __user *data, 1096f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto size_t len, loff_t *ppos) 1106f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto{ 1116f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto if (len) { 1126f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto if (!nowayout) { 1136f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto size_t i; 1146f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 1156f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto expect_close = 0; 1166f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto for (i = 0; i != len; i++) { 1176f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto char c; 1186f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto if (get_user(c, data + i)) 1196f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto return -EFAULT; 1206f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto if (c == 'V') 1216f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto expect_close = 1; 1226f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto } 1236f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto } 1246f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto txx9wdt_ping(); 1256f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto } 1266f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto return len; 1276f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto} 1286f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 1298dc244f7deac4c0e95ce0ffd26f494bb6e1534c0Alan Coxstatic long txx9wdt_ioctl(struct file *file, unsigned int cmd, 1308dc244f7deac4c0e95ce0ffd26f494bb6e1534c0Alan Cox unsigned long arg) 1316f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto{ 1326f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto void __user *argp = (void __user *)arg; 1336f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto int __user *p = argp; 1346f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto int new_timeout; 1358dc244f7deac4c0e95ce0ffd26f494bb6e1534c0Alan Cox static const struct watchdog_info ident = { 1366f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto .options = WDIOF_SETTIMEOUT | 1376f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto WDIOF_KEEPALIVEPING | 1386f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto WDIOF_MAGICCLOSE, 1396f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto .firmware_version = 0, 1406f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto .identity = "Hardware Watchdog for TXx9", 1416f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto }; 1426f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 1436f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto switch (cmd) { 1446f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto case WDIOC_GETSUPPORT: 1456f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; 1466f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto case WDIOC_GETSTATUS: 1476f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto case WDIOC_GETBOOTSTATUS: 1486f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto return put_user(0, p); 1496f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto case WDIOC_KEEPALIVE: 1506f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto txx9wdt_ping(); 1516f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto return 0; 1526f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto case WDIOC_SETTIMEOUT: 1536f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto if (get_user(new_timeout, p)) 1546f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto return -EFAULT; 1556f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto if (new_timeout < 1 || new_timeout > WD_MAX_TIMEOUT) 1566f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto return -EINVAL; 1576f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto timeout = new_timeout; 1586f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto txx9wdt_stop(); 1596f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto txx9wdt_start(); 1606f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto /* Fall */ 1616f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto case WDIOC_GETTIMEOUT: 1626f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto return put_user(timeout, p); 1630c06090c9472db0525cb6fe229c3bea33bbbbb3cWim Van Sebroeck default: 1640c06090c9472db0525cb6fe229c3bea33bbbbb3cWim Van Sebroeck return -ENOTTY; 1656f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto } 1666f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto} 1676f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 1686f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemotostatic const struct file_operations txx9wdt_fops = { 1698dc244f7deac4c0e95ce0ffd26f494bb6e1534c0Alan Cox .owner = THIS_MODULE, 1708dc244f7deac4c0e95ce0ffd26f494bb6e1534c0Alan Cox .llseek = no_llseek, 1718dc244f7deac4c0e95ce0ffd26f494bb6e1534c0Alan Cox .write = txx9wdt_write, 1728dc244f7deac4c0e95ce0ffd26f494bb6e1534c0Alan Cox .unlocked_ioctl = txx9wdt_ioctl, 1738dc244f7deac4c0e95ce0ffd26f494bb6e1534c0Alan Cox .open = txx9wdt_open, 1748dc244f7deac4c0e95ce0ffd26f494bb6e1534c0Alan Cox .release = txx9wdt_release, 1756f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto}; 1766f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 1776f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemotostatic struct miscdevice txx9wdt_miscdev = { 1788dc244f7deac4c0e95ce0ffd26f494bb6e1534c0Alan Cox .minor = WATCHDOG_MINOR, 1798dc244f7deac4c0e95ce0ffd26f494bb6e1534c0Alan Cox .name = "watchdog", 1808dc244f7deac4c0e95ce0ffd26f494bb6e1534c0Alan Cox .fops = &txx9wdt_fops, 1816f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto}; 1826f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 1836f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemotostatic int __init txx9wdt_probe(struct platform_device *dev) 1846f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto{ 1856f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto struct resource *res; 1866f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto int ret; 1876f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 1886f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto txx9_imclk = clk_get(NULL, "imbus_clk"); 1896f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto if (IS_ERR(txx9_imclk)) { 1906f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto ret = PTR_ERR(txx9_imclk); 1916f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto txx9_imclk = NULL; 1926f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto goto exit; 1936f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto } 1946f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto ret = clk_enable(txx9_imclk); 1956f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto if (ret) { 1966f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto clk_put(txx9_imclk); 1976f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto txx9_imclk = NULL; 1986f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto goto exit; 1996f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto } 2006f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 2016f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto res = platform_get_resource(dev, IORESOURCE_MEM, 0); 2026f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto if (!res) 2036f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto goto exit_busy; 204b782a563758ac963c794d9fbaaff494140c28fd6H Hartley Sweeten if (!devm_request_mem_region(&dev->dev, res->start, resource_size(res), 2056f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto "txx9wdt")) 2066f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto goto exit_busy; 207b782a563758ac963c794d9fbaaff494140c28fd6H Hartley Sweeten txx9wdt_reg = devm_ioremap(&dev->dev, res->start, resource_size(res)); 2086f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto if (!txx9wdt_reg) 2096f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto goto exit_busy; 2106f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 2116f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto ret = misc_register(&txx9wdt_miscdev); 2126f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto if (ret) { 2136f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto goto exit; 2146f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto } 2156f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 2166f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto printk(KERN_INFO "Hardware Watchdog Timer for TXx9: " 2176f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto "timeout=%d sec (max %ld) (nowayout= %d)\n", 2186f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto timeout, WD_MAX_TIMEOUT, nowayout); 2196f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 2206f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto return 0; 2216f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemotoexit_busy: 2226f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto ret = -EBUSY; 2236f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemotoexit: 2246f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto if (txx9_imclk) { 2256f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto clk_disable(txx9_imclk); 2266f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto clk_put(txx9_imclk); 2276f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto } 2286f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto return ret; 2296f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto} 2306f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 2316f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemotostatic int __exit txx9wdt_remove(struct platform_device *dev) 2326f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto{ 2336f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto misc_deregister(&txx9wdt_miscdev); 2346f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto clk_disable(txx9_imclk); 2356f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto clk_put(txx9_imclk); 2366f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto return 0; 2376f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto} 2386f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 239168b5251adddb1554926cfb94f79a8a28bc6ebe5Wim Van Sebroeckstatic void txx9wdt_shutdown(struct platform_device *dev) 240168b5251adddb1554926cfb94f79a8a28bc6ebe5Wim Van Sebroeck{ 241168b5251adddb1554926cfb94f79a8a28bc6ebe5Wim Van Sebroeck txx9wdt_stop(); 242168b5251adddb1554926cfb94f79a8a28bc6ebe5Wim Van Sebroeck} 243168b5251adddb1554926cfb94f79a8a28bc6ebe5Wim Van Sebroeck 2446f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemotostatic struct platform_driver txx9wdt_driver = { 2456f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto .remove = __exit_p(txx9wdt_remove), 246168b5251adddb1554926cfb94f79a8a28bc6ebe5Wim Van Sebroeck .shutdown = txx9wdt_shutdown, 2476f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto .driver = { 2486f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto .name = "txx9wdt", 2496f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto .owner = THIS_MODULE, 2506f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto }, 2516f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto}; 2526f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 2536f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemotostatic int __init watchdog_init(void) 2546f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto{ 2556f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto return platform_driver_probe(&txx9wdt_driver, txx9wdt_probe); 2566f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto} 2576f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 2586f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemotostatic void __exit watchdog_exit(void) 2596f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto{ 2606f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto platform_driver_unregister(&txx9wdt_driver); 2616f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto} 2626f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 2636f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemotomodule_init(watchdog_init); 2646f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemotomodule_exit(watchdog_exit); 2656f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi Nemoto 2666f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi NemotoMODULE_DESCRIPTION("TXx9 Watchdog Driver"); 2676f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi NemotoMODULE_LICENSE("GPL"); 2686f702fce387e16e16d7930b5c9927d5e71d36eceAtsushi NemotoMODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); 269f37d193c7c150c40059c7ce5de34e8b28a9cd4aeKay SieversMODULE_ALIAS("platform:txx9wdt"); 270