1 // SPDX-License-Identifier: GPL-2.0-only 2 /** 3 * The industrial I/O periodic hrtimer trigger driver 4 * 5 * Copyright (C) Intuitive Aerial AB 6 * Written by Marten Svanfeldt, marten@intuitiveaerial.com 7 * Copyright (C) 2012, Analog Devices Inc. 8 * Author: Lars-Peter Clausen <lars@metafoo.de> 9 * Copyright (C) 2015, Intel Corporation 10 */ 11 #include <linux/kernel.h> 12 #include <linux/slab.h> 13 #include <linux/hrtimer.h> 14 15 #include <linux/iio/iio.h> 16 #include <linux/iio/trigger.h> 17 #include <linux/iio/sw_trigger.h> 18 19 /* default sampling frequency - 100Hz */ 20 #define HRTIMER_DEFAULT_SAMPLING_FREQUENCY 100 21 22 struct iio_hrtimer_info { 23 struct iio_sw_trigger swt; 24 struct hrtimer timer; 25 unsigned long sampling_frequency; 26 ktime_t period; 27 }; 28 29 static const struct config_item_type iio_hrtimer_type = { 30 .ct_owner = THIS_MODULE, 31 }; 32 33 static 34 ssize_t iio_hrtimer_show_sampling_frequency(struct device *dev, 35 struct device_attribute *attr, 36 char *buf) 37 { 38 struct iio_trigger *trig = to_iio_trigger(dev); 39 struct iio_hrtimer_info *info = iio_trigger_get_drvdata(trig); 40 41 return snprintf(buf, PAGE_SIZE, "%lu\n", info->sampling_frequency); 42 } 43 44 static 45 ssize_t iio_hrtimer_store_sampling_frequency(struct device *dev, 46 struct device_attribute *attr, 47 const char *buf, size_t len) 48 { 49 struct iio_trigger *trig = to_iio_trigger(dev); 50 struct iio_hrtimer_info *info = iio_trigger_get_drvdata(trig); 51 unsigned long val; 52 int ret; 53 54 ret = kstrtoul(buf, 10, &val); 55 if (ret) 56 return ret; 57 58 if (!val || val > NSEC_PER_SEC) 59 return -EINVAL; 60 61 info->sampling_frequency = val; 62 info->period = NSEC_PER_SEC / val; 63 64 return len; 65 } 66 67 static DEVICE_ATTR(sampling_frequency, S_IRUGO | S_IWUSR, 68 iio_hrtimer_show_sampling_frequency, 69 iio_hrtimer_store_sampling_frequency); 70 71 static struct attribute *iio_hrtimer_attrs[] = { 72 &dev_attr_sampling_frequency.attr, 73 NULL 74 }; 75 76 static const struct attribute_group iio_hrtimer_attr_group = { 77 .attrs = iio_hrtimer_attrs, 78 }; 79 80 static const struct attribute_group *iio_hrtimer_attr_groups[] = { 81 &iio_hrtimer_attr_group, 82 NULL 83 }; 84 85 static enum hrtimer_restart iio_hrtimer_trig_handler(struct hrtimer *timer) 86 { 87 struct iio_hrtimer_info *info; 88 89 info = container_of(timer, struct iio_hrtimer_info, timer); 90 91 hrtimer_forward_now(timer, info->period); 92 iio_trigger_poll(info->swt.trigger); 93 94 return HRTIMER_RESTART; 95 } 96 97 static int iio_trig_hrtimer_set_state(struct iio_trigger *trig, bool state) 98 { 99 struct iio_hrtimer_info *trig_info; 100 101 trig_info = iio_trigger_get_drvdata(trig); 102 103 if (state) 104 hrtimer_start(&trig_info->timer, trig_info->period, 105 HRTIMER_MODE_REL_HARD); 106 else 107 hrtimer_cancel(&trig_info->timer); 108 109 return 0; 110 } 111 112 static const struct iio_trigger_ops iio_hrtimer_trigger_ops = { 113 .set_trigger_state = iio_trig_hrtimer_set_state, 114 }; 115 116 static struct iio_sw_trigger *iio_trig_hrtimer_probe(const char *name) 117 { 118 struct iio_hrtimer_info *trig_info; 119 int ret; 120 121 trig_info = kzalloc(sizeof(*trig_info), GFP_KERNEL); 122 if (!trig_info) 123 return ERR_PTR(-ENOMEM); 124 125 trig_info->swt.trigger = iio_trigger_alloc("%s", name); 126 if (!trig_info->swt.trigger) { 127 ret = -ENOMEM; 128 goto err_free_trig_info; 129 } 130 131 iio_trigger_set_drvdata(trig_info->swt.trigger, trig_info); 132 trig_info->swt.trigger->ops = &iio_hrtimer_trigger_ops; 133 trig_info->swt.trigger->dev.groups = iio_hrtimer_attr_groups; 134 135 hrtimer_init(&trig_info->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_HARD); 136 trig_info->timer.function = iio_hrtimer_trig_handler; 137 138 trig_info->sampling_frequency = HRTIMER_DEFAULT_SAMPLING_FREQUENCY; 139 trig_info->period = NSEC_PER_SEC / trig_info->sampling_frequency; 140 141 ret = iio_trigger_register(trig_info->swt.trigger); 142 if (ret) 143 goto err_free_trigger; 144 145 iio_swt_group_init_type_name(&trig_info->swt, name, &iio_hrtimer_type); 146 return &trig_info->swt; 147 err_free_trigger: 148 iio_trigger_free(trig_info->swt.trigger); 149 err_free_trig_info: 150 kfree(trig_info); 151 152 return ERR_PTR(ret); 153 } 154 155 static int iio_trig_hrtimer_remove(struct iio_sw_trigger *swt) 156 { 157 struct iio_hrtimer_info *trig_info; 158 159 trig_info = iio_trigger_get_drvdata(swt->trigger); 160 161 iio_trigger_unregister(swt->trigger); 162 163 /* cancel the timer after unreg to make sure no one rearms it */ 164 hrtimer_cancel(&trig_info->timer); 165 iio_trigger_free(swt->trigger); 166 kfree(trig_info); 167 168 return 0; 169 } 170 171 static const struct iio_sw_trigger_ops iio_trig_hrtimer_ops = { 172 .probe = iio_trig_hrtimer_probe, 173 .remove = iio_trig_hrtimer_remove, 174 }; 175 176 static struct iio_sw_trigger_type iio_trig_hrtimer = { 177 .name = "hrtimer", 178 .owner = THIS_MODULE, 179 .ops = &iio_trig_hrtimer_ops, 180 }; 181 182 module_iio_sw_trigger_driver(iio_trig_hrtimer); 183 184 MODULE_AUTHOR("Marten Svanfeldt <marten@intuitiveaerial.com>"); 185 MODULE_AUTHOR("Daniel Baluta <daniel.baluta@intel.com>"); 186 MODULE_DESCRIPTION("Periodic hrtimer trigger for the IIO subsystem"); 187 MODULE_LICENSE("GPL v2"); 188