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