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