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