^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /* The industrial I/O core in kernel channel mapping
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (c) 2011 Jonathan Cameron
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/iio/iio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "iio_core.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/iio/machine.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/iio/driver.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/iio/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) struct iio_map_internal {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) struct iio_dev *indio_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) struct iio_map *map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) struct list_head l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) static LIST_HEAD(iio_map_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) static DEFINE_MUTEX(iio_map_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) int iio_map_array_register(struct iio_dev *indio_dev, struct iio_map *maps)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) int i = 0, ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) struct iio_map_internal *mapi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) if (maps == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) mutex_lock(&iio_map_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) while (maps[i].consumer_dev_name != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) mapi = kzalloc(sizeof(*mapi), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) if (mapi == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) goto error_ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) mapi->map = &maps[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) mapi->indio_dev = indio_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) list_add_tail(&mapi->l, &iio_map_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) error_ret:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) mutex_unlock(&iio_map_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) EXPORT_SYMBOL_GPL(iio_map_array_register);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * Remove all map entries associated with the given iio device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) int iio_map_array_unregister(struct iio_dev *indio_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) int ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) struct iio_map_internal *mapi, *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) mutex_lock(&iio_map_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) list_for_each_entry_safe(mapi, next, &iio_map_list, l) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) if (indio_dev == mapi->indio_dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) list_del(&mapi->l);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) kfree(mapi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) mutex_unlock(&iio_map_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) EXPORT_SYMBOL_GPL(iio_map_array_unregister);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) static const struct iio_chan_spec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) *iio_chan_spec_from_name(const struct iio_dev *indio_dev, const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) const struct iio_chan_spec *chan = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) for (i = 0; i < indio_dev->num_channels; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) if (indio_dev->channels[i].datasheet_name &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) strcmp(name, indio_dev->channels[i].datasheet_name) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) chan = &indio_dev->channels[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) return chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #ifdef CONFIG_OF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) static int iio_dev_node_match(struct device *dev, const void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) return dev->of_node == data && dev->type == &iio_device_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) * __of_iio_simple_xlate - translate iiospec to the IIO channel index
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) * @indio_dev: pointer to the iio_dev structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) * @iiospec: IIO specifier as found in the device tree
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) * This is simple translation function, suitable for the most 1:1 mapped
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) * channels in IIO chips. This function performs only one sanity check:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) * whether IIO index is less than num_channels (that is specified in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) * iio_dev).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) static int __of_iio_simple_xlate(struct iio_dev *indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) const struct of_phandle_args *iiospec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) if (!iiospec->args_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) if (iiospec->args[0] >= indio_dev->num_channels) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) dev_err(&indio_dev->dev, "invalid channel index %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) iiospec->args[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) return iiospec->args[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) static int __of_iio_channel_get(struct iio_channel *channel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) struct device_node *np, int index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) struct device *idev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) struct iio_dev *indio_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) struct of_phandle_args iiospec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) err = of_parse_phandle_with_args(np, "io-channels",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) "#io-channel-cells",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) index, &iiospec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) idev = bus_find_device(&iio_bus_type, NULL, iiospec.np,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) iio_dev_node_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) of_node_put(iiospec.np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) if (idev == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) return -EPROBE_DEFER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) indio_dev = dev_to_iio_dev(idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) channel->indio_dev = indio_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) if (indio_dev->info->of_xlate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) index = indio_dev->info->of_xlate(indio_dev, &iiospec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) index = __of_iio_simple_xlate(indio_dev, &iiospec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) if (index < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) goto err_put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) channel->channel = &indio_dev->channels[index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) err_put:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) iio_device_put(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) return index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) static struct iio_channel *of_iio_channel_get(struct device_node *np, int index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) struct iio_channel *channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) if (index < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) channel = kzalloc(sizeof(*channel), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) if (channel == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) err = __of_iio_channel_get(channel, np, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) goto err_free_channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) return channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) err_free_channel:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) kfree(channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) return ERR_PTR(err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) static struct iio_channel *of_iio_channel_get_by_name(struct device_node *np,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) struct iio_channel *chan = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) /* Walk up the tree of devices looking for a matching iio channel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) while (np) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) int index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) * For named iio channels, first look up the name in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) * "io-channel-names" property. If it cannot be found, the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) * index will be an error code, and of_iio_channel_get()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) * will fail.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) if (name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) index = of_property_match_string(np, "io-channel-names",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) chan = of_iio_channel_get(np, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) if (!IS_ERR(chan) || PTR_ERR(chan) == -EPROBE_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) else if (name && index >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) pr_err("ERROR: could not get IIO channel %pOF:%s(%i)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) np, name ? name : "", index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) * No matching IIO channel found on this node.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) * If the parent node has a "io-channel-ranges" property,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) * then we can try one of its channels.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) np = np->parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) if (np && !of_get_property(np, "io-channel-ranges", NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) return chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) static struct iio_channel *of_iio_channel_get_all(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) struct iio_channel *chans;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) int i, mapind, nummaps = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) ret = of_parse_phandle_with_args(dev->of_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) "io-channels",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) "#io-channel-cells",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) nummaps, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) } while (++nummaps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) if (nummaps == 0) /* no error, return NULL to search map table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) /* NULL terminated array to save passing size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) chans = kcalloc(nummaps + 1, sizeof(*chans), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) if (chans == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) /* Search for OF matches */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) for (mapind = 0; mapind < nummaps; mapind++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) ret = __of_iio_channel_get(&chans[mapind], dev->of_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) mapind);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) goto error_free_chans;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) return chans;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) error_free_chans:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) for (i = 0; i < mapind; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) iio_device_put(chans[i].indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) kfree(chans);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) return ERR_PTR(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) #else /* CONFIG_OF */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) static inline struct iio_channel *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) of_iio_channel_get_by_name(struct device_node *np, const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) static inline struct iio_channel *of_iio_channel_get_all(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) #endif /* CONFIG_OF */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) static struct iio_channel *iio_channel_get_sys(const char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) const char *channel_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) struct iio_map_internal *c_i = NULL, *c = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) struct iio_channel *channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) if (name == NULL && channel_name == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) return ERR_PTR(-ENODEV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) /* first find matching entry the channel map */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) mutex_lock(&iio_map_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) list_for_each_entry(c_i, &iio_map_list, l) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) if ((name && strcmp(name, c_i->map->consumer_dev_name) != 0) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) (channel_name &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) strcmp(channel_name, c_i->map->consumer_channel) != 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) c = c_i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) iio_device_get(c->indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) mutex_unlock(&iio_map_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) if (c == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) return ERR_PTR(-ENODEV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) channel = kzalloc(sizeof(*channel), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) if (channel == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) goto error_no_mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) channel->indio_dev = c->indio_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) if (c->map->adc_channel_label) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) channel->channel =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) iio_chan_spec_from_name(channel->indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) c->map->adc_channel_label);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) if (channel->channel == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) goto error_no_chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) return channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) error_no_chan:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) kfree(channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) error_no_mem:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) iio_device_put(c->indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) return ERR_PTR(err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) struct iio_channel *iio_channel_get(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) const char *channel_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) const char *name = dev ? dev_name(dev) : NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) struct iio_channel *channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) if (dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) channel = of_iio_channel_get_by_name(dev->of_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) channel_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) if (channel != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) return channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) return iio_channel_get_sys(name, channel_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) EXPORT_SYMBOL_GPL(iio_channel_get);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) void iio_channel_release(struct iio_channel *channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) if (!channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) iio_device_put(channel->indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) kfree(channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) EXPORT_SYMBOL_GPL(iio_channel_release);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) static void devm_iio_channel_free(struct device *dev, void *res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) struct iio_channel *channel = *(struct iio_channel **)res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) iio_channel_release(channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) struct iio_channel *devm_iio_channel_get(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) const char *channel_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) struct iio_channel **ptr, *channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) ptr = devres_alloc(devm_iio_channel_free, sizeof(*ptr), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) if (!ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) channel = iio_channel_get(dev, channel_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) if (IS_ERR(channel)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) devres_free(ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) return channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) *ptr = channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) devres_add(dev, ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) return channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) EXPORT_SYMBOL_GPL(devm_iio_channel_get);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) struct iio_channel *iio_channel_get_all(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) struct iio_channel *chans;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) struct iio_map_internal *c = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) int nummaps = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) int mapind = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) int i, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) if (dev == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) chans = of_iio_channel_get_all(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) if (chans)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) return chans;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) name = dev_name(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) mutex_lock(&iio_map_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) /* first count the matching maps */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) list_for_each_entry(c, &iio_map_list, l)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) if (name && strcmp(name, c->map->consumer_dev_name) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) nummaps++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) if (nummaps == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) goto error_ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) /* NULL terminated array to save passing size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) chans = kcalloc(nummaps + 1, sizeof(*chans), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) if (chans == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) goto error_ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) /* for each map fill in the chans element */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) list_for_each_entry(c, &iio_map_list, l) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) if (name && strcmp(name, c->map->consumer_dev_name) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) chans[mapind].indio_dev = c->indio_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) chans[mapind].data = c->map->consumer_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) chans[mapind].channel =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) iio_chan_spec_from_name(chans[mapind].indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) c->map->adc_channel_label);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) if (chans[mapind].channel == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) goto error_free_chans;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) iio_device_get(chans[mapind].indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) mapind++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) if (mapind == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) goto error_free_chans;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) mutex_unlock(&iio_map_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) return chans;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) error_free_chans:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) for (i = 0; i < nummaps; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) iio_device_put(chans[i].indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) kfree(chans);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) error_ret:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) mutex_unlock(&iio_map_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) return ERR_PTR(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) EXPORT_SYMBOL_GPL(iio_channel_get_all);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) void iio_channel_release_all(struct iio_channel *channels)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) struct iio_channel *chan = &channels[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) while (chan->indio_dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) iio_device_put(chan->indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) chan++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) kfree(channels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) EXPORT_SYMBOL_GPL(iio_channel_release_all);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) static void devm_iio_channel_free_all(struct device *dev, void *res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) struct iio_channel *channels = *(struct iio_channel **)res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) iio_channel_release_all(channels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) struct iio_channel *devm_iio_channel_get_all(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) struct iio_channel **ptr, *channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) ptr = devres_alloc(devm_iio_channel_free_all, sizeof(*ptr), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) if (!ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) channels = iio_channel_get_all(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) if (IS_ERR(channels)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) devres_free(ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) return channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) *ptr = channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) devres_add(dev, ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) return channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) EXPORT_SYMBOL_GPL(devm_iio_channel_get_all);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) static int iio_channel_read(struct iio_channel *chan, int *val, int *val2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) enum iio_chan_info_enum info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) int unused;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) int vals[INDIO_MAX_RAW_ELEMENTS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) int val_len = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) if (val2 == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) val2 = &unused;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) if (!iio_channel_has_info(chan->channel, info))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) if (chan->indio_dev->info->read_raw_multi) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) ret = chan->indio_dev->info->read_raw_multi(chan->indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) chan->channel, INDIO_MAX_RAW_ELEMENTS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) vals, &val_len, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) *val = vals[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) *val2 = vals[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) ret = chan->indio_dev->info->read_raw(chan->indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) chan->channel, val, val2, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) int iio_read_channel_raw(struct iio_channel *chan, int *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) mutex_lock(&chan->indio_dev->info_exist_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) if (chan->indio_dev->info == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) goto err_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) ret = iio_channel_read(chan, val, NULL, IIO_CHAN_INFO_RAW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) err_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) mutex_unlock(&chan->indio_dev->info_exist_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) EXPORT_SYMBOL_GPL(iio_read_channel_raw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) int iio_read_channel_average_raw(struct iio_channel *chan, int *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) mutex_lock(&chan->indio_dev->info_exist_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) if (chan->indio_dev->info == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) goto err_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) ret = iio_channel_read(chan, val, NULL, IIO_CHAN_INFO_AVERAGE_RAW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) err_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) mutex_unlock(&chan->indio_dev->info_exist_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) EXPORT_SYMBOL_GPL(iio_read_channel_average_raw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) static int iio_convert_raw_to_processed_unlocked(struct iio_channel *chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) int raw, int *processed, unsigned int scale)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) int scale_type, scale_val, scale_val2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) int offset_type, offset_val, offset_val2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) s64 raw64 = raw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) offset_type = iio_channel_read(chan, &offset_val, &offset_val2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) IIO_CHAN_INFO_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) if (offset_type >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) switch (offset_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) case IIO_VAL_INT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) case IIO_VAL_INT_PLUS_MICRO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) case IIO_VAL_INT_PLUS_NANO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) * Both IIO_VAL_INT_PLUS_MICRO and IIO_VAL_INT_PLUS_NANO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) * implicitely truncate the offset to it's integer form.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) case IIO_VAL_FRACTIONAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) offset_val /= offset_val2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) case IIO_VAL_FRACTIONAL_LOG2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) offset_val >>= offset_val2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) raw64 += offset_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) scale_type = iio_channel_read(chan, &scale_val, &scale_val2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) IIO_CHAN_INFO_SCALE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) if (scale_type < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) * If no channel scaling is available apply consumer scale to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) * raw value and return.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) *processed = raw * scale;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) switch (scale_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) case IIO_VAL_INT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) *processed = raw64 * scale_val * scale;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) case IIO_VAL_INT_PLUS_MICRO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) if (scale_val2 < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) *processed = -raw64 * scale_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) *processed = raw64 * scale_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) *processed += div_s64(raw64 * (s64)scale_val2 * scale,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) 1000000LL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) case IIO_VAL_INT_PLUS_NANO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) if (scale_val2 < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) *processed = -raw64 * scale_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) *processed = raw64 * scale_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) *processed += div_s64(raw64 * (s64)scale_val2 * scale,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) 1000000000LL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) case IIO_VAL_FRACTIONAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) *processed = div_s64(raw64 * (s64)scale_val * scale,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) scale_val2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) case IIO_VAL_FRACTIONAL_LOG2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) *processed = (raw64 * (s64)scale_val * scale) >> scale_val2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) int iio_convert_raw_to_processed(struct iio_channel *chan, int raw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) int *processed, unsigned int scale)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) mutex_lock(&chan->indio_dev->info_exist_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) if (chan->indio_dev->info == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) goto err_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) ret = iio_convert_raw_to_processed_unlocked(chan, raw, processed,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) scale);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) err_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) mutex_unlock(&chan->indio_dev->info_exist_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) EXPORT_SYMBOL_GPL(iio_convert_raw_to_processed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) int iio_read_channel_attribute(struct iio_channel *chan, int *val, int *val2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) enum iio_chan_info_enum attribute)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) mutex_lock(&chan->indio_dev->info_exist_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) if (chan->indio_dev->info == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) goto err_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) ret = iio_channel_read(chan, val, val2, attribute);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) err_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) mutex_unlock(&chan->indio_dev->info_exist_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) EXPORT_SYMBOL_GPL(iio_read_channel_attribute);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) int iio_read_channel_offset(struct iio_channel *chan, int *val, int *val2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) return iio_read_channel_attribute(chan, val, val2, IIO_CHAN_INFO_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) EXPORT_SYMBOL_GPL(iio_read_channel_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) int iio_read_channel_processed(struct iio_channel *chan, int *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) mutex_lock(&chan->indio_dev->info_exist_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) if (chan->indio_dev->info == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) goto err_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) if (iio_channel_has_info(chan->channel, IIO_CHAN_INFO_PROCESSED)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) ret = iio_channel_read(chan, val, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) IIO_CHAN_INFO_PROCESSED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) ret = iio_channel_read(chan, val, NULL, IIO_CHAN_INFO_RAW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) goto err_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) ret = iio_convert_raw_to_processed_unlocked(chan, *val, val, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) err_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) mutex_unlock(&chan->indio_dev->info_exist_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) EXPORT_SYMBOL_GPL(iio_read_channel_processed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) int iio_read_channel_scale(struct iio_channel *chan, int *val, int *val2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) return iio_read_channel_attribute(chan, val, val2, IIO_CHAN_INFO_SCALE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) EXPORT_SYMBOL_GPL(iio_read_channel_scale);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) static int iio_channel_read_avail(struct iio_channel *chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) const int **vals, int *type, int *length,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) enum iio_chan_info_enum info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) if (!iio_channel_has_available(chan->channel, info))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) return chan->indio_dev->info->read_avail(chan->indio_dev, chan->channel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) vals, type, length, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) int iio_read_avail_channel_attribute(struct iio_channel *chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) const int **vals, int *type, int *length,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) enum iio_chan_info_enum attribute)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) mutex_lock(&chan->indio_dev->info_exist_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) if (!chan->indio_dev->info) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) goto err_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) ret = iio_channel_read_avail(chan, vals, type, length, attribute);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) err_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) mutex_unlock(&chan->indio_dev->info_exist_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) EXPORT_SYMBOL_GPL(iio_read_avail_channel_attribute);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) int iio_read_avail_channel_raw(struct iio_channel *chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) const int **vals, int *length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) int type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) ret = iio_read_avail_channel_attribute(chan, vals, &type, length,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) IIO_CHAN_INFO_RAW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) if (ret >= 0 && type != IIO_VAL_INT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) /* raw values are assumed to be IIO_VAL_INT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) EXPORT_SYMBOL_GPL(iio_read_avail_channel_raw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) static int iio_channel_read_max(struct iio_channel *chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) int *val, int *val2, int *type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) enum iio_chan_info_enum info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) int unused;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) const int *vals;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) int length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) if (!val2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) val2 = &unused;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) ret = iio_channel_read_avail(chan, &vals, type, &length, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) switch (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) case IIO_AVAIL_RANGE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) switch (*type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) case IIO_VAL_INT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) *val = vals[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) *val = vals[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) *val2 = vals[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) case IIO_AVAIL_LIST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) if (length <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) switch (*type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) case IIO_VAL_INT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) *val = vals[--length];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) while (length) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) if (vals[--length] > *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) *val = vals[length];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) /* FIXME: learn about max for other iio values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) int iio_read_max_channel_raw(struct iio_channel *chan, int *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) int type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) mutex_lock(&chan->indio_dev->info_exist_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) if (!chan->indio_dev->info) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) goto err_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) ret = iio_channel_read_max(chan, val, NULL, &type, IIO_CHAN_INFO_RAW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) err_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) mutex_unlock(&chan->indio_dev->info_exist_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) EXPORT_SYMBOL_GPL(iio_read_max_channel_raw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) int iio_get_channel_type(struct iio_channel *chan, enum iio_chan_type *type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) /* Need to verify underlying driver has not gone away */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) mutex_lock(&chan->indio_dev->info_exist_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) if (chan->indio_dev->info == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) goto err_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) *type = chan->channel->type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) err_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) mutex_unlock(&chan->indio_dev->info_exist_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) EXPORT_SYMBOL_GPL(iio_get_channel_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) static int iio_channel_write(struct iio_channel *chan, int val, int val2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) enum iio_chan_info_enum info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) return chan->indio_dev->info->write_raw(chan->indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) chan->channel, val, val2, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) int iio_write_channel_attribute(struct iio_channel *chan, int val, int val2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) enum iio_chan_info_enum attribute)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) mutex_lock(&chan->indio_dev->info_exist_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) if (chan->indio_dev->info == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) goto err_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) ret = iio_channel_write(chan, val, val2, attribute);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) err_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) mutex_unlock(&chan->indio_dev->info_exist_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) EXPORT_SYMBOL_GPL(iio_write_channel_attribute);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) int iio_write_channel_raw(struct iio_channel *chan, int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) return iio_write_channel_attribute(chan, val, 0, IIO_CHAN_INFO_RAW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) EXPORT_SYMBOL_GPL(iio_write_channel_raw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) unsigned int iio_get_channel_ext_info_count(struct iio_channel *chan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) const struct iio_chan_spec_ext_info *ext_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) unsigned int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) if (!chan->channel->ext_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) for (ext_info = chan->channel->ext_info; ext_info->name; ext_info++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) ++i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) EXPORT_SYMBOL_GPL(iio_get_channel_ext_info_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) static const struct iio_chan_spec_ext_info *iio_lookup_ext_info(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) const struct iio_channel *chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) const char *attr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) const struct iio_chan_spec_ext_info *ext_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) if (!chan->channel->ext_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) for (ext_info = chan->channel->ext_info; ext_info->name; ++ext_info) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) if (!strcmp(attr, ext_info->name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) return ext_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) ssize_t iio_read_channel_ext_info(struct iio_channel *chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) const char *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) const struct iio_chan_spec_ext_info *ext_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) ext_info = iio_lookup_ext_info(chan, attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) if (!ext_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) return ext_info->read(chan->indio_dev, ext_info->private,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) chan->channel, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) EXPORT_SYMBOL_GPL(iio_read_channel_ext_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) ssize_t iio_write_channel_ext_info(struct iio_channel *chan, const char *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) const char *buf, size_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) const struct iio_chan_spec_ext_info *ext_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) ext_info = iio_lookup_ext_info(chan, attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) if (!ext_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) return ext_info->write(chan->indio_dev, ext_info->private,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) chan->channel, buf, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) EXPORT_SYMBOL_GPL(iio_write_channel_ext_info);