1 /* $NetBSD: admwdog.c,v 1.1 2007/03/20 08:52:02 dyoung Exp $ */ 2 3 /*- 4 * Copyright (c) 2007 David Young. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or 7 * without modification, are permitted provided that the following 8 * conditions are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above 12 * copyright notice, this list of conditions and the following 13 * disclaimer in the documentation and/or other materials provided 14 * with the distribution. 15 * 3. The name of the author may not be used to endorse or promote 16 * products derived from this software without specific prior 17 * written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY 20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 22 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 24 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 26 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 28 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 29 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 30 * OF SUCH DAMAGE. 31 */ 32 33 #include <sys/cdefs.h> 34 35 __KERNEL_RCSID(0, "$NetBSD: admwdog.c,v 1.1 2007/03/20 08:52:02 dyoung Exp $"); 36 37 #include <sys/param.h> 38 #include <sys/systm.h> 39 #include <sys/device.h> 40 #include <sys/wdog.h> 41 #include <sys/kernel.h> /* for hz */ 42 43 #include <machine/bus.h> 44 45 #include <dev/sysmon/sysmonvar.h> 46 47 #include <mips/adm5120/include/adm5120reg.h> 48 #include <mips/adm5120/include/adm5120var.h> 49 #include <mips/adm5120/include/adm5120_obiovar.h> 50 #include <mips/adm5120/dev/if_admswvar.h> 51 52 /* maximum watchdog period, seconds */ 53 #define ADMWDOG_MAX_PERIOD (__SHIFTOUT_MASK(ADM5120_WDOG_WTS_MASK) / 100) 54 55 static int admwdog_setmode(struct sysmon_wdog *smw); 56 static int admwdog_tickle(struct sysmon_wdog *smw); 57 58 static inline uint32_t 59 admwdog_read(struct admsw_softc *sc) 60 { 61 return bus_space_read_4(sc->sc_st, sc->sc_ioh, ADM5120_WDOG0); 62 } 63 64 static inline void 65 admwdog_write(struct admsw_softc *sc, uint32_t val) 66 { 67 bus_space_write_4(sc->sc_st, sc->sc_ioh, ADM5120_WDOG0, val); 68 } 69 70 static void 71 admwdog_reset(struct admsw_softc *sc) 72 { 73 int s; 74 uint32_t wdog0; 75 76 wdog0 = __SHIFTIN(sc->sc_smw.smw_period * 100, ADM5120_WDOG_WTS_MASK) | 77 __SHIFTIN(1, ADM5120_WDOG_WT_MASK); 78 79 s = splhigh(); 80 81 admwdog_write(sc, wdog0); 82 (void)admwdog_read(sc); 83 admwdog_write(sc, ADM5120_WDOG0_WTTR | wdog0); 84 85 splx(s); 86 } 87 88 static int 89 admwdog_setmode(struct sysmon_wdog *smw) 90 { 91 struct admsw_softc *sc = smw->smw_cookie; 92 93 if ((smw->smw_mode & WDOG_MODE_MASK) == WDOG_MODE_DISARMED) { 94 admwdog_write(sc, 0); 95 return 0; 96 } 97 98 if (smw->smw_period == WDOG_PERIOD_DEFAULT) 99 smw->smw_period = 32; 100 else if (smw->smw_period > ADMWDOG_MAX_PERIOD) 101 return EINVAL; 102 103 admwdog_reset(sc); 104 105 return 0; 106 } 107 108 static int 109 admwdog_tickle(struct sysmon_wdog *smw) 110 { 111 struct admsw_softc *sc = smw->smw_cookie; 112 113 (void)admwdog_read(sc); 114 return 0; 115 } 116 117 void 118 admwdog_attach(struct admsw_softc *sc) 119 { 120 struct sysmon_wdog *smw = &sc->sc_smw; 121 122 /* deactivate watchdog */ 123 admwdog_write(sc, 0); 124 125 smw->smw_name = device_xname(&sc->sc_dev); 126 smw->smw_cookie = sc; 127 smw->smw_setmode = admwdog_setmode; 128 smw->smw_tickle = admwdog_tickle; 129 smw->smw_period = ADMWDOG_MAX_PERIOD; 130 131 sysmon_wdog_register(&sc->sc_smw); 132 } 133