summaryrefslogtreecommitdiffstats
path: root/include/linux/pps_kernel.h
blob: 54bf1484d41f0333cc860c84307d23eda76477e5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/*
 * PPS API kernel header
 *
 * Copyright (C) 2009   Rodolfo Giometti <giometti@linux.it>
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#ifndef LINUX_PPS_KERNEL_H
#define LINUX_PPS_KERNEL_H

#include <linux/pps.h>

#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/time.h>

/*
 * Global defines
 */

struct pps_device;

/* The specific PPS source info */
struct pps_source_info {
	char name[PPS_MAX_NAME_LEN];		/* simbolic name */
	char path[PPS_MAX_NAME_LEN];		/* path of connected device */
	int mode;				/* PPS's allowed mode */

	void (*echo)(struct pps_device *pps,
			int event, void *data);	/* PPS echo function */

	struct module *owner;
	struct device *dev;		/* Parent device for device_create */
};

struct pps_event_time {
#ifdef CONFIG_NTP_PPS
	struct timespec64 ts_raw;
#endif /* CONFIG_NTP_PPS */
	struct timespec64 ts_real;
};

/* The main struct */
struct pps_device {
	struct pps_source_info info;		/* PSS source info */

	struct pps_kparams params;		/* PPS's current params */

	__u32 assert_sequence;			/* PPS' assert event seq # */
	__u32 clear_sequence;			/* PPS' clear event seq # */
	struct pps_ktime assert_tu;
	struct pps_ktime clear_tu;
	int current_mode;			/* PPS mode at event time */

	unsigned int last_ev;			/* last PPS event id */
	wait_queue_head_t queue;		/* PPS event queue */

	unsigned int id;			/* PPS source unique ID */
	void const *lookup_cookie;		/* pps_lookup_dev only */
	struct cdev cdev;
	struct device *dev;
	struct fasync_struct *async_queue;	/* fasync method */
	spinlock_t lock;
};

/*
 * Global variables
 */

extern const struct attribute_group *pps_groups[];

/*
 * Internal functions.
 *
 * These are not actually part of the exported API, but this is a
 * convenient header file to put them in.
 */

extern int pps_register_cdev(struct pps_device *pps);
extern void pps_unregister_cdev(struct pps_device *pps);

/*
 * Exported functions
 */

extern struct pps_device *pps_register_source(
		struct pps_source_info *info, int default_params);
extern void pps_unregister_source(struct pps_device *pps);
extern void pps_event(struct pps_device *pps,
		struct pps_event_time *ts, int event, void *data);
/* Look up a pps device by magic cookie */
struct pps_device *pps_lookup_dev(void const *cookie);

static inline void timespec_to_pps_ktime(struct pps_ktime *kt,
		struct timespec64 ts)
{
	kt->sec = ts.tv_sec;
	kt->nsec = ts.tv_nsec;
}

#ifdef CONFIG_NTP_PPS

static inline void pps_get_ts(struct pps_event_time *ts)
{
	ktime_get_raw_and_real_ts64(&ts->ts_raw, &ts->ts_real);
}

#else /* CONFIG_NTP_PPS */

static inline void pps_get_ts(struct pps_event_time *ts)
{
	ktime_get_real_ts64(&ts->ts_real);
}

#endif /* CONFIG_NTP_PPS */

/* Subtract known time delay from PPS event time(s) */
static inline void pps_sub_ts(struct pps_event_time *ts, struct timespec64 delta)
{
	ts->ts_real = timespec64_sub(ts->ts_real, delta);
#ifdef CONFIG_NTP_PPS
	ts->ts_raw = timespec64_sub(ts->ts_raw, delta);
#endif
}

#endif /* LINUX_PPS_KERNEL_H */