xref: /openbmc/linux/drivers/net/fddi/skfp/hwt.c (revision cdd38c5f1ce4398ec58fec95904b75824daab7b5)
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