1 /* $NetBSD: wdog.c,v 1.12 2002/10/23 09:11:57 jdolecek 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/param.h> 30 #include <sys/buf.h> 31 #include <sys/systm.h> 32 #include <sys/kernel.h> 33 #include <sys/uio.h> 34 #include <sys/device.h> 35 #include <sys/fcntl.h> 36 #include <sys/ioctl.h> 37 #include <sys/malloc.h> 38 #include <sys/proc.h> 39 #include <sys/syslog.h> 40 #include <sys/conf.h> 41 42 #include <machine/cpu.h> 43 #include <machine/intr.h> 44 45 #include <sh3/frame.h> 46 #include <sh3/wdtreg.h> 47 #include <sh3/wdogvar.h> 48 #include <sh3/exception.h> 49 50 struct wdog_softc { 51 struct device sc_dev; /* generic device structures */ 52 int flags; 53 }; 54 55 static int wdogmatch(struct device *, struct cfdata *, void *); 56 static void wdogattach(struct device *, struct device *, void *); 57 static int wdogintr(void *); 58 59 CFATTACH_DECL(wdog, sizeof(struct wdog_softc), 60 wdogmatch, wdogattach, NULL, NULL); 61 62 extern struct cfdriver wdog_cd; 63 64 dev_type_open(wdogopen); 65 dev_type_close(wdogclose); 66 dev_type_ioctl(wdogioctl); 67 68 const struct cdevsw wdog_cdevsw = { 69 wdogopen, wdogclose, noread, nowrite, wdogioctl, 70 nostop, notty, nopoll, nommap, nokqfilter, 71 }; 72 73 void 74 wdog_wr_cnt(unsigned char x) 75 { 76 77 SHREG_WTCNT_W = WTCNT_W_M | (unsigned short) x; 78 } 79 80 void 81 wdog_wr_csr(unsigned char x) 82 { 83 84 SHREG_WTCSR_W = WTCSR_W_M | (unsigned short) x; 85 } 86 87 static int 88 wdogmatch(struct device *parent, struct cfdata *cfp, void *aux) 89 { 90 91 if (strcmp(cfp->cf_name, "wdog")) 92 return (0); 93 94 return (1); 95 } 96 97 /* 98 * functions for probeing. 99 */ 100 /* ARGSUSED */ 101 static void 102 wdogattach(struct device *parent, struct device *self, void *aux) 103 { 104 struct wdog_softc *sc = (struct wdog_softc *)self; 105 106 sc->flags = 0; 107 108 wdog_wr_csr(WTCSR_WT | WTCSR_CKS_4096); /* default to wt mode */ 109 110 intc_intr_establish(SH_INTEVT_WDT_ITI, IST_LEVEL, IPL_SOFTCLOCK, 111 wdogintr, 0); 112 113 printf("\nwdog0: internal watchdog timer\n"); 114 } 115 116 /*ARGSUSED*/ 117 int 118 wdogopen(dev_t dev, int flag, int mode, struct proc *p) 119 { 120 struct wdog_softc *sc = wdog_cd.cd_devs[0]; /* XXX */ 121 122 if (minor(dev) != 0) 123 return (ENXIO); 124 if (sc->flags & WDOGF_OPEN) 125 return (EBUSY); 126 sc->flags |= WDOGF_OPEN; 127 return (0); 128 } 129 130 /*ARGSUSED*/ 131 int 132 wdogclose(dev_t dev, int flag, int mode, struct proc *p) 133 { 134 struct wdog_softc *sc = wdog_cd.cd_devs[0]; /* XXX */ 135 136 if (sc->flags & WDOGF_OPEN) 137 sc->flags = 0; 138 139 return (0); 140 } 141 142 extern unsigned int maxwdog; 143 144 /*ARGSUSED*/ 145 int 146 wdogioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) 147 { 148 int error = 0; 149 int request; 150 151 switch (cmd) { 152 case SIOWDOGSETMODE: 153 request = *(int *)data; 154 155 switch (request) { 156 case WDOGM_RESET: 157 wdog_wr_csr(SHREG_WTCSR_R | WTCSR_WT); 158 break; 159 case WDOGM_INTR: 160 wdog_wr_csr(SHREG_WTCSR_R & ~WTCSR_WT); 161 break; 162 default: 163 error = EINVAL; 164 break; 165 } 166 break; 167 case SIORESETWDOG: 168 wdog_wr_cnt(0); /* reset to zero */ 169 break; 170 case SIOSTARTWDOG: 171 wdog_wr_csr(WTCSR_WT | WTCSR_CKS_4096); 172 wdog_wr_cnt(0); /* reset to zero */ 173 wdog_wr_csr(SHREG_WTCSR_R | WTCSR_TME); /* start!!! */ 174 break; 175 case SIOSTOPWDOG: 176 wdog_wr_csr(SHREG_WTCSR_R & ~WTCSR_TME); /* stop */ 177 break; 178 case SIOSETWDOG: 179 request = *(int *)data; 180 181 if (request > 2) { 182 error = EINVAL; 183 break; 184 } 185 break; 186 default: 187 error = EINVAL; 188 break; 189 } 190 191 return (error); 192 } 193 194 int 195 wdogintr(void *arg) 196 { 197 struct trapframe *frame = arg; 198 199 wdog_wr_csr(SHREG_WTCSR_R & ~WTCSR_IOVF); /* clear overflow bit */ 200 wdog_wr_cnt(0); /* reset to zero */ 201 printf("wdog trapped: spc = %x\n", frame->tf_spc); 202 203 return (0); 204 } 205