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