aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars-Peter Clausen <lars@metafoo.de>2018-01-10 05:13:03 -0500
committerMark Brown <broonie@kernel.org>2018-01-10 05:30:05 -0500
commit48b66f8f936f369bb1a43c12aedbfeb2975baf4c (patch)
tree3e144fd0c144199e8ca83238214f9c0fa1b69008
parent4fbd8d194f06c8a3fd2af1ce560ddb31f7ec8323 (diff)
iio: Add hardware consumer buffer support
Hardware consumer interface can be used when one IIO device has a direct connection to another device in hardware. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@st.com> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--drivers/iio/buffer/Kconfig10
-rw-r--r--drivers/iio/buffer/Makefile1
-rw-r--r--drivers/iio/buffer/industrialio-hw-consumer.c181
-rw-r--r--include/linux/iio/hw-consumer.h19
4 files changed, 211 insertions, 0 deletions
diff --git a/drivers/iio/buffer/Kconfig b/drivers/iio/buffer/Kconfig
index 4ffd3db7817f..338774cba19b 100644
--- a/drivers/iio/buffer/Kconfig
+++ b/drivers/iio/buffer/Kconfig
@@ -29,6 +29,16 @@ config IIO_BUFFER_DMAENGINE
29 29
30 Should be selected by drivers that want to use this functionality. 30 Should be selected by drivers that want to use this functionality.
31 31
32config IIO_BUFFER_HW_CONSUMER
33 tristate "Industrial I/O HW buffering"
34 help
35 Provides a way to bonding when an IIO device has a direct connection
36 to another device in hardware. In this case buffers for data transfers
37 are handled by hardware.
38
39 Should be selected by drivers that want to use the generic Hw consumer
40 interface.
41
32config IIO_KFIFO_BUF 42config IIO_KFIFO_BUF
33 tristate "Industrial I/O buffering based on kfifo" 43 tristate "Industrial I/O buffering based on kfifo"
34 help 44 help
diff --git a/drivers/iio/buffer/Makefile b/drivers/iio/buffer/Makefile
index 95f9f41c58b7..1403eb2f9409 100644
--- a/drivers/iio/buffer/Makefile
+++ b/drivers/iio/buffer/Makefile
@@ -7,5 +7,6 @@
7obj-$(CONFIG_IIO_BUFFER_CB) += industrialio-buffer-cb.o 7obj-$(CONFIG_IIO_BUFFER_CB) += industrialio-buffer-cb.o
8obj-$(CONFIG_IIO_BUFFER_DMA) += industrialio-buffer-dma.o 8obj-$(CONFIG_IIO_BUFFER_DMA) += industrialio-buffer-dma.o
9obj-$(CONFIG_IIO_BUFFER_DMAENGINE) += industrialio-buffer-dmaengine.o 9obj-$(CONFIG_IIO_BUFFER_DMAENGINE) += industrialio-buffer-dmaengine.o
10obj-$(CONFIG_IIO_BUFFER_HW_CONSUMER) += industrialio-hw-consumer.o
10obj-$(CONFIG_IIO_TRIGGERED_BUFFER) += industrialio-triggered-buffer.o 11obj-$(CONFIG_IIO_TRIGGERED_BUFFER) += industrialio-triggered-buffer.o
11obj-$(CONFIG_IIO_KFIFO_BUF) += kfifo_buf.o 12obj-$(CONFIG_IIO_KFIFO_BUF) += kfifo_buf.o
diff --git a/drivers/iio/buffer/industrialio-hw-consumer.c b/drivers/iio/buffer/industrialio-hw-consumer.c
new file mode 100644
index 000000000000..993ecdcdab64
--- /dev/null
+++ b/drivers/iio/buffer/industrialio-hw-consumer.c
@@ -0,0 +1,181 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright 2017 Analog Devices Inc.
4 * Author: Lars-Peter Clausen <lars@metafoo.de>
5 */
6
7#include <linux/err.h>
8#include <linux/export.h>
9#include <linux/slab.h>
10#include <linux/module.h>
11
12#include <linux/iio/iio.h>
13#include <linux/iio/consumer.h>
14#include <linux/iio/hw-consumer.h>
15#include <linux/iio/buffer_impl.h>
16
17/**
18 * struct iio_hw_consumer - IIO hw consumer block
19 * @buffers: hardware buffers list head.
20 * @channels: IIO provider channels.
21 */
22struct iio_hw_consumer {
23 struct list_head buffers;
24 struct iio_channel *channels;
25};
26
27struct hw_consumer_buffer {
28 struct list_head head;
29 struct iio_dev *indio_dev;
30 struct iio_buffer buffer;
31 long scan_mask[];
32};
33
34static struct hw_consumer_buffer *iio_buffer_to_hw_consumer_buffer(
35 struct iio_buffer *buffer)
36{
37 return container_of(buffer, struct hw_consumer_buffer, buffer);
38}
39
40static void iio_hw_buf_release(struct iio_buffer *buffer)
41{
42 struct hw_consumer_buffer *hw_buf =
43 iio_buffer_to_hw_consumer_buffer(buffer);
44 kfree(hw_buf);
45}
46
47static const struct iio_buffer_access_funcs iio_hw_buf_access = {
48 .release = &iio_hw_buf_release,
49 .modes = INDIO_BUFFER_HARDWARE,
50};
51
52static struct hw_consumer_buffer *iio_hw_consumer_get_buffer(
53 struct iio_hw_consumer *hwc, struct iio_dev *indio_dev)
54{
55 size_t mask_size = BITS_TO_LONGS(indio_dev->masklength) * sizeof(long);
56 struct hw_consumer_buffer *buf;
57
58 list_for_each_entry(buf, &hwc->buffers, head) {
59 if (buf->indio_dev == indio_dev)
60 return buf;
61 }
62
63 buf = kzalloc(sizeof(*buf) + mask_size, GFP_KERNEL);
64 if (!buf)
65 return NULL;
66
67 buf->buffer.access = &iio_hw_buf_access;
68 buf->indio_dev = indio_dev;
69 buf->buffer.scan_mask = buf->scan_mask;
70
71 iio_buffer_init(&buf->buffer);
72 list_add_tail(&buf->head, &hwc->buffers);
73
74 return buf;
75}
76
77/**
78 * iio_hw_consumer_alloc() - Allocate IIO hardware consumer
79 * @dev: Pointer to consumer device.
80 *
81 * Returns a valid iio_hw_consumer on success or a ERR_PTR() on failure.
82 */
83struct iio_hw_consumer *iio_hw_consumer_alloc(struct device *dev)
84{
85 struct hw_consumer_buffer *buf;
86 struct iio_hw_consumer *hwc;
87 struct iio_channel *chan;
88 int ret;
89
90 hwc = kzalloc(sizeof(*hwc), GFP_KERNEL);
91 if (!hwc)
92 return ERR_PTR(-ENOMEM);
93
94 INIT_LIST_HEAD(&hwc->buffers);
95
96 hwc->channels = iio_channel_get_all(dev);
97 if (IS_ERR(hwc->channels)) {
98 ret = PTR_ERR(hwc->channels);
99 goto err_free_hwc;
100 }
101
102 chan = &hwc->channels[0];
103 while (chan->indio_dev) {
104 buf = iio_hw_consumer_get_buffer(hwc, chan->indio_dev);
105 if (!buf) {
106 ret = -ENOMEM;
107 goto err_put_buffers;
108 }
109 set_bit(chan->channel->scan_index, buf->buffer.scan_mask);
110 chan++;
111 }
112
113 return hwc;
114
115err_put_buffers:
116 list_for_each_entry(buf, &hwc->buffers, head)
117 iio_buffer_put(&buf->buffer);
118 iio_channel_release_all(hwc->channels);
119err_free_hwc:
120 kfree(hwc);
121 return ERR_PTR(ret);
122}
123EXPORT_SYMBOL_GPL(iio_hw_consumer_alloc);
124
125/**
126 * iio_hw_consumer_free() - Free IIO hardware consumer
127 * @hwc: hw consumer to free.
128 */
129void iio_hw_consumer_free(struct iio_hw_consumer *hwc)
130{
131 struct hw_consumer_buffer *buf, *n;
132
133 iio_channel_release_all(hwc->channels);
134 list_for_each_entry_safe(buf, n, &hwc->buffers, head)
135 iio_buffer_put(&buf->buffer);
136 kfree(hwc);
137}
138EXPORT_SYMBOL_GPL(iio_hw_consumer_free);
139
140/**
141 * iio_hw_consumer_enable() - Enable IIO hardware consumer
142 * @hwc: iio_hw_consumer to enable.
143 *
144 * Returns 0 on success.
145 */
146int iio_hw_consumer_enable(struct iio_hw_consumer *hwc)
147{
148 struct hw_consumer_buffer *buf;
149 int ret;
150
151 list_for_each_entry(buf, &hwc->buffers, head) {
152 ret = iio_update_buffers(buf->indio_dev, &buf->buffer, NULL);
153 if (ret)
154 goto err_disable_buffers;
155 }
156
157 return 0;
158
159err_disable_buffers:
160 list_for_each_entry_continue_reverse(buf, &hwc->buffers, head)
161 iio_update_buffers(buf->indio_dev, NULL, &buf->buffer);
162 return ret;
163}
164EXPORT_SYMBOL_GPL(iio_hw_consumer_enable);
165
166/**
167 * iio_hw_consumer_disable() - Disable IIO hardware consumer
168 * @hwc: iio_hw_consumer to disable.
169 */
170void iio_hw_consumer_disable(struct iio_hw_consumer *hwc)
171{
172 struct hw_consumer_buffer *buf;
173
174 list_for_each_entry(buf, &hwc->buffers, head)
175 iio_update_buffers(buf->indio_dev, NULL, &buf->buffer);
176}
177EXPORT_SYMBOL_GPL(iio_hw_consumer_disable);
178
179MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
180MODULE_DESCRIPTION("Hardware consumer buffer the IIO framework");
181MODULE_LICENSE("GPL v2");
diff --git a/include/linux/iio/hw-consumer.h b/include/linux/iio/hw-consumer.h
new file mode 100644
index 000000000000..db8c00b9c7a5
--- /dev/null
+++ b/include/linux/iio/hw-consumer.h
@@ -0,0 +1,19 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Industrial I/O in kernel hardware consumer interface
4 *
5 * Copyright 2017 Analog Devices Inc.
6 * Author: Lars-Peter Clausen <lars@metafoo.de>
7 */
8
9#ifndef LINUX_IIO_HW_CONSUMER_H
10#define LINUX_IIO_HW_CONSUMER_H
11
12struct iio_hw_consumer;
13
14struct iio_hw_consumer *iio_hw_consumer_alloc(struct device *dev);
15void iio_hw_consumer_free(struct iio_hw_consumer *hwc);
16int iio_hw_consumer_enable(struct iio_hw_consumer *hwc);
17void iio_hw_consumer_disable(struct iio_hw_consumer *hwc);
18
19#endif