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