blob: fce2c6dd18db022f550cb261a8b7318fbf6d7762 [file] [log] [blame]
#!/bin/sh
#
# Program the hardware watchdog counter.
#
onusr1()
{
quit
}
quit()
{
$stop
exit 0
}
trap onusr1 USR1
delay=5
if is-windcharger; then
timeout=170
delay=30
WDIOC_GETBOOTSTATUS=0x40045702
fi
platform=$(cat /etc/platform)
if [ -c /dev/watchdog ]; then
init=devwatchdog_init
setup=devwatchdog_setup
pushback=devwatchdog_pushback
stop=devwatchdog_stop
file=/dev/watchdog
elif [ -c /dev/comcerto_wdt ]; then
init=devwatchdog_init
setup=devwatchdog_setup
pushback=devwatchdog_pushback
stop=devwatchdog_stop
file=/dev/comcerto_wdt
elif grep -q "BCM7425" /proc/cpuinfo; then
# GFHD100
init=bcm7425_init
setup=bcm_setup
pushback=bcm_pushback
stop=
elif grep -q "BCM7429" /proc/cpuinfo; then
# GFHD200
init=bcm7429_init
setup=bcm_setup
pushback=bcm_pushback
stop=
elif [ "$platform" = "GFHD254" ]; then
init=bcm7252_init
setup=bcm_setup
pushback=bcm_pushback
else
echo "Unknown CPU type, cannot initialize watchdog timer"
cat /proc/cpuinfo
exit 1
fi
if [ -e /proc/$$/oom_score_adj ]; then
echo -1000 >/proc/$$/oom_score_adj
elif [ -e /proc/$$/oom_adj ]; then
# Older kernels (e.g. fiberjack) need this to adjust the oom score.
echo -1000 >/proc/$$/oom_adj
else
echo "WARNING: Failed to adjust OOM score for pid: $$!"
fi
write()
{
devmem "$@" >/dev/null
}
#
# /dev/watchdog support
#
# delay can be set when loading module
devwatchdog_init()
{
wait-until-created $file
if [ -n "$timeout" ]; then
WDIOC_SETTIMEOUT=-1073457402 # 0xc0045706
ioctl -l 4 -- /dev/watchdog $WDIOC_SETTIMEOUT $timeout
fi
if [ -n "$WDIOC_GETBOOTSTATUS" ]; then
if ! ioctl -l 4 -- /dev/watchdog $WDIOC_GETBOOTSTATUS |
grep "return buf: 00 00 00 00"; then
echo "*** Warning *** watchdog reboot detected"
fi
fi
}
devwatchdog_setup()
{
if [ ! -e "$file" ]; then
echo "watchdog setup failed: $file does not exist!"
fi
exec 9>$file
}
devwatchdog_pushback()
{
echo -n X >&9
}
devwatchdog_stop()
{
echo -n V >&9
}
#
# BCM support
#
# The watch counter. It counts at a clock rate of 27Mhz,
# so the largest timeout we can program is 159s. The watchdog timer triggers
# an NMI midway which as at approx. 79.5s. Our custom NMI handler in the
# kernel dumps the CPU registers and calls panic() i.e. reboots the box. If,
# for some reason, this fails, the watchdog timer will eventually assert a chip
# reset event after another 79.5s. (The software watchdog is currently at 70s)
bcm7425_init()
{
timer_wdtimeout_reg=0x104067e8
timer_wdcmd_reg=0x104067ec
timer_wdchiprst_cnt_reg=0x104067f0
timer_wdctrl_reg=0x104067fc
}
bcm7429_init()
{
timer_wdtimeout_reg=0x104066e8
timer_wdcmd_reg=0x104066ec
timer_wdchiprst_cnt_reg=0x104066f0
timer_wdctrl_reg=0x104066fc
}
bcm7252_init()
{
timer_wdtimeout_reg=0xf040a7a8
timer_wdcmd_reg=0xf040a7ac
timer_wdchiprst_cnt_reg=0xf040a7b0
timer_wdctrl_reg=0xf040a7bc
}
bcm_setup()
{
# WD timeout value: 159.072862778 seconds (an NMI is triggered halfway through)
wdtimeout_val=0xffffffff
# WD event mode: NMI asserted when WD timer is midway, and chip reset asserted
# when WD timer expires
wd_event_mode=0x2
# WD chip reset length: 2.49 seconds (maximum)
wdchiprst_cnt_val=0x3ffffff
# Stop and reprogram the watchdog timer
write $timer_wdcmd_reg 32 0xee00
write $timer_wdcmd_reg 32 0x00ee
write $timer_wdtimeout_reg 32 $wdtimeout_val
write $timer_wdctrl_reg 32 $wd_event_mode
write $timer_wdchiprst_cnt_reg 32 $wdchiprst_cnt_val
}
bcm_pushback()
{
write $timer_wdcmd_reg 32 0xff00
write $timer_wdcmd_reg 32 0x00ff
}
#
# init, setup, pushback timer
#
$init
$setup
# Start the watchdog timer and reload every n seconds
while true; do
$pushback
sleep $delay
done
quit