Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:14

0001 /**
0002  * @file
0003  *
0004  * @ingroup RTEMSScoreTimecounter
0005  *
0006  * @brief This header file provides interfaces of the Pulse Per Second (PPS)
0007  *   support.
0008  */
0009 
0010 /*-
0011  * ----------------------------------------------------------------------------
0012  * "THE BEER-WARE LICENSE" (Revision 42):
0013  * <phk@FreeBSD.org> wrote this file.  As long as you retain this notice you
0014  * can do whatever you want with this stuff. If we meet some day, and you think
0015  * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
0016  * ----------------------------------------------------------------------------
0017  *
0018  * Copyright (c) 2011 The FreeBSD Foundation
0019  * All rights reserved.
0020  *
0021  * Portions of this software were developed by Julien Ridoux at the University
0022  * of Melbourne under sponsorship from the FreeBSD Foundation.
0023  *
0024  * The is a FreeBSD version of the RFC 2783 API for Pulse Per Second 
0025  * timing interfaces.  
0026  */
0027 
0028 #ifndef _SYS_TIMEPPS_H_
0029 #define _SYS_TIMEPPS_H_
0030 
0031 #include <sys/_ffcounter.h>
0032 #include <sys/ioccom.h>
0033 #include <sys/time.h>
0034 #ifdef __rtems__
0035 #include <rtems/score/atomic.h>
0036 #define PPS_SYNC
0037 #define hardpps _Timecounter_Discipline
0038 #ifdef __cplusplus
0039 extern "C" {
0040 #endif /* __cplusplus */
0041 #endif /* __rtems__ */
0042 
0043 #define PPS_API_VERS_1  1
0044 
0045 typedef int pps_handle_t;   
0046 
0047 #ifndef __rtems__
0048 typedef unsigned pps_seq_t;
0049 #else /* __rtems__ */
0050 typedef Atomic_Uint pps_seq_t;
0051 #endif /* __rtems__ */
0052 
0053 typedef struct ntp_fp {
0054     unsigned int    integral;
0055     unsigned int    fractional;
0056 } ntp_fp_t;
0057 
0058 typedef union pps_timeu {
0059     struct timespec tspec;
0060     ntp_fp_t    ntpfp;
0061     unsigned long   longpad[3];
0062 } pps_timeu_t;
0063 
0064 typedef struct {
0065     pps_seq_t   assert_sequence;    /* assert event seq # */
0066     pps_seq_t   clear_sequence;     /* clear event seq # */
0067     pps_timeu_t assert_tu;
0068     pps_timeu_t clear_tu;
0069     int     current_mode;       /* current mode bits */
0070 } pps_info_t;
0071 
0072 typedef struct {
0073     pps_seq_t   assert_sequence;    /* assert event seq # */
0074     pps_seq_t   clear_sequence;     /* clear event seq # */
0075     pps_timeu_t assert_tu;
0076     pps_timeu_t clear_tu;
0077     ffcounter   assert_ffcount;     /* ffcounter on assert event */
0078     ffcounter   clear_ffcount;      /* ffcounter on clear event */
0079     int     current_mode;       /* current mode bits */
0080 } pps_info_ffc_t;
0081 
0082 #define assert_timestamp        assert_tu.tspec
0083 #define clear_timestamp         clear_tu.tspec
0084 
0085 #define assert_timestamp_ntpfp  assert_tu.ntpfp
0086 #define clear_timestamp_ntpfp   clear_tu.ntpfp
0087 
0088 typedef struct {
0089     int api_version;            /* API version # */
0090     int mode;               /* mode bits */
0091     pps_timeu_t assert_off_tu;
0092     pps_timeu_t clear_off_tu;
0093 } pps_params_t;
0094 
0095 #define assert_offset   assert_off_tu.tspec
0096 #define clear_offset    clear_off_tu.tspec
0097 
0098 #define assert_offset_ntpfp     assert_off_tu.ntpfp
0099 #define clear_offset_ntpfp      clear_off_tu.ntpfp
0100 
0101 
0102 #define PPS_CAPTUREASSERT   0x01
0103 #define PPS_CAPTURECLEAR    0x02
0104 #define PPS_CAPTUREBOTH     0x03
0105 
0106 #define PPS_OFFSETASSERT    0x10
0107 #define PPS_OFFSETCLEAR     0x20
0108 
0109 #define PPS_ECHOASSERT      0x40
0110 #define PPS_ECHOCLEAR       0x80
0111 
0112 #define PPS_CANWAIT     0x100
0113 #define PPS_CANPOLL     0x200
0114 
0115 #define PPS_TSFMT_TSPEC     0x1000
0116 #define PPS_TSFMT_NTPFP     0x2000
0117 
0118 #define PPS_TSCLK_FBCK      0x10000
0119 #define PPS_TSCLK_FFWD      0x20000
0120 #define PPS_TSCLK_MASK      0x30000
0121 
0122 #define PPS_KC_HARDPPS      0
0123 #define PPS_KC_HARDPPS_PLL  1
0124 #define PPS_KC_HARDPPS_FLL  2
0125 
0126 struct pps_fetch_args {
0127     int tsformat;
0128     pps_info_t  pps_info_buf;
0129     struct timespec timeout;
0130 };
0131 
0132 struct pps_fetch_ffc_args {
0133     int     tsformat;
0134     pps_info_ffc_t  pps_info_buf_ffc;
0135     struct timespec timeout;
0136 };
0137 
0138 struct pps_kcbind_args {
0139     int kernel_consumer;
0140     int edge;
0141     int tsformat;
0142 };
0143 
0144 #define PPS_IOC_CREATE      _IO('1', 1)
0145 #define PPS_IOC_DESTROY     _IO('1', 2)
0146 #define PPS_IOC_SETPARAMS   _IOW('1', 3, pps_params_t)
0147 #define PPS_IOC_GETPARAMS   _IOR('1', 4, pps_params_t)
0148 #define PPS_IOC_GETCAP      _IOR('1', 5, int)
0149 #define PPS_IOC_FETCH       _IOWR('1', 6, struct pps_fetch_args)
0150 #define PPS_IOC_KCBIND      _IOW('1', 7, struct pps_kcbind_args)
0151 #define PPS_IOC_FETCH_FFCOUNTER _IOWR('1', 8, struct pps_fetch_ffc_args)
0152 
0153 #ifdef _KERNEL
0154 
0155 struct mtx;
0156 
0157 #define KCMODE_EDGEMASK     0x03
0158 #define KCMODE_ABIFLAG      0x80000000 /* Internal use: abi-aware driver. */
0159 
0160 #define PPS_ABI_VERSION     1
0161 
0162 #define PPSFLAG_MTX_SPIN    0x01    /* Driver mtx is MTX_SPIN type. */
0163 
0164 struct pps_state {
0165     /* Capture information. */
0166     struct timehands *capth;
0167     struct fftimehands *capffth;
0168     unsigned    capgen;
0169     unsigned    capcount;
0170 
0171     /* State information. */
0172     pps_params_t    ppsparam;
0173     pps_info_t  ppsinfo;
0174     pps_info_ffc_t  ppsinfo_ffc;
0175     int     kcmode;
0176     int     ppscap;
0177     struct timecounter *ppstc;
0178     unsigned    ppscount[3];
0179 #ifdef __rtems__
0180     /**
0181      * @brief  Wait for an event.
0182      *
0183      * Called internally when time_pps_fetch() is used.
0184      * It is initialized by pps_init() to a handler which just returns ETIMEDOUT.
0185      *
0186      * @param pps is the pointer to the object.
0187      *
0188      * @param timeout
0189      *
0190      * @retval 0 A wakeup event was received.
0191      *
0192      * @retval ETIMEDOUT A timeout occurred while waiting for the event.
0193      */
0194     int (*wait)(struct pps_state *pps, struct timespec timeout);
0195 
0196     /**
0197      * @brief Wakeup the tasks waiting for an event.
0198      *
0199      * @param pps is the pointer to the object.
0200      */
0201     void (*wakeup)(struct pps_state *pps);
0202 #endif /* __rtems__ */
0203     /*
0204      * The following fields are valid if the driver calls pps_init_abi().
0205      */
0206     uint16_t    driver_abi; /* Driver sets before pps_init_abi(). */
0207     uint16_t    kernel_abi; /* Kernel sets during pps_init_abi(). */
0208     struct mtx  *driver_mtx;    /* Optional, valid if non-NULL. */
0209     uint32_t    flags;
0210 };
0211 
0212 void pps_capture(struct pps_state *pps);
0213 void pps_event(struct pps_state *pps, int event);
0214 void pps_init(struct pps_state *pps);
0215 void pps_init_abi(struct pps_state *pps);
0216 int pps_ioctl(unsigned long cmd, caddr_t data, struct pps_state *pps);
0217 void hardpps(struct timespec *tsp, long nsec);
0218 
0219 #else /* !_KERNEL */
0220 
0221 static __inline int
0222 time_pps_create(int filedes, pps_handle_t *handle)
0223 {
0224     int error;
0225 
0226     *handle = -1;
0227     error = ioctl(filedes, PPS_IOC_CREATE, 0);
0228     if (error < 0) 
0229         return (-1);
0230     *handle = filedes;
0231     return (0);
0232 }
0233 
0234 static __inline int
0235 time_pps_destroy(pps_handle_t handle)
0236 {
0237     return (ioctl(handle, PPS_IOC_DESTROY, 0));
0238 }
0239 
0240 static __inline int
0241 time_pps_setparams(pps_handle_t handle, const pps_params_t *ppsparams)
0242 {
0243     return (ioctl(handle, PPS_IOC_SETPARAMS, ppsparams));
0244 }
0245 
0246 static __inline int
0247 time_pps_getparams(pps_handle_t handle, pps_params_t *ppsparams)
0248 {
0249     return (ioctl(handle, PPS_IOC_GETPARAMS, ppsparams));
0250 }
0251 
0252 static __inline int 
0253 time_pps_getcap(pps_handle_t handle, int *mode)
0254 {
0255     return (ioctl(handle, PPS_IOC_GETCAP, mode));
0256 }
0257 
0258 static __inline int
0259 time_pps_fetch(pps_handle_t handle, const int tsformat,
0260     pps_info_t *ppsinfobuf, const struct timespec *timeout)
0261 {
0262     int error;
0263     struct pps_fetch_args arg;
0264 
0265     arg.tsformat = tsformat;
0266     if (timeout == NULL) {
0267         arg.timeout.tv_sec = -1;
0268         arg.timeout.tv_nsec = -1;
0269     } else
0270         arg.timeout = *timeout;
0271     error = ioctl(handle, PPS_IOC_FETCH, &arg);
0272     *ppsinfobuf = arg.pps_info_buf;
0273     return (error);
0274 }
0275 
0276 static __inline int
0277 time_pps_fetch_ffc(pps_handle_t handle, const int tsformat,
0278     pps_info_ffc_t *ppsinfobuf, const struct timespec *timeout)
0279 {
0280     struct pps_fetch_ffc_args arg;
0281     int error;
0282 
0283     arg.tsformat = tsformat;
0284     if (timeout == NULL) {
0285         arg.timeout.tv_sec = -1;
0286         arg.timeout.tv_nsec = -1;
0287     } else {
0288         arg.timeout = *timeout;
0289     }
0290     error = ioctl(handle, PPS_IOC_FETCH_FFCOUNTER, &arg);
0291     *ppsinfobuf = arg.pps_info_buf_ffc;
0292     return (error);
0293 }
0294 
0295 static __inline int
0296 time_pps_kcbind(pps_handle_t handle, const int kernel_consumer,
0297     const int edge, const int tsformat)
0298 {
0299     struct pps_kcbind_args arg;
0300 
0301     arg.kernel_consumer = kernel_consumer;
0302     arg.edge = edge;
0303     arg.tsformat = tsformat;
0304     return (ioctl(handle, PPS_IOC_KCBIND, &arg));
0305 }
0306 
0307 #endif /* KERNEL */
0308 
0309 #ifdef __rtems__
0310 #ifdef __cplusplus
0311 }
0312 #endif /* __cplusplus */
0313 #endif /* __rtems__ */
0314 #endif /* !_SYS_TIMEPPS_H_ */