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