/* * The Allegro MicroSystems ALS31300 has an EEPROM space to configure how * the device works and how the interrupt line behaves. * Only the default setup with external trigger is supported. * * While the bindings supports declaring an interrupt line, those * events are not supported. * * It should be possible to adapt the driver to the current * device EEPROM setup at runtime.
*/
enum als31300_channels {
TEMPERATURE = 0,
AXIS_X,
AXIS_Y,
AXIS_Z,
};
struct als31300_variant_info {
u8 sensitivity;
};
struct als31300_data { struct device *dev; /* protects power on/off the device and access HW */ struct mutex mutex; conststruct als31300_variant_info *variant_info; struct regmap *map;
};
/* The whole measure is split into 2x32-bit registers, we need to read them both at once */ staticint als31300_get_measure(struct als31300_data *data,
u16 *t, s16 *x, s16 *y, s16 *z)
{
u32 buf[2]; int ret, err;
guard(mutex)(&data->mutex);
ret = pm_runtime_resume_and_get(data->dev); if (ret) return ret;
/* * Loop until data is valid, new data should have the * ALS31300_VOL_MSB_NEW_DATA bit set to 1. * Max update rate is 2KHz, wait up to 1ms.
*/
ret = read_poll_timeout(regmap_bulk_read, err,
err || FIELD_GET(ALS31300_VOL_MSB_NEW_DATA, buf[0]),
20, USEC_PER_MSEC, false,
data->map, ALS31300_VOL_MSB, buf, ARRAY_SIZE(buf)); /* Bail out on read_poll_timeout() error */ if (ret) goto out;
/* Bail out on regmap_bulk_read() error */ if (err) {
dev_err(data->dev, "read data failed, error %d\n", ret);
ret = err; goto out;
}
staticint als31300_read_raw(struct iio_dev *indio_dev, conststruct iio_chan_spec *chan, int *val, int *val2, long mask)
{ struct als31300_data *data = iio_priv(indio_dev);
s16 x, y, z;
u16 t; int ret;
switch (mask) { case IIO_CHAN_INFO_PROCESSED: case IIO_CHAN_INFO_RAW:
ret = als31300_get_measure(data, &t, &x, &y, &z); if (ret) return ret;
switch (chan->address) { case TEMPERATURE:
*val = t; return IIO_VAL_INT; case AXIS_X:
*val = x; return IIO_VAL_INT; case AXIS_Y:
*val = y; return IIO_VAL_INT; case AXIS_Z:
*val = z; return IIO_VAL_INT; default: return -EINVAL;
} case IIO_CHAN_INFO_SCALE: switch (chan->type) { case IIO_TEMP: /* * Fractional part of: * 1000 * 302 * (value - 1708) * temp = ---------------------------- * 4096 * to convert temperature in millicelcius.
*/
*val = MILLI * 302;
*val2 = 4096; return IIO_VAL_FRACTIONAL; case IIO_MAGN: /* * Devices are configured in factory * with different sensitivities: * - 500 GAUSS <-> 4 LSB/Gauss * - 1000 GAUSS <-> 2 LSB/Gauss * - 2000 GAUSS <-> 1 LSB/Gauss * with translates by a division of the returned * value to get Gauss value. * The sensitivity cannot be read at runtime * so the value depends on the model compatible * or device id.
*/
*val = 1;
*val2 = data->variant_info->sensitivity; return IIO_VAL_FRACTIONAL; default: return -EINVAL;
} case IIO_CHAN_INFO_OFFSET: switch (chan->type) { case IIO_TEMP:
*val = -1708; return IIO_VAL_INT; default: return -EINVAL;
} default: return -EINVAL;
}
}
staticint als31300_set_operating_mode(struct als31300_data *data, unsignedint val)
{ int ret;
ret = regmap_update_bits(data->map, ALS31300_VOL_MODE,
ALS31300_VOL_MODE_SLEEP, val); if (ret) {
dev_err(data->dev, "failed to set operating mode (%pe)\n", ERR_PTR(ret)); return ret;
}
/* The time it takes to exit sleep mode is equivalent to Power-On Delay Time */ if (val == ALS31300_VOL_MODE_ACTIVE_MODE)
fsleep(600);
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.