18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (c) 2011 Jonathan Cameron 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * A reference industrial I/O driver to illustrate the functionality available. 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * There are numerous real drivers to illustrate the finer points. 88c2ecf20Sopenharmony_ci * The purpose of this driver is to provide a driver with far more comments 98c2ecf20Sopenharmony_ci * and explanatory notes than any 'real' driver would have. 108c2ecf20Sopenharmony_ci * Anyone starting out writing an IIO driver should first make sure they 118c2ecf20Sopenharmony_ci * understand all of this driver except those bits specifically marked 128c2ecf20Sopenharmony_ci * as being present to allow us to 'fake' the presence of hardware. 138c2ecf20Sopenharmony_ci */ 148c2ecf20Sopenharmony_ci#include <linux/kernel.h> 158c2ecf20Sopenharmony_ci#include <linux/slab.h> 168c2ecf20Sopenharmony_ci#include <linux/module.h> 178c2ecf20Sopenharmony_ci#include <linux/string.h> 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#include <linux/iio/iio.h> 208c2ecf20Sopenharmony_ci#include <linux/iio/sysfs.h> 218c2ecf20Sopenharmony_ci#include <linux/iio/events.h> 228c2ecf20Sopenharmony_ci#include <linux/iio/buffer.h> 238c2ecf20Sopenharmony_ci#include <linux/iio/sw_device.h> 248c2ecf20Sopenharmony_ci#include "iio_simple_dummy.h" 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_cistatic const struct config_item_type iio_dummy_type = { 278c2ecf20Sopenharmony_ci .ct_owner = THIS_MODULE, 288c2ecf20Sopenharmony_ci}; 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci/** 318c2ecf20Sopenharmony_ci * struct iio_dummy_accel_calibscale - realworld to register mapping 328c2ecf20Sopenharmony_ci * @val: first value in read_raw - here integer part. 338c2ecf20Sopenharmony_ci * @val2: second value in read_raw etc - here micro part. 348c2ecf20Sopenharmony_ci * @regval: register value - magic device specific numbers. 358c2ecf20Sopenharmony_ci */ 368c2ecf20Sopenharmony_cistruct iio_dummy_accel_calibscale { 378c2ecf20Sopenharmony_ci int val; 388c2ecf20Sopenharmony_ci int val2; 398c2ecf20Sopenharmony_ci int regval; /* what would be written to hardware */ 408c2ecf20Sopenharmony_ci}; 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_cistatic const struct iio_dummy_accel_calibscale dummy_scales[] = { 438c2ecf20Sopenharmony_ci { 0, 100, 0x8 }, /* 0.000100 */ 448c2ecf20Sopenharmony_ci { 0, 133, 0x7 }, /* 0.000133 */ 458c2ecf20Sopenharmony_ci { 733, 13, 0x9 }, /* 733.000013 */ 468c2ecf20Sopenharmony_ci}; 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci#ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci/* 518c2ecf20Sopenharmony_ci * simple event - triggered when value rises above 528c2ecf20Sopenharmony_ci * a threshold 538c2ecf20Sopenharmony_ci */ 548c2ecf20Sopenharmony_cistatic const struct iio_event_spec iio_dummy_event = { 558c2ecf20Sopenharmony_ci .type = IIO_EV_TYPE_THRESH, 568c2ecf20Sopenharmony_ci .dir = IIO_EV_DIR_RISING, 578c2ecf20Sopenharmony_ci .mask_separate = BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_ENABLE), 588c2ecf20Sopenharmony_ci}; 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci/* 618c2ecf20Sopenharmony_ci * simple step detect event - triggered when a step is detected 628c2ecf20Sopenharmony_ci */ 638c2ecf20Sopenharmony_cistatic const struct iio_event_spec step_detect_event = { 648c2ecf20Sopenharmony_ci .type = IIO_EV_TYPE_CHANGE, 658c2ecf20Sopenharmony_ci .dir = IIO_EV_DIR_NONE, 668c2ecf20Sopenharmony_ci .mask_separate = BIT(IIO_EV_INFO_ENABLE), 678c2ecf20Sopenharmony_ci}; 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci/* 708c2ecf20Sopenharmony_ci * simple transition event - triggered when the reported running confidence 718c2ecf20Sopenharmony_ci * value rises above a threshold value 728c2ecf20Sopenharmony_ci */ 738c2ecf20Sopenharmony_cistatic const struct iio_event_spec iio_running_event = { 748c2ecf20Sopenharmony_ci .type = IIO_EV_TYPE_THRESH, 758c2ecf20Sopenharmony_ci .dir = IIO_EV_DIR_RISING, 768c2ecf20Sopenharmony_ci .mask_separate = BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_ENABLE), 778c2ecf20Sopenharmony_ci}; 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci/* 808c2ecf20Sopenharmony_ci * simple transition event - triggered when the reported walking confidence 818c2ecf20Sopenharmony_ci * value falls under a threshold value 828c2ecf20Sopenharmony_ci */ 838c2ecf20Sopenharmony_cistatic const struct iio_event_spec iio_walking_event = { 848c2ecf20Sopenharmony_ci .type = IIO_EV_TYPE_THRESH, 858c2ecf20Sopenharmony_ci .dir = IIO_EV_DIR_FALLING, 868c2ecf20Sopenharmony_ci .mask_separate = BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_ENABLE), 878c2ecf20Sopenharmony_ci}; 888c2ecf20Sopenharmony_ci#endif 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci/* 918c2ecf20Sopenharmony_ci * iio_dummy_channels - Description of available channels 928c2ecf20Sopenharmony_ci * 938c2ecf20Sopenharmony_ci * This array of structures tells the IIO core about what the device 948c2ecf20Sopenharmony_ci * actually provides for a given channel. 958c2ecf20Sopenharmony_ci */ 968c2ecf20Sopenharmony_cistatic const struct iio_chan_spec iio_dummy_channels[] = { 978c2ecf20Sopenharmony_ci /* indexed ADC channel in_voltage0_raw etc */ 988c2ecf20Sopenharmony_ci { 998c2ecf20Sopenharmony_ci .type = IIO_VOLTAGE, 1008c2ecf20Sopenharmony_ci /* Channel has a numeric index of 0 */ 1018c2ecf20Sopenharmony_ci .indexed = 1, 1028c2ecf20Sopenharmony_ci .channel = 0, 1038c2ecf20Sopenharmony_ci /* What other information is available? */ 1048c2ecf20Sopenharmony_ci .info_mask_separate = 1058c2ecf20Sopenharmony_ci /* 1068c2ecf20Sopenharmony_ci * in_voltage0_raw 1078c2ecf20Sopenharmony_ci * Raw (unscaled no bias removal etc) measurement 1088c2ecf20Sopenharmony_ci * from the device. 1098c2ecf20Sopenharmony_ci */ 1108c2ecf20Sopenharmony_ci BIT(IIO_CHAN_INFO_RAW) | 1118c2ecf20Sopenharmony_ci /* 1128c2ecf20Sopenharmony_ci * in_voltage0_offset 1138c2ecf20Sopenharmony_ci * Offset for userspace to apply prior to scale 1148c2ecf20Sopenharmony_ci * when converting to standard units (microvolts) 1158c2ecf20Sopenharmony_ci */ 1168c2ecf20Sopenharmony_ci BIT(IIO_CHAN_INFO_OFFSET) | 1178c2ecf20Sopenharmony_ci /* 1188c2ecf20Sopenharmony_ci * in_voltage0_scale 1198c2ecf20Sopenharmony_ci * Multipler for userspace to apply post offset 1208c2ecf20Sopenharmony_ci * when converting to standard units (microvolts) 1218c2ecf20Sopenharmony_ci */ 1228c2ecf20Sopenharmony_ci BIT(IIO_CHAN_INFO_SCALE), 1238c2ecf20Sopenharmony_ci /* 1248c2ecf20Sopenharmony_ci * sampling_frequency 1258c2ecf20Sopenharmony_ci * The frequency in Hz at which the channels are sampled 1268c2ecf20Sopenharmony_ci */ 1278c2ecf20Sopenharmony_ci .info_mask_shared_by_dir = BIT(IIO_CHAN_INFO_SAMP_FREQ), 1288c2ecf20Sopenharmony_ci /* The ordering of elements in the buffer via an enum */ 1298c2ecf20Sopenharmony_ci .scan_index = DUMMY_INDEX_VOLTAGE_0, 1308c2ecf20Sopenharmony_ci .scan_type = { /* Description of storage in buffer */ 1318c2ecf20Sopenharmony_ci .sign = 'u', /* unsigned */ 1328c2ecf20Sopenharmony_ci .realbits = 13, /* 13 bits */ 1338c2ecf20Sopenharmony_ci .storagebits = 16, /* 16 bits used for storage */ 1348c2ecf20Sopenharmony_ci .shift = 0, /* zero shift */ 1358c2ecf20Sopenharmony_ci }, 1368c2ecf20Sopenharmony_ci#ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS 1378c2ecf20Sopenharmony_ci .event_spec = &iio_dummy_event, 1388c2ecf20Sopenharmony_ci .num_event_specs = 1, 1398c2ecf20Sopenharmony_ci#endif /* CONFIG_IIO_SIMPLE_DUMMY_EVENTS */ 1408c2ecf20Sopenharmony_ci }, 1418c2ecf20Sopenharmony_ci /* Differential ADC channel in_voltage1-voltage2_raw etc*/ 1428c2ecf20Sopenharmony_ci { 1438c2ecf20Sopenharmony_ci .type = IIO_VOLTAGE, 1448c2ecf20Sopenharmony_ci .differential = 1, 1458c2ecf20Sopenharmony_ci /* 1468c2ecf20Sopenharmony_ci * Indexing for differential channels uses channel 1478c2ecf20Sopenharmony_ci * for the positive part, channel2 for the negative. 1488c2ecf20Sopenharmony_ci */ 1498c2ecf20Sopenharmony_ci .indexed = 1, 1508c2ecf20Sopenharmony_ci .channel = 1, 1518c2ecf20Sopenharmony_ci .channel2 = 2, 1528c2ecf20Sopenharmony_ci /* 1538c2ecf20Sopenharmony_ci * in_voltage1-voltage2_raw 1548c2ecf20Sopenharmony_ci * Raw (unscaled no bias removal etc) measurement 1558c2ecf20Sopenharmony_ci * from the device. 1568c2ecf20Sopenharmony_ci */ 1578c2ecf20Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), 1588c2ecf20Sopenharmony_ci /* 1598c2ecf20Sopenharmony_ci * in_voltage-voltage_scale 1608c2ecf20Sopenharmony_ci * Shared version of scale - shared by differential 1618c2ecf20Sopenharmony_ci * input channels of type IIO_VOLTAGE. 1628c2ecf20Sopenharmony_ci */ 1638c2ecf20Sopenharmony_ci .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), 1648c2ecf20Sopenharmony_ci /* 1658c2ecf20Sopenharmony_ci * sampling_frequency 1668c2ecf20Sopenharmony_ci * The frequency in Hz at which the channels are sampled 1678c2ecf20Sopenharmony_ci */ 1688c2ecf20Sopenharmony_ci .scan_index = DUMMY_INDEX_DIFFVOLTAGE_1M2, 1698c2ecf20Sopenharmony_ci .scan_type = { /* Description of storage in buffer */ 1708c2ecf20Sopenharmony_ci .sign = 's', /* signed */ 1718c2ecf20Sopenharmony_ci .realbits = 12, /* 12 bits */ 1728c2ecf20Sopenharmony_ci .storagebits = 16, /* 16 bits used for storage */ 1738c2ecf20Sopenharmony_ci .shift = 0, /* zero shift */ 1748c2ecf20Sopenharmony_ci }, 1758c2ecf20Sopenharmony_ci }, 1768c2ecf20Sopenharmony_ci /* Differential ADC channel in_voltage3-voltage4_raw etc*/ 1778c2ecf20Sopenharmony_ci { 1788c2ecf20Sopenharmony_ci .type = IIO_VOLTAGE, 1798c2ecf20Sopenharmony_ci .differential = 1, 1808c2ecf20Sopenharmony_ci .indexed = 1, 1818c2ecf20Sopenharmony_ci .channel = 3, 1828c2ecf20Sopenharmony_ci .channel2 = 4, 1838c2ecf20Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), 1848c2ecf20Sopenharmony_ci .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), 1858c2ecf20Sopenharmony_ci .info_mask_shared_by_dir = BIT(IIO_CHAN_INFO_SAMP_FREQ), 1868c2ecf20Sopenharmony_ci .scan_index = DUMMY_INDEX_DIFFVOLTAGE_3M4, 1878c2ecf20Sopenharmony_ci .scan_type = { 1888c2ecf20Sopenharmony_ci .sign = 's', 1898c2ecf20Sopenharmony_ci .realbits = 11, 1908c2ecf20Sopenharmony_ci .storagebits = 16, 1918c2ecf20Sopenharmony_ci .shift = 0, 1928c2ecf20Sopenharmony_ci }, 1938c2ecf20Sopenharmony_ci }, 1948c2ecf20Sopenharmony_ci /* 1958c2ecf20Sopenharmony_ci * 'modified' (i.e. axis specified) acceleration channel 1968c2ecf20Sopenharmony_ci * in_accel_z_raw 1978c2ecf20Sopenharmony_ci */ 1988c2ecf20Sopenharmony_ci { 1998c2ecf20Sopenharmony_ci .type = IIO_ACCEL, 2008c2ecf20Sopenharmony_ci .modified = 1, 2018c2ecf20Sopenharmony_ci /* Channel 2 is use for modifiers */ 2028c2ecf20Sopenharmony_ci .channel2 = IIO_MOD_X, 2038c2ecf20Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 2048c2ecf20Sopenharmony_ci /* 2058c2ecf20Sopenharmony_ci * Internal bias and gain correction values. Applied 2068c2ecf20Sopenharmony_ci * by the hardware or driver prior to userspace 2078c2ecf20Sopenharmony_ci * seeing the readings. Typically part of hardware 2088c2ecf20Sopenharmony_ci * calibration. 2098c2ecf20Sopenharmony_ci */ 2108c2ecf20Sopenharmony_ci BIT(IIO_CHAN_INFO_CALIBSCALE) | 2118c2ecf20Sopenharmony_ci BIT(IIO_CHAN_INFO_CALIBBIAS), 2128c2ecf20Sopenharmony_ci .info_mask_shared_by_dir = BIT(IIO_CHAN_INFO_SAMP_FREQ), 2138c2ecf20Sopenharmony_ci .scan_index = DUMMY_INDEX_ACCELX, 2148c2ecf20Sopenharmony_ci .scan_type = { /* Description of storage in buffer */ 2158c2ecf20Sopenharmony_ci .sign = 's', /* signed */ 2168c2ecf20Sopenharmony_ci .realbits = 16, /* 16 bits */ 2178c2ecf20Sopenharmony_ci .storagebits = 16, /* 16 bits used for storage */ 2188c2ecf20Sopenharmony_ci .shift = 0, /* zero shift */ 2198c2ecf20Sopenharmony_ci }, 2208c2ecf20Sopenharmony_ci }, 2218c2ecf20Sopenharmony_ci /* 2228c2ecf20Sopenharmony_ci * Convenience macro for timestamps. 4 is the index in 2238c2ecf20Sopenharmony_ci * the buffer. 2248c2ecf20Sopenharmony_ci */ 2258c2ecf20Sopenharmony_ci IIO_CHAN_SOFT_TIMESTAMP(4), 2268c2ecf20Sopenharmony_ci /* DAC channel out_voltage0_raw */ 2278c2ecf20Sopenharmony_ci { 2288c2ecf20Sopenharmony_ci .type = IIO_VOLTAGE, 2298c2ecf20Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), 2308c2ecf20Sopenharmony_ci .scan_index = -1, /* No buffer support */ 2318c2ecf20Sopenharmony_ci .output = 1, 2328c2ecf20Sopenharmony_ci .indexed = 1, 2338c2ecf20Sopenharmony_ci .channel = 0, 2348c2ecf20Sopenharmony_ci }, 2358c2ecf20Sopenharmony_ci { 2368c2ecf20Sopenharmony_ci .type = IIO_STEPS, 2378c2ecf20Sopenharmony_ci .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_ENABLE) | 2388c2ecf20Sopenharmony_ci BIT(IIO_CHAN_INFO_CALIBHEIGHT), 2398c2ecf20Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), 2408c2ecf20Sopenharmony_ci .scan_index = -1, /* No buffer support */ 2418c2ecf20Sopenharmony_ci#ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS 2428c2ecf20Sopenharmony_ci .event_spec = &step_detect_event, 2438c2ecf20Sopenharmony_ci .num_event_specs = 1, 2448c2ecf20Sopenharmony_ci#endif /* CONFIG_IIO_SIMPLE_DUMMY_EVENTS */ 2458c2ecf20Sopenharmony_ci }, 2468c2ecf20Sopenharmony_ci { 2478c2ecf20Sopenharmony_ci .type = IIO_ACTIVITY, 2488c2ecf20Sopenharmony_ci .modified = 1, 2498c2ecf20Sopenharmony_ci .channel2 = IIO_MOD_RUNNING, 2508c2ecf20Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), 2518c2ecf20Sopenharmony_ci .scan_index = -1, /* No buffer support */ 2528c2ecf20Sopenharmony_ci#ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS 2538c2ecf20Sopenharmony_ci .event_spec = &iio_running_event, 2548c2ecf20Sopenharmony_ci .num_event_specs = 1, 2558c2ecf20Sopenharmony_ci#endif /* CONFIG_IIO_SIMPLE_DUMMY_EVENTS */ 2568c2ecf20Sopenharmony_ci }, 2578c2ecf20Sopenharmony_ci { 2588c2ecf20Sopenharmony_ci .type = IIO_ACTIVITY, 2598c2ecf20Sopenharmony_ci .modified = 1, 2608c2ecf20Sopenharmony_ci .channel2 = IIO_MOD_WALKING, 2618c2ecf20Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), 2628c2ecf20Sopenharmony_ci .scan_index = -1, /* No buffer support */ 2638c2ecf20Sopenharmony_ci#ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS 2648c2ecf20Sopenharmony_ci .event_spec = &iio_walking_event, 2658c2ecf20Sopenharmony_ci .num_event_specs = 1, 2668c2ecf20Sopenharmony_ci#endif /* CONFIG_IIO_SIMPLE_DUMMY_EVENTS */ 2678c2ecf20Sopenharmony_ci }, 2688c2ecf20Sopenharmony_ci}; 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci/** 2718c2ecf20Sopenharmony_ci * iio_dummy_read_raw() - data read function. 2728c2ecf20Sopenharmony_ci * @indio_dev: the struct iio_dev associated with this device instance 2738c2ecf20Sopenharmony_ci * @chan: the channel whose data is to be read 2748c2ecf20Sopenharmony_ci * @val: first element of returned value (typically INT) 2758c2ecf20Sopenharmony_ci * @val2: second element of returned value (typically MICRO) 2768c2ecf20Sopenharmony_ci * @mask: what we actually want to read as per the info_mask_* 2778c2ecf20Sopenharmony_ci * in iio_chan_spec. 2788c2ecf20Sopenharmony_ci */ 2798c2ecf20Sopenharmony_cistatic int iio_dummy_read_raw(struct iio_dev *indio_dev, 2808c2ecf20Sopenharmony_ci struct iio_chan_spec const *chan, 2818c2ecf20Sopenharmony_ci int *val, 2828c2ecf20Sopenharmony_ci int *val2, 2838c2ecf20Sopenharmony_ci long mask) 2848c2ecf20Sopenharmony_ci{ 2858c2ecf20Sopenharmony_ci struct iio_dummy_state *st = iio_priv(indio_dev); 2868c2ecf20Sopenharmony_ci int ret = -EINVAL; 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_ci mutex_lock(&st->lock); 2898c2ecf20Sopenharmony_ci switch (mask) { 2908c2ecf20Sopenharmony_ci case IIO_CHAN_INFO_RAW: /* magic value - channel value read */ 2918c2ecf20Sopenharmony_ci switch (chan->type) { 2928c2ecf20Sopenharmony_ci case IIO_VOLTAGE: 2938c2ecf20Sopenharmony_ci if (chan->output) { 2948c2ecf20Sopenharmony_ci /* Set integer part to cached value */ 2958c2ecf20Sopenharmony_ci *val = st->dac_val; 2968c2ecf20Sopenharmony_ci ret = IIO_VAL_INT; 2978c2ecf20Sopenharmony_ci } else if (chan->differential) { 2988c2ecf20Sopenharmony_ci if (chan->channel == 1) 2998c2ecf20Sopenharmony_ci *val = st->differential_adc_val[0]; 3008c2ecf20Sopenharmony_ci else 3018c2ecf20Sopenharmony_ci *val = st->differential_adc_val[1]; 3028c2ecf20Sopenharmony_ci ret = IIO_VAL_INT; 3038c2ecf20Sopenharmony_ci } else { 3048c2ecf20Sopenharmony_ci *val = st->single_ended_adc_val; 3058c2ecf20Sopenharmony_ci ret = IIO_VAL_INT; 3068c2ecf20Sopenharmony_ci } 3078c2ecf20Sopenharmony_ci break; 3088c2ecf20Sopenharmony_ci case IIO_ACCEL: 3098c2ecf20Sopenharmony_ci *val = st->accel_val; 3108c2ecf20Sopenharmony_ci ret = IIO_VAL_INT; 3118c2ecf20Sopenharmony_ci break; 3128c2ecf20Sopenharmony_ci default: 3138c2ecf20Sopenharmony_ci break; 3148c2ecf20Sopenharmony_ci } 3158c2ecf20Sopenharmony_ci break; 3168c2ecf20Sopenharmony_ci case IIO_CHAN_INFO_PROCESSED: 3178c2ecf20Sopenharmony_ci switch (chan->type) { 3188c2ecf20Sopenharmony_ci case IIO_STEPS: 3198c2ecf20Sopenharmony_ci *val = st->steps; 3208c2ecf20Sopenharmony_ci ret = IIO_VAL_INT; 3218c2ecf20Sopenharmony_ci break; 3228c2ecf20Sopenharmony_ci case IIO_ACTIVITY: 3238c2ecf20Sopenharmony_ci switch (chan->channel2) { 3248c2ecf20Sopenharmony_ci case IIO_MOD_RUNNING: 3258c2ecf20Sopenharmony_ci *val = st->activity_running; 3268c2ecf20Sopenharmony_ci ret = IIO_VAL_INT; 3278c2ecf20Sopenharmony_ci break; 3288c2ecf20Sopenharmony_ci case IIO_MOD_WALKING: 3298c2ecf20Sopenharmony_ci *val = st->activity_walking; 3308c2ecf20Sopenharmony_ci ret = IIO_VAL_INT; 3318c2ecf20Sopenharmony_ci break; 3328c2ecf20Sopenharmony_ci default: 3338c2ecf20Sopenharmony_ci break; 3348c2ecf20Sopenharmony_ci } 3358c2ecf20Sopenharmony_ci break; 3368c2ecf20Sopenharmony_ci default: 3378c2ecf20Sopenharmony_ci break; 3388c2ecf20Sopenharmony_ci } 3398c2ecf20Sopenharmony_ci break; 3408c2ecf20Sopenharmony_ci case IIO_CHAN_INFO_OFFSET: 3418c2ecf20Sopenharmony_ci /* only single ended adc -> 7 */ 3428c2ecf20Sopenharmony_ci *val = 7; 3438c2ecf20Sopenharmony_ci ret = IIO_VAL_INT; 3448c2ecf20Sopenharmony_ci break; 3458c2ecf20Sopenharmony_ci case IIO_CHAN_INFO_SCALE: 3468c2ecf20Sopenharmony_ci switch (chan->type) { 3478c2ecf20Sopenharmony_ci case IIO_VOLTAGE: 3488c2ecf20Sopenharmony_ci switch (chan->differential) { 3498c2ecf20Sopenharmony_ci case 0: 3508c2ecf20Sopenharmony_ci /* only single ended adc -> 0.001333 */ 3518c2ecf20Sopenharmony_ci *val = 0; 3528c2ecf20Sopenharmony_ci *val2 = 1333; 3538c2ecf20Sopenharmony_ci ret = IIO_VAL_INT_PLUS_MICRO; 3548c2ecf20Sopenharmony_ci break; 3558c2ecf20Sopenharmony_ci case 1: 3568c2ecf20Sopenharmony_ci /* all differential adc -> 0.000001344 */ 3578c2ecf20Sopenharmony_ci *val = 0; 3588c2ecf20Sopenharmony_ci *val2 = 1344; 3598c2ecf20Sopenharmony_ci ret = IIO_VAL_INT_PLUS_NANO; 3608c2ecf20Sopenharmony_ci } 3618c2ecf20Sopenharmony_ci break; 3628c2ecf20Sopenharmony_ci default: 3638c2ecf20Sopenharmony_ci break; 3648c2ecf20Sopenharmony_ci } 3658c2ecf20Sopenharmony_ci break; 3668c2ecf20Sopenharmony_ci case IIO_CHAN_INFO_CALIBBIAS: 3678c2ecf20Sopenharmony_ci /* only the acceleration axis - read from cache */ 3688c2ecf20Sopenharmony_ci *val = st->accel_calibbias; 3698c2ecf20Sopenharmony_ci ret = IIO_VAL_INT; 3708c2ecf20Sopenharmony_ci break; 3718c2ecf20Sopenharmony_ci case IIO_CHAN_INFO_CALIBSCALE: 3728c2ecf20Sopenharmony_ci *val = st->accel_calibscale->val; 3738c2ecf20Sopenharmony_ci *val2 = st->accel_calibscale->val2; 3748c2ecf20Sopenharmony_ci ret = IIO_VAL_INT_PLUS_MICRO; 3758c2ecf20Sopenharmony_ci break; 3768c2ecf20Sopenharmony_ci case IIO_CHAN_INFO_SAMP_FREQ: 3778c2ecf20Sopenharmony_ci *val = 3; 3788c2ecf20Sopenharmony_ci *val2 = 33; 3798c2ecf20Sopenharmony_ci ret = IIO_VAL_INT_PLUS_NANO; 3808c2ecf20Sopenharmony_ci break; 3818c2ecf20Sopenharmony_ci case IIO_CHAN_INFO_ENABLE: 3828c2ecf20Sopenharmony_ci switch (chan->type) { 3838c2ecf20Sopenharmony_ci case IIO_STEPS: 3848c2ecf20Sopenharmony_ci *val = st->steps_enabled; 3858c2ecf20Sopenharmony_ci ret = IIO_VAL_INT; 3868c2ecf20Sopenharmony_ci break; 3878c2ecf20Sopenharmony_ci default: 3888c2ecf20Sopenharmony_ci break; 3898c2ecf20Sopenharmony_ci } 3908c2ecf20Sopenharmony_ci break; 3918c2ecf20Sopenharmony_ci case IIO_CHAN_INFO_CALIBHEIGHT: 3928c2ecf20Sopenharmony_ci switch (chan->type) { 3938c2ecf20Sopenharmony_ci case IIO_STEPS: 3948c2ecf20Sopenharmony_ci *val = st->height; 3958c2ecf20Sopenharmony_ci ret = IIO_VAL_INT; 3968c2ecf20Sopenharmony_ci break; 3978c2ecf20Sopenharmony_ci default: 3988c2ecf20Sopenharmony_ci break; 3998c2ecf20Sopenharmony_ci } 4008c2ecf20Sopenharmony_ci break; 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_ci default: 4038c2ecf20Sopenharmony_ci break; 4048c2ecf20Sopenharmony_ci } 4058c2ecf20Sopenharmony_ci mutex_unlock(&st->lock); 4068c2ecf20Sopenharmony_ci return ret; 4078c2ecf20Sopenharmony_ci} 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_ci/** 4108c2ecf20Sopenharmony_ci * iio_dummy_write_raw() - data write function. 4118c2ecf20Sopenharmony_ci * @indio_dev: the struct iio_dev associated with this device instance 4128c2ecf20Sopenharmony_ci * @chan: the channel whose data is to be written 4138c2ecf20Sopenharmony_ci * @val: first element of value to set (typically INT) 4148c2ecf20Sopenharmony_ci * @val2: second element of value to set (typically MICRO) 4158c2ecf20Sopenharmony_ci * @mask: what we actually want to write as per the info_mask_* 4168c2ecf20Sopenharmony_ci * in iio_chan_spec. 4178c2ecf20Sopenharmony_ci * 4188c2ecf20Sopenharmony_ci * Note that all raw writes are assumed IIO_VAL_INT and info mask elements 4198c2ecf20Sopenharmony_ci * are assumed to be IIO_INT_PLUS_MICRO unless the callback write_raw_get_fmt 4208c2ecf20Sopenharmony_ci * in struct iio_info is provided by the driver. 4218c2ecf20Sopenharmony_ci */ 4228c2ecf20Sopenharmony_cistatic int iio_dummy_write_raw(struct iio_dev *indio_dev, 4238c2ecf20Sopenharmony_ci struct iio_chan_spec const *chan, 4248c2ecf20Sopenharmony_ci int val, 4258c2ecf20Sopenharmony_ci int val2, 4268c2ecf20Sopenharmony_ci long mask) 4278c2ecf20Sopenharmony_ci{ 4288c2ecf20Sopenharmony_ci int i; 4298c2ecf20Sopenharmony_ci int ret = 0; 4308c2ecf20Sopenharmony_ci struct iio_dummy_state *st = iio_priv(indio_dev); 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_ci switch (mask) { 4338c2ecf20Sopenharmony_ci case IIO_CHAN_INFO_RAW: 4348c2ecf20Sopenharmony_ci switch (chan->type) { 4358c2ecf20Sopenharmony_ci case IIO_VOLTAGE: 4368c2ecf20Sopenharmony_ci if (chan->output == 0) 4378c2ecf20Sopenharmony_ci return -EINVAL; 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ci /* Locking not required as writing single value */ 4408c2ecf20Sopenharmony_ci mutex_lock(&st->lock); 4418c2ecf20Sopenharmony_ci st->dac_val = val; 4428c2ecf20Sopenharmony_ci mutex_unlock(&st->lock); 4438c2ecf20Sopenharmony_ci return 0; 4448c2ecf20Sopenharmony_ci default: 4458c2ecf20Sopenharmony_ci return -EINVAL; 4468c2ecf20Sopenharmony_ci } 4478c2ecf20Sopenharmony_ci case IIO_CHAN_INFO_PROCESSED: 4488c2ecf20Sopenharmony_ci switch (chan->type) { 4498c2ecf20Sopenharmony_ci case IIO_STEPS: 4508c2ecf20Sopenharmony_ci mutex_lock(&st->lock); 4518c2ecf20Sopenharmony_ci st->steps = val; 4528c2ecf20Sopenharmony_ci mutex_unlock(&st->lock); 4538c2ecf20Sopenharmony_ci return 0; 4548c2ecf20Sopenharmony_ci case IIO_ACTIVITY: 4558c2ecf20Sopenharmony_ci if (val < 0) 4568c2ecf20Sopenharmony_ci val = 0; 4578c2ecf20Sopenharmony_ci if (val > 100) 4588c2ecf20Sopenharmony_ci val = 100; 4598c2ecf20Sopenharmony_ci switch (chan->channel2) { 4608c2ecf20Sopenharmony_ci case IIO_MOD_RUNNING: 4618c2ecf20Sopenharmony_ci st->activity_running = val; 4628c2ecf20Sopenharmony_ci return 0; 4638c2ecf20Sopenharmony_ci case IIO_MOD_WALKING: 4648c2ecf20Sopenharmony_ci st->activity_walking = val; 4658c2ecf20Sopenharmony_ci return 0; 4668c2ecf20Sopenharmony_ci default: 4678c2ecf20Sopenharmony_ci return -EINVAL; 4688c2ecf20Sopenharmony_ci } 4698c2ecf20Sopenharmony_ci break; 4708c2ecf20Sopenharmony_ci default: 4718c2ecf20Sopenharmony_ci return -EINVAL; 4728c2ecf20Sopenharmony_ci } 4738c2ecf20Sopenharmony_ci case IIO_CHAN_INFO_CALIBSCALE: 4748c2ecf20Sopenharmony_ci mutex_lock(&st->lock); 4758c2ecf20Sopenharmony_ci /* Compare against table - hard matching here */ 4768c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(dummy_scales); i++) 4778c2ecf20Sopenharmony_ci if (val == dummy_scales[i].val && 4788c2ecf20Sopenharmony_ci val2 == dummy_scales[i].val2) 4798c2ecf20Sopenharmony_ci break; 4808c2ecf20Sopenharmony_ci if (i == ARRAY_SIZE(dummy_scales)) 4818c2ecf20Sopenharmony_ci ret = -EINVAL; 4828c2ecf20Sopenharmony_ci else 4838c2ecf20Sopenharmony_ci st->accel_calibscale = &dummy_scales[i]; 4848c2ecf20Sopenharmony_ci mutex_unlock(&st->lock); 4858c2ecf20Sopenharmony_ci return ret; 4868c2ecf20Sopenharmony_ci case IIO_CHAN_INFO_CALIBBIAS: 4878c2ecf20Sopenharmony_ci mutex_lock(&st->lock); 4888c2ecf20Sopenharmony_ci st->accel_calibbias = val; 4898c2ecf20Sopenharmony_ci mutex_unlock(&st->lock); 4908c2ecf20Sopenharmony_ci return 0; 4918c2ecf20Sopenharmony_ci case IIO_CHAN_INFO_ENABLE: 4928c2ecf20Sopenharmony_ci switch (chan->type) { 4938c2ecf20Sopenharmony_ci case IIO_STEPS: 4948c2ecf20Sopenharmony_ci mutex_lock(&st->lock); 4958c2ecf20Sopenharmony_ci st->steps_enabled = val; 4968c2ecf20Sopenharmony_ci mutex_unlock(&st->lock); 4978c2ecf20Sopenharmony_ci return 0; 4988c2ecf20Sopenharmony_ci default: 4998c2ecf20Sopenharmony_ci return -EINVAL; 5008c2ecf20Sopenharmony_ci } 5018c2ecf20Sopenharmony_ci case IIO_CHAN_INFO_CALIBHEIGHT: 5028c2ecf20Sopenharmony_ci switch (chan->type) { 5038c2ecf20Sopenharmony_ci case IIO_STEPS: 5048c2ecf20Sopenharmony_ci st->height = val; 5058c2ecf20Sopenharmony_ci return 0; 5068c2ecf20Sopenharmony_ci default: 5078c2ecf20Sopenharmony_ci return -EINVAL; 5088c2ecf20Sopenharmony_ci } 5098c2ecf20Sopenharmony_ci 5108c2ecf20Sopenharmony_ci default: 5118c2ecf20Sopenharmony_ci return -EINVAL; 5128c2ecf20Sopenharmony_ci } 5138c2ecf20Sopenharmony_ci} 5148c2ecf20Sopenharmony_ci 5158c2ecf20Sopenharmony_ci/* 5168c2ecf20Sopenharmony_ci * Device type specific information. 5178c2ecf20Sopenharmony_ci */ 5188c2ecf20Sopenharmony_cistatic const struct iio_info iio_dummy_info = { 5198c2ecf20Sopenharmony_ci .read_raw = &iio_dummy_read_raw, 5208c2ecf20Sopenharmony_ci .write_raw = &iio_dummy_write_raw, 5218c2ecf20Sopenharmony_ci#ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS 5228c2ecf20Sopenharmony_ci .read_event_config = &iio_simple_dummy_read_event_config, 5238c2ecf20Sopenharmony_ci .write_event_config = &iio_simple_dummy_write_event_config, 5248c2ecf20Sopenharmony_ci .read_event_value = &iio_simple_dummy_read_event_value, 5258c2ecf20Sopenharmony_ci .write_event_value = &iio_simple_dummy_write_event_value, 5268c2ecf20Sopenharmony_ci#endif /* CONFIG_IIO_SIMPLE_DUMMY_EVENTS */ 5278c2ecf20Sopenharmony_ci}; 5288c2ecf20Sopenharmony_ci 5298c2ecf20Sopenharmony_ci/** 5308c2ecf20Sopenharmony_ci * iio_dummy_init_device() - device instance specific init 5318c2ecf20Sopenharmony_ci * @indio_dev: the iio device structure 5328c2ecf20Sopenharmony_ci * 5338c2ecf20Sopenharmony_ci * Most drivers have one of these to set up default values, 5348c2ecf20Sopenharmony_ci * reset the device to known state etc. 5358c2ecf20Sopenharmony_ci */ 5368c2ecf20Sopenharmony_cistatic int iio_dummy_init_device(struct iio_dev *indio_dev) 5378c2ecf20Sopenharmony_ci{ 5388c2ecf20Sopenharmony_ci struct iio_dummy_state *st = iio_priv(indio_dev); 5398c2ecf20Sopenharmony_ci 5408c2ecf20Sopenharmony_ci st->dac_val = 0; 5418c2ecf20Sopenharmony_ci st->single_ended_adc_val = 73; 5428c2ecf20Sopenharmony_ci st->differential_adc_val[0] = 33; 5438c2ecf20Sopenharmony_ci st->differential_adc_val[1] = -34; 5448c2ecf20Sopenharmony_ci st->accel_val = 34; 5458c2ecf20Sopenharmony_ci st->accel_calibbias = -7; 5468c2ecf20Sopenharmony_ci st->accel_calibscale = &dummy_scales[0]; 5478c2ecf20Sopenharmony_ci st->steps = 47; 5488c2ecf20Sopenharmony_ci st->activity_running = 98; 5498c2ecf20Sopenharmony_ci st->activity_walking = 4; 5508c2ecf20Sopenharmony_ci 5518c2ecf20Sopenharmony_ci return 0; 5528c2ecf20Sopenharmony_ci} 5538c2ecf20Sopenharmony_ci 5548c2ecf20Sopenharmony_ci/** 5558c2ecf20Sopenharmony_ci * iio_dummy_probe() - device instance probe 5568c2ecf20Sopenharmony_ci * @name: name of this instance. 5578c2ecf20Sopenharmony_ci * 5588c2ecf20Sopenharmony_ci * Arguments are bus type specific. 5598c2ecf20Sopenharmony_ci * I2C: iio_dummy_probe(struct i2c_client *client, 5608c2ecf20Sopenharmony_ci * const struct i2c_device_id *id) 5618c2ecf20Sopenharmony_ci * SPI: iio_dummy_probe(struct spi_device *spi) 5628c2ecf20Sopenharmony_ci */ 5638c2ecf20Sopenharmony_cistatic struct iio_sw_device *iio_dummy_probe(const char *name) 5648c2ecf20Sopenharmony_ci{ 5658c2ecf20Sopenharmony_ci int ret; 5668c2ecf20Sopenharmony_ci struct iio_dev *indio_dev; 5678c2ecf20Sopenharmony_ci struct iio_dummy_state *st; 5688c2ecf20Sopenharmony_ci struct iio_sw_device *swd; 5698c2ecf20Sopenharmony_ci struct device *parent = NULL; 5708c2ecf20Sopenharmony_ci 5718c2ecf20Sopenharmony_ci /* 5728c2ecf20Sopenharmony_ci * With hardware: Set the parent device. 5738c2ecf20Sopenharmony_ci * parent = &spi->dev; 5748c2ecf20Sopenharmony_ci * parent = &client->dev; 5758c2ecf20Sopenharmony_ci */ 5768c2ecf20Sopenharmony_ci 5778c2ecf20Sopenharmony_ci swd = kzalloc(sizeof(*swd), GFP_KERNEL); 5788c2ecf20Sopenharmony_ci if (!swd) 5798c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 5808c2ecf20Sopenharmony_ci 5818c2ecf20Sopenharmony_ci /* 5828c2ecf20Sopenharmony_ci * Allocate an IIO device. 5838c2ecf20Sopenharmony_ci * 5848c2ecf20Sopenharmony_ci * This structure contains all generic state 5858c2ecf20Sopenharmony_ci * information about the device instance. 5868c2ecf20Sopenharmony_ci * It also has a region (accessed by iio_priv() 5878c2ecf20Sopenharmony_ci * for chip specific state information. 5888c2ecf20Sopenharmony_ci */ 5898c2ecf20Sopenharmony_ci indio_dev = iio_device_alloc(parent, sizeof(*st)); 5908c2ecf20Sopenharmony_ci if (!indio_dev) { 5918c2ecf20Sopenharmony_ci ret = -ENOMEM; 5928c2ecf20Sopenharmony_ci goto error_free_swd; 5938c2ecf20Sopenharmony_ci } 5948c2ecf20Sopenharmony_ci 5958c2ecf20Sopenharmony_ci st = iio_priv(indio_dev); 5968c2ecf20Sopenharmony_ci mutex_init(&st->lock); 5978c2ecf20Sopenharmony_ci 5988c2ecf20Sopenharmony_ci iio_dummy_init_device(indio_dev); 5998c2ecf20Sopenharmony_ci 6008c2ecf20Sopenharmony_ci /* 6018c2ecf20Sopenharmony_ci * Make the iio_dev struct available to remove function. 6028c2ecf20Sopenharmony_ci * Bus equivalents 6038c2ecf20Sopenharmony_ci * i2c_set_clientdata(client, indio_dev); 6048c2ecf20Sopenharmony_ci * spi_set_drvdata(spi, indio_dev); 6058c2ecf20Sopenharmony_ci */ 6068c2ecf20Sopenharmony_ci swd->device = indio_dev; 6078c2ecf20Sopenharmony_ci 6088c2ecf20Sopenharmony_ci /* 6098c2ecf20Sopenharmony_ci * Set the device name. 6108c2ecf20Sopenharmony_ci * 6118c2ecf20Sopenharmony_ci * This is typically a part number and obtained from the module 6128c2ecf20Sopenharmony_ci * id table. 6138c2ecf20Sopenharmony_ci * e.g. for i2c and spi: 6148c2ecf20Sopenharmony_ci * indio_dev->name = id->name; 6158c2ecf20Sopenharmony_ci * indio_dev->name = spi_get_device_id(spi)->name; 6168c2ecf20Sopenharmony_ci */ 6178c2ecf20Sopenharmony_ci indio_dev->name = kstrdup(name, GFP_KERNEL); 6188c2ecf20Sopenharmony_ci if (!indio_dev->name) { 6198c2ecf20Sopenharmony_ci ret = -ENOMEM; 6208c2ecf20Sopenharmony_ci goto error_free_device; 6218c2ecf20Sopenharmony_ci } 6228c2ecf20Sopenharmony_ci 6238c2ecf20Sopenharmony_ci /* Provide description of available channels */ 6248c2ecf20Sopenharmony_ci indio_dev->channels = iio_dummy_channels; 6258c2ecf20Sopenharmony_ci indio_dev->num_channels = ARRAY_SIZE(iio_dummy_channels); 6268c2ecf20Sopenharmony_ci 6278c2ecf20Sopenharmony_ci /* 6288c2ecf20Sopenharmony_ci * Provide device type specific interface functions and 6298c2ecf20Sopenharmony_ci * constant data. 6308c2ecf20Sopenharmony_ci */ 6318c2ecf20Sopenharmony_ci indio_dev->info = &iio_dummy_info; 6328c2ecf20Sopenharmony_ci 6338c2ecf20Sopenharmony_ci /* Specify that device provides sysfs type interfaces */ 6348c2ecf20Sopenharmony_ci indio_dev->modes = INDIO_DIRECT_MODE; 6358c2ecf20Sopenharmony_ci 6368c2ecf20Sopenharmony_ci ret = iio_simple_dummy_events_register(indio_dev); 6378c2ecf20Sopenharmony_ci if (ret < 0) 6388c2ecf20Sopenharmony_ci goto error_free_name; 6398c2ecf20Sopenharmony_ci 6408c2ecf20Sopenharmony_ci ret = iio_simple_dummy_configure_buffer(indio_dev); 6418c2ecf20Sopenharmony_ci if (ret < 0) 6428c2ecf20Sopenharmony_ci goto error_unregister_events; 6438c2ecf20Sopenharmony_ci 6448c2ecf20Sopenharmony_ci ret = iio_device_register(indio_dev); 6458c2ecf20Sopenharmony_ci if (ret < 0) 6468c2ecf20Sopenharmony_ci goto error_unconfigure_buffer; 6478c2ecf20Sopenharmony_ci 6488c2ecf20Sopenharmony_ci iio_swd_group_init_type_name(swd, name, &iio_dummy_type); 6498c2ecf20Sopenharmony_ci 6508c2ecf20Sopenharmony_ci return swd; 6518c2ecf20Sopenharmony_cierror_unconfigure_buffer: 6528c2ecf20Sopenharmony_ci iio_simple_dummy_unconfigure_buffer(indio_dev); 6538c2ecf20Sopenharmony_cierror_unregister_events: 6548c2ecf20Sopenharmony_ci iio_simple_dummy_events_unregister(indio_dev); 6558c2ecf20Sopenharmony_cierror_free_name: 6568c2ecf20Sopenharmony_ci kfree(indio_dev->name); 6578c2ecf20Sopenharmony_cierror_free_device: 6588c2ecf20Sopenharmony_ci iio_device_free(indio_dev); 6598c2ecf20Sopenharmony_cierror_free_swd: 6608c2ecf20Sopenharmony_ci kfree(swd); 6618c2ecf20Sopenharmony_ci return ERR_PTR(ret); 6628c2ecf20Sopenharmony_ci} 6638c2ecf20Sopenharmony_ci 6648c2ecf20Sopenharmony_ci/** 6658c2ecf20Sopenharmony_ci * iio_dummy_remove() - device instance removal function 6668c2ecf20Sopenharmony_ci * @swd: pointer to software IIO device abstraction 6678c2ecf20Sopenharmony_ci * 6688c2ecf20Sopenharmony_ci * Parameters follow those of iio_dummy_probe for buses. 6698c2ecf20Sopenharmony_ci */ 6708c2ecf20Sopenharmony_cistatic int iio_dummy_remove(struct iio_sw_device *swd) 6718c2ecf20Sopenharmony_ci{ 6728c2ecf20Sopenharmony_ci /* 6738c2ecf20Sopenharmony_ci * Get a pointer to the device instance iio_dev structure 6748c2ecf20Sopenharmony_ci * from the bus subsystem. E.g. 6758c2ecf20Sopenharmony_ci * struct iio_dev *indio_dev = i2c_get_clientdata(client); 6768c2ecf20Sopenharmony_ci * struct iio_dev *indio_dev = spi_get_drvdata(spi); 6778c2ecf20Sopenharmony_ci */ 6788c2ecf20Sopenharmony_ci struct iio_dev *indio_dev = swd->device; 6798c2ecf20Sopenharmony_ci 6808c2ecf20Sopenharmony_ci /* Unregister the device */ 6818c2ecf20Sopenharmony_ci iio_device_unregister(indio_dev); 6828c2ecf20Sopenharmony_ci 6838c2ecf20Sopenharmony_ci /* Device specific code to power down etc */ 6848c2ecf20Sopenharmony_ci 6858c2ecf20Sopenharmony_ci /* Buffered capture related cleanup */ 6868c2ecf20Sopenharmony_ci iio_simple_dummy_unconfigure_buffer(indio_dev); 6878c2ecf20Sopenharmony_ci 6888c2ecf20Sopenharmony_ci iio_simple_dummy_events_unregister(indio_dev); 6898c2ecf20Sopenharmony_ci 6908c2ecf20Sopenharmony_ci /* Free all structures */ 6918c2ecf20Sopenharmony_ci kfree(indio_dev->name); 6928c2ecf20Sopenharmony_ci iio_device_free(indio_dev); 6938c2ecf20Sopenharmony_ci 6948c2ecf20Sopenharmony_ci return 0; 6958c2ecf20Sopenharmony_ci} 6968c2ecf20Sopenharmony_ci 6978c2ecf20Sopenharmony_ci/* 6988c2ecf20Sopenharmony_ci * module_iio_sw_device_driver() - device driver registration 6998c2ecf20Sopenharmony_ci * 7008c2ecf20Sopenharmony_ci * Varies depending on bus type of the device. As there is no device 7018c2ecf20Sopenharmony_ci * here, call probe directly. For information on device registration 7028c2ecf20Sopenharmony_ci * i2c: 7038c2ecf20Sopenharmony_ci * Documentation/i2c/writing-clients.rst 7048c2ecf20Sopenharmony_ci * spi: 7058c2ecf20Sopenharmony_ci * Documentation/spi/spi-summary.rst 7068c2ecf20Sopenharmony_ci */ 7078c2ecf20Sopenharmony_cistatic const struct iio_sw_device_ops iio_dummy_device_ops = { 7088c2ecf20Sopenharmony_ci .probe = iio_dummy_probe, 7098c2ecf20Sopenharmony_ci .remove = iio_dummy_remove, 7108c2ecf20Sopenharmony_ci}; 7118c2ecf20Sopenharmony_ci 7128c2ecf20Sopenharmony_cistatic struct iio_sw_device_type iio_dummy_device = { 7138c2ecf20Sopenharmony_ci .name = "dummy", 7148c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 7158c2ecf20Sopenharmony_ci .ops = &iio_dummy_device_ops, 7168c2ecf20Sopenharmony_ci}; 7178c2ecf20Sopenharmony_ci 7188c2ecf20Sopenharmony_cimodule_iio_sw_device_driver(iio_dummy_device); 7198c2ecf20Sopenharmony_ci 7208c2ecf20Sopenharmony_ciMODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>"); 7218c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("IIO dummy driver"); 7228c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 723