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