1 /* $NetBSD: wdog.c,v 1.4 2000/10/31 02:04:12 msaitoh 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 41 #include <machine/cpu.h> 42 #include <machine/conf.h> 43 #include <sh3/frame.h> 44 #include <sh3/shbvar.h> 45 #include <sh3/wdtreg.h> 46 #include <sh3/wdogvar.h> 47 48 struct wdog_softc { 49 struct device sc_dev; /* generic device structures */ 50 unsigned int iobase; 51 int flags; 52 }; 53 54 static int wdogmatch __P((struct device *, struct cfdata *, void *)); 55 static void wdogattach __P((struct device *, struct device *, void *)); 56 static int wdogintr __P((void *)); 57 58 struct cfattach wdog_ca = { 59 sizeof(struct wdog_softc), wdogmatch, wdogattach 60 }; 61 62 extern struct cfdriver wdog_cd; 63 64 void 65 wdog_wr_cnt(x) 66 unsigned char x; 67 { 68 69 SHREG_WTCNT_W = WTCNT_W_M | (unsigned short) x; 70 } 71 72 void 73 wdog_wr_csr(x) 74 unsigned char x; 75 { 76 77 SHREG_WTCSR_W = WTCSR_W_M | (unsigned short) x; 78 } 79 80 static int 81 wdogmatch(parent, cfp, aux) 82 struct device *parent; 83 struct cfdata *cfp; 84 void *aux; 85 { 86 struct shb_attach_args *sa = aux; 87 88 if (strcmp(cfp->cf_driver->cd_name, "wdog")) 89 return 0; 90 91 sa->ia_iosize = 4; /* XXX */ 92 93 return (1); 94 } 95 96 /* 97 * functions for probeing. 98 */ 99 /* ARGSUSED */ 100 static void 101 wdogattach(parent, self, aux) 102 struct device *parent, *self; 103 void *aux; 104 { 105 struct wdog_softc *sc = (struct wdog_softc *)self; 106 struct shb_attach_args *sa = aux; 107 108 sc->iobase = sa->ia_iobase; 109 sc->flags = 0; 110 111 wdog_wr_csr(WTCSR_WT | WTCSR_CKS_4096); /* default to wt mode */ 112 113 shb_intr_establish(WDOG_IRQ, IST_EDGE, IPL_SOFTCLOCK, wdogintr, 0); 114 115 printf("\nwdog0: internal watchdog timer\n"); 116 } 117 118 /*ARGSUSED*/ 119 int 120 wdogopen(dev, flag, mode, p) 121 dev_t dev; 122 int flag, mode; 123 struct proc *p; 124 { 125 struct wdog_softc *sc = wdog_cd.cd_devs[0]; /* XXX */ 126 127 if (minor(dev) != 0) 128 return (ENXIO); 129 if (sc->flags & WDOGF_OPEN) 130 return (EBUSY); 131 sc->flags |= WDOGF_OPEN; 132 return (0); 133 } 134 135 /*ARGSUSED*/ 136 int 137 wdogclose(dev, flag, mode, p) 138 dev_t dev; 139 int flag, mode; 140 struct proc *p; 141 { 142 struct wdog_softc *sc = wdog_cd.cd_devs[0]; /* XXX */ 143 144 if (sc->flags & WDOGF_OPEN) 145 sc->flags = 0; 146 147 return (0); 148 } 149 150 extern unsigned int maxwdog; 151 152 /*ARGSUSED*/ 153 int 154 wdogioctl (dev, cmd, data, flag, p) 155 dev_t dev; 156 u_long cmd; 157 caddr_t data; 158 int flag; 159 struct proc *p; 160 { 161 int error = 0; 162 int request; 163 164 switch (cmd) { 165 case SIOWDOGSETMODE: 166 request = *(int *)data; 167 168 switch (request) { 169 case WDOGM_RESET: 170 wdog_wr_csr(SHREG_WTCSR_R | WTCSR_WT); 171 break; 172 case WDOGM_INTR: 173 wdog_wr_csr(SHREG_WTCSR_R & ~WTCSR_WT); 174 break; 175 default: 176 error = EINVAL; 177 break; 178 } 179 break; 180 case SIORESETWDOG: 181 wdog_wr_cnt(0); /* reset to zero */ 182 break; 183 case SIOSTARTWDOG: 184 wdog_wr_csr(WTCSR_WT | WTCSR_CKS_4096); 185 wdog_wr_cnt(0); /* reset to zero */ 186 wdog_wr_csr(SHREG_WTCSR_R | WTCSR_TME); /* start!!! */ 187 break; 188 case SIOSTOPWDOG: 189 wdog_wr_csr(SHREG_WTCSR_R & ~WTCSR_TME); /* stop */ 190 break; 191 case SIOSETWDOG: 192 request = *(int *)data; 193 194 if (request > 2) { 195 error = EINVAL; 196 break; 197 } 198 break; 199 default: 200 error = EINVAL; 201 break; 202 } 203 204 return (error); 205 } 206 207 int 208 wdogintr(arg) 209 void *arg; 210 { 211 struct trapframe *frame = arg; 212 213 wdog_wr_csr(SHREG_WTCSR_R & ~WTCSR_IOVF); /* clear overflow bit */ 214 wdog_wr_cnt(0); /* reset to zero */ 215 printf("wdog trapped: spc = %x\n", frame->tf_spc); 216 217 return (0); 218 } 219