/* * Remove all map entries associated with the given iio device
*/ int iio_map_array_unregister(struct iio_dev *indio_dev)
{
guard(mutex)(&iio_map_list_lock); return iio_map_array_unregister_locked(indio_dev);
}
EXPORT_SYMBOL_GPL(iio_map_array_unregister);
for (i = 0; i < indio_dev->num_channels; i++) if (indio_dev->channels[i].datasheet_name &&
strcmp(name, indio_dev->channels[i].datasheet_name) == 0) {
chan = &indio_dev->channels[i]; break;
} return chan;
}
/** * __fwnode_iio_simple_xlate - translate iiospec to the IIO channel index * @indio_dev: pointer to the iio_dev structure * @iiospec: IIO specifier as found in the device tree * * This is simple translation function, suitable for the most 1:1 mapped * channels in IIO chips. This function performs only one sanity check: * whether IIO index is less than num_channels (that is specified in the * iio_dev).
*/ staticint __fwnode_iio_simple_xlate(struct iio_dev *indio_dev, conststruct fwnode_reference_args *iiospec)
{ if (!iiospec->nargs) return 0;
if (iiospec->args[0] >= indio_dev->num_channels) {
dev_err(&indio_dev->dev, "invalid channel index %llu\n",
iiospec->args[0]); return -EINVAL;
}
err = __fwnode_iio_channel_get(channel, fwnode, index); if (err) return ERR_PTR(err);
return_ptr(channel);
}
staticstruct iio_channel *
__fwnode_iio_channel_get_by_name(struct fwnode_handle *fwnode, constchar *name)
{ struct iio_channel *chan; int index = 0;
/* * For named iio channels, first look up the name in the * "io-channel-names" property. If it cannot be found, the * index will be an error code, and fwnode_iio_channel_get() * will fail.
*/ if (name)
index = fwnode_property_match_string(fwnode, "io-channel-names",
name);
chan = fwnode_iio_channel_get(fwnode, index); if (!IS_ERR(chan) || PTR_ERR(chan) == -EPROBE_DEFER) return chan; if (name) { if (index >= 0) {
pr_err("ERROR: could not get IIO channel %pfw:%s(%i)\n",
fwnode, name, index); /* * In this case, we found 'name' in 'io-channel-names' * but somehow we still fail so that we should not proceed * with any other lookup. Hence, explicitly return -EINVAL * (maybe not the better error code) so that the caller * won't do a system lookup.
*/ return ERR_PTR(-EINVAL);
} /* * If index < 0, then fwnode_property_get_reference_args() fails * with -EINVAL or -ENOENT (ACPI case) which is expected. We * should not proceed if we get any other error.
*/ if (PTR_ERR(chan) != -EINVAL && PTR_ERR(chan) != -ENOENT) return chan;
} elseif (PTR_ERR(chan) != -ENOENT) { /* * if !name, then we should only proceed the lookup if * fwnode_property_get_reference_args() returns -ENOENT.
*/ return chan;
}
/* so we continue the lookup */ return ERR_PTR(-ENODEV);
}
/* Walk up the tree of devices looking for a matching iio channel */
chan = __fwnode_iio_channel_get_by_name(fwnode, name); if (!IS_ERR(chan) || PTR_ERR(chan) != -ENODEV) return chan;
/* * No matching IIO channel found on this node. * If the parent node has a "io-channel-ranges" property, * then we can try one of its channels.
*/
fwnode_for_each_parent_node(fwnode, parent) { if (!fwnode_property_present(parent, "io-channel-ranges")) {
fwnode_handle_put(parent); return ERR_PTR(-ENODEV);
}
struct iio_channel *iio_channel_get_all(struct device *dev)
{ constchar *name; struct iio_map_internal *c = NULL; struct iio_channel *fw_chans; int nummaps = 0; int mapind = 0; int i, ret;
if (!dev) return ERR_PTR(-EINVAL);
fw_chans = fwnode_iio_channel_get_all(dev); /* * We only want to carry on if the error is -ENODEV. Anything else * should be reported up the stack.
*/ if (!IS_ERR(fw_chans) || PTR_ERR(fw_chans) != -ENODEV) return fw_chans;
name = dev_name(dev);
guard(mutex)(&iio_map_list_lock); /* first count the matching maps */
list_for_each_entry(c, &iio_map_list, l) if (name && strcmp(name, c->map->consumer_dev_name) != 0) continue; else
nummaps++;
if (nummaps == 0) return ERR_PTR(-ENODEV);
/* NULL terminated array to save passing size */ struct iio_channel *chans __free(kfree) =
kcalloc(nummaps + 1, sizeof(*chans), GFP_KERNEL); if (!chans) return ERR_PTR(-ENOMEM);
/* for each map fill in the chans element */
list_for_each_entry(c, &iio_map_list, l) { if (name && strcmp(name, c->map->consumer_dev_name) != 0) continue;
chans[mapind].indio_dev = c->indio_dev;
chans[mapind].data = c->map->consumer_data;
chans[mapind].channel =
iio_chan_spec_from_name(chans[mapind].indio_dev,
c->map->adc_channel_label); if (!chans[mapind].channel) {
ret = -EINVAL; goto error_free_chans;
}
iio_device_get(chans[mapind].indio_dev);
mapind++;
} if (mapind == 0) {
ret = -ENODEV; goto error_free_chans;
}
return_ptr(chans);
error_free_chans: for (i = 0; i < mapind; i++)
iio_device_put(chans[i].indio_dev); return ERR_PTR(ret);
}
EXPORT_SYMBOL_GPL(iio_channel_get_all);
staticint iio_channel_read(struct iio_channel *chan, int *val, int *val2, enum iio_chan_info_enum info)
{ conststruct iio_info *iio_info = chan->indio_dev->info; int unused; int vals[INDIO_MAX_RAW_ELEMENTS]; int ret; int val_len = 2;
if (!val2)
val2 = &unused;
if (!iio_channel_has_info(chan->channel, info)) return -EINVAL;
staticint iio_convert_raw_to_processed_unlocked(struct iio_channel *chan, int raw, int *processed, unsignedint scale)
{ int scale_type, scale_val, scale_val2; int offset_type, offset_val, offset_val2;
s64 denominator, raw64 = raw;
offset_type = iio_channel_read(chan, &offset_val, &offset_val2,
IIO_CHAN_INFO_OFFSET); if (offset_type >= 0) { switch (offset_type) { case IIO_VAL_INT: break; case IIO_VAL_INT_PLUS_MICRO: case IIO_VAL_INT_PLUS_NANO: /* * Both IIO_VAL_INT_PLUS_MICRO and IIO_VAL_INT_PLUS_NANO * implicitely truncate the offset to it's integer form.
*/ break; case IIO_VAL_FRACTIONAL:
offset_val /= offset_val2; break; case IIO_VAL_FRACTIONAL_LOG2:
offset_val >>= offset_val2; break; default: return -EINVAL;
}
raw64 += offset_val;
}
scale_type = iio_channel_read(chan, &scale_val, &scale_val2,
IIO_CHAN_INFO_SCALE); if (scale_type < 0) { /* * If no channel scaling is available apply consumer scale to * raw value and return.
*/
*processed = raw64 * scale; return 0;
}
int iio_read_channel_processed(struct iio_channel *chan, int *val)
{ /* This is just a special case with scale factor 1 */ return iio_read_channel_processed_scale(chan, val, 1);
}
EXPORT_SYMBOL_GPL(iio_read_channel_processed);
int iio_read_channel_scale(struct iio_channel *chan, int *val, int *val2)
{ return iio_read_channel_attribute(chan, val, val2, IIO_CHAN_INFO_SCALE);
}
EXPORT_SYMBOL_GPL(iio_read_channel_scale);
staticint iio_channel_read_avail(struct iio_channel *chan, constint **vals, int *type, int *length, enum iio_chan_info_enum info)
{ conststruct iio_info *iio_info = chan->indio_dev->info;
if (!iio_channel_has_available(chan->channel, info)) return -EINVAL;
staticint iio_channel_read_max(struct iio_channel *chan, int *val, int *val2, int *type, enum iio_chan_info_enum info)
{ constint *vals; int length; int ret;
ret = iio_channel_read_avail(chan, &vals, type, &length, info); if (ret < 0) return ret;
switch (ret) { case IIO_AVAIL_RANGE: switch (*type) { case IIO_VAL_INT:
*val = vals[2]; break; default:
*val = vals[4]; if (val2)
*val2 = vals[5];
} return 0;
case IIO_AVAIL_LIST: if (length <= 0) return -EINVAL; switch (*type) { case IIO_VAL_INT:
*val = max_array(vals, length); break; default: /* TODO: learn about max for other iio values */ return -EINVAL;
} return 0;
default: return -EINVAL;
}
}
int iio_read_max_channel_raw(struct iio_channel *chan, int *val)
{ struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(chan->indio_dev); int type;
guard(mutex)(&iio_dev_opaque->info_exist_lock); if (!chan->indio_dev->info) return -ENODEV;
staticint iio_channel_read_min(struct iio_channel *chan, int *val, int *val2, int *type, enum iio_chan_info_enum info)
{ constint *vals; int length; int ret;
ret = iio_channel_read_avail(chan, &vals, type, &length, info); if (ret < 0) return ret;
switch (ret) { case IIO_AVAIL_RANGE: switch (*type) { case IIO_VAL_INT:
*val = vals[0]; break; default:
*val = vals[0]; if (val2)
*val2 = vals[1];
} return 0;
case IIO_AVAIL_LIST: if (length <= 0) return -EINVAL; switch (*type) { case IIO_VAL_INT:
*val = min_array(vals, length); break; default: /* TODO: learn about min for other iio values */ return -EINVAL;
} return 0;
default: return -EINVAL;
}
}
int iio_read_min_channel_raw(struct iio_channel *chan, int *val)
{ struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(chan->indio_dev); int type;
guard(mutex)(&iio_dev_opaque->info_exist_lock); if (!chan->indio_dev->info) return -ENODEV;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.