162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (c) 2011 Jonathan Cameron 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Buffer handling elements of industrial I/O reference driver. 662306a36Sopenharmony_ci * Uses the kfifo buffer. 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * To test without hardware use the sysfs trigger. 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include <linux/kernel.h> 1262306a36Sopenharmony_ci#include <linux/export.h> 1362306a36Sopenharmony_ci#include <linux/slab.h> 1462306a36Sopenharmony_ci#include <linux/interrupt.h> 1562306a36Sopenharmony_ci#include <linux/irq.h> 1662306a36Sopenharmony_ci#include <linux/bitmap.h> 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#include <linux/iio/iio.h> 1962306a36Sopenharmony_ci#include <linux/iio/buffer.h> 2062306a36Sopenharmony_ci#include <linux/iio/trigger_consumer.h> 2162306a36Sopenharmony_ci#include <linux/iio/triggered_buffer.h> 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#include "iio_simple_dummy.h" 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci/* Some fake data */ 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_cistatic const s16 fakedata[] = { 2862306a36Sopenharmony_ci [DUMMY_INDEX_VOLTAGE_0] = 7, 2962306a36Sopenharmony_ci [DUMMY_INDEX_DIFFVOLTAGE_1M2] = -33, 3062306a36Sopenharmony_ci [DUMMY_INDEX_DIFFVOLTAGE_3M4] = -2, 3162306a36Sopenharmony_ci [DUMMY_INDEX_ACCELX] = 344, 3262306a36Sopenharmony_ci}; 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci/** 3562306a36Sopenharmony_ci * iio_simple_dummy_trigger_h() - the trigger handler function 3662306a36Sopenharmony_ci * @irq: the interrupt number 3762306a36Sopenharmony_ci * @p: private data - always a pointer to the poll func. 3862306a36Sopenharmony_ci * 3962306a36Sopenharmony_ci * This is the guts of buffered capture. On a trigger event occurring, 4062306a36Sopenharmony_ci * if the pollfunc is attached then this handler is called as a threaded 4162306a36Sopenharmony_ci * interrupt (and hence may sleep). It is responsible for grabbing data 4262306a36Sopenharmony_ci * from the device and pushing it into the associated buffer. 4362306a36Sopenharmony_ci */ 4462306a36Sopenharmony_cistatic irqreturn_t iio_simple_dummy_trigger_h(int irq, void *p) 4562306a36Sopenharmony_ci{ 4662306a36Sopenharmony_ci struct iio_poll_func *pf = p; 4762306a36Sopenharmony_ci struct iio_dev *indio_dev = pf->indio_dev; 4862306a36Sopenharmony_ci int i = 0, j; 4962306a36Sopenharmony_ci u16 *data; 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL); 5262306a36Sopenharmony_ci if (!data) 5362306a36Sopenharmony_ci goto done; 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci /* 5662306a36Sopenharmony_ci * Three common options here: 5762306a36Sopenharmony_ci * hardware scans: 5862306a36Sopenharmony_ci * certain combinations of channels make up a fast read. The capture 5962306a36Sopenharmony_ci * will consist of all of them. Hence we just call the grab data 6062306a36Sopenharmony_ci * function and fill the buffer without processing. 6162306a36Sopenharmony_ci * software scans: 6262306a36Sopenharmony_ci * can be considered to be random access so efficient reading is just 6362306a36Sopenharmony_ci * a case of minimal bus transactions. 6462306a36Sopenharmony_ci * software culled hardware scans: 6562306a36Sopenharmony_ci * occasionally a driver may process the nearest hardware scan to avoid 6662306a36Sopenharmony_ci * storing elements that are not desired. This is the fiddliest option 6762306a36Sopenharmony_ci * by far. 6862306a36Sopenharmony_ci * Here let's pretend we have random access. And the values are in the 6962306a36Sopenharmony_ci * constant table fakedata. 7062306a36Sopenharmony_ci */ 7162306a36Sopenharmony_ci for_each_set_bit(j, indio_dev->active_scan_mask, indio_dev->masklength) 7262306a36Sopenharmony_ci data[i++] = fakedata[j]; 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci iio_push_to_buffers_with_timestamp(indio_dev, data, 7562306a36Sopenharmony_ci iio_get_time_ns(indio_dev)); 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci kfree(data); 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_cidone: 8062306a36Sopenharmony_ci /* 8162306a36Sopenharmony_ci * Tell the core we are done with this trigger and ready for the 8262306a36Sopenharmony_ci * next one. 8362306a36Sopenharmony_ci */ 8462306a36Sopenharmony_ci iio_trigger_notify_done(indio_dev->trig); 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci return IRQ_HANDLED; 8762306a36Sopenharmony_ci} 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_cistatic const struct iio_buffer_setup_ops iio_simple_dummy_buffer_setup_ops = { 9062306a36Sopenharmony_ci}; 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ciint iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev) 9362306a36Sopenharmony_ci{ 9462306a36Sopenharmony_ci return iio_triggered_buffer_setup(indio_dev, NULL, 9562306a36Sopenharmony_ci iio_simple_dummy_trigger_h, 9662306a36Sopenharmony_ci &iio_simple_dummy_buffer_setup_ops); 9762306a36Sopenharmony_ci} 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci/** 10062306a36Sopenharmony_ci * iio_simple_dummy_unconfigure_buffer() - release buffer resources 10162306a36Sopenharmony_ci * @indio_dev: device instance state 10262306a36Sopenharmony_ci */ 10362306a36Sopenharmony_civoid iio_simple_dummy_unconfigure_buffer(struct iio_dev *indio_dev) 10462306a36Sopenharmony_ci{ 10562306a36Sopenharmony_ci iio_triggered_buffer_cleanup(indio_dev); 10662306a36Sopenharmony_ci} 107