// SPDX-License-Identifier: GPL-2.0-only /* * kxsd9.c simple support for the Kionix KXSD9 3D * accelerometer. * * Copyright (c) 2008-2009 Jonathan Cameron <jic23@kernel.org> * * The i2c interface is very similar, so shouldn't be a problem once * I have a suitable wire made up. * * TODO: Support the motion detector
*/
staticint kxsd9_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask)
{ int ret = -EINVAL; struct kxsd9_state *st = iio_priv(indio_dev);
pm_runtime_get_sync(st->dev);
if (mask == IIO_CHAN_INFO_SCALE) { /* Check no integer component */ if (val) return -EINVAL;
ret = kxsd9_write_scale(indio_dev, val2);
}
staticint kxsd9_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask)
{ int ret = -EINVAL; struct kxsd9_state *st = iio_priv(indio_dev); unsignedint regval;
__be16 raw_val;
u16 nval;
pm_runtime_get_sync(st->dev);
switch (mask) { case IIO_CHAN_INFO_RAW:
ret = regmap_bulk_read(st->map, chan->address, &raw_val, sizeof(raw_val)); if (ret) goto error_ret;
nval = be16_to_cpu(raw_val); /* Only 12 bits are valid */
nval >>= 4;
*val = nval;
ret = IIO_VAL_INT; break; case IIO_CHAN_INFO_OFFSET: /* This has a bias of -2048 */
*val = KXSD9_ZERO_G_OFFSET;
ret = IIO_VAL_INT; break; case IIO_CHAN_INFO_SCALE:
ret = regmap_read(st->map,
KXSD9_REG_CTRL_C,
®val); if (ret < 0) goto error_ret;
*val = 0;
*val2 = kxsd9_micro_scales[regval & KXSD9_CTRL_C_FS_MASK];
ret = IIO_VAL_INT_PLUS_MICRO; break;
}
staticint kxsd9_power_up(struct kxsd9_state *st)
{ int ret;
/* Enable the regulators */
ret = regulator_bulk_enable(ARRAY_SIZE(st->regs), st->regs); if (ret) {
dev_err(st->dev, "Cannot enable regulators\n"); return ret;
}
/* Power up */
ret = regmap_write(st->map,
KXSD9_REG_CTRL_B,
KXSD9_CTRL_B_ENABLE); if (ret) return ret;
/* * Set 1000Hz LPF, 2g fullscale, motion wakeup threshold 1g, * latched wakeup
*/
ret = regmap_write(st->map,
KXSD9_REG_CTRL_C,
KXSD9_CTRL_C_LP_1000HZ |
KXSD9_CTRL_C_MOT_LEV |
KXSD9_CTRL_C_MOT_LAT |
st->scale); if (ret) return ret;
/* * Power-up time depends on the LPF setting, but typ 15.9 ms, let's * set 20 ms to allow for some slack.
*/
msleep(20);
return 0;
};
staticint kxsd9_power_down(struct kxsd9_state *st)
{ int ret;
/* * Set into low power mode - since there may be more users of the * regulators this is the first step of the power saving: it will * make sure we conserve power even if there are others users on the * regulators.
*/
ret = regmap_clear_bits(st->map, KXSD9_REG_CTRL_B, KXSD9_CTRL_B_ENABLE); if (ret) return ret;
/* Disable the regulators */
ret = regulator_bulk_disable(ARRAY_SIZE(st->regs), st->regs); if (ret) {
dev_err(st->dev, "Cannot disable regulators\n"); return ret;
}
/* Read the mounting matrix, if present */
ret = iio_read_mount_matrix(dev, &st->orientation); if (ret) return ret;
/* Fetch and turn on regulators */
st->regs[0].supply = kxsd9_reg_vdd;
st->regs[1].supply = kxsd9_reg_iovdd;
ret = devm_regulator_bulk_get(dev,
ARRAY_SIZE(st->regs),
st->regs); if (ret) {
dev_err(dev, "Cannot get regulators\n"); return ret;
} /* Default scaling */
st->scale = KXSD9_CTRL_C_FS_2G;
kxsd9_power_up(st);
ret = iio_triggered_buffer_setup(indio_dev,
iio_pollfunc_store_time,
kxsd9_trigger_handler,
&kxsd9_buffer_setup_ops); if (ret) {
dev_err(dev, "triggered buffer setup failed\n"); goto err_power_down;
}
ret = iio_device_register(indio_dev); if (ret) goto err_cleanup_buffer;
dev_set_drvdata(dev, indio_dev);
/* Enable runtime PM */
pm_runtime_get_noresume(dev);
pm_runtime_set_active(dev);
pm_runtime_enable(dev); /* * Set autosuspend to two orders of magnitude larger than the * start-up time. 20ms start-up time means 2000ms autosuspend, * i.e. 2 seconds.
*/
pm_runtime_set_autosuspend_delay(dev, 2000);
pm_runtime_use_autosuspend(dev);
pm_runtime_put(dev);
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.