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