Merge git://git.kernel.org/pub/scm/linux/kernel/git/wim/linux-2.6-watchdog

* git://git.kernel.org/pub/scm/linux/kernel/git/wim/linux-2.6-watchdog:
  watchdog: booke_wdt: clean up status messages
  watchdog: cleanup spaces before tabs
  watchdog: convert to DEFINE_PCI_DEVICE_TABLE
  watchdog: Xen watchdog driver
  watchdog: Intel SCU Watchdog Timer Driver for Moorestown and Medfield platforms.
  watchdog: jz4740_wdt - fix magic character checking
  watchdog: add JZ4740 watchdog driver
  watchdog: it87_wdt: Add support for IT8721F watchdog
  watchdog: hpwdt: build hpwdt as module by default with NMI_DECODING enabled
  watchdog: hpwdt: Fix a couple of typos
This commit is contained in:
Linus Torvalds
2011-03-17 17:09:29 -07:00
42 changed files with 1498 additions and 92 deletions
@@ -30,6 +30,7 @@ extern struct platform_device jz4740_i2s_device;
extern struct platform_device jz4740_pcm_device;
extern struct platform_device jz4740_codec_device;
extern struct platform_device jz4740_adc_device;
extern struct platform_device jz4740_wdt_device;
void jz4740_serial_device_register(void);
+16
View File
@@ -289,3 +289,19 @@ void jz4740_serial_device_register(void)
platform_device_register(&jz4740_uart_device);
}
/* Watchdog */
static struct resource jz4740_wdt_resources[] = {
{
.start = JZ4740_WDT_BASE_ADDR,
.end = JZ4740_WDT_BASE_ADDR + 0x10 - 1,
.flags = IORESOURCE_MEM,
},
};
struct platform_device jz4740_wdt_device = {
.name = "jz4740-wdt",
.id = -1,
.num_resources = ARRAY_SIZE(jz4740_wdt_resources),
.resource = jz4740_wdt_resources,
};
+31 -3
View File
@@ -533,6 +533,16 @@ config I6300ESB_WDT
To compile this driver as a module, choose M here: the
module will be called i6300esb.
config INTEL_SCU_WATCHDOG
bool "Intel SCU Watchdog for Mobile Platforms"
depends on WATCHDOG
depends on INTEL_SCU_IPC
---help---
Hardware driver for the watchdog time built into the Intel SCU
for Intel Mobile Platforms.
To compile this driver as a module, choose M here.
config ITCO_WDT
tristate "Intel TCO Timer/Watchdog"
depends on (X86 || IA64) && PCI
@@ -580,7 +590,7 @@ config IT87_WDT
depends on X86 && EXPERIMENTAL
---help---
This is the driver for the hardware watchdog on the ITE IT8702,
IT8712, IT8716, IT8718, IT8720, IT8726, IT8712 Super I/O chips.
IT8712, IT8716, IT8718, IT8720, IT8721, IT8726 Super I/O chips.
This watchdog simply watches your kernel to make sure it doesn't
freeze, and if it does, it reboots your computer after a certain
amount of time.
@@ -589,18 +599,20 @@ config IT87_WDT
be called it87_wdt.
config HP_WATCHDOG
tristate "HP Proliant iLO2+ Hardware Watchdog Timer"
tristate "HP ProLiant iLO2+ Hardware Watchdog Timer"
depends on X86
default m
help
A software monitoring watchdog and NMI sourcing driver. This driver
will detect lockups and provide a stack trace. This is a driver that
will only load on a HP ProLiant system with a minimum of iLO2 support.
will only load on an HP ProLiant system with a minimum of iLO2 support.
To compile this driver as a module, choose M here: the module will be
called hpwdt.
config HPWDT_NMI_DECODING
bool "NMI decoding support for the HP ProLiant iLO2+ Hardware Watchdog Timer"
depends on HP_WATCHDOG
default y
help
When an NMI occurs this feature will make the necessary BIOS calls to
log the cause of the NMI.
@@ -903,6 +915,12 @@ config INDYDOG
timer expired and no process has written to /dev/watchdog during
that time.
config JZ4740_WDT
tristate "Ingenic jz4740 SoC hardware watchdog"
depends on MACH_JZ4740
help
Hardware driver for the built-in watchdog timer on Ingenic jz4740 SoCs.
config WDT_MTX1
tristate "MTX-1 Hardware Watchdog"
depends on MIPS_MTX1
@@ -1111,6 +1129,16 @@ config WATCHDOG_RIO
# XTENSA Architecture
# Xen Architecture
config XEN_WDT
tristate "Xen Watchdog support"
depends on XEN
help
Say Y here to support the hypervisor watchdog capability provided
by Xen 4.0 and newer. The watchdog timeout period is normally one
minute but can be changed with a boot-time parameter.
#
# ISA-based Watchdog Cards
#
+5
View File
@@ -102,6 +102,7 @@ obj-$(CONFIG_W83877F_WDT) += w83877f_wdt.o
obj-$(CONFIG_W83977F_WDT) += w83977f_wdt.o
obj-$(CONFIG_MACHZ_WDT) += machzwd.o
obj-$(CONFIG_SBC_EPX_C3_WATCHDOG) += sbc_epx_c3.o
obj-$(CONFIG_INTEL_SCU_WATCHDOG) += intel_scu_watchdog.o
# M32R Architecture
@@ -114,6 +115,7 @@ obj-$(CONFIG_BCM47XX_WDT) += bcm47xx_wdt.o
obj-$(CONFIG_BCM63XX_WDT) += bcm63xx_wdt.o
obj-$(CONFIG_RC32434_WDT) += rc32434_wdt.o
obj-$(CONFIG_INDYDOG) += indydog.o
obj-$(CONFIG_JZ4740_WDT) += jz4740_wdt.o
obj-$(CONFIG_WDT_MTX1) += mtx-1_wdt.o
obj-$(CONFIG_PNX833X_WDT) += pnx833x_wdt.o
obj-$(CONFIG_SIBYTE_WDOG) += sb_wdog.o
@@ -148,6 +150,9 @@ obj-$(CONFIG_WATCHDOG_CP1XXX) += cpwd.o
# XTENSA Architecture
# Xen
obj-$(CONFIG_XEN_WDT) += xen_wdt.o
# Architecture Independant
obj-$(CONFIG_WM831X_WATCHDOG) += wm831x_wdt.o
obj-$(CONFIG_WM8350_WATCHDOG) += wm8350_wdt.o
+5 -5
View File
@@ -301,7 +301,7 @@ static int ali_notify_sys(struct notifier_block *this,
* want to register another driver on the same PCI id.
*/
static struct pci_device_id ali_pci_tbl[] __used = {
static DEFINE_PCI_DEVICE_TABLE(ali_pci_tbl) __used = {
{ PCI_VENDOR_ID_AL, 0x1533, PCI_ANY_ID, PCI_ANY_ID,},
{ PCI_VENDOR_ID_AL, 0x1535, PCI_ANY_ID, PCI_ANY_ID,},
{ 0, },
@@ -362,12 +362,12 @@ static int __init ali_find_watchdog(void)
*/
static const struct file_operations ali_fops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
.owner = THIS_MODULE,
.llseek = no_llseek,
.write = ali_write,
.unlocked_ioctl = ali_ioctl,
.open = ali_open,
.release = ali_release,
.open = ali_open,
.release = ali_release,
};
static struct miscdevice ali_miscdev = {
+1 -1
View File
@@ -430,7 +430,7 @@ err_out:
module_init(alim7101_wdt_init);
module_exit(alim7101_wdt_unload);
static struct pci_device_id alim7101_pci_tbl[] __devinitdata __used = {
static DEFINE_PCI_DEVICE_TABLE(alim7101_pci_tbl) __used = {
{ PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533) },
{ PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101) },
{ }
+2 -2
View File
@@ -150,8 +150,8 @@ static ssize_t bcm47xx_wdt_write(struct file *file, const char __user *data,
}
static const struct watchdog_info bcm47xx_wdt_info = {
.identity = DRV_NAME,
.options = WDIOF_SETTIMEOUT |
.identity = DRV_NAME,
.options = WDIOF_SETTIMEOUT |
WDIOF_KEEPALIVEPING |
WDIOF_MAGICCLOSE,
};
+2 -2
View File
@@ -63,7 +63,7 @@ static DEFINE_SPINLOCK(bfin_wdt_spinlock);
/**
* bfin_wdt_keepalive - Keep the Userspace Watchdog Alive
*
* The Userspace watchdog got a KeepAlive: schedule the next timeout.
* The Userspace watchdog got a KeepAlive: schedule the next timeout.
*/
static int bfin_wdt_keepalive(void)
{
@@ -337,7 +337,7 @@ static int bfin_wdt_resume(struct platform_device *pdev)
static const struct file_operations bfin_wdt_fops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
.write = bfin_wdt_write,
.write = bfin_wdt_write,
.unlocked_ioctl = bfin_wdt_ioctl,
.open = bfin_wdt_open,
.release = bfin_wdt_release,
+9 -10
View File
@@ -4,7 +4,7 @@
* Author: Matthew McClintock
* Maintainer: Kumar Gala <galak@kernel.crashing.org>
*
* Copyright 2005, 2008, 2010 Freescale Semiconductor Inc.
* Copyright 2005, 2008, 2010-2011 Freescale Semiconductor Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -221,9 +221,8 @@ static int booke_wdt_open(struct inode *inode, struct file *file)
if (booke_wdt_enabled == 0) {
booke_wdt_enabled = 1;
on_each_cpu(__booke_wdt_enable, NULL, 0);
printk(KERN_INFO
"PowerPC Book-E Watchdog Timer Enabled (wdt_period=%d)\n",
booke_wdt_period);
pr_debug("booke_wdt: watchdog enabled (timeout = %llu sec)\n",
period_to_sec(booke_wdt_period));
}
spin_unlock(&booke_wdt_lock);
@@ -240,6 +239,7 @@ static int booke_wdt_release(struct inode *inode, struct file *file)
*/
on_each_cpu(__booke_wdt_disable, NULL, 0);
booke_wdt_enabled = 0;
pr_debug("booke_wdt: watchdog disabled\n");
#endif
clear_bit(0, &wdt_is_active);
@@ -271,21 +271,20 @@ static int __init booke_wdt_init(void)
{
int ret = 0;
printk(KERN_INFO "PowerPC Book-E Watchdog Timer Loaded\n");
pr_info("booke_wdt: powerpc book-e watchdog driver loaded\n");
ident.firmware_version = cur_cpu_spec->pvr_value;
ret = misc_register(&booke_wdt_miscdev);
if (ret) {
printk(KERN_CRIT "Cannot register miscdev on minor=%d: %d\n",
WATCHDOG_MINOR, ret);
pr_err("booke_wdt: cannot register device (minor=%u, ret=%i)\n",
WATCHDOG_MINOR, ret);
return ret;
}
spin_lock(&booke_wdt_lock);
if (booke_wdt_enabled == 1) {
printk(KERN_INFO
"PowerPC Book-E Watchdog Timer Enabled (wdt_period=%d)\n",
booke_wdt_period);
pr_info("booke_wdt: watchdog enabled (timeout = %llu sec)\n",
period_to_sec(booke_wdt_period));
on_each_cpu(__booke_wdt_enable, NULL, 0);
}
spin_unlock(&booke_wdt_lock);
+18 -18
View File
@@ -5,10 +5,10 @@
* interface and Solaris-compatible ioctls as best it is
* able.
*
* NOTE: CP1400 systems appear to have a defective intr_mask
* register on the PLD, preventing the disabling of
* timer interrupts. We use a timer to periodically
* reset 'stopped' watchdogs on affected platforms.
* NOTE: CP1400 systems appear to have a defective intr_mask
* register on the PLD, preventing the disabling of
* timer interrupts. We use a timer to periodically
* reset 'stopped' watchdogs on affected platforms.
*
* Copyright (c) 2000 Eric Brower (ebrower@usa.net)
* Copyright (C) 2008 David S. Miller <davem@davemloft.net>
@@ -107,13 +107,13 @@ static struct cpwd *cpwd_device;
* -------------------
* |- counter val -|
* -------------------
* dcntr - Current 16-bit downcounter value.
* When downcounter reaches '0' watchdog expires.
* Reading this register resets downcounter with
* 'limit' value.
* limit - 16-bit countdown value in 1/10th second increments.
* Writing this register begins countdown with input value.
* Reading from this register does not affect counter.
* dcntr - Current 16-bit downcounter value.
* When downcounter reaches '0' watchdog expires.
* Reading this register resets downcounter with
* 'limit' value.
* limit - 16-bit countdown value in 1/10th second increments.
* Writing this register begins countdown with input value.
* Reading from this register does not affect counter.
* NOTES: After watchdog reset, dcntr and limit contain '1'
*
* status register (byte access):
@@ -123,7 +123,7 @@ static struct cpwd *cpwd_device;
* |- UNUSED -| EXP | RUN |
* ---------------------------
* status- Bit 0 - Watchdog is running
* Bit 1 - Watchdog has expired
* Bit 1 - Watchdog has expired
*
*** PLD register block definition (struct wd_pld_regblk)
*
@@ -197,7 +197,7 @@ static u8 cpwd_readb(void __iomem *addr)
* Because of the CP1400 defect this should only be
* called during initialzation or by wd_[start|stop]timer()
*
* index - sub-device index, or -1 for 'all'
* index - sub-device index, or -1 for 'all'
* enable - non-zero to enable interrupts, zero to disable
*/
static void cpwd_toggleintr(struct cpwd *p, int index, int enable)
@@ -317,13 +317,13 @@ static int cpwd_getstatus(struct cpwd *p, int index)
} else {
/* Fudge WD_EXPIRED status for defective CP1400--
* IF timer is running
* AND brokenstop is set
* AND an interrupt has been serviced
* AND brokenstop is set
* AND an interrupt has been serviced
* we are WD_EXPIRED.
*
* IF timer is running
* AND brokenstop is set
* AND no interrupt has been serviced
* AND brokenstop is set
* AND no interrupt has been serviced
* we are WD_FREERUN.
*/
if (p->broken &&
@@ -613,7 +613,7 @@ static int __devinit cpwd_probe(struct platform_device *op)
if (p->broken) {
init_timer(&cpwd_timer);
cpwd_timer.function = cpwd_brokentimer;
cpwd_timer.function = cpwd_brokentimer;
cpwd_timer.data = (unsigned long) p;
cpwd_timer.expires = WD_BTIMEOUT;
+1 -1
View File
@@ -201,7 +201,7 @@ static void eurwdt_ping(void)
static ssize_t eurwdt_write(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
if (count) {
if (count) {
if (!nowayout) {
size_t i;
+1 -1
View File
@@ -52,7 +52,7 @@ static void __iomem *pci_mem_addr; /* the PCI-memory address */
static unsigned long __iomem *hpwdt_timer_reg;
static unsigned long __iomem *hpwdt_timer_con;
static struct pci_device_id hpwdt_devices[] = {
static DEFINE_PCI_DEVICE_TABLE(hpwdt_devices) = {
{ PCI_DEVICE(PCI_VENDOR_ID_COMPAQ, 0xB203) }, /* iLO2 */
{ PCI_DEVICE(PCI_VENDOR_ID_HP, 0x3306) }, /* iLO3 */
{0}, /* terminate list */
+1 -1
View File
@@ -334,7 +334,7 @@ static struct miscdevice esb_miscdev = {
/*
* Data for PCI driver interface
*/
static struct pci_device_id esb_pci_tbl[] = {
static DEFINE_PCI_DEVICE_TABLE(esb_pci_tbl) = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_9), },
{ 0, }, /* End of list */
};
+2 -2
View File
@@ -247,7 +247,7 @@ static struct {
{NULL, 0}
};
#define ITCO_PCI_DEVICE(dev, data) \
#define ITCO_PCI_DEVICE(dev, data) \
.vendor = PCI_VENDOR_ID_INTEL, \
.device = dev, \
.subvendor = PCI_ANY_ID, \
@@ -262,7 +262,7 @@ static struct {
* pci_driver, because the I/O Controller Hub has also other
* functions that probably will be registered by other drivers.
*/
static struct pci_device_id iTCO_wdt_pci_tbl[] = {
static DEFINE_PCI_DEVICE_TABLE(iTCO_wdt_pci_tbl) = {
{ ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801AA_0, TCO_ICH)},
{ ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801AB_0, TCO_ICH0)},
{ ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801BA_0, TCO_ICH2)},
File diff suppressed because it is too large Load Diff
+66
View File
@@ -0,0 +1,66 @@
/*
* Intel_SCU 0.2: An Intel SCU IOH Based Watchdog Device
* for Intel part #(s):
* - AF82MP20 PCH
*
* Copyright (C) 2009-2010 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General
* Public License as published by the Free Software Foundation.
*
* 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.
* You should have received a copy of the GNU General Public
* License along with this program; if not, write to the Free
* Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
* The full GNU General Public License is included in this
* distribution in the file called COPYING.
*
*/
#ifndef __INTEL_SCU_WATCHDOG_H
#define __INTEL_SCU_WATCHDOG_H
#define PFX "Intel_SCU: "
#define WDT_VER "0.3"
/* minimum time between interrupts */
#define MIN_TIME_CYCLE 1
/* Time from warning to reboot is 2 seconds */
#define DEFAULT_SOFT_TO_HARD_MARGIN 2
#define MAX_TIME 170
#define DEFAULT_TIME 5
#define MAX_SOFT_TO_HARD_MARGIN (MAX_TIME-MIN_TIME_CYCLE)
/* Ajustment to clock tick frequency to make timing come out right */
#define FREQ_ADJUSTMENT 8
struct intel_scu_watchdog_dev {
ulong driver_open;
ulong driver_closed;
u32 timer_started;
u32 timer_set;
u32 threshold;
u32 soft_threshold;
u32 __iomem *timer_load_count_addr;
u32 __iomem *timer_current_value_addr;
u32 __iomem *timer_control_addr;
u32 __iomem *timer_clear_interrupt_addr;
u32 __iomem *timer_interrupt_status_addr;
struct sfi_timer_table_entry *timer_tbl_ptr;
struct notifier_block intel_scu_notifier;
struct miscdevice miscdev;
};
extern int sfi_mtimer_num;
/* extern struct sfi_timer_table_entry *sfi_get_mtmr(int hint); */
#endif /* __INTEL_SCU_WATCHDOG_H */
+1 -1
View File
@@ -69,7 +69,7 @@ static unsigned short address;
#define IT8712F_DEVID 0x8712
#define LDN_GPIO 0x07 /* GPIO and Watch Dog Timer */
#define LDN_GAME 0x09 /* Game Port */
#define LDN_GAME 0x09 /* Game Port */
#define WDT_CONTROL 0x71 /* WDT Register: Control */
#define WDT_CONFIG 0x72 /* WDT Register: Configuration */
+16 -12
View File
@@ -12,7 +12,7 @@
* http://www.ite.com.tw/
*
* Support of the watchdog timers, which are available on
* IT8702, IT8712, IT8716, IT8718, IT8720 and IT8726.
* IT8702, IT8712, IT8716, IT8718, IT8720, IT8721 and IT8726.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -45,7 +45,7 @@
#include <asm/system.h>
#define WATCHDOG_VERSION "1.13"
#define WATCHDOG_VERSION "1.14"
#define WATCHDOG_NAME "IT87 WDT"
#define PFX WATCHDOG_NAME ": "
#define DRIVER_VERSION WATCHDOG_NAME " driver, v" WATCHDOG_VERSION "\n"
@@ -54,7 +54,7 @@
/* Defaults for Module Parameter */
#define DEFAULT_NOGAMEPORT 0
#define DEFAULT_EXCLUSIVE 1
#define DEFAULT_TIMEOUT 60
#define DEFAULT_TIMEOUT 60
#define DEFAULT_TESTMODE 0
#define DEFAULT_NOWAYOUT WATCHDOG_NOWAYOUT
@@ -70,9 +70,9 @@
/* Configuration Registers and Functions */
#define LDNREG 0x07
#define CHIPID 0x20
#define CHIPREV 0x22
#define CHIPREV 0x22
#define ACTREG 0x30
#define BASEREG 0x60
#define BASEREG 0x60
/* Chip Id numbers */
#define NO_DEV_ID 0xffff
@@ -82,10 +82,11 @@
#define IT8716_ID 0x8716
#define IT8718_ID 0x8718
#define IT8720_ID 0x8720
#define IT8721_ID 0x8721
#define IT8726_ID 0x8726 /* the data sheet suggest wrongly 0x8716 */
/* GPIO Configuration Registers LDN=0x07 */
#define WDTCTRL 0x71
#define WDTCTRL 0x71
#define WDTCFG 0x72
#define WDTVALLSB 0x73
#define WDTVALMSB 0x74
@@ -94,7 +95,7 @@
#define WDT_CIRINT 0x80
#define WDT_MOUSEINT 0x40
#define WDT_KYBINT 0x20
#define WDT_GAMEPORT 0x10 /* not in it8718, it8720 */
#define WDT_GAMEPORT 0x10 /* not in it8718, it8720, it8721 */
#define WDT_FORCE 0x02
#define WDT_ZERO 0x01
@@ -102,11 +103,11 @@
#define WDT_TOV1 0x80
#define WDT_KRST 0x40
#define WDT_TOVE 0x20
#define WDT_PWROK 0x10
#define WDT_PWROK 0x10 /* not in it8721 */
#define WDT_INT_MASK 0x0f
/* CIR Configuration Register LDN=0x0a */
#define CIR_ILS 0x70
#define CIR_ILS 0x70
/* The default Base address is not always available, we use this */
#define CIR_BASE 0x0208
@@ -134,7 +135,7 @@
#define WDTS_USE_GP 4
#define WDTS_EXPECTED 5
static unsigned int base, gpact, ciract, max_units;
static unsigned int base, gpact, ciract, max_units, chip_type;
static unsigned long wdt_status;
static DEFINE_SPINLOCK(spinlock);
@@ -215,7 +216,7 @@ static inline void superio_outw(int val, int reg)
/* Internal function, should be called after superio_select(GPIO) */
static void wdt_update_timeout(void)
{
unsigned char cfg = WDT_KRST | WDT_PWROK;
unsigned char cfg = WDT_KRST;
int tm = timeout;
if (testmode)
@@ -226,6 +227,9 @@ static void wdt_update_timeout(void)
else
tm /= 60;
if (chip_type != IT8721_ID)
cfg |= WDT_PWROK;
superio_outb(cfg, WDTCFG);
superio_outb(tm, WDTVALLSB);
if (max_units > 255)
@@ -555,7 +559,6 @@ static int __init it87_wdt_init(void)
{
int rc = 0;
int try_gameport = !nogameport;
u16 chip_type;
u8 chip_rev;
unsigned long flags;
@@ -581,6 +584,7 @@ static int __init it87_wdt_init(void)
break;
case IT8718_ID:
case IT8720_ID:
case IT8721_ID:
max_units = 65535;
try_gameport = 0;
break;
+322
View File
@@ -0,0 +1,322 @@
/*
* Copyright (C) 2010, Paul Cercueil <paul@crapouillou.net>
* JZ4740 Watchdog driver
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/watchdog.h>
#include <linux/init.h>
#include <linux/bitops.h>
#include <linux/platform_device.h>
#include <linux/spinlock.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include <linux/device.h>
#include <linux/clk.h>
#include <linux/slab.h>
#include <asm/mach-jz4740/timer.h>
#define JZ_REG_WDT_TIMER_DATA 0x0
#define JZ_REG_WDT_COUNTER_ENABLE 0x4
#define JZ_REG_WDT_TIMER_COUNTER 0x8
#define JZ_REG_WDT_TIMER_CONTROL 0xC
#define JZ_WDT_CLOCK_PCLK 0x1
#define JZ_WDT_CLOCK_RTC 0x2
#define JZ_WDT_CLOCK_EXT 0x4
#define WDT_IN_USE 0
#define WDT_OK_TO_CLOSE 1
#define JZ_WDT_CLOCK_DIV_SHIFT 3
#define JZ_WDT_CLOCK_DIV_1 (0 << JZ_WDT_CLOCK_DIV_SHIFT)
#define JZ_WDT_CLOCK_DIV_4 (1 << JZ_WDT_CLOCK_DIV_SHIFT)
#define JZ_WDT_CLOCK_DIV_16 (2 << JZ_WDT_CLOCK_DIV_SHIFT)
#define JZ_WDT_CLOCK_DIV_64 (3 << JZ_WDT_CLOCK_DIV_SHIFT)
#define JZ_WDT_CLOCK_DIV_256 (4 << JZ_WDT_CLOCK_DIV_SHIFT)
#define JZ_WDT_CLOCK_DIV_1024 (5 << JZ_WDT_CLOCK_DIV_SHIFT)
#define DEFAULT_HEARTBEAT 5
#define MAX_HEARTBEAT 2048
static struct {
void __iomem *base;
struct resource *mem;
struct clk *rtc_clk;
unsigned long status;
} jz4740_wdt;
static int heartbeat = DEFAULT_HEARTBEAT;
static void jz4740_wdt_service(void)
{
writew(0x0, jz4740_wdt.base + JZ_REG_WDT_TIMER_COUNTER);
}
static void jz4740_wdt_set_heartbeat(int new_heartbeat)
{
unsigned int rtc_clk_rate;
unsigned int timeout_value;
unsigned short clock_div = JZ_WDT_CLOCK_DIV_1;
heartbeat = new_heartbeat;
rtc_clk_rate = clk_get_rate(jz4740_wdt.rtc_clk);
timeout_value = rtc_clk_rate * heartbeat;
while (timeout_value > 0xffff) {
if (clock_div == JZ_WDT_CLOCK_DIV_1024) {
/* Requested timeout too high;
* use highest possible value. */
timeout_value = 0xffff;
break;
}
timeout_value >>= 2;
clock_div += (1 << JZ_WDT_CLOCK_DIV_SHIFT);
}
writeb(0x0, jz4740_wdt.base + JZ_REG_WDT_COUNTER_ENABLE);
writew(clock_div, jz4740_wdt.base + JZ_REG_WDT_TIMER_CONTROL);
writew((u16)timeout_value, jz4740_wdt.base + JZ_REG_WDT_TIMER_DATA);
writew(0x0, jz4740_wdt.base + JZ_REG_WDT_TIMER_COUNTER);
writew(clock_div | JZ_WDT_CLOCK_RTC,
jz4740_wdt.base + JZ_REG_WDT_TIMER_CONTROL);
writeb(0x1, jz4740_wdt.base + JZ_REG_WDT_COUNTER_ENABLE);
}
static void jz4740_wdt_enable(void)
{
jz4740_timer_enable_watchdog();
jz4740_wdt_set_heartbeat(heartbeat);
}
static void jz4740_wdt_disable(void)
{
jz4740_timer_disable_watchdog();
writeb(0x0, jz4740_wdt.base + JZ_REG_WDT_COUNTER_ENABLE);
}
static int jz4740_wdt_open(struct inode *inode, struct file *file)
{
if (test_and_set_bit(WDT_IN_USE, &jz4740_wdt.status))
return -EBUSY;
jz4740_wdt_enable();
return nonseekable_open(inode, file);
}
static ssize_t jz4740_wdt_write(struct file *file, const char *data,
size_t len, loff_t *ppos)
{
if (len) {
size_t i;
clear_bit(WDT_OK_TO_CLOSE, &jz4740_wdt.status);
for (i = 0; i != len; i++) {
char c;
if (get_user(c, data + i))
return -EFAULT;
if (c == 'V')
set_bit(WDT_OK_TO_CLOSE, &jz4740_wdt.status);
}
jz4740_wdt_service();
}
return len;
}
static const struct watchdog_info ident = {
.options = WDIOF_KEEPALIVEPING,
.identity = "jz4740 Watchdog",
};
static long jz4740_wdt_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
int ret = -ENOTTY;
int heartbeat_seconds;
switch (cmd) {
case WDIOC_GETSUPPORT:
ret = copy_to_user((struct watchdog_info *)arg, &ident,
sizeof(ident)) ? -EFAULT : 0;
break;
case WDIOC_GETSTATUS:
case WDIOC_GETBOOTSTATUS:
ret = put_user(0, (int *)arg);
break;
case WDIOC_KEEPALIVE:
jz4740_wdt_service();
return 0;
case WDIOC_SETTIMEOUT:
if (get_user(heartbeat_seconds, (int __user *)arg))
return -EFAULT;
jz4740_wdt_set_heartbeat(heartbeat_seconds);
return 0;
case WDIOC_GETTIMEOUT:
return put_user(heartbeat, (int *)arg);
default:
break;
}
return ret;
}
static int jz4740_wdt_release(struct inode *inode, struct file *file)
{
jz4740_wdt_service();
if (test_and_clear_bit(WDT_OK_TO_CLOSE, &jz4740_wdt.status))
jz4740_wdt_disable();
clear_bit(WDT_IN_USE, &jz4740_wdt.status);
return 0;
}
static const struct file_operations jz4740_wdt_fops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
.write = jz4740_wdt_write,
.unlocked_ioctl = jz4740_wdt_ioctl,
.open = jz4740_wdt_open,
.release = jz4740_wdt_release,
};
static struct miscdevice jz4740_wdt_miscdev = {
.minor = WATCHDOG_MINOR,
.name = "watchdog",
.fops = &jz4740_wdt_fops,
};
static int __devinit jz4740_wdt_probe(struct platform_device *pdev)
{
int ret = 0, size;
struct resource *res;
struct device *dev = &pdev->dev;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res == NULL) {
dev_err(dev, "failed to get memory region resource\n");
return -ENXIO;
}
size = resource_size(res);
jz4740_wdt.mem = request_mem_region(res->start, size, pdev->name);
if (jz4740_wdt.mem == NULL) {
dev_err(dev, "failed to get memory region\n");
return -EBUSY;
}
jz4740_wdt.base = ioremap_nocache(res->start, size);
if (jz4740_wdt.base == NULL) {
dev_err(dev, "failed to map memory region\n");
ret = -EBUSY;
goto err_release_region;
}
jz4740_wdt.rtc_clk = clk_get(NULL, "rtc");
if (IS_ERR(jz4740_wdt.rtc_clk)) {
dev_err(dev, "cannot find RTC clock\n");
ret = PTR_ERR(jz4740_wdt.rtc_clk);
goto err_iounmap;
}
ret = misc_register(&jz4740_wdt_miscdev);
if (ret < 0) {
dev_err(dev, "cannot register misc device\n");
goto err_disable_clk;
}
return 0;
err_disable_clk:
clk_put(jz4740_wdt.rtc_clk);
err_iounmap:
iounmap(jz4740_wdt.base);
err_release_region:
release_mem_region(jz4740_wdt.mem->start,
resource_size(jz4740_wdt.mem));
return ret;
}
static int __devexit jz4740_wdt_remove(struct platform_device *pdev)
{
jz4740_wdt_disable();
misc_deregister(&jz4740_wdt_miscdev);
clk_put(jz4740_wdt.rtc_clk);
iounmap(jz4740_wdt.base);
jz4740_wdt.base = NULL;
release_mem_region(jz4740_wdt.mem->start,
resource_size(jz4740_wdt.mem));
jz4740_wdt.mem = NULL;
return 0;
}
static struct platform_driver jz4740_wdt_driver = {
.probe = jz4740_wdt_probe,
.remove = __devexit_p(jz4740_wdt_remove),
.driver = {
.name = "jz4740-wdt",
.owner = THIS_MODULE,
},
};
static int __init jz4740_wdt_init(void)
{
return platform_driver_register(&jz4740_wdt_driver);
}
module_init(jz4740_wdt_init);
static void __exit jz4740_wdt_exit(void)
{
platform_driver_unregister(&jz4740_wdt_driver);
}
module_exit(jz4740_wdt_exit);
MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>");
MODULE_DESCRIPTION("jz4740 Watchdog Driver");
module_param(heartbeat, int, 0);
MODULE_PARM_DESC(heartbeat,
"Watchdog heartbeat period in seconds from 1 to "
__MODULE_STRING(MAX_HEARTBEAT) ", default "
__MODULE_STRING(DEFAULT_HEARTBEAT));
MODULE_LICENSE("GPL");
MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
MODULE_ALIAS("platform:jz4740-wdt");
+1 -1
View File
@@ -54,7 +54,7 @@
/* indexes */ /* size */
#define ZFL_VERSION 0x02 /* 16 */
#define CONTROL 0x10 /* 16 */
#define CONTROL 0x10 /* 16 */
#define STATUS 0x12 /* 8 */
#define COUNTER_1 0x0C /* 16 */
#define COUNTER_2 0x0E /* 8 */

Some files were not shown because too many files have changed in this diff Show More