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 ktime_get_real_ts64(time); 43 return 0; 44 } 45 46 static int pps_gen_dummy_enable(struct pps_gen_device *pps_gen, bool enable) 47 { 48 if (enable) 49 mod_timer(&ktimer, jiffies + get_random_delay()); 50 else 51 timer_delete_sync(&ktimer); 52 53 return 0; 54 } 55 56 /* 57 * The PPS info struct 58 */ 59 60 static const struct pps_gen_source_info pps_gen_dummy_info = { 61 .use_system_clock = true, 62 .get_time = pps_gen_dummy_get_time, 63 .enable = pps_gen_dummy_enable, 64 }; 65 66 /* 67 * Module staff 68 */ 69 70 static void __exit pps_gen_dummy_exit(void) 71 { 72 timer_delete_sync(&ktimer); 73 pps_gen_unregister_source(pps_gen); 74 } 75 76 static int __init pps_gen_dummy_init(void) 77 { 78 pps_gen = pps_gen_register_source(&pps_gen_dummy_info); 79 if (IS_ERR(pps_gen)) 80 return PTR_ERR(pps_gen); 81 82 timer_setup(&ktimer, pps_gen_ktimer_event, 0); 83 84 return 0; 85 } 86 87 module_init(pps_gen_dummy_init); 88 module_exit(pps_gen_dummy_exit); 89 90 MODULE_AUTHOR("Rodolfo Giometti <giometti@enneenne.com>"); 91 MODULE_DESCRIPTION("LinuxPPS dummy generator"); 92 MODULE_LICENSE("GPL"); 93