1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /******************************************************************************
3 *
4 * (C)Copyright 1998,1999 SysKonnect,
5 * a business unit of Schneider & Koch & Co. Datensysteme GmbH.
6 *
7 * See the file "skfddi.c" for further information.
8 *
9 * The information in this file is provided "AS IS" without warranty.
10 *
11 ******************************************************************************/
12
13 /*
14 * Timer Driver for FBI board (timer chip 82C54)
15 */
16
17 /*
18 * Modifications:
19 *
20 * 28-Jun-1994 sw Edit v1.6.
21 * MCA: Added support for the SK-NET FDDI-FM2 adapter. The
22 * following functions have been added(+) or modified(*):
23 * hwt_start(*), hwt_stop(*), hwt_restart(*), hwt_read(*)
24 */
25
26 #include "h/types.h"
27 #include "h/fddi.h"
28 #include "h/smc.h"
29
30 /*
31 * Prototypes of local functions.
32 */
33 /* 28-Jun-1994 sw - Note: hwt_restart() is also used in module 'drvfbi.c'. */
34 /*static void hwt_restart() ; */
35
36 /************************
37 *
38 * hwt_start
39 *
40 * Start hardware timer (clock ticks are 16us).
41 *
42 * void hwt_start(
43 * struct s_smc *smc,
44 * u_long time) ;
45 * In
46 * smc - A pointer to the SMT Context structure.
47 *
48 * time - The time in units of 16us to load the timer with.
49 * Out
50 * Nothing.
51 *
52 ************************/
53 #define HWT_MAX (65000)
54
hwt_start(struct s_smc * smc,u_long time)55 void hwt_start(struct s_smc *smc, u_long time)
56 {
57 u_short cnt ;
58
59 if (time > HWT_MAX)
60 time = HWT_MAX ;
61
62 smc->hw.t_start = time ;
63 smc->hw.t_stop = 0L ;
64
65 cnt = (u_short)time ;
66 /*
67 * if time < 16 us
68 * time = 16 us
69 */
70 if (!cnt)
71 cnt++ ;
72
73 outpd(ADDR(B2_TI_INI), (u_long) cnt * 200) ; /* Load timer value. */
74 outpw(ADDR(B2_TI_CRTL), TIM_START) ; /* Start timer. */
75
76 smc->hw.timer_activ = TRUE ;
77 }
78
79 /************************
80 *
81 * hwt_stop
82 *
83 * Stop hardware timer.
84 *
85 * void hwt_stop(
86 * struct s_smc *smc) ;
87 * In
88 * smc - A pointer to the SMT Context structure.
89 * Out
90 * Nothing.
91 *
92 ************************/
hwt_stop(struct s_smc * smc)93 void hwt_stop(struct s_smc *smc)
94 {
95 outpw(ADDR(B2_TI_CRTL), TIM_STOP) ;
96 outpw(ADDR(B2_TI_CRTL), TIM_CL_IRQ) ;
97
98 smc->hw.timer_activ = FALSE ;
99 }
100
101 /************************
102 *
103 * hwt_init
104 *
105 * Initialize hardware timer.
106 *
107 * void hwt_init(
108 * struct s_smc *smc) ;
109 * In
110 * smc - A pointer to the SMT Context structure.
111 * Out
112 * Nothing.
113 *
114 ************************/
hwt_init(struct s_smc * smc)115 void hwt_init(struct s_smc *smc)
116 {
117 smc->hw.t_start = 0 ;
118 smc->hw.t_stop = 0 ;
119 smc->hw.timer_activ = FALSE ;
120
121 hwt_restart(smc) ;
122 }
123
124 /************************
125 *
126 * hwt_restart
127 *
128 * Clear timer interrupt.
129 *
130 * void hwt_restart(
131 * struct s_smc *smc) ;
132 * In
133 * smc - A pointer to the SMT Context structure.
134 * Out
135 * Nothing.
136 *
137 ************************/
hwt_restart(struct s_smc * smc)138 void hwt_restart(struct s_smc *smc)
139 {
140 hwt_stop(smc) ;
141 }
142
143 /************************
144 *
145 * hwt_read
146 *
147 * Stop hardware timer and read time elapsed since last start.
148 *
149 * u_long hwt_read(smc) ;
150 * In
151 * smc - A pointer to the SMT Context structure.
152 * Out
153 * The elapsed time since last start in units of 16us.
154 *
155 ************************/
hwt_read(struct s_smc * smc)156 u_long hwt_read(struct s_smc *smc)
157 {
158 u_short tr ;
159 u_long is ;
160
161 if (smc->hw.timer_activ) {
162 hwt_stop(smc) ;
163 tr = (u_short)((inpd(ADDR(B2_TI_VAL))/200) & 0xffff) ;
164
165 is = GET_ISR() ;
166 /* Check if timer expired (or wraparound). */
167 if ((tr > smc->hw.t_start) || (is & IS_TIMINT)) {
168 hwt_restart(smc) ;
169 smc->hw.t_stop = smc->hw.t_start ;
170 }
171 else
172 smc->hw.t_stop = smc->hw.t_start - tr ;
173 }
174 return smc->hw.t_stop;
175 }
176
177 #ifdef PCI
178 /************************
179 *
180 * hwt_quick_read
181 *
182 * Stop hardware timer and read timer value and start the timer again.
183 *
184 * u_long hwt_read(smc) ;
185 * In
186 * smc - A pointer to the SMT Context structure.
187 * Out
188 * current timer value in units of 80ns.
189 *
190 ************************/
hwt_quick_read(struct s_smc * smc)191 u_long hwt_quick_read(struct s_smc *smc)
192 {
193 u_long interval ;
194 u_long time ;
195
196 interval = inpd(ADDR(B2_TI_INI)) ;
197 outpw(ADDR(B2_TI_CRTL), TIM_STOP) ;
198 time = inpd(ADDR(B2_TI_VAL)) ;
199 outpd(ADDR(B2_TI_INI),time) ;
200 outpw(ADDR(B2_TI_CRTL), TIM_START) ;
201 outpd(ADDR(B2_TI_INI),interval) ;
202
203 return time;
204 }
205
206 /************************
207 *
208 * hwt_wait_time(smc,start,duration)
209 *
210 * This function returnes after the amount of time is elapsed
211 * since the start time.
212 *
213 * para start start time
214 * duration time to wait
215 *
216 * NOTE: The function will return immediately, if the timer is not
217 * started
218 ************************/
hwt_wait_time(struct s_smc * smc,u_long start,long int duration)219 void hwt_wait_time(struct s_smc *smc, u_long start, long int duration)
220 {
221 long diff ;
222 long interval ;
223 int wrapped ;
224
225 /*
226 * check if timer is running
227 */
228 if (smc->hw.timer_activ == FALSE ||
229 hwt_quick_read(smc) == hwt_quick_read(smc)) {
230 return ;
231 }
232
233 interval = inpd(ADDR(B2_TI_INI)) ;
234 if (interval > duration) {
235 do {
236 diff = (long)(start - hwt_quick_read(smc)) ;
237 if (diff < 0) {
238 diff += interval ;
239 }
240 } while (diff <= duration) ;
241 }
242 else {
243 diff = interval ;
244 wrapped = 0 ;
245 do {
246 if (!wrapped) {
247 if (hwt_quick_read(smc) >= start) {
248 diff += interval ;
249 wrapped = 1 ;
250 }
251 }
252 else {
253 if (hwt_quick_read(smc) < start) {
254 wrapped = 0 ;
255 }
256 }
257 } while (diff <= duration) ;
258 }
259 }
260 #endif
261
262