aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/pps_kernel.h
blob: 80a980cc8d95f174a120fbd1aece4bdf7e55315b (plain) (blame)
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
/*
 * 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];		/* symbolic name */
	char path[PPS_MAX_NAME_LEN];		/* path of connected device */
	int mode;				/* PPS 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 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;		/* For 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;
}

static inline void pps_get_ts(struct pps_event_time *ts)
{
	struct system_time_snapshot snap;

	ktime_get_snapshot(&snap);
	ts->ts_real = ktime_to_timespec64(snap.real);
#ifdef CONFIG_NTP_PPS
	ts->ts_raw = ktime_to_timespec64(snap.raw);
#endif
}

/* 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 */