xref: /linux/drivers/pps/generators/pps_gen-dummy.c (revision 16cd1c2657762c62a00ac78eecaa25868f7e601b)
1580afe4aSRodolfo Giometti // SPDX-License-Identifier: GPL-2.0-or-later
2580afe4aSRodolfo Giometti /*
3580afe4aSRodolfo Giometti  * PPS dummy generator
4580afe4aSRodolfo Giometti  *
5580afe4aSRodolfo Giometti  * Copyright (C) 2024 Rodolfo Giometti <giometti@enneenne.com>
6580afe4aSRodolfo Giometti  */
7580afe4aSRodolfo Giometti 
8580afe4aSRodolfo Giometti #include <linux/kernel.h>
9580afe4aSRodolfo Giometti #include <linux/module.h>
10580afe4aSRodolfo Giometti #include <linux/init.h>
11580afe4aSRodolfo Giometti #include <linux/time.h>
12580afe4aSRodolfo Giometti #include <linux/timer.h>
13580afe4aSRodolfo Giometti #include <linux/random.h>
14580afe4aSRodolfo Giometti #include <linux/pps_gen_kernel.h>
15580afe4aSRodolfo Giometti 
16580afe4aSRodolfo Giometti static struct pps_gen_device *pps_gen;
17580afe4aSRodolfo Giometti static struct timer_list ktimer;
18580afe4aSRodolfo Giometti 
get_random_delay(void)19580afe4aSRodolfo Giometti static unsigned int get_random_delay(void)
20580afe4aSRodolfo Giometti {
21580afe4aSRodolfo Giometti 	unsigned int delay = get_random_u8() & 0x0f;
22580afe4aSRodolfo Giometti 
23580afe4aSRodolfo Giometti 	return (delay + 1) * HZ;
24580afe4aSRodolfo Giometti }
25580afe4aSRodolfo Giometti 
26580afe4aSRodolfo Giometti /*
27580afe4aSRodolfo Giometti  * The kernel timer
28580afe4aSRodolfo Giometti  */
29580afe4aSRodolfo Giometti 
pps_gen_ktimer_event(struct timer_list * unused)30580afe4aSRodolfo Giometti static void pps_gen_ktimer_event(struct timer_list *unused)
31580afe4aSRodolfo Giometti {
32580afe4aSRodolfo Giometti 	pps_gen_event(pps_gen, PPS_GEN_EVENT_MISSEDPULSE, NULL);
33580afe4aSRodolfo Giometti }
34580afe4aSRodolfo Giometti 
35580afe4aSRodolfo Giometti /*
36580afe4aSRodolfo Giometti  * PPS Generator methods
37580afe4aSRodolfo Giometti  */
38580afe4aSRodolfo Giometti 
pps_gen_dummy_get_time(struct pps_gen_device * pps_gen,struct timespec64 * time)39580afe4aSRodolfo Giometti static int pps_gen_dummy_get_time(struct pps_gen_device *pps_gen,
40580afe4aSRodolfo Giometti 					struct timespec64 *time)
41580afe4aSRodolfo Giometti {
42580afe4aSRodolfo Giometti 	struct system_time_snapshot snap;
43580afe4aSRodolfo Giometti 
44580afe4aSRodolfo Giometti 	ktime_get_snapshot(&snap);
45580afe4aSRodolfo Giometti 	*time = ktime_to_timespec64(snap.real);
46580afe4aSRodolfo Giometti 
47580afe4aSRodolfo Giometti 	return 0;
48580afe4aSRodolfo Giometti }
49580afe4aSRodolfo Giometti 
pps_gen_dummy_enable(struct pps_gen_device * pps_gen,bool enable)50580afe4aSRodolfo Giometti static int pps_gen_dummy_enable(struct pps_gen_device *pps_gen, bool enable)
51580afe4aSRodolfo Giometti {
52580afe4aSRodolfo Giometti 	if (enable)
53580afe4aSRodolfo Giometti 		mod_timer(&ktimer, jiffies + get_random_delay());
54580afe4aSRodolfo Giometti 	else
55*8fa7292fSThomas Gleixner 		timer_delete_sync(&ktimer);
56580afe4aSRodolfo Giometti 
57580afe4aSRodolfo Giometti 	return 0;
58580afe4aSRodolfo Giometti }
59580afe4aSRodolfo Giometti 
60580afe4aSRodolfo Giometti /*
61580afe4aSRodolfo Giometti  * The PPS info struct
62580afe4aSRodolfo Giometti  */
63580afe4aSRodolfo Giometti 
64ac9c5170SSubramanian Mohan static const struct pps_gen_source_info pps_gen_dummy_info = {
65580afe4aSRodolfo Giometti 	.use_system_clock	= true,
66580afe4aSRodolfo Giometti 	.get_time		= pps_gen_dummy_get_time,
67580afe4aSRodolfo Giometti 	.enable			= pps_gen_dummy_enable,
68580afe4aSRodolfo Giometti };
69580afe4aSRodolfo Giometti 
70580afe4aSRodolfo Giometti /*
71580afe4aSRodolfo Giometti  * Module staff
72580afe4aSRodolfo Giometti  */
73580afe4aSRodolfo Giometti 
pps_gen_dummy_exit(void)74580afe4aSRodolfo Giometti static void __exit pps_gen_dummy_exit(void)
75580afe4aSRodolfo Giometti {
76*8fa7292fSThomas Gleixner 	timer_delete_sync(&ktimer);
77580afe4aSRodolfo Giometti 	pps_gen_unregister_source(pps_gen);
78580afe4aSRodolfo Giometti }
79580afe4aSRodolfo Giometti 
pps_gen_dummy_init(void)80580afe4aSRodolfo Giometti static int __init pps_gen_dummy_init(void)
81580afe4aSRodolfo Giometti {
82580afe4aSRodolfo Giometti 	pps_gen = pps_gen_register_source(&pps_gen_dummy_info);
83580afe4aSRodolfo Giometti 	if (IS_ERR(pps_gen))
84580afe4aSRodolfo Giometti 		return PTR_ERR(pps_gen);
85580afe4aSRodolfo Giometti 
86580afe4aSRodolfo Giometti 	timer_setup(&ktimer, pps_gen_ktimer_event, 0);
87580afe4aSRodolfo Giometti 
88580afe4aSRodolfo Giometti 	return 0;
89580afe4aSRodolfo Giometti }
90580afe4aSRodolfo Giometti 
91580afe4aSRodolfo Giometti module_init(pps_gen_dummy_init);
92580afe4aSRodolfo Giometti module_exit(pps_gen_dummy_exit);
93580afe4aSRodolfo Giometti 
94580afe4aSRodolfo Giometti MODULE_AUTHOR("Rodolfo Giometti <giometti@enneenne.com>");
95580afe4aSRodolfo Giometti MODULE_DESCRIPTION("LinuxPPS dummy generator");
96580afe4aSRodolfo Giometti MODULE_LICENSE("GPL");
97