aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJonathan Cameron <jic23@cam.ac.uk>2009-08-18 13:06:29 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2009-09-15 15:02:25 -0400
commit0a1231dfea57516fb6cf107afdfb625a11a1cc5e (patch)
tree408b9906efb7a667e429c4f571a58d611393c8cb /drivers
parent14cd9a73d97e3c1063fa1b2b02ef32ac8a914e11 (diff)
Staging: IIO: max1363 add software ring buffer support using ring_sw
Changes since V2: * Moved to new registration methodology. Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/staging/iio/adc/Makefile1
-rw-r--r--drivers/staging/iio/adc/max1363.h14
-rw-r--r--drivers/staging/iio/adc/max1363_ring.c241
3 files changed, 255 insertions, 1 deletions
diff --git a/drivers/staging/iio/adc/Makefile b/drivers/staging/iio/adc/Makefile
index 2a37feed4add..0c2b6f39e8c8 100644
--- a/drivers/staging/iio/adc/Makefile
+++ b/drivers/staging/iio/adc/Makefile
@@ -3,5 +3,6 @@
3# 3#
4 4
5max1363-y := max1363_core.o 5max1363-y := max1363_core.o
6max1363-$(CONFIG_IIO_RING_BUFFER) += max1363_ring.o
6 7
7obj-$(CONFIG_MAX1363) += max1363.o 8obj-$(CONFIG_MAX1363) += max1363.o
diff --git a/drivers/staging/iio/adc/max1363.h b/drivers/staging/iio/adc/max1363.h
index a9d5c21a6c3c..8aca81f14d0b 100644
--- a/drivers/staging/iio/adc/max1363.h
+++ b/drivers/staging/iio/adc/max1363.h
@@ -228,6 +228,18 @@ struct max1363_state {
228 struct iio_trigger *trig; 228 struct iio_trigger *trig;
229 struct regulator *reg; 229 struct regulator *reg;
230}; 230};
231#ifdef CONFIG_IIO_RING_BUFFER
232
233ssize_t max1363_scan_from_ring(struct device *dev,
234 struct device_attribute *attr,
235 char *buf);
236int max1363_register_ring_funcs_and_init(struct iio_dev *indio_dev);
237void max1363_ring_cleanup(struct iio_dev *indio_dev);
238
239int max1363_initialize_ring(struct iio_ring_buffer *ring);
240void max1363_uninitialize_ring(struct iio_ring_buffer *ring);
241
242#else /* CONFIG_IIO_RING_BUFFER */
231 243
232static inline void max1363_uninitialize_ring(struct iio_ring_buffer *ring) 244static inline void max1363_uninitialize_ring(struct iio_ring_buffer *ring)
233{ 245{
@@ -253,5 +265,5 @@ max1363_register_ring_funcs_and_init(struct iio_dev *indio_dev)
253}; 265};
254 266
255static inline void max1363_ring_cleanup(struct iio_dev *indio_dev) {}; 267static inline void max1363_ring_cleanup(struct iio_dev *indio_dev) {};
256 268#endif /* CONFIG_IIO_RING_BUFFER */
257#endif /* _MAX1363_H_ */ 269#endif /* _MAX1363_H_ */
diff --git a/drivers/staging/iio/adc/max1363_ring.c b/drivers/staging/iio/adc/max1363_ring.c
new file mode 100644
index 000000000000..a953eac6fd62
--- /dev/null
+++ b/drivers/staging/iio/adc/max1363_ring.c
@@ -0,0 +1,241 @@
1/*
2 * Copyright (C) 2008 Jonathan Cameron
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * max1363_ring.c
9 */
10
11#include <linux/interrupt.h>
12#include <linux/gpio.h>
13#include <linux/workqueue.h>
14#include <linux/device.h>
15#include <linux/kernel.h>
16#include <linux/sysfs.h>
17#include <linux/list.h>
18#include <linux/i2c.h>
19
20#include "../iio.h"
21#include "../ring_generic.h"
22#include "../ring_sw.h"
23#include "../trigger.h"
24#include "../sysfs.h"
25
26#include "max1363.h"
27
28ssize_t max1363_scan_from_ring(struct device *dev,
29 struct device_attribute *attr,
30 char *buf)
31{
32 struct iio_dev *dev_info = dev_get_drvdata(dev);
33 struct max1363_state *info = dev_info->dev_data;
34 int i, ret, len = 0;
35 char *ring_data;
36
37 ring_data = kmalloc(info->current_mode->numvals*2, GFP_KERNEL);
38 if (ring_data == NULL) {
39 ret = -ENOMEM;
40 goto error_ret;
41 }
42 ret = dev_info->ring->access.read_last(dev_info->ring, ring_data);
43 if (ret)
44 goto error_free_ring_data;
45 len += sprintf(buf+len, "ring ");
46 for (i = 0; i < info->current_mode->numvals; i++)
47 len += sprintf(buf + len, "%d ",
48 ((int)(ring_data[i*2 + 0] & 0x0F) << 8)
49 + ((int)(ring_data[i*2 + 1])));
50 len += sprintf(buf + len, "\n");
51 kfree(ring_data);
52
53 return len;
54
55error_free_ring_data:
56 kfree(ring_data);
57error_ret:
58 return ret;
59}
60
61/**
62 * max1363_ring_preenable() setup the parameters of the ring before enabling
63 *
64 * The complex nature of the setting of the nuber of bytes per datum is due
65 * to this driver currently ensuring that the timestamp is stored at an 8
66 * byte boundary.
67 **/
68static int max1363_ring_preenable(struct iio_dev *indio_dev)
69{
70 struct max1363_state *st = indio_dev->dev_data;
71 size_t d_size;
72
73 if (indio_dev->ring->access.set_bpd) {
74 d_size = st->current_mode->numvals*2 + sizeof(s64);
75 if (d_size % 8)
76 d_size += 8 - (d_size % 8);
77 indio_dev->ring->access.set_bpd(indio_dev->ring, d_size);
78 }
79
80 return 0;
81}
82
83/**
84 * max1363_ring_postenable() typical ring post enable
85 *
86 * Only not moved into the core for the hardware ring buffer cases
87 * that are more sophisticated.
88 **/
89static int max1363_ring_postenable(struct iio_dev *indio_dev)
90{
91 if (indio_dev->trig == NULL)
92 return 0;
93 return iio_trigger_attach_poll_func(indio_dev->trig,
94 indio_dev->pollfunc);
95}
96
97/**
98 * max1363_ring_predisable() runs just prior to ring buffer being disabled
99 *
100 * Typical predisable function which ensures that no trigger events can
101 * occur before we disable the ring buffer (and hence would have no idea
102 * what to do with them)
103 **/
104static int max1363_ring_predisable(struct iio_dev *indio_dev)
105{
106 if (indio_dev->trig)
107 return iio_trigger_dettach_poll_func(indio_dev->trig,
108 indio_dev->pollfunc);
109 else
110 return 0;
111}
112
113/**
114 * max1363_poll_func_th() th of trigger launched polling to ring buffer
115 *
116 * As sampling only occurs on i2c comms occuring, leave timestamping until
117 * then. Some triggers will generate their own time stamp. Currently
118 * there is no way of notifying them when no one cares.
119 **/
120void max1363_poll_func_th(struct iio_dev *indio_dev)
121{
122 struct max1363_state *st = indio_dev->dev_data;
123
124 schedule_work(&st->poll_work);
125
126 return;
127}
128/**
129 * max1363_poll_bh_to_ring() bh of trigger launched polling to ring buffer
130 * @work_s: the work struct through which this was scheduled
131 *
132 * Currently there is no option in this driver to disable the saving of
133 * timestamps within the ring.
134 * I think the one copy of this at a time was to avoid problems if the
135 * trigger was set far too high and the reads then locked up the computer.
136 **/
137static void max1363_poll_bh_to_ring(struct work_struct *work_s)
138{
139 struct max1363_state *st = container_of(work_s, struct max1363_state,
140 poll_work);
141 struct iio_dev *indio_dev = st->indio_dev;
142 struct iio_sw_ring_buffer *ring = iio_to_sw_ring(indio_dev->ring);
143 s64 time_ns;
144 __u8 *rxbuf;
145 int b_sent;
146 size_t d_size;
147
148 /* Ensure the timestamp is 8 byte aligned */
149 d_size = st->current_mode->numvals*2 + sizeof(s64);
150 if (d_size % sizeof(s64))
151 d_size += sizeof(s64) - (d_size % sizeof(s64));
152
153 /* Ensure only one copy of this function running at a time */
154 if (atomic_inc_return(&st->protect_ring) > 1)
155 return;
156
157 /* Monitor mode prevents reading. Whilst not currently implemented
158 * might as well have this test in here in the meantime as it does
159 * no harm.
160 */
161 if (st->current_mode->numvals == 0)
162 return;
163
164 rxbuf = kmalloc(d_size, GFP_KERNEL);
165 if (rxbuf == NULL)
166 return;
167
168 b_sent = i2c_master_recv(st->client,
169 rxbuf,
170 st->current_mode->numvals*2);
171 if (b_sent < 0)
172 goto done;
173
174 time_ns = iio_get_time_ns();
175
176 memcpy(rxbuf + d_size - sizeof(s64), &time_ns, sizeof(time_ns));
177
178 indio_dev->ring->access.store_to(&ring->buf, rxbuf, time_ns);
179done:
180 kfree(rxbuf);
181 atomic_dec(&st->protect_ring);
182}
183
184
185int max1363_register_ring_funcs_and_init(struct iio_dev *indio_dev)
186{
187 struct max1363_state *st = indio_dev->dev_data;
188 int ret = 0;
189
190 indio_dev->ring = iio_sw_rb_allocate(indio_dev);
191 if (!indio_dev->ring) {
192 ret = -ENOMEM;
193 goto error_ret;
194 }
195 /* Effectively select the ring buffer implementation */
196 iio_ring_sw_register_funcs(&st->indio_dev->ring->access);
197 indio_dev->pollfunc = kzalloc(sizeof(*indio_dev->pollfunc), GFP_KERNEL);
198 if (indio_dev->pollfunc == NULL) {
199 ret = -ENOMEM;
200 goto error_deallocate_sw_rb;
201 }
202 /* Configure the polling function called on trigger interrupts */
203 indio_dev->pollfunc->poll_func_main = &max1363_poll_func_th;
204 indio_dev->pollfunc->private_data = indio_dev;
205
206 /* Ring buffer functions - here trigger setup related */
207 indio_dev->ring->postenable = &max1363_ring_postenable;
208 indio_dev->ring->preenable = &max1363_ring_preenable;
209 indio_dev->ring->predisable = &max1363_ring_predisable;
210 INIT_WORK(&st->poll_work, &max1363_poll_bh_to_ring);
211
212 /* Flag that polled ring buffering is possible */
213 indio_dev->modes |= INDIO_RING_TRIGGERED;
214 return 0;
215error_deallocate_sw_rb:
216 iio_sw_rb_free(indio_dev->ring);
217error_ret:
218 return ret;
219}
220
221void max1363_ring_cleanup(struct iio_dev *indio_dev)
222{
223 /* ensure that the trigger has been detached */
224 if (indio_dev->trig) {
225 iio_put_trigger(indio_dev->trig);
226 iio_trigger_dettach_poll_func(indio_dev->trig,
227 indio_dev->pollfunc);
228 }
229 kfree(indio_dev->pollfunc);
230 iio_sw_rb_free(indio_dev->ring);
231}
232
233void max1363_uninitialize_ring(struct iio_ring_buffer *ring)
234{
235 iio_ring_buffer_unregister(ring);
236};
237
238int max1363_initialize_ring(struct iio_ring_buffer *ring)
239{
240 return iio_ring_buffer_register(ring);
241};