Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 163619
b: refs/heads/master
c: dcfb748
h: refs/heads/master
i:
  163617: 2bd901a
  163615: e4dc0bb
v: v3
  • Loading branch information
Chris Friesen authored and Wim Van Sebroeck committed Sep 18, 2009
1 parent f9aee29 commit 994392a
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 5 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 9fd868f440c3d722199a14200b2a64a0a5e70221
refs/heads/master: dcfb748422d01245b6e89c94d85fcdb3c71a56a0
57 changes: 53 additions & 4 deletions trunk/drivers/watchdog/booke_wdt.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@

#include <asm/reg_booke.h>
#include <asm/system.h>
#include <asm/time.h>
#include <asm/div64.h>

/* If the kernel parameter wdt=1, the watchdog will be enabled at boot.
* Also, the wdt_period sets the watchdog timer period timeout.
Expand All @@ -32,7 +34,7 @@
*/

#ifdef CONFIG_FSL_BOOKE
#define WDT_PERIOD_DEFAULT 63 /* Ex. wdt_period=28 bus=333Mhz,reset=~40sec */
#define WDT_PERIOD_DEFAULT 38 /* Ex. wdt_period=28 bus=333Mhz,reset=~40sec */
#else
#define WDT_PERIOD_DEFAULT 3 /* Refer to the PPC40x and PPC4xx manuals */
#endif /* for timing information */
Expand All @@ -41,7 +43,7 @@ u32 booke_wdt_enabled;
u32 booke_wdt_period = WDT_PERIOD_DEFAULT;

#ifdef CONFIG_FSL_BOOKE
#define WDTP(x) ((((63-x)&0x3)<<30)|(((63-x)&0x3c)<<15))
#define WDTP(x) ((((x)&0x3)<<30)|(((x)&0x3c)<<15))
#define WDTP_MASK (WDTP(0))
#else
#define WDTP(x) (TCR_WP(x))
Expand All @@ -50,6 +52,45 @@ u32 booke_wdt_period = WDT_PERIOD_DEFAULT;

static DEFINE_SPINLOCK(booke_wdt_lock);

/* For the specified period, determine the number of seconds
* corresponding to the reset time. There will be a watchdog
* exception at approximately 3/5 of this time.
*
* The formula to calculate this is given by:
* 2.5 * (2^(63-period+1)) / timebase_freq
*
* In order to simplify things, we assume that period is
* at least 1. This will still result in a very long timeout.
*/
static unsigned long long period_to_sec(unsigned int period)
{
unsigned long long tmp = 1ULL << (64 - period);
unsigned long tmp2 = ppc_tb_freq;

/* tmp may be a very large number and we don't want to overflow,
* so divide the timebase freq instead of multiplying tmp
*/
tmp2 = tmp2 / 5 * 2;

do_div(tmp, tmp2);
return tmp;
}

/*
* This procedure will find the highest period which will give a timeout
* greater than the one required. e.g. for a bus speed of 66666666 and
* and a parameter of 2 secs, then this procedure will return a value of 38.
*/
static unsigned int sec_to_period(unsigned int secs)
{
unsigned int period;
for (period = 63; period > 0; period--) {
if (period_to_sec(period) >= secs)
return period;
}
return 0;
}

static void __booke_wdt_ping(void *data)
{
mtspr(SPRN_TSR, TSR_ENW|TSR_WIS);
Expand Down Expand Up @@ -93,7 +134,7 @@ static long booke_wdt_ioctl(struct file *file,

switch (cmd) {
case WDIOC_GETSUPPORT:
if (copy_to_user(arg, &ident, sizeof(struct watchdog_info)))
if (copy_to_user((void *)arg, &ident, sizeof(ident)))
return -EFAULT;
case WDIOC_GETSTATUS:
return put_user(ident.options, p);
Expand All @@ -115,8 +156,16 @@ static long booke_wdt_ioctl(struct file *file,
booke_wdt_ping();
return 0;
case WDIOC_SETTIMEOUT:
if (get_user(booke_wdt_period, p))
if (get_user(tmp, p))
return -EFAULT;
#ifdef CONFIG_FSL_BOOKE
/* period of 1 gives the largest possible timeout */
if (tmp > period_to_sec(1))
return -EINVAL;
booke_wdt_period = sec_to_period(tmp);
#else
booke_wdt_period = tmp;
#endif
mtspr(SPRN_TCR, (mfspr(SPRN_TCR) & ~WDTP_MASK) |
WDTP(booke_wdt_period));
return 0;
Expand Down

0 comments on commit 994392a

Please sign in to comment.