1 /* $NetBSD: hat.c,v 1.7 2021/04/30 02:11:37 thorpej Exp $ */
2
3 /*
4 * Copyright 1997
5 * Digital Equipment Corporation. All rights reserved.
6 *
7 * This software is furnished under license and may be used and
8 * copied only in accordance with the following terms and conditions.
9 * Subject to these conditions, you may download, copy, install,
10 * use, modify and distribute this software in source and/or binary
11 * form. No title or ownership is transferred hereby.
12 *
13 * 1) Any source code used, modified or distributed must reproduce
14 * and retain this copyright notice and list of conditions as
15 * they appear in the source file.
16 *
17 * 2) No right is granted to use any trade name, trademark, or logo of
18 * Digital Equipment Corporation. Neither the "Digital Equipment
19 * Corporation" name nor any trademark or logo of Digital Equipment
20 * Corporation may be used to endorse or promote products derived
21 * from this software without the prior written permission of
22 * Digital Equipment Corporation.
23 *
24 * 3) This software is provided "AS-IS" and any express or implied
25 * warranties, including but not limited to, any implied warranties
26 * of merchantability, fitness for a particular purpose, or
27 * non-infringement are disclaimed. In no event shall DIGITAL be
28 * liable for any damages whatsoever, and in particular, DIGITAL
29 * shall not be liable for special, indirect, consequential, or
30 * incidental damages or damages for lost profits, loss of
31 * revenue or loss of use, whether such damages arise in contract,
32 * negligence, tort, under statute, in equity, at law or otherwise,
33 * even if advised of the possibility of such damage.
34 */
35
36 /*
37 * hat.c
38 *
39 * implementation of high-availability timer on SHARK
40 *
41 * Created : 19/05/97
42 */
43
44 #include <sys/cdefs.h>
45 __KERNEL_RCSID(0, "$NetBSD: hat.c,v 1.7 2021/04/30 02:11:37 thorpej Exp $");
46
47 #include <sys/param.h>
48 #include <sys/systm.h>
49 #include <sys/time.h>
50 #include <sys/kernel.h>
51 #include <sys/device.h>
52
53 #include <arm/fiq.h>
54
55 #include <machine/cpu.h>
56 #include <machine/intr.h>
57 #include <machine/pio.h>
58 #include <arm/cpufunc.h>
59
60 #include <dev/ic/i8253reg.h>
61
62 #include <dev/isa/isareg.h>
63 #include <dev/isa/isavar.h>
64
65 #include "isadma.h"
66
67 #include <shark/shark/shark_fiq.h>
68 #include <shark/shark/sequoia.h>
69 #include <shark/shark/hat.h>
70
71 static int hatOn = 0;
72
73 /* interface to high-availability timer */
74
75 static void hatClkCount(int);
76 static void hatEnableSWTCH(void);
77
78 static void (*hatWedgeFn)(int);
79
80 extern struct fiqregs shark_fiqregs;
81
82 int
hatClkOff(void)83 hatClkOff(void)
84 {
85 u_int16_t seqReg;
86
87 if (!hatOn) return -1;
88 hatOn = 0;
89 hatWedgeFn = NULL;
90
91 sequoiaLock();
92
93 /* disable the SWTCH pin */
94
95 sequoiaRead(PMC_PMCMCR2_REG, &seqReg);
96 sequoiaWrite(PMC_PMCMCR2_REG, seqReg | (PMCMCR2_M_SWTCHEN));
97
98 sequoiaUnlock();
99
100 /* turn off timer 2 */
101 outb(ATSR_REG1_REG,
102 inb(ATSR_REG1_REG) & ~((REG1_M_TMR2EN) | (REG1_M_SPKREN)));
103
104 fiq_getregs(&shark_fiqregs);
105
106 /* get rid of the C routine and stack */
107 shark_fiqregs.fr_r9 = 0;
108 shark_fiqregs.fr_r13 = 0;
109
110 fiq_setregs(&shark_fiqregs);
111 #if (NISADMA > 0)
112 isa_dmathaw(&isa_chipset_tag); /* XXX */
113 #endif
114
115 return 0;
116 }
117
118 int
hatClkOn(int count,void (* hatFn)(int),int arg,unsigned char * stack,void (* wedgeFn)(int))119 hatClkOn(int count, void (*hatFn)(int), int arg,
120 unsigned char *stack, void (*wedgeFn)(int))
121 {
122 u_int16_t seqReg;
123
124 if (hatOn)
125 return -1;
126
127 hatWedgeFn = wedgeFn;
128
129 #if (NISADMA > 0)
130 isa_dmafreeze(&isa_chipset_tag); /* XXX */
131 #endif
132
133 fiq_getregs(&shark_fiqregs);
134
135 /* set the C routine and stack */
136 shark_fiqregs.fr_r9 = (u_int)hatFn;
137 shark_fiqregs.fr_r10 = (u_int)arg;
138 shark_fiqregs.fr_r13 = (u_int)stack;
139
140 fiq_setregs(&shark_fiqregs);
141
142 sequoiaLock();
143
144 /* no debounce on SWTCH */
145 sequoiaRead(PMC_DBCR_REG, &seqReg);
146 sequoiaWrite(PMC_DBCR_REG, seqReg | DBCR_M_DBDIS0);
147
148 hatEnableSWTCH(); /* enable the SWTCH -> PMI logic */
149
150 /* turn on timer 2 */
151 outb(ATSR_REG1_REG,
152 inb(ATSR_REG1_REG) | (REG1_M_TMR2EN) | (REG1_M_SPKREN));
153
154 /* start timer 2 running */
155 hatClkCount(count);
156
157 /* enable the SWTCH pin */
158 sequoiaRead(PMC_PMCMCR2_REG, &seqReg);
159 sequoiaWrite(PMC_PMCMCR2_REG, seqReg | (PMCMCR2_M_SWTCHEN));
160
161 sequoiaUnlock();
162
163 hatOn = 1;
164 return 0;
165 }
166
167
168 int
hatClkAdjust(int count)169 hatClkAdjust(int count)
170 {
171 if (!hatOn)
172 return -1;
173
174 hatClkCount(count);
175 sequoiaLock();
176 hatEnableSWTCH();
177 sequoiaUnlock();
178
179 return 0;
180 }
181
182 static void
hatEnableSWTCH(void)183 hatEnableSWTCH(void)
184 {
185 u_int16_t seqReg;
186
187 KASSERT(sequoiaIsLocked());
188
189 /* SWTCH input causes PMI, not automatic switch to standby mode! */
190 /* clearing bit 9 is bad news. seems to enable PMI from secondary
191 activity timeout! */
192 /* first setting, then clearing this bit seems to unwedge the edge
193 detect logic in the sequoia */
194
195 sequoiaRead(PMC_PMIMCR_REG, &seqReg);
196 sequoiaWrite(PMC_PMIMCR_REG, seqReg | (PMIMCR_M_IMSKSWSTBY));
197 sequoiaWrite(PMC_PMIMCR_REG, seqReg & ~(PMIMCR_M_IMSKSWSTBY));
198 }
199
200 void
hatUnwedge(void)201 hatUnwedge(void)
202 {
203 static int lastFiqsHappened = -1;
204 extern int fiqs_happened;
205
206 if (!hatOn)
207 return;
208
209 if (lastFiqsHappened == fiqs_happened) {
210 sequoiaLock();
211 hatEnableSWTCH();
212 sequoiaUnlock();
213 if (hatWedgeFn)
214 (*hatWedgeFn)(fiqs_happened);
215 } else {
216 lastFiqsHappened = fiqs_happened;
217 }
218 }
219
220 static void
hatClkCount(int count)221 hatClkCount(int count)
222 {
223 u_int savedints;
224
225 savedints = disable_interrupts(I32_bit);
226
227 outb(TIMER_MODE, TIMER_SEL2|TIMER_RATEGEN|TIMER_16BIT);
228 outb(TIMER_CNTR2, count % 256);
229 outb(TIMER_CNTR2, count / 256);
230
231 restore_interrupts(savedints);
232 }
233