18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (c) 2011 Jonathan Cameron 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Buffer handling elements of industrial I/O reference driver. 68c2ecf20Sopenharmony_ci * Uses the kfifo buffer. 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * To test without hardware use the sysfs trigger. 98c2ecf20Sopenharmony_ci */ 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <linux/kernel.h> 128c2ecf20Sopenharmony_ci#include <linux/export.h> 138c2ecf20Sopenharmony_ci#include <linux/slab.h> 148c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 158c2ecf20Sopenharmony_ci#include <linux/irq.h> 168c2ecf20Sopenharmony_ci#include <linux/bitmap.h> 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci#include <linux/iio/iio.h> 198c2ecf20Sopenharmony_ci#include <linux/iio/trigger_consumer.h> 208c2ecf20Sopenharmony_ci#include <linux/iio/buffer.h> 218c2ecf20Sopenharmony_ci#include <linux/iio/kfifo_buf.h> 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci#include "iio_simple_dummy.h" 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci/* Some fake data */ 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_cistatic const s16 fakedata[] = { 288c2ecf20Sopenharmony_ci [DUMMY_INDEX_VOLTAGE_0] = 7, 298c2ecf20Sopenharmony_ci [DUMMY_INDEX_DIFFVOLTAGE_1M2] = -33, 308c2ecf20Sopenharmony_ci [DUMMY_INDEX_DIFFVOLTAGE_3M4] = -2, 318c2ecf20Sopenharmony_ci [DUMMY_INDEX_ACCELX] = 344, 328c2ecf20Sopenharmony_ci}; 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci/** 358c2ecf20Sopenharmony_ci * iio_simple_dummy_trigger_h() - the trigger handler function 368c2ecf20Sopenharmony_ci * @irq: the interrupt number 378c2ecf20Sopenharmony_ci * @p: private data - always a pointer to the poll func. 388c2ecf20Sopenharmony_ci * 398c2ecf20Sopenharmony_ci * This is the guts of buffered capture. On a trigger event occurring, 408c2ecf20Sopenharmony_ci * if the pollfunc is attached then this handler is called as a threaded 418c2ecf20Sopenharmony_ci * interrupt (and hence may sleep). It is responsible for grabbing data 428c2ecf20Sopenharmony_ci * from the device and pushing it into the associated buffer. 438c2ecf20Sopenharmony_ci */ 448c2ecf20Sopenharmony_cistatic irqreturn_t iio_simple_dummy_trigger_h(int irq, void *p) 458c2ecf20Sopenharmony_ci{ 468c2ecf20Sopenharmony_ci struct iio_poll_func *pf = p; 478c2ecf20Sopenharmony_ci struct iio_dev *indio_dev = pf->indio_dev; 488c2ecf20Sopenharmony_ci int len = 0; 498c2ecf20Sopenharmony_ci u16 *data; 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL); 528c2ecf20Sopenharmony_ci if (!data) 538c2ecf20Sopenharmony_ci goto done; 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength)) { 568c2ecf20Sopenharmony_ci /* 578c2ecf20Sopenharmony_ci * Three common options here: 588c2ecf20Sopenharmony_ci * hardware scans: certain combinations of channels make 598c2ecf20Sopenharmony_ci * up a fast read. The capture will consist of all of them. 608c2ecf20Sopenharmony_ci * Hence we just call the grab data function and fill the 618c2ecf20Sopenharmony_ci * buffer without processing. 628c2ecf20Sopenharmony_ci * software scans: can be considered to be random access 638c2ecf20Sopenharmony_ci * so efficient reading is just a case of minimal bus 648c2ecf20Sopenharmony_ci * transactions. 658c2ecf20Sopenharmony_ci * software culled hardware scans: 668c2ecf20Sopenharmony_ci * occasionally a driver may process the nearest hardware 678c2ecf20Sopenharmony_ci * scan to avoid storing elements that are not desired. This 688c2ecf20Sopenharmony_ci * is the fiddliest option by far. 698c2ecf20Sopenharmony_ci * Here let's pretend we have random access. And the values are 708c2ecf20Sopenharmony_ci * in the constant table fakedata. 718c2ecf20Sopenharmony_ci */ 728c2ecf20Sopenharmony_ci int i, j; 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci for (i = 0, j = 0; 758c2ecf20Sopenharmony_ci i < bitmap_weight(indio_dev->active_scan_mask, 768c2ecf20Sopenharmony_ci indio_dev->masklength); 778c2ecf20Sopenharmony_ci i++, j++) { 788c2ecf20Sopenharmony_ci j = find_next_bit(indio_dev->active_scan_mask, 798c2ecf20Sopenharmony_ci indio_dev->masklength, j); 808c2ecf20Sopenharmony_ci /* random access read from the 'device' */ 818c2ecf20Sopenharmony_ci data[i] = fakedata[j]; 828c2ecf20Sopenharmony_ci len += 2; 838c2ecf20Sopenharmony_ci } 848c2ecf20Sopenharmony_ci } 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci iio_push_to_buffers_with_timestamp(indio_dev, data, 878c2ecf20Sopenharmony_ci iio_get_time_ns(indio_dev)); 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci kfree(data); 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_cidone: 928c2ecf20Sopenharmony_ci /* 938c2ecf20Sopenharmony_ci * Tell the core we are done with this trigger and ready for the 948c2ecf20Sopenharmony_ci * next one. 958c2ecf20Sopenharmony_ci */ 968c2ecf20Sopenharmony_ci iio_trigger_notify_done(indio_dev->trig); 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci return IRQ_HANDLED; 998c2ecf20Sopenharmony_ci} 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_cistatic const struct iio_buffer_setup_ops iio_simple_dummy_buffer_setup_ops = { 1028c2ecf20Sopenharmony_ci}; 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ciint iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev) 1058c2ecf20Sopenharmony_ci{ 1068c2ecf20Sopenharmony_ci int ret; 1078c2ecf20Sopenharmony_ci struct iio_buffer *buffer; 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci /* Allocate a buffer to use - here a kfifo */ 1108c2ecf20Sopenharmony_ci buffer = iio_kfifo_allocate(); 1118c2ecf20Sopenharmony_ci if (!buffer) { 1128c2ecf20Sopenharmony_ci ret = -ENOMEM; 1138c2ecf20Sopenharmony_ci goto error_ret; 1148c2ecf20Sopenharmony_ci } 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci iio_device_attach_buffer(indio_dev, buffer); 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci /* 1198c2ecf20Sopenharmony_ci * Tell the core what device type specific functions should 1208c2ecf20Sopenharmony_ci * be run on either side of buffer capture enable / disable. 1218c2ecf20Sopenharmony_ci */ 1228c2ecf20Sopenharmony_ci indio_dev->setup_ops = &iio_simple_dummy_buffer_setup_ops; 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci /* 1258c2ecf20Sopenharmony_ci * Configure a polling function. 1268c2ecf20Sopenharmony_ci * When a trigger event with this polling function connected 1278c2ecf20Sopenharmony_ci * occurs, this function is run. Typically this grabs data 1288c2ecf20Sopenharmony_ci * from the device. 1298c2ecf20Sopenharmony_ci * 1308c2ecf20Sopenharmony_ci * NULL for the bottom half. This is normally implemented only if we 1318c2ecf20Sopenharmony_ci * either want to ping a capture now pin (no sleeping) or grab 1328c2ecf20Sopenharmony_ci * a timestamp as close as possible to a data ready trigger firing. 1338c2ecf20Sopenharmony_ci * 1348c2ecf20Sopenharmony_ci * IRQF_ONESHOT ensures irqs are masked such that only one instance 1358c2ecf20Sopenharmony_ci * of the handler can run at a time. 1368c2ecf20Sopenharmony_ci * 1378c2ecf20Sopenharmony_ci * "iio_simple_dummy_consumer%d" formatting string for the irq 'name' 1388c2ecf20Sopenharmony_ci * as seen under /proc/interrupts. Remaining parameters as per printk. 1398c2ecf20Sopenharmony_ci */ 1408c2ecf20Sopenharmony_ci indio_dev->pollfunc = iio_alloc_pollfunc(NULL, 1418c2ecf20Sopenharmony_ci &iio_simple_dummy_trigger_h, 1428c2ecf20Sopenharmony_ci IRQF_ONESHOT, 1438c2ecf20Sopenharmony_ci indio_dev, 1448c2ecf20Sopenharmony_ci "iio_simple_dummy_consumer%d", 1458c2ecf20Sopenharmony_ci indio_dev->id); 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci if (!indio_dev->pollfunc) { 1488c2ecf20Sopenharmony_ci ret = -ENOMEM; 1498c2ecf20Sopenharmony_ci goto error_free_buffer; 1508c2ecf20Sopenharmony_ci } 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci /* 1538c2ecf20Sopenharmony_ci * Notify the core that this device is capable of buffered capture 1548c2ecf20Sopenharmony_ci * driven by a trigger. 1558c2ecf20Sopenharmony_ci */ 1568c2ecf20Sopenharmony_ci indio_dev->modes |= INDIO_BUFFER_TRIGGERED; 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci return 0; 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_cierror_free_buffer: 1618c2ecf20Sopenharmony_ci iio_kfifo_free(indio_dev->buffer); 1628c2ecf20Sopenharmony_cierror_ret: 1638c2ecf20Sopenharmony_ci return ret; 1648c2ecf20Sopenharmony_ci} 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci/** 1678c2ecf20Sopenharmony_ci * iio_simple_dummy_unconfigure_buffer() - release buffer resources 1688c2ecf20Sopenharmony_ci * @indio_dev: device instance state 1698c2ecf20Sopenharmony_ci */ 1708c2ecf20Sopenharmony_civoid iio_simple_dummy_unconfigure_buffer(struct iio_dev *indio_dev) 1718c2ecf20Sopenharmony_ci{ 1728c2ecf20Sopenharmony_ci iio_dealloc_pollfunc(indio_dev->pollfunc); 1738c2ecf20Sopenharmony_ci iio_kfifo_free(indio_dev->buffer); 1748c2ecf20Sopenharmony_ci} 175