1 1.20 andvar /* $NetBSD: wdog.c,v 1.20 2025/01/27 21:20:25 andvar Exp $ */ 2 1.2 msaitoh 3 1.2 msaitoh /*- 4 1.2 msaitoh * Copyright (C) 2000 SAITOH Masanobu. All rights reserved. 5 1.2 msaitoh * 6 1.2 msaitoh * Redistribution and use in source and binary forms, with or without 7 1.2 msaitoh * modification, are permitted provided that the following conditions 8 1.2 msaitoh * are met: 9 1.2 msaitoh * 1. Redistributions of source code must retain the above copyright 10 1.2 msaitoh * notice, this list of conditions and the following disclaimer. 11 1.2 msaitoh * 2. Redistributions in binary form must reproduce the above copyright 12 1.2 msaitoh * notice, this list of conditions and the following disclaimer in the 13 1.2 msaitoh * documentation and/or other materials provided with the distribution. 14 1.2 msaitoh * 3. The name of the author may not be used to endorse or promote products 15 1.2 msaitoh * derived from this software without specific prior written permission. 16 1.2 msaitoh * 17 1.2 msaitoh * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 1.2 msaitoh * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 1.2 msaitoh * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 1.2 msaitoh * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 1.2 msaitoh * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 1.2 msaitoh * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 1.2 msaitoh * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 1.2 msaitoh * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 1.2 msaitoh * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 1.2 msaitoh * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 1.2 msaitoh */ 28 1.13 lukem 29 1.13 lukem #include <sys/cdefs.h> 30 1.20 andvar __KERNEL_RCSID(0, "$NetBSD: wdog.c,v 1.20 2025/01/27 21:20:25 andvar Exp $"); 31 1.2 msaitoh 32 1.1 msaitoh #include <sys/param.h> 33 1.1 msaitoh #include <sys/buf.h> 34 1.1 msaitoh #include <sys/systm.h> 35 1.1 msaitoh #include <sys/kernel.h> 36 1.1 msaitoh #include <sys/uio.h> 37 1.1 msaitoh #include <sys/device.h> 38 1.1 msaitoh #include <sys/fcntl.h> 39 1.1 msaitoh #include <sys/ioctl.h> 40 1.1 msaitoh #include <sys/proc.h> 41 1.1 msaitoh #include <sys/syslog.h> 42 1.7 gehenna #include <sys/conf.h> 43 1.1 msaitoh 44 1.1 msaitoh #include <machine/cpu.h> 45 1.6 uch #include <machine/intr.h> 46 1.6 uch 47 1.4 msaitoh #include <sh3/frame.h> 48 1.1 msaitoh #include <sh3/wdtreg.h> 49 1.1 msaitoh #include <sh3/wdogvar.h> 50 1.6 uch #include <sh3/exception.h> 51 1.1 msaitoh 52 1.1 msaitoh struct wdog_softc { 53 1.16 uwe device_t sc_dev; 54 1.1 msaitoh int flags; 55 1.1 msaitoh }; 56 1.1 msaitoh 57 1.16 uwe static int wdogmatch(device_t, cfdata_t, void *); 58 1.16 uwe static void wdogattach(device_t, device_t, void *); 59 1.5 uch static int wdogintr(void *); 60 1.1 msaitoh 61 1.16 uwe CFATTACH_DECL_NEW(wdog, sizeof(struct wdog_softc), 62 1.11 thorpej wdogmatch, wdogattach, NULL, NULL); 63 1.1 msaitoh 64 1.1 msaitoh extern struct cfdriver wdog_cd; 65 1.7 gehenna 66 1.7 gehenna dev_type_open(wdogopen); 67 1.7 gehenna dev_type_close(wdogclose); 68 1.7 gehenna dev_type_ioctl(wdogioctl); 69 1.7 gehenna 70 1.7 gehenna const struct cdevsw wdog_cdevsw = { 71 1.17 dholland .d_open = wdogopen, 72 1.17 dholland .d_close = wdogclose, 73 1.17 dholland .d_read = noread, 74 1.17 dholland .d_write = nowrite, 75 1.17 dholland .d_ioctl = wdogioctl, 76 1.17 dholland .d_stop = nostop, 77 1.17 dholland .d_tty = notty, 78 1.17 dholland .d_poll = nopoll, 79 1.17 dholland .d_mmap = nommap, 80 1.17 dholland .d_kqfilter = nokqfilter, 81 1.18 dholland .d_discard = nodiscard, 82 1.17 dholland .d_flag = 0 83 1.7 gehenna }; 84 1.1 msaitoh 85 1.1 msaitoh void 86 1.5 uch wdog_wr_cnt(unsigned char x) 87 1.1 msaitoh { 88 1.1 msaitoh 89 1.1 msaitoh SHREG_WTCNT_W = WTCNT_W_M | (unsigned short) x; 90 1.1 msaitoh } 91 1.1 msaitoh 92 1.1 msaitoh void 93 1.5 uch wdog_wr_csr(unsigned char x) 94 1.1 msaitoh { 95 1.1 msaitoh 96 1.1 msaitoh SHREG_WTCSR_W = WTCSR_W_M | (unsigned short) x; 97 1.1 msaitoh } 98 1.1 msaitoh 99 1.1 msaitoh static int 100 1.16 uwe wdogmatch(device_t parent, cfdata_t cfp, void *aux) 101 1.1 msaitoh { 102 1.1 msaitoh 103 1.8 thorpej if (strcmp(cfp->cf_name, "wdog")) 104 1.6 uch return (0); 105 1.1 msaitoh 106 1.1 msaitoh return (1); 107 1.1 msaitoh } 108 1.1 msaitoh 109 1.1 msaitoh /* 110 1.20 andvar * functions for probing. 111 1.1 msaitoh */ 112 1.1 msaitoh /* ARGSUSED */ 113 1.1 msaitoh static void 114 1.16 uwe wdogattach(device_t parent, device_t self, void *aux) 115 1.1 msaitoh { 116 1.16 uwe struct wdog_softc *sc; 117 1.1 msaitoh 118 1.16 uwe sc = device_private(self); 119 1.16 uwe sc->sc_dev = self; 120 1.16 uwe 121 1.16 uwe aprint_naive("\n"); 122 1.16 uwe aprint_normal(": internal watchdog timer\n"); 123 1.1 msaitoh 124 1.4 msaitoh wdog_wr_csr(WTCSR_WT | WTCSR_CKS_4096); /* default to wt mode */ 125 1.4 msaitoh 126 1.6 uch intc_intr_establish(SH_INTEVT_WDT_ITI, IST_LEVEL, IPL_SOFTCLOCK, 127 1.6 uch wdogintr, 0); 128 1.1 msaitoh } 129 1.1 msaitoh 130 1.1 msaitoh /*ARGSUSED*/ 131 1.1 msaitoh int 132 1.14 christos wdogopen(dev_t dev, int flag, int mode, struct lwp *l) 133 1.1 msaitoh { 134 1.16 uwe struct wdog_softc *sc; 135 1.1 msaitoh 136 1.16 uwe sc = device_lookup_private(&wdog_cd, minor(dev)); 137 1.16 uwe if (sc == NULL) 138 1.1 msaitoh return (ENXIO); 139 1.16 uwe 140 1.1 msaitoh if (sc->flags & WDOGF_OPEN) 141 1.1 msaitoh return (EBUSY); 142 1.1 msaitoh sc->flags |= WDOGF_OPEN; 143 1.1 msaitoh return (0); 144 1.1 msaitoh } 145 1.1 msaitoh 146 1.1 msaitoh /*ARGSUSED*/ 147 1.1 msaitoh int 148 1.14 christos wdogclose(dev_t dev, int flag, int mode, struct lwp *l) 149 1.1 msaitoh { 150 1.16 uwe struct wdog_softc *sc; 151 1.16 uwe 152 1.16 uwe sc = device_lookup_private(&wdog_cd, minor(dev)); 153 1.1 msaitoh 154 1.1 msaitoh if (sc->flags & WDOGF_OPEN) 155 1.1 msaitoh sc->flags = 0; 156 1.1 msaitoh 157 1.1 msaitoh return (0); 158 1.1 msaitoh } 159 1.1 msaitoh 160 1.1 msaitoh extern unsigned int maxwdog; 161 1.1 msaitoh 162 1.1 msaitoh /*ARGSUSED*/ 163 1.1 msaitoh int 164 1.15 christos wdogioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) 165 1.1 msaitoh { 166 1.1 msaitoh int error = 0; 167 1.1 msaitoh int request; 168 1.1 msaitoh 169 1.1 msaitoh switch (cmd) { 170 1.4 msaitoh case SIOWDOGSETMODE: 171 1.4 msaitoh request = *(int *)data; 172 1.4 msaitoh 173 1.4 msaitoh switch (request) { 174 1.4 msaitoh case WDOGM_RESET: 175 1.4 msaitoh wdog_wr_csr(SHREG_WTCSR_R | WTCSR_WT); 176 1.4 msaitoh break; 177 1.4 msaitoh case WDOGM_INTR: 178 1.4 msaitoh wdog_wr_csr(SHREG_WTCSR_R & ~WTCSR_WT); 179 1.4 msaitoh break; 180 1.4 msaitoh default: 181 1.4 msaitoh error = EINVAL; 182 1.4 msaitoh break; 183 1.4 msaitoh } 184 1.4 msaitoh break; 185 1.1 msaitoh case SIORESETWDOG: 186 1.1 msaitoh wdog_wr_cnt(0); /* reset to zero */ 187 1.1 msaitoh break; 188 1.1 msaitoh case SIOSTARTWDOG: 189 1.1 msaitoh wdog_wr_csr(WTCSR_WT | WTCSR_CKS_4096); 190 1.1 msaitoh wdog_wr_cnt(0); /* reset to zero */ 191 1.1 msaitoh wdog_wr_csr(SHREG_WTCSR_R | WTCSR_TME); /* start!!! */ 192 1.1 msaitoh break; 193 1.1 msaitoh case SIOSTOPWDOG: 194 1.1 msaitoh wdog_wr_csr(SHREG_WTCSR_R & ~WTCSR_TME); /* stop */ 195 1.1 msaitoh break; 196 1.1 msaitoh case SIOSETWDOG: 197 1.1 msaitoh request = *(int *)data; 198 1.1 msaitoh 199 1.1 msaitoh if (request > 2) { 200 1.1 msaitoh error = EINVAL; 201 1.1 msaitoh break; 202 1.1 msaitoh } 203 1.1 msaitoh break; 204 1.1 msaitoh default: 205 1.1 msaitoh error = EINVAL; 206 1.1 msaitoh break; 207 1.1 msaitoh } 208 1.1 msaitoh 209 1.1 msaitoh return (error); 210 1.4 msaitoh } 211 1.4 msaitoh 212 1.4 msaitoh int 213 1.5 uch wdogintr(void *arg) 214 1.4 msaitoh { 215 1.4 msaitoh struct trapframe *frame = arg; 216 1.4 msaitoh 217 1.4 msaitoh wdog_wr_csr(SHREG_WTCSR_R & ~WTCSR_IOVF); /* clear overflow bit */ 218 1.4 msaitoh wdog_wr_cnt(0); /* reset to zero */ 219 1.4 msaitoh printf("wdog trapped: spc = %x\n", frame->tf_spc); 220 1.4 msaitoh 221 1.4 msaitoh return (0); 222 1.1 msaitoh } 223