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 */ 22 struct iio_hw_consumer { 23 struct list_head buffers; 24 struct iio_channel *channels; 25 }; 26 27 struct hw_consumer_buffer { 28 struct list_head head; 29 struct iio_dev *indio_dev; 30 struct iio_buffer buffer; 31 }; 32 33 static struct hw_consumer_buffer *iio_buffer_to_hw_consumer_buffer( 34 struct iio_buffer *buffer) 35 { 36 return container_of(buffer, struct hw_consumer_buffer, buffer); 37 } 38 39 static void iio_hw_buf_release(struct iio_buffer *buffer) 40 { 41 struct hw_consumer_buffer *hw_buf = 42 iio_buffer_to_hw_consumer_buffer(buffer); 43 kfree(hw_buf); 44 } 45 46 static const struct iio_buffer_access_funcs iio_hw_buf_access = { 47 .release = &iio_hw_buf_release, 48 .modes = INDIO_BUFFER_HARDWARE, 49 }; 50 51 static struct hw_consumer_buffer *iio_hw_consumer_get_buffer( 52 struct iio_hw_consumer *hwc, struct iio_dev *indio_dev) 53 { 54 struct hw_consumer_buffer *buf; 55 56 list_for_each_entry(buf, &hwc->buffers, head) { 57 if (buf->indio_dev == indio_dev) 58 return buf; 59 } 60 61 buf = kzalloc_obj(*buf); 62 if (!buf) 63 return NULL; 64 65 buf->buffer.access = &iio_hw_buf_access; 66 buf->indio_dev = indio_dev; 67 buf->buffer.scan_mask = bitmap_zalloc(iio_get_masklength(indio_dev), 68 GFP_KERNEL); 69 if (!buf->buffer.scan_mask) { 70 kfree(buf); 71 return NULL; 72 } 73 74 iio_buffer_init(&buf->buffer); 75 list_add_tail(&buf->head, &hwc->buffers); 76 77 return buf; 78 } 79 80 /** 81 * iio_hw_consumer_alloc() - Allocate IIO hardware consumer 82 * @dev: Pointer to consumer device. 83 * 84 * Returns a valid iio_hw_consumer on success or a ERR_PTR() on failure. 85 */ 86 struct iio_hw_consumer *iio_hw_consumer_alloc(struct device *dev) 87 { 88 struct hw_consumer_buffer *buf; 89 struct iio_hw_consumer *hwc; 90 struct iio_channel *chan; 91 int ret; 92 93 hwc = kzalloc_obj(*hwc); 94 if (!hwc) 95 return ERR_PTR(-ENOMEM); 96 97 INIT_LIST_HEAD(&hwc->buffers); 98 99 hwc->channels = iio_channel_get_all(dev); 100 if (IS_ERR(hwc->channels)) { 101 ret = PTR_ERR(hwc->channels); 102 goto err_free_hwc; 103 } 104 105 chan = &hwc->channels[0]; 106 while (chan->indio_dev) { 107 buf = iio_hw_consumer_get_buffer(hwc, chan->indio_dev); 108 if (!buf) { 109 ret = -ENOMEM; 110 goto err_put_buffers; 111 } 112 set_bit(chan->channel->scan_index, buf->buffer.scan_mask); 113 chan++; 114 } 115 116 return hwc; 117 118 err_put_buffers: 119 list_for_each_entry(buf, &hwc->buffers, head) 120 iio_buffer_put(&buf->buffer); 121 iio_channel_release_all(hwc->channels); 122 err_free_hwc: 123 kfree(hwc); 124 return ERR_PTR(ret); 125 } 126 EXPORT_SYMBOL_GPL(iio_hw_consumer_alloc); 127 128 /** 129 * iio_hw_consumer_free() - Free IIO hardware consumer 130 * @hwc: hw consumer to free. 131 */ 132 void iio_hw_consumer_free(struct iio_hw_consumer *hwc) 133 { 134 struct hw_consumer_buffer *buf, *n; 135 136 iio_channel_release_all(hwc->channels); 137 list_for_each_entry_safe(buf, n, &hwc->buffers, head) 138 iio_buffer_put(&buf->buffer); 139 kfree(hwc); 140 } 141 EXPORT_SYMBOL_GPL(iio_hw_consumer_free); 142 143 static void devm_iio_hw_consumer_release(void *iio_hwc) 144 { 145 iio_hw_consumer_free(iio_hwc); 146 } 147 148 /** 149 * devm_iio_hw_consumer_alloc - Resource-managed iio_hw_consumer_alloc() 150 * @dev: Pointer to consumer device. 151 * 152 * Managed iio_hw_consumer_alloc. iio_hw_consumer allocated with this function 153 * is automatically freed on driver detach. 154 * 155 * returns pointer to allocated iio_hw_consumer on success, NULL on failure. 156 */ 157 struct iio_hw_consumer *devm_iio_hw_consumer_alloc(struct device *dev) 158 { 159 struct iio_hw_consumer *iio_hwc; 160 int ret; 161 162 iio_hwc = iio_hw_consumer_alloc(dev); 163 if (IS_ERR(iio_hwc)) 164 return iio_hwc; 165 166 ret = devm_add_action_or_reset(dev, devm_iio_hw_consumer_release, 167 iio_hwc); 168 if (ret) 169 return ERR_PTR(ret); 170 171 return iio_hwc; 172 } 173 EXPORT_SYMBOL_GPL(devm_iio_hw_consumer_alloc); 174 175 /** 176 * iio_hw_consumer_enable() - Enable IIO hardware consumer 177 * @hwc: iio_hw_consumer to enable. 178 * 179 * Returns 0 on success. 180 */ 181 int iio_hw_consumer_enable(struct iio_hw_consumer *hwc) 182 { 183 struct hw_consumer_buffer *buf; 184 int ret; 185 186 list_for_each_entry(buf, &hwc->buffers, head) { 187 ret = iio_update_buffers(buf->indio_dev, &buf->buffer, NULL); 188 if (ret) 189 goto err_disable_buffers; 190 } 191 192 return 0; 193 194 err_disable_buffers: 195 list_for_each_entry_continue_reverse(buf, &hwc->buffers, head) 196 iio_update_buffers(buf->indio_dev, NULL, &buf->buffer); 197 return ret; 198 } 199 EXPORT_SYMBOL_GPL(iio_hw_consumer_enable); 200 201 /** 202 * iio_hw_consumer_disable() - Disable IIO hardware consumer 203 * @hwc: iio_hw_consumer to disable. 204 */ 205 void iio_hw_consumer_disable(struct iio_hw_consumer *hwc) 206 { 207 struct hw_consumer_buffer *buf; 208 209 list_for_each_entry(buf, &hwc->buffers, head) 210 iio_update_buffers(buf->indio_dev, NULL, &buf->buffer); 211 } 212 EXPORT_SYMBOL_GPL(iio_hw_consumer_disable); 213 214 MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); 215 MODULE_DESCRIPTION("Hardware consumer buffer the IIO framework"); 216 MODULE_LICENSE("GPL v2"); 217