1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * PPS dummy generator 4 * 5 * Copyright (C) 2024 Rodolfo Giometti <giometti@enneenne.com> 6 */ 7 8 #include <linux/kernel.h> 9 #include <linux/module.h> 10 #include <linux/init.h> 11 #include <linux/time.h> 12 #include <linux/timer.h> 13 #include <linux/random.h> 14 #include <linux/pps_gen_kernel.h> 15 16 static struct pps_gen_device *pps_gen; 17 static struct timer_list ktimer; 18 19 static unsigned int get_random_delay(void) 20 { 21 unsigned int delay = get_random_u8() & 0x0f; 22 23 return (delay + 1) * HZ; 24 } 25 26 /* 27 * The kernel timer 28 */ 29 30 static void pps_gen_ktimer_event(struct timer_list *unused) 31 { 32 pps_gen_event(pps_gen, PPS_GEN_EVENT_MISSEDPULSE, NULL); 33 } 34 35 /* 36 * PPS Generator methods 37 */ 38 39 static int pps_gen_dummy_get_time(struct pps_gen_device *pps_gen, 40 struct timespec64 *time) 41 { 42 struct system_time_snapshot snap; 43 44 ktime_get_snapshot(&snap); 45 *time = ktime_to_timespec64(snap.real); 46 47 return 0; 48 } 49 50 static int pps_gen_dummy_enable(struct pps_gen_device *pps_gen, bool enable) 51 { 52 if (enable) 53 mod_timer(&ktimer, jiffies + get_random_delay()); 54 else 55 del_timer_sync(&ktimer); 56 57 return 0; 58 } 59 60 /* 61 * The PPS info struct 62 */ 63 64 static struct pps_gen_source_info pps_gen_dummy_info = { 65 .use_system_clock = true, 66 .get_time = pps_gen_dummy_get_time, 67 .enable = pps_gen_dummy_enable, 68 }; 69 70 /* 71 * Module staff 72 */ 73 74 static void __exit pps_gen_dummy_exit(void) 75 { 76 del_timer_sync(&ktimer); 77 pps_gen_unregister_source(pps_gen); 78 } 79 80 static int __init pps_gen_dummy_init(void) 81 { 82 pps_gen = pps_gen_register_source(&pps_gen_dummy_info); 83 if (IS_ERR(pps_gen)) 84 return PTR_ERR(pps_gen); 85 86 timer_setup(&ktimer, pps_gen_ktimer_event, 0); 87 88 return 0; 89 } 90 91 module_init(pps_gen_dummy_init); 92 module_exit(pps_gen_dummy_exit); 93 94 MODULE_AUTHOR("Rodolfo Giometti <giometti@enneenne.com>"); 95 MODULE_DESCRIPTION("LinuxPPS dummy generator"); 96 MODULE_LICENSE("GPL"); 97