1/* $NetBSD: wdog.c,v 1.15 2007/03/04 06:00:40 christos Exp $ */ 2 3/*- 4 * Copyright (C) 2000 SAITOH Masanobu. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * 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 copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29#include <sys/cdefs.h> 30__KERNEL_RCSID(0, "$NetBSD: wdog.c,v 1.15 2007/03/04 06:00:40 christos Exp $"); 31 32#include <sys/param.h> 33#include <sys/buf.h> 34#include <sys/systm.h> 35#include <sys/kernel.h> 36#include <sys/uio.h> 37#include <sys/device.h> 38#include <sys/fcntl.h> 39#include <sys/ioctl.h> 40#include <sys/malloc.h> 41#include <sys/proc.h> 42#include <sys/syslog.h> 43#include <sys/conf.h> 44 45#include <machine/cpu.h> 46#include <machine/intr.h> 47 48#include <sh3/frame.h> 49#include <sh3/wdtreg.h> 50#include <sh3/wdogvar.h> 51#include <sh3/exception.h> 52 53struct wdog_softc { 54 device_t sc_dev; 55 int flags; 56}; 57 58static int wdogmatch(device_t, cfdata_t, void *); 59static void wdogattach(device_t, device_t, void *); 60static int wdogintr(void *); 61 62CFATTACH_DECL_NEW(wdog, sizeof(struct wdog_softc), 63 wdogmatch, wdogattach, NULL, NULL); 64 65extern struct cfdriver wdog_cd; 66 67dev_type_open(wdogopen); 68dev_type_close(wdogclose); 69dev_type_ioctl(wdogioctl); 70 71const struct cdevsw wdog_cdevsw = { 72 wdogopen, wdogclose, noread, nowrite, wdogioctl, 73 nostop, notty, nopoll, nommap, nokqfilter, 74}; 75 76void 77wdog_wr_cnt(unsigned char x) 78{ 79 80 SHREG_WTCNT_W = WTCNT_W_M | (unsigned short) x; 81} 82 83void 84wdog_wr_csr(unsigned char x) 85{ 86 87 SHREG_WTCSR_W = WTCSR_W_M | (unsigned short) x; 88} 89 90static int 91wdogmatch(device_t parent, cfdata_t cfp, void *aux) 92{ 93 94 if (strcmp(cfp->cf_name, "wdog")) 95 return (0); 96 97 return (1); 98} 99 100/* 101 * functions for probeing. 102 */ 103/* ARGSUSED */ 104static void 105wdogattach(device_t parent, device_t self, void *aux) 106{ 107 struct wdog_softc *sc; 108 109 sc = device_private(self); 110 sc->sc_dev = self; 111 112 aprint_naive("\n"); 113 aprint_normal(": internal watchdog timer\n"); 114 115 wdog_wr_csr(WTCSR_WT | WTCSR_CKS_4096); /* default to wt mode */ 116 117 intc_intr_establish(SH_INTEVT_WDT_ITI, IST_LEVEL, IPL_SOFTCLOCK, 118 wdogintr, 0); 119} 120 121/*ARGSUSED*/ 122int 123wdogopen(dev_t dev, int flag, int mode, struct lwp *l) 124{ 125 struct wdog_softc *sc; 126 127 sc = device_lookup_private(&wdog_cd, minor(dev)); 128 if (sc == NULL) 129 return (ENXIO); 130 131 if (sc->flags & WDOGF_OPEN) 132 return (EBUSY); 133 sc->flags |= WDOGF_OPEN; 134 return (0); 135} 136 137/*ARGSUSED*/ 138int 139wdogclose(dev_t dev, int flag, int mode, struct lwp *l) 140{ 141 struct wdog_softc *sc; 142 143 sc = device_lookup_private(&wdog_cd, minor(dev)); 144 145 if (sc->flags & WDOGF_OPEN) 146 sc->flags = 0; 147 148 return (0); 149} 150 151extern unsigned int maxwdog; 152 153/*ARGSUSED*/ 154int 155wdogioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) 156{ 157 int error = 0; 158 int request; 159 160 switch (cmd) { 161 case SIOWDOGSETMODE: 162 request = *(int *)data; 163 164 switch (request) { 165 case WDOGM_RESET: 166 wdog_wr_csr(SHREG_WTCSR_R | WTCSR_WT); 167 break; 168 case WDOGM_INTR: 169 wdog_wr_csr(SHREG_WTCSR_R & ~WTCSR_WT); 170 break; 171 default: 172 error = EINVAL; 173 break; 174 } 175 break; 176 case SIORESETWDOG: 177 wdog_wr_cnt(0); /* reset to zero */ 178 break; 179 case SIOSTARTWDOG: 180 wdog_wr_csr(WTCSR_WT | WTCSR_CKS_4096); 181 wdog_wr_cnt(0); /* reset to zero */ 182 wdog_wr_csr(SHREG_WTCSR_R | WTCSR_TME); /* start!!! */ 183 break; 184 case SIOSTOPWDOG: 185 wdog_wr_csr(SHREG_WTCSR_R & ~WTCSR_TME); /* stop */ 186 break; 187 case SIOSETWDOG: 188 request = *(int *)data; 189 190 if (request > 2) { 191 error = EINVAL; 192 break; 193 } 194 break; 195 default: 196 error = EINVAL; 197 break; 198 } 199 200 return (error); 201} 202 203int 204wdogintr(void *arg) 205{ 206 struct trapframe *frame = arg; 207 208 wdog_wr_csr(SHREG_WTCSR_R & ~WTCSR_IOVF); /* clear overflow bit */ 209 wdog_wr_cnt(0); /* reset to zero */ 210 printf("wdog trapped: spc = %x\n", frame->tf_spc); 211 212 return (0); 213} 214