1*2874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 233f810b2SJeff Kirsher /****************************************************************************** 333f810b2SJeff Kirsher * 433f810b2SJeff Kirsher * (C)Copyright 1998,1999 SysKonnect, 533f810b2SJeff Kirsher * a business unit of Schneider & Koch & Co. Datensysteme GmbH. 633f810b2SJeff Kirsher * 733f810b2SJeff Kirsher * See the file "skfddi.c" for further information. 833f810b2SJeff Kirsher * 933f810b2SJeff Kirsher * The information in this file is provided "AS IS" without warranty. 1033f810b2SJeff Kirsher * 1133f810b2SJeff Kirsher ******************************************************************************/ 1233f810b2SJeff Kirsher 1333f810b2SJeff Kirsher /* 1433f810b2SJeff Kirsher * Timer Driver for FBI board (timer chip 82C54) 1533f810b2SJeff Kirsher */ 1633f810b2SJeff Kirsher 1733f810b2SJeff Kirsher /* 1833f810b2SJeff Kirsher * Modifications: 1933f810b2SJeff Kirsher * 2033f810b2SJeff Kirsher * 28-Jun-1994 sw Edit v1.6. 2133f810b2SJeff Kirsher * MCA: Added support for the SK-NET FDDI-FM2 adapter. The 2233f810b2SJeff Kirsher * following functions have been added(+) or modified(*): 2333f810b2SJeff Kirsher * hwt_start(*), hwt_stop(*), hwt_restart(*), hwt_read(*) 2433f810b2SJeff Kirsher */ 2533f810b2SJeff Kirsher 2633f810b2SJeff Kirsher #include "h/types.h" 2733f810b2SJeff Kirsher #include "h/fddi.h" 2833f810b2SJeff Kirsher #include "h/smc.h" 2933f810b2SJeff Kirsher 3033f810b2SJeff Kirsher #ifndef lint 3133f810b2SJeff Kirsher static const char ID_sccs[] = "@(#)hwt.c 1.13 97/04/23 (C) SK " ; 3233f810b2SJeff Kirsher #endif 3333f810b2SJeff Kirsher 3433f810b2SJeff Kirsher /* 3533f810b2SJeff Kirsher * Prototypes of local functions. 3633f810b2SJeff Kirsher */ 3733f810b2SJeff Kirsher /* 28-Jun-1994 sw - Note: hwt_restart() is also used in module 'drvfbi.c'. */ 3833f810b2SJeff Kirsher /*static void hwt_restart() ; */ 3933f810b2SJeff Kirsher 4033f810b2SJeff Kirsher /************************ 4133f810b2SJeff Kirsher * 4233f810b2SJeff Kirsher * hwt_start 4333f810b2SJeff Kirsher * 4433f810b2SJeff Kirsher * Start hardware timer (clock ticks are 16us). 4533f810b2SJeff Kirsher * 4633f810b2SJeff Kirsher * void hwt_start( 4733f810b2SJeff Kirsher * struct s_smc *smc, 4833f810b2SJeff Kirsher * u_long time) ; 4933f810b2SJeff Kirsher * In 5033f810b2SJeff Kirsher * smc - A pointer to the SMT Context structure. 5133f810b2SJeff Kirsher * 5233f810b2SJeff Kirsher * time - The time in units of 16us to load the timer with. 5333f810b2SJeff Kirsher * Out 5433f810b2SJeff Kirsher * Nothing. 5533f810b2SJeff Kirsher * 5633f810b2SJeff Kirsher ************************/ 5733f810b2SJeff Kirsher #define HWT_MAX (65000) 5833f810b2SJeff Kirsher 5933f810b2SJeff Kirsher void hwt_start(struct s_smc *smc, u_long time) 6033f810b2SJeff Kirsher { 6133f810b2SJeff Kirsher u_short cnt ; 6233f810b2SJeff Kirsher 6333f810b2SJeff Kirsher if (time > HWT_MAX) 6433f810b2SJeff Kirsher time = HWT_MAX ; 6533f810b2SJeff Kirsher 6633f810b2SJeff Kirsher smc->hw.t_start = time ; 6733f810b2SJeff Kirsher smc->hw.t_stop = 0L ; 6833f810b2SJeff Kirsher 6933f810b2SJeff Kirsher cnt = (u_short)time ; 7033f810b2SJeff Kirsher /* 7133f810b2SJeff Kirsher * if time < 16 us 7233f810b2SJeff Kirsher * time = 16 us 7333f810b2SJeff Kirsher */ 7433f810b2SJeff Kirsher if (!cnt) 7533f810b2SJeff Kirsher cnt++ ; 7633f810b2SJeff Kirsher 7733f810b2SJeff Kirsher outpd(ADDR(B2_TI_INI), (u_long) cnt * 200) ; /* Load timer value. */ 7833f810b2SJeff Kirsher outpw(ADDR(B2_TI_CRTL), TIM_START) ; /* Start timer. */ 7933f810b2SJeff Kirsher 8033f810b2SJeff Kirsher smc->hw.timer_activ = TRUE ; 8133f810b2SJeff Kirsher } 8233f810b2SJeff Kirsher 8333f810b2SJeff Kirsher /************************ 8433f810b2SJeff Kirsher * 8533f810b2SJeff Kirsher * hwt_stop 8633f810b2SJeff Kirsher * 8733f810b2SJeff Kirsher * Stop hardware timer. 8833f810b2SJeff Kirsher * 8933f810b2SJeff Kirsher * void hwt_stop( 9033f810b2SJeff Kirsher * struct s_smc *smc) ; 9133f810b2SJeff Kirsher * In 9233f810b2SJeff Kirsher * smc - A pointer to the SMT Context structure. 9333f810b2SJeff Kirsher * Out 9433f810b2SJeff Kirsher * Nothing. 9533f810b2SJeff Kirsher * 9633f810b2SJeff Kirsher ************************/ 9733f810b2SJeff Kirsher void hwt_stop(struct s_smc *smc) 9833f810b2SJeff Kirsher { 9933f810b2SJeff Kirsher outpw(ADDR(B2_TI_CRTL), TIM_STOP) ; 10033f810b2SJeff Kirsher outpw(ADDR(B2_TI_CRTL), TIM_CL_IRQ) ; 10133f810b2SJeff Kirsher 10233f810b2SJeff Kirsher smc->hw.timer_activ = FALSE ; 10333f810b2SJeff Kirsher } 10433f810b2SJeff Kirsher 10533f810b2SJeff Kirsher /************************ 10633f810b2SJeff Kirsher * 10733f810b2SJeff Kirsher * hwt_init 10833f810b2SJeff Kirsher * 10933f810b2SJeff Kirsher * Initialize hardware timer. 11033f810b2SJeff Kirsher * 11133f810b2SJeff Kirsher * void hwt_init( 11233f810b2SJeff Kirsher * struct s_smc *smc) ; 11333f810b2SJeff Kirsher * In 11433f810b2SJeff Kirsher * smc - A pointer to the SMT Context structure. 11533f810b2SJeff Kirsher * Out 11633f810b2SJeff Kirsher * Nothing. 11733f810b2SJeff Kirsher * 11833f810b2SJeff Kirsher ************************/ 11933f810b2SJeff Kirsher void hwt_init(struct s_smc *smc) 12033f810b2SJeff Kirsher { 12133f810b2SJeff Kirsher smc->hw.t_start = 0 ; 12233f810b2SJeff Kirsher smc->hw.t_stop = 0 ; 12333f810b2SJeff Kirsher smc->hw.timer_activ = FALSE ; 12433f810b2SJeff Kirsher 12533f810b2SJeff Kirsher hwt_restart(smc) ; 12633f810b2SJeff Kirsher } 12733f810b2SJeff Kirsher 12833f810b2SJeff Kirsher /************************ 12933f810b2SJeff Kirsher * 13033f810b2SJeff Kirsher * hwt_restart 13133f810b2SJeff Kirsher * 13233f810b2SJeff Kirsher * Clear timer interrupt. 13333f810b2SJeff Kirsher * 13433f810b2SJeff Kirsher * void hwt_restart( 13533f810b2SJeff Kirsher * struct s_smc *smc) ; 13633f810b2SJeff Kirsher * In 13733f810b2SJeff Kirsher * smc - A pointer to the SMT Context structure. 13833f810b2SJeff Kirsher * Out 13933f810b2SJeff Kirsher * Nothing. 14033f810b2SJeff Kirsher * 14133f810b2SJeff Kirsher ************************/ 14233f810b2SJeff Kirsher void hwt_restart(struct s_smc *smc) 14333f810b2SJeff Kirsher { 14433f810b2SJeff Kirsher hwt_stop(smc) ; 14533f810b2SJeff Kirsher } 14633f810b2SJeff Kirsher 14733f810b2SJeff Kirsher /************************ 14833f810b2SJeff Kirsher * 14933f810b2SJeff Kirsher * hwt_read 15033f810b2SJeff Kirsher * 15133f810b2SJeff Kirsher * Stop hardware timer and read time elapsed since last start. 15233f810b2SJeff Kirsher * 15333f810b2SJeff Kirsher * u_long hwt_read(smc) ; 15433f810b2SJeff Kirsher * In 15533f810b2SJeff Kirsher * smc - A pointer to the SMT Context structure. 15633f810b2SJeff Kirsher * Out 15733f810b2SJeff Kirsher * The elapsed time since last start in units of 16us. 15833f810b2SJeff Kirsher * 15933f810b2SJeff Kirsher ************************/ 16033f810b2SJeff Kirsher u_long hwt_read(struct s_smc *smc) 16133f810b2SJeff Kirsher { 16233f810b2SJeff Kirsher u_short tr ; 16333f810b2SJeff Kirsher u_long is ; 16433f810b2SJeff Kirsher 16533f810b2SJeff Kirsher if (smc->hw.timer_activ) { 16633f810b2SJeff Kirsher hwt_stop(smc) ; 16733f810b2SJeff Kirsher tr = (u_short)((inpd(ADDR(B2_TI_VAL))/200) & 0xffff) ; 16833f810b2SJeff Kirsher 16933f810b2SJeff Kirsher is = GET_ISR() ; 17033f810b2SJeff Kirsher /* Check if timer expired (or wraparound). */ 17133f810b2SJeff Kirsher if ((tr > smc->hw.t_start) || (is & IS_TIMINT)) { 17233f810b2SJeff Kirsher hwt_restart(smc) ; 17333f810b2SJeff Kirsher smc->hw.t_stop = smc->hw.t_start ; 17433f810b2SJeff Kirsher } 17533f810b2SJeff Kirsher else 17633f810b2SJeff Kirsher smc->hw.t_stop = smc->hw.t_start - tr ; 17733f810b2SJeff Kirsher } 17833f810b2SJeff Kirsher return smc->hw.t_stop; 17933f810b2SJeff Kirsher } 18033f810b2SJeff Kirsher 18133f810b2SJeff Kirsher #ifdef PCI 18233f810b2SJeff Kirsher /************************ 18333f810b2SJeff Kirsher * 18433f810b2SJeff Kirsher * hwt_quick_read 18533f810b2SJeff Kirsher * 18633f810b2SJeff Kirsher * Stop hardware timer and read timer value and start the timer again. 18733f810b2SJeff Kirsher * 18833f810b2SJeff Kirsher * u_long hwt_read(smc) ; 18933f810b2SJeff Kirsher * In 19033f810b2SJeff Kirsher * smc - A pointer to the SMT Context structure. 19133f810b2SJeff Kirsher * Out 19233f810b2SJeff Kirsher * current timer value in units of 80ns. 19333f810b2SJeff Kirsher * 19433f810b2SJeff Kirsher ************************/ 19533f810b2SJeff Kirsher u_long hwt_quick_read(struct s_smc *smc) 19633f810b2SJeff Kirsher { 19733f810b2SJeff Kirsher u_long interval ; 19833f810b2SJeff Kirsher u_long time ; 19933f810b2SJeff Kirsher 20033f810b2SJeff Kirsher interval = inpd(ADDR(B2_TI_INI)) ; 20133f810b2SJeff Kirsher outpw(ADDR(B2_TI_CRTL), TIM_STOP) ; 20233f810b2SJeff Kirsher time = inpd(ADDR(B2_TI_VAL)) ; 20333f810b2SJeff Kirsher outpd(ADDR(B2_TI_INI),time) ; 20433f810b2SJeff Kirsher outpw(ADDR(B2_TI_CRTL), TIM_START) ; 20533f810b2SJeff Kirsher outpd(ADDR(B2_TI_INI),interval) ; 20633f810b2SJeff Kirsher 20733f810b2SJeff Kirsher return time; 20833f810b2SJeff Kirsher } 20933f810b2SJeff Kirsher 21033f810b2SJeff Kirsher /************************ 21133f810b2SJeff Kirsher * 21233f810b2SJeff Kirsher * hwt_wait_time(smc,start,duration) 21333f810b2SJeff Kirsher * 21433f810b2SJeff Kirsher * This function returnes after the amount of time is elapsed 21533f810b2SJeff Kirsher * since the start time. 21633f810b2SJeff Kirsher * 21733f810b2SJeff Kirsher * para start start time 21833f810b2SJeff Kirsher * duration time to wait 21933f810b2SJeff Kirsher * 22033f810b2SJeff Kirsher * NOTE: The function will return immediately, if the timer is not 22133f810b2SJeff Kirsher * started 22233f810b2SJeff Kirsher ************************/ 22333f810b2SJeff Kirsher void hwt_wait_time(struct s_smc *smc, u_long start, long int duration) 22433f810b2SJeff Kirsher { 22533f810b2SJeff Kirsher long diff ; 22633f810b2SJeff Kirsher long interval ; 22733f810b2SJeff Kirsher int wrapped ; 22833f810b2SJeff Kirsher 22933f810b2SJeff Kirsher /* 23033f810b2SJeff Kirsher * check if timer is running 23133f810b2SJeff Kirsher */ 23233f810b2SJeff Kirsher if (smc->hw.timer_activ == FALSE || 23333f810b2SJeff Kirsher hwt_quick_read(smc) == hwt_quick_read(smc)) { 23433f810b2SJeff Kirsher return ; 23533f810b2SJeff Kirsher } 23633f810b2SJeff Kirsher 23733f810b2SJeff Kirsher interval = inpd(ADDR(B2_TI_INI)) ; 23833f810b2SJeff Kirsher if (interval > duration) { 23933f810b2SJeff Kirsher do { 24033f810b2SJeff Kirsher diff = (long)(start - hwt_quick_read(smc)) ; 24133f810b2SJeff Kirsher if (diff < 0) { 24233f810b2SJeff Kirsher diff += interval ; 24333f810b2SJeff Kirsher } 24433f810b2SJeff Kirsher } while (diff <= duration) ; 24533f810b2SJeff Kirsher } 24633f810b2SJeff Kirsher else { 24733f810b2SJeff Kirsher diff = interval ; 24833f810b2SJeff Kirsher wrapped = 0 ; 24933f810b2SJeff Kirsher do { 25033f810b2SJeff Kirsher if (!wrapped) { 25133f810b2SJeff Kirsher if (hwt_quick_read(smc) >= start) { 25233f810b2SJeff Kirsher diff += interval ; 25333f810b2SJeff Kirsher wrapped = 1 ; 25433f810b2SJeff Kirsher } 25533f810b2SJeff Kirsher } 25633f810b2SJeff Kirsher else { 25733f810b2SJeff Kirsher if (hwt_quick_read(smc) < start) { 25833f810b2SJeff Kirsher wrapped = 0 ; 25933f810b2SJeff Kirsher } 26033f810b2SJeff Kirsher } 26133f810b2SJeff Kirsher } while (diff <= duration) ; 26233f810b2SJeff Kirsher } 26333f810b2SJeff Kirsher } 26433f810b2SJeff Kirsher #endif 26533f810b2SJeff Kirsher 266