staticint adux1020_read_fifo(struct adux1020_data *data, u16 *buf, u8 buf_len)
{ unsignedint regval; int i, ret;
/* Enable 32MHz clock */
ret = regmap_write(data->regmap, ADUX1020_REG_TEST_MODES_3,
ADUX1020_FORCE_CLOCK_ON); if (ret < 0) return ret;
for (i = 0; i < buf_len; i++) {
ret = regmap_read(data->regmap, ADUX1020_REG_DATA_BUFFER,
®val); if (ret < 0) return ret;
buf[i] = regval;
}
/* Set 32MHz clock to be controlled by internal state machine */ return regmap_write(data->regmap, ADUX1020_REG_TEST_MODES_3,
ADUX1020_FORCE_CLOCK_RESET);
}
staticint adux1020_set_mode(struct adux1020_data *data, enum adux1020_op_modes mode)
{ int ret;
/* Switch to standby mode before changing the mode */
ret = regmap_write(data->regmap, ADUX1020_REG_OP_MODE,
ADUX1020_MODE_STANDBY); if (ret < 0) return ret;
/* Set data out and switch to the desired mode */ switch (mode) { case ADUX1020_MODE_PROX_I:
ret = regmap_update_bits(data->regmap, ADUX1020_REG_OP_MODE,
ADUX1020_DATA_OUT_MODE_MASK,
ADUX1020_DATA_OUT_PROX_I); if (ret < 0) return ret;
ret = regmap_update_bits(data->regmap, ADUX1020_REG_OP_MODE,
ADUX1020_OP_MODE_MASK,
ADUX1020_MODE_PROX_I); if (ret < 0) return ret; break; default: return -EINVAL;
}
/* Disable INT pin as polling is going to be used */
ret = regmap_write(data->regmap, ADUX1020_REG_INT_ENABLE,
ADUX1020_INT_DISABLE); if (ret < 0) return ret;
/* Enable mode interrupt */
ret = regmap_update_bits(data->regmap, ADUX1020_REG_INT_MASK,
ADUX1020_MODE_INT_MASK,
adux1020_modes[mode].int_en); if (ret < 0) return ret;
while (tries--) {
ret = regmap_read(data->regmap, ADUX1020_REG_INT_STATUS,
&status); if (ret < 0) return ret;
status &= ADUX1020_FIFO_STATUS_MASK; if (status >= adux1020_modes[mode].bytes) break;
msleep(20);
}
if (tries < 0) return -EIO;
ret = adux1020_read_fifo(data, val, adux1020_modes[mode].buf_len); if (ret < 0) return ret;
/* Clear mode interrupt */
ret = regmap_write(data->regmap, ADUX1020_REG_INT_STATUS,
(~adux1020_modes[mode].int_en)); if (ret < 0) return ret;
staticint adux1020_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask)
{ struct adux1020_data *data = iio_priv(indio_dev);
u16 buf[3]; int ret = -EINVAL; unsignedint regval;
mutex_lock(&data->lock);
switch (mask) { case IIO_CHAN_INFO_RAW: switch (chan->type) { case IIO_PROXIMITY:
ret = adux1020_set_mode(data, ADUX1020_MODE_PROX_I); if (ret < 0) goto fail;
ret = adux1020_measure(data, ADUX1020_MODE_PROX_I, buf); if (ret < 0) goto fail;
*val = buf[0];
ret = IIO_VAL_INT; break; default: break;
} break; case IIO_CHAN_INFO_PROCESSED: switch (chan->type) { case IIO_CURRENT:
ret = regmap_read(data->regmap,
ADUX1020_REG_LED_CURRENT, ®val); if (ret < 0) goto fail;
staticinlineint adux1020_find_index(constint array[][2], int count, int val, int val2)
{ int i;
for (i = 0; i < count; i++) if (val == array[i][0] && val2 == array[i][1]) return i;
return -EINVAL;
}
staticint adux1020_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask)
{ struct adux1020_data *data = iio_priv(indio_dev); int i, ret = -EINVAL;
mutex_lock(&data->lock);
switch (mask) { case IIO_CHAN_INFO_SAMP_FREQ: if (chan->type == IIO_PROXIMITY) {
i = adux1020_find_index(adux1020_rates,
ARRAY_SIZE(adux1020_rates),
val, val2); if (i < 0) {
ret = i; goto fail;
}
ret = regmap_update_bits(data->regmap,
ADUX1020_REG_FREQUENCY,
ADUX1020_PROX_FREQ_MASK,
ADUX1020_PROX_FREQ(i));
} break; case IIO_CHAN_INFO_PROCESSED: if (chan->type == IIO_CURRENT) {
i = adux1020_find_index(adux1020_led_currents,
ARRAY_SIZE(adux1020_led_currents),
val, val2); if (i < 0) {
ret = i; goto fail;
}
ret = regmap_write(data->regmap, ADUX1020_REG_INT_ENABLE,
ADUX1020_INT_ENABLE); if (ret < 0) goto fail;
ret = regmap_write(data->regmap, ADUX1020_REG_INT_POLARITY, 0); if (ret < 0) goto fail;
switch (chan->type) { case IIO_PROXIMITY: if (dir == IIO_EV_DIR_RISING)
mask = ADUX1020_PROX_ON1_INT; else
mask = ADUX1020_PROX_OFF1_INT;
if (state)
ret = regmap_clear_bits(data->regmap,
ADUX1020_REG_INT_MASK, mask); else
ret = regmap_set_bits(data->regmap,
ADUX1020_REG_INT_MASK, mask); if (ret < 0) goto fail;
/* * Trigger proximity interrupt when the intensity is above * or below threshold
*/
ret = regmap_set_bits(data->regmap, ADUX1020_REG_PROX_TYPE,
ADUX1020_PROX_TYPE); if (ret < 0) goto fail;
/* Set proximity mode */
ret = adux1020_set_mode(data, ADUX1020_MODE_PROX_I); break; default:
ret = -EINVAL; break;
}
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.