123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648 |
- // SPDX-License-Identifier: GPL-2.0
- /*
- * FXOS8700 - NXP IMU (accelerometer plus magnetometer)
- *
- * IIO core driver for FXOS8700, with support for I2C/SPI busses
- *
- * TODO: Buffer, trigger, and IRQ support
- */
- #include <linux/module.h>
- #include <linux/regmap.h>
- #include <linux/acpi.h>
- #include <linux/bitops.h>
- #include <linux/iio/iio.h>
- #include <linux/iio/sysfs.h>
- #include "fxos8700.h"
- /* Register Definitions */
- #define FXOS8700_STATUS 0x00
- #define FXOS8700_OUT_X_MSB 0x01
- #define FXOS8700_OUT_X_LSB 0x02
- #define FXOS8700_OUT_Y_MSB 0x03
- #define FXOS8700_OUT_Y_LSB 0x04
- #define FXOS8700_OUT_Z_MSB 0x05
- #define FXOS8700_OUT_Z_LSB 0x06
- #define FXOS8700_F_SETUP 0x09
- #define FXOS8700_TRIG_CFG 0x0a
- #define FXOS8700_SYSMOD 0x0b
- #define FXOS8700_INT_SOURCE 0x0c
- #define FXOS8700_WHO_AM_I 0x0d
- #define FXOS8700_XYZ_DATA_CFG 0x0e
- #define FXOS8700_HP_FILTER_CUTOFF 0x0f
- #define FXOS8700_PL_STATUS 0x10
- #define FXOS8700_PL_CFG 0x11
- #define FXOS8700_PL_COUNT 0x12
- #define FXOS8700_PL_BF_ZCOMP 0x13
- #define FXOS8700_PL_THS_REG 0x14
- #define FXOS8700_A_FFMT_CFG 0x15
- #define FXOS8700_A_FFMT_SRC 0x16
- #define FXOS8700_A_FFMT_THS 0x17
- #define FXOS8700_A_FFMT_COUNT 0x18
- #define FXOS8700_TRANSIENT_CFG 0x1d
- #define FXOS8700_TRANSIENT_SRC 0x1e
- #define FXOS8700_TRANSIENT_THS 0x1f
- #define FXOS8700_TRANSIENT_COUNT 0x20
- #define FXOS8700_PULSE_CFG 0x21
- #define FXOS8700_PULSE_SRC 0x22
- #define FXOS8700_PULSE_THSX 0x23
- #define FXOS8700_PULSE_THSY 0x24
- #define FXOS8700_PULSE_THSZ 0x25
- #define FXOS8700_PULSE_TMLT 0x26
- #define FXOS8700_PULSE_LTCY 0x27
- #define FXOS8700_PULSE_WIND 0x28
- #define FXOS8700_ASLP_COUNT 0x29
- #define FXOS8700_CTRL_REG1 0x2a
- #define FXOS8700_CTRL_REG2 0x2b
- #define FXOS8700_CTRL_REG3 0x2c
- #define FXOS8700_CTRL_REG4 0x2d
- #define FXOS8700_CTRL_REG5 0x2e
- #define FXOS8700_OFF_X 0x2f
- #define FXOS8700_OFF_Y 0x30
- #define FXOS8700_OFF_Z 0x31
- #define FXOS8700_M_DR_STATUS 0x32
- #define FXOS8700_M_OUT_X_MSB 0x33
- #define FXOS8700_M_OUT_X_LSB 0x34
- #define FXOS8700_M_OUT_Y_MSB 0x35
- #define FXOS8700_M_OUT_Y_LSB 0x36
- #define FXOS8700_M_OUT_Z_MSB 0x37
- #define FXOS8700_M_OUT_Z_LSB 0x38
- #define FXOS8700_CMP_X_MSB 0x39
- #define FXOS8700_CMP_X_LSB 0x3a
- #define FXOS8700_CMP_Y_MSB 0x3b
- #define FXOS8700_CMP_Y_LSB 0x3c
- #define FXOS8700_CMP_Z_MSB 0x3d
- #define FXOS8700_CMP_Z_LSB 0x3e
- #define FXOS8700_M_OFF_X_MSB 0x3f
- #define FXOS8700_M_OFF_X_LSB 0x40
- #define FXOS8700_M_OFF_Y_MSB 0x41
- #define FXOS8700_M_OFF_Y_LSB 0x42
- #define FXOS8700_M_OFF_Z_MSB 0x43
- #define FXOS8700_M_OFF_Z_LSB 0x44
- #define FXOS8700_MAX_X_MSB 0x45
- #define FXOS8700_MAX_X_LSB 0x46
- #define FXOS8700_MAX_Y_MSB 0x47
- #define FXOS8700_MAX_Y_LSB 0x48
- #define FXOS8700_MAX_Z_MSB 0x49
- #define FXOS8700_MAX_Z_LSB 0x4a
- #define FXOS8700_MIN_X_MSB 0x4b
- #define FXOS8700_MIN_X_LSB 0x4c
- #define FXOS8700_MIN_Y_MSB 0x4d
- #define FXOS8700_MIN_Y_LSB 0x4e
- #define FXOS8700_MIN_Z_MSB 0x4f
- #define FXOS8700_MIN_Z_LSB 0x50
- #define FXOS8700_TEMP 0x51
- #define FXOS8700_M_THS_CFG 0x52
- #define FXOS8700_M_THS_SRC 0x53
- #define FXOS8700_M_THS_X_MSB 0x54
- #define FXOS8700_M_THS_X_LSB 0x55
- #define FXOS8700_M_THS_Y_MSB 0x56
- #define FXOS8700_M_THS_Y_LSB 0x57
- #define FXOS8700_M_THS_Z_MSB 0x58
- #define FXOS8700_M_THS_Z_LSB 0x59
- #define FXOS8700_M_THS_COUNT 0x5a
- #define FXOS8700_M_CTRL_REG1 0x5b
- #define FXOS8700_M_CTRL_REG2 0x5c
- #define FXOS8700_M_CTRL_REG3 0x5d
- #define FXOS8700_M_INT_SRC 0x5e
- #define FXOS8700_A_VECM_CFG 0x5f
- #define FXOS8700_A_VECM_THS_MSB 0x60
- #define FXOS8700_A_VECM_THS_LSB 0x61
- #define FXOS8700_A_VECM_CNT 0x62
- #define FXOS8700_A_VECM_INITX_MSB 0x63
- #define FXOS8700_A_VECM_INITX_LSB 0x64
- #define FXOS8700_A_VECM_INITY_MSB 0x65
- #define FXOS8700_A_VECM_INITY_LSB 0x66
- #define FXOS8700_A_VECM_INITZ_MSB 0x67
- #define FXOS8700_A_VECM_INITZ_LSB 0x68
- #define FXOS8700_M_VECM_CFG 0x69
- #define FXOS8700_M_VECM_THS_MSB 0x6a
- #define FXOS8700_M_VECM_THS_LSB 0x6b
- #define FXOS8700_M_VECM_CNT 0x6c
- #define FXOS8700_M_VECM_INITX_MSB 0x6d
- #define FXOS8700_M_VECM_INITX_LSB 0x6e
- #define FXOS8700_M_VECM_INITY_MSB 0x6f
- #define FXOS8700_M_VECM_INITY_LSB 0x70
- #define FXOS8700_M_VECM_INITZ_MSB 0x71
- #define FXOS8700_M_VECM_INITZ_LSB 0x72
- #define FXOS8700_A_FFMT_THS_X_MSB 0x73
- #define FXOS8700_A_FFMT_THS_X_LSB 0x74
- #define FXOS8700_A_FFMT_THS_Y_MSB 0x75
- #define FXOS8700_A_FFMT_THS_Y_LSB 0x76
- #define FXOS8700_A_FFMT_THS_Z_MSB 0x77
- #define FXOS8700_A_FFMT_THS_Z_LSB 0x78
- #define FXOS8700_A_TRAN_INIT_MSB 0x79
- #define FXOS8700_A_TRAN_INIT_LSB_X 0x7a
- #define FXOS8700_A_TRAN_INIT_LSB_Y 0x7b
- #define FXOS8700_A_TRAN_INIT_LSB_Z 0x7d
- #define FXOS8700_TM_NVM_LOCK 0x7e
- #define FXOS8700_NVM_DATA0_35 0x80
- #define FXOS8700_NVM_DATA_BNK3 0xa4
- #define FXOS8700_NVM_DATA_BNK2 0xa5
- #define FXOS8700_NVM_DATA_BNK1 0xa6
- #define FXOS8700_NVM_DATA_BNK0 0xa7
- /* Bit definitions for FXOS8700_CTRL_REG1 */
- #define FXOS8700_CTRL_ODR_MSK 0x38
- #define FXOS8700_CTRL_ODR_MAX 0x00
- #define FXOS8700_CTRL_ODR_MIN GENMASK(4, 3)
- /* Bit definitions for FXOS8700_M_CTRL_REG1 */
- #define FXOS8700_HMS_MASK GENMASK(1, 0)
- #define FXOS8700_OS_MASK GENMASK(4, 2)
- /* Bit definitions for FXOS8700_M_CTRL_REG2 */
- #define FXOS8700_MAXMIN_RST BIT(2)
- #define FXOS8700_MAXMIN_DIS_THS BIT(3)
- #define FXOS8700_MAXMIN_DIS BIT(4)
- #define FXOS8700_ACTIVE 0x01
- #define FXOS8700_ACTIVE_MIN_USLEEP 4000 /* from table 6 in datasheet */
- #define FXOS8700_DEVICE_ID 0xC7
- #define FXOS8700_PRE_DEVICE_ID 0xC4
- #define FXOS8700_DATA_BUF_SIZE 3
- struct fxos8700_data {
- struct regmap *regmap;
- struct iio_trigger *trig;
- __be16 buf[FXOS8700_DATA_BUF_SIZE] ____cacheline_aligned;
- };
- /* Regmap info */
- static const struct regmap_range read_range[] = {
- {
- .range_min = FXOS8700_STATUS,
- .range_max = FXOS8700_A_FFMT_COUNT,
- }, {
- .range_min = FXOS8700_TRANSIENT_CFG,
- .range_max = FXOS8700_A_FFMT_THS_Z_LSB,
- },
- };
- static const struct regmap_range write_range[] = {
- {
- .range_min = FXOS8700_F_SETUP,
- .range_max = FXOS8700_TRIG_CFG,
- }, {
- .range_min = FXOS8700_XYZ_DATA_CFG,
- .range_max = FXOS8700_HP_FILTER_CUTOFF,
- }, {
- .range_min = FXOS8700_PL_CFG,
- .range_max = FXOS8700_A_FFMT_CFG,
- }, {
- .range_min = FXOS8700_A_FFMT_THS,
- .range_max = FXOS8700_TRANSIENT_CFG,
- }, {
- .range_min = FXOS8700_TRANSIENT_THS,
- .range_max = FXOS8700_PULSE_CFG,
- }, {
- .range_min = FXOS8700_PULSE_THSX,
- .range_max = FXOS8700_OFF_Z,
- }, {
- .range_min = FXOS8700_M_OFF_X_MSB,
- .range_max = FXOS8700_M_OFF_Z_LSB,
- }, {
- .range_min = FXOS8700_M_THS_CFG,
- .range_max = FXOS8700_M_THS_CFG,
- }, {
- .range_min = FXOS8700_M_THS_X_MSB,
- .range_max = FXOS8700_M_CTRL_REG3,
- }, {
- .range_min = FXOS8700_A_VECM_CFG,
- .range_max = FXOS8700_A_FFMT_THS_Z_LSB,
- },
- };
- static const struct regmap_access_table driver_read_table = {
- .yes_ranges = read_range,
- .n_yes_ranges = ARRAY_SIZE(read_range),
- };
- static const struct regmap_access_table driver_write_table = {
- .yes_ranges = write_range,
- .n_yes_ranges = ARRAY_SIZE(write_range),
- };
- const struct regmap_config fxos8700_regmap_config = {
- .reg_bits = 8,
- .val_bits = 8,
- .max_register = FXOS8700_NVM_DATA_BNK0,
- .rd_table = &driver_read_table,
- .wr_table = &driver_write_table,
- };
- EXPORT_SYMBOL(fxos8700_regmap_config);
- #define FXOS8700_CHANNEL(_type, _axis) { \
- .type = _type, \
- .modified = 1, \
- .channel2 = IIO_MOD_##_axis, \
- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
- .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
- BIT(IIO_CHAN_INFO_SAMP_FREQ), \
- }
- enum fxos8700_accel_scale_bits {
- MODE_2G = 0,
- MODE_4G,
- MODE_8G,
- };
- /* scan indexes follow DATA register order */
- enum fxos8700_scan_axis {
- FXOS8700_SCAN_ACCEL_X = 0,
- FXOS8700_SCAN_ACCEL_Y,
- FXOS8700_SCAN_ACCEL_Z,
- FXOS8700_SCAN_MAGN_X,
- FXOS8700_SCAN_MAGN_Y,
- FXOS8700_SCAN_MAGN_Z,
- FXOS8700_SCAN_RHALL,
- FXOS8700_SCAN_TIMESTAMP,
- };
- enum fxos8700_sensor {
- FXOS8700_ACCEL = 0,
- FXOS8700_MAGN,
- FXOS8700_NUM_SENSORS /* must be last */
- };
- enum fxos8700_int_pin {
- FXOS8700_PIN_INT1,
- FXOS8700_PIN_INT2
- };
- struct fxos8700_scale {
- u8 bits;
- int uscale;
- };
- struct fxos8700_odr {
- u8 bits;
- int odr;
- int uodr;
- };
- static const struct fxos8700_scale fxos8700_accel_scale[] = {
- { MODE_2G, 244},
- { MODE_4G, 488},
- { MODE_8G, 976},
- };
- /*
- * Accellerometer and magnetometer have the same ODR options, set in the
- * CTRL_REG1 register. ODR is halved when using both sensors at once in
- * hybrid mode.
- */
- static const struct fxos8700_odr fxos8700_odr[] = {
- {0x00, 800, 0},
- {0x01, 400, 0},
- {0x02, 200, 0},
- {0x03, 100, 0},
- {0x04, 50, 0},
- {0x05, 12, 500000},
- {0x06, 6, 250000},
- {0x07, 1, 562500},
- };
- static const struct iio_chan_spec fxos8700_channels[] = {
- FXOS8700_CHANNEL(IIO_ACCEL, X),
- FXOS8700_CHANNEL(IIO_ACCEL, Y),
- FXOS8700_CHANNEL(IIO_ACCEL, Z),
- FXOS8700_CHANNEL(IIO_MAGN, X),
- FXOS8700_CHANNEL(IIO_MAGN, Y),
- FXOS8700_CHANNEL(IIO_MAGN, Z),
- IIO_CHAN_SOFT_TIMESTAMP(FXOS8700_SCAN_TIMESTAMP),
- };
- static enum fxos8700_sensor fxos8700_to_sensor(enum iio_chan_type iio_type)
- {
- switch (iio_type) {
- case IIO_ACCEL:
- return FXOS8700_ACCEL;
- case IIO_ANGL_VEL:
- return FXOS8700_MAGN;
- default:
- return -EINVAL;
- }
- }
- static int fxos8700_set_active_mode(struct fxos8700_data *data,
- enum fxos8700_sensor t, bool mode)
- {
- int ret;
- ret = regmap_write(data->regmap, FXOS8700_CTRL_REG1, mode);
- if (ret)
- return ret;
- usleep_range(FXOS8700_ACTIVE_MIN_USLEEP,
- FXOS8700_ACTIVE_MIN_USLEEP + 1000);
- return 0;
- }
- static int fxos8700_set_scale(struct fxos8700_data *data,
- enum fxos8700_sensor t, int uscale)
- {
- int i;
- static const int scale_num = ARRAY_SIZE(fxos8700_accel_scale);
- struct device *dev = regmap_get_device(data->regmap);
- if (t == FXOS8700_MAGN) {
- dev_err(dev, "Magnetometer scale is locked at 1200uT\n");
- return -EINVAL;
- }
- for (i = 0; i < scale_num; i++)
- if (fxos8700_accel_scale[i].uscale == uscale)
- break;
- if (i == scale_num)
- return -EINVAL;
- return regmap_write(data->regmap, FXOS8700_XYZ_DATA_CFG,
- fxos8700_accel_scale[i].bits);
- }
- static int fxos8700_get_scale(struct fxos8700_data *data,
- enum fxos8700_sensor t, int *uscale)
- {
- int i, ret, val;
- static const int scale_num = ARRAY_SIZE(fxos8700_accel_scale);
- if (t == FXOS8700_MAGN) {
- *uscale = 1200; /* Magnetometer is locked at 1200uT */
- return 0;
- }
- ret = regmap_read(data->regmap, FXOS8700_XYZ_DATA_CFG, &val);
- if (ret)
- return ret;
- for (i = 0; i < scale_num; i++) {
- if (fxos8700_accel_scale[i].bits == (val & 0x3)) {
- *uscale = fxos8700_accel_scale[i].uscale;
- return 0;
- }
- }
- return -EINVAL;
- }
- static int fxos8700_get_data(struct fxos8700_data *data, int chan_type,
- int axis, int *val)
- {
- u8 base, reg;
- int ret;
- enum fxos8700_sensor type = fxos8700_to_sensor(chan_type);
- base = type ? FXOS8700_OUT_X_MSB : FXOS8700_M_OUT_X_MSB;
- /* Block read 6 bytes of device output registers to avoid data loss */
- ret = regmap_bulk_read(data->regmap, base, data->buf,
- FXOS8700_DATA_BUF_SIZE);
- if (ret)
- return ret;
- /* Convert axis to buffer index */
- reg = axis - IIO_MOD_X;
- /* Convert to native endianness */
- *val = sign_extend32(be16_to_cpu(data->buf[reg]), 15);
- return 0;
- }
- static int fxos8700_set_odr(struct fxos8700_data *data, enum fxos8700_sensor t,
- int odr, int uodr)
- {
- int i, ret, val;
- bool active_mode;
- static const int odr_num = ARRAY_SIZE(fxos8700_odr);
- ret = regmap_read(data->regmap, FXOS8700_CTRL_REG1, &val);
- if (ret)
- return ret;
- active_mode = val & FXOS8700_ACTIVE;
- if (active_mode) {
- /*
- * The device must be in standby mode to change any of the
- * other fields within CTRL_REG1
- */
- ret = regmap_write(data->regmap, FXOS8700_CTRL_REG1,
- val & ~FXOS8700_ACTIVE);
- if (ret)
- return ret;
- }
- for (i = 0; i < odr_num; i++)
- if (fxos8700_odr[i].odr == odr && fxos8700_odr[i].uodr == uodr)
- break;
- if (i >= odr_num)
- return -EINVAL;
- return regmap_update_bits(data->regmap,
- FXOS8700_CTRL_REG1,
- FXOS8700_CTRL_ODR_MSK + FXOS8700_ACTIVE,
- fxos8700_odr[i].bits << 3 | active_mode);
- }
- static int fxos8700_get_odr(struct fxos8700_data *data, enum fxos8700_sensor t,
- int *odr, int *uodr)
- {
- int i, val, ret;
- static const int odr_num = ARRAY_SIZE(fxos8700_odr);
- ret = regmap_read(data->regmap, FXOS8700_CTRL_REG1, &val);
- if (ret)
- return ret;
- val &= FXOS8700_CTRL_ODR_MSK;
- for (i = 0; i < odr_num; i++)
- if (val == fxos8700_odr[i].bits)
- break;
- if (i >= odr_num)
- return -EINVAL;
- *odr = fxos8700_odr[i].odr;
- *uodr = fxos8700_odr[i].uodr;
- return 0;
- }
- static int fxos8700_read_raw(struct iio_dev *indio_dev,
- struct iio_chan_spec const *chan,
- int *val, int *val2, long mask)
- {
- int ret;
- struct fxos8700_data *data = iio_priv(indio_dev);
- switch (mask) {
- case IIO_CHAN_INFO_RAW:
- ret = fxos8700_get_data(data, chan->type, chan->channel2, val);
- if (ret)
- return ret;
- return IIO_VAL_INT;
- case IIO_CHAN_INFO_SCALE:
- *val = 0;
- ret = fxos8700_get_scale(data, fxos8700_to_sensor(chan->type),
- val2);
- return ret ? ret : IIO_VAL_INT_PLUS_MICRO;
- case IIO_CHAN_INFO_SAMP_FREQ:
- ret = fxos8700_get_odr(data, fxos8700_to_sensor(chan->type),
- val, val2);
- return ret ? ret : IIO_VAL_INT_PLUS_MICRO;
- default:
- return -EINVAL;
- }
- }
- static int fxos8700_write_raw(struct iio_dev *indio_dev,
- struct iio_chan_spec const *chan,
- int val, int val2, long mask)
- {
- struct fxos8700_data *data = iio_priv(indio_dev);
- switch (mask) {
- case IIO_CHAN_INFO_SCALE:
- return fxos8700_set_scale(data, fxos8700_to_sensor(chan->type),
- val2);
- case IIO_CHAN_INFO_SAMP_FREQ:
- return fxos8700_set_odr(data, fxos8700_to_sensor(chan->type),
- val, val2);
- default:
- return -EINVAL;
- }
- }
- static IIO_CONST_ATTR(in_accel_sampling_frequency_available,
- "1.5625 6.25 12.5 50 100 200 400 800");
- static IIO_CONST_ATTR(in_magn_sampling_frequency_available,
- "1.5625 6.25 12.5 50 100 200 400 800");
- static IIO_CONST_ATTR(in_accel_scale_available, "0.000244 0.000488 0.000976");
- static IIO_CONST_ATTR(in_magn_scale_available, "0.000001200");
- static struct attribute *fxos8700_attrs[] = {
- &iio_const_attr_in_accel_sampling_frequency_available.dev_attr.attr,
- &iio_const_attr_in_magn_sampling_frequency_available.dev_attr.attr,
- &iio_const_attr_in_accel_scale_available.dev_attr.attr,
- &iio_const_attr_in_magn_scale_available.dev_attr.attr,
- NULL,
- };
- static const struct attribute_group fxos8700_attrs_group = {
- .attrs = fxos8700_attrs,
- };
- static const struct iio_info fxos8700_info = {
- .read_raw = fxos8700_read_raw,
- .write_raw = fxos8700_write_raw,
- .attrs = &fxos8700_attrs_group,
- };
- static int fxos8700_chip_init(struct fxos8700_data *data, bool use_spi)
- {
- int ret;
- unsigned int val;
- struct device *dev = regmap_get_device(data->regmap);
- ret = regmap_read(data->regmap, FXOS8700_WHO_AM_I, &val);
- if (ret) {
- dev_err(dev, "Error reading chip id\n");
- return ret;
- }
- if (val != FXOS8700_DEVICE_ID && val != FXOS8700_PRE_DEVICE_ID) {
- dev_err(dev, "Wrong chip id, got %x expected %x or %x\n",
- val, FXOS8700_DEVICE_ID, FXOS8700_PRE_DEVICE_ID);
- return -ENODEV;
- }
- ret = fxos8700_set_active_mode(data, FXOS8700_ACCEL, true);
- if (ret)
- return ret;
- ret = fxos8700_set_active_mode(data, FXOS8700_MAGN, true);
- if (ret)
- return ret;
- /*
- * The device must be in standby mode to change any of the other fields
- * within CTRL_REG1
- */
- ret = regmap_write(data->regmap, FXOS8700_CTRL_REG1, 0x00);
- if (ret)
- return ret;
- /* Set max oversample ratio (OSR) and both devices active */
- ret = regmap_write(data->regmap, FXOS8700_M_CTRL_REG1,
- FXOS8700_HMS_MASK | FXOS8700_OS_MASK);
- if (ret)
- return ret;
- /* Disable and rst min/max measurements & threshold */
- ret = regmap_write(data->regmap, FXOS8700_M_CTRL_REG2,
- FXOS8700_MAXMIN_RST | FXOS8700_MAXMIN_DIS_THS |
- FXOS8700_MAXMIN_DIS);
- if (ret)
- return ret;
- /* Max ODR (800Hz individual or 400Hz hybrid), active mode */
- ret = regmap_write(data->regmap, FXOS8700_CTRL_REG1,
- FXOS8700_CTRL_ODR_MAX | FXOS8700_ACTIVE);
- if (ret)
- return ret;
- /* Set for max full-scale range (+/-8G) */
- return regmap_write(data->regmap, FXOS8700_XYZ_DATA_CFG, MODE_8G);
- }
- static void fxos8700_chip_uninit(void *data)
- {
- struct fxos8700_data *fxos8700_data = data;
- fxos8700_set_active_mode(fxos8700_data, FXOS8700_ACCEL, false);
- fxos8700_set_active_mode(fxos8700_data, FXOS8700_MAGN, false);
- }
- int fxos8700_core_probe(struct device *dev, struct regmap *regmap,
- const char *name, bool use_spi)
- {
- struct iio_dev *indio_dev;
- struct fxos8700_data *data;
- int ret;
- indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
- if (!indio_dev)
- return -ENOMEM;
- data = iio_priv(indio_dev);
- dev_set_drvdata(dev, indio_dev);
- data->regmap = regmap;
- ret = fxos8700_chip_init(data, use_spi);
- if (ret)
- return ret;
- ret = devm_add_action_or_reset(dev, fxos8700_chip_uninit, data);
- if (ret)
- return ret;
- indio_dev->channels = fxos8700_channels;
- indio_dev->num_channels = ARRAY_SIZE(fxos8700_channels);
- indio_dev->name = name ? name : "fxos8700";
- indio_dev->modes = INDIO_DIRECT_MODE;
- indio_dev->info = &fxos8700_info;
- return devm_iio_device_register(dev, indio_dev);
- }
- EXPORT_SYMBOL_GPL(fxos8700_core_probe);
- MODULE_AUTHOR("Robert Jones <rjones@gateworks.com>");
- MODULE_DESCRIPTION("FXOS8700 6-Axis Acc and Mag Combo Sensor driver");
- MODULE_LICENSE("GPL v2");
|