linux/drivers/iio/imu/fxos8700_core.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * FXOS8700 - NXP IMU (accelerometer plus magnetometer)
   4 *
   5 * IIO core driver for FXOS8700, with support for I2C/SPI busses
   6 *
   7 * TODO: Buffer, trigger, and IRQ support
   8 */
   9#include <linux/module.h>
  10#include <linux/regmap.h>
  11#include <linux/acpi.h>
  12#include <linux/bitops.h>
  13
  14#include <linux/iio/iio.h>
  15#include <linux/iio/sysfs.h>
  16
  17#include "fxos8700.h"
  18
  19/* Register Definitions */
  20#define FXOS8700_STATUS             0x00
  21#define FXOS8700_OUT_X_MSB          0x01
  22#define FXOS8700_OUT_X_LSB          0x02
  23#define FXOS8700_OUT_Y_MSB          0x03
  24#define FXOS8700_OUT_Y_LSB          0x04
  25#define FXOS8700_OUT_Z_MSB          0x05
  26#define FXOS8700_OUT_Z_LSB          0x06
  27#define FXOS8700_F_SETUP            0x09
  28#define FXOS8700_TRIG_CFG           0x0a
  29#define FXOS8700_SYSMOD             0x0b
  30#define FXOS8700_INT_SOURCE         0x0c
  31#define FXOS8700_WHO_AM_I           0x0d
  32#define FXOS8700_XYZ_DATA_CFG       0x0e
  33#define FXOS8700_HP_FILTER_CUTOFF   0x0f
  34#define FXOS8700_PL_STATUS          0x10
  35#define FXOS8700_PL_CFG             0x11
  36#define FXOS8700_PL_COUNT           0x12
  37#define FXOS8700_PL_BF_ZCOMP        0x13
  38#define FXOS8700_PL_THS_REG         0x14
  39#define FXOS8700_A_FFMT_CFG         0x15
  40#define FXOS8700_A_FFMT_SRC         0x16
  41#define FXOS8700_A_FFMT_THS         0x17
  42#define FXOS8700_A_FFMT_COUNT       0x18
  43#define FXOS8700_TRANSIENT_CFG      0x1d
  44#define FXOS8700_TRANSIENT_SRC      0x1e
  45#define FXOS8700_TRANSIENT_THS      0x1f
  46#define FXOS8700_TRANSIENT_COUNT    0x20
  47#define FXOS8700_PULSE_CFG          0x21
  48#define FXOS8700_PULSE_SRC          0x22
  49#define FXOS8700_PULSE_THSX         0x23
  50#define FXOS8700_PULSE_THSY         0x24
  51#define FXOS8700_PULSE_THSZ         0x25
  52#define FXOS8700_PULSE_TMLT         0x26
  53#define FXOS8700_PULSE_LTCY         0x27
  54#define FXOS8700_PULSE_WIND         0x28
  55#define FXOS8700_ASLP_COUNT         0x29
  56#define FXOS8700_CTRL_REG1          0x2a
  57#define FXOS8700_CTRL_REG2          0x2b
  58#define FXOS8700_CTRL_REG3          0x2c
  59#define FXOS8700_CTRL_REG4          0x2d
  60#define FXOS8700_CTRL_REG5          0x2e
  61#define FXOS8700_OFF_X              0x2f
  62#define FXOS8700_OFF_Y              0x30
  63#define FXOS8700_OFF_Z              0x31
  64#define FXOS8700_M_DR_STATUS        0x32
  65#define FXOS8700_M_OUT_X_MSB        0x33
  66#define FXOS8700_M_OUT_X_LSB        0x34
  67#define FXOS8700_M_OUT_Y_MSB        0x35
  68#define FXOS8700_M_OUT_Y_LSB        0x36
  69#define FXOS8700_M_OUT_Z_MSB        0x37
  70#define FXOS8700_M_OUT_Z_LSB        0x38
  71#define FXOS8700_CMP_X_MSB          0x39
  72#define FXOS8700_CMP_X_LSB          0x3a
  73#define FXOS8700_CMP_Y_MSB          0x3b
  74#define FXOS8700_CMP_Y_LSB          0x3c
  75#define FXOS8700_CMP_Z_MSB          0x3d
  76#define FXOS8700_CMP_Z_LSB          0x3e
  77#define FXOS8700_M_OFF_X_MSB        0x3f
  78#define FXOS8700_M_OFF_X_LSB        0x40
  79#define FXOS8700_M_OFF_Y_MSB        0x41
  80#define FXOS8700_M_OFF_Y_LSB        0x42
  81#define FXOS8700_M_OFF_Z_MSB        0x43
  82#define FXOS8700_M_OFF_Z_LSB        0x44
  83#define FXOS8700_MAX_X_MSB          0x45
  84#define FXOS8700_MAX_X_LSB          0x46
  85#define FXOS8700_MAX_Y_MSB          0x47
  86#define FXOS8700_MAX_Y_LSB          0x48
  87#define FXOS8700_MAX_Z_MSB          0x49
  88#define FXOS8700_MAX_Z_LSB          0x4a
  89#define FXOS8700_MIN_X_MSB          0x4b
  90#define FXOS8700_MIN_X_LSB          0x4c
  91#define FXOS8700_MIN_Y_MSB          0x4d
  92#define FXOS8700_MIN_Y_LSB          0x4e
  93#define FXOS8700_MIN_Z_MSB          0x4f
  94#define FXOS8700_MIN_Z_LSB          0x50
  95#define FXOS8700_TEMP               0x51
  96#define FXOS8700_M_THS_CFG          0x52
  97#define FXOS8700_M_THS_SRC          0x53
  98#define FXOS8700_M_THS_X_MSB        0x54
  99#define FXOS8700_M_THS_X_LSB        0x55
 100#define FXOS8700_M_THS_Y_MSB        0x56
 101#define FXOS8700_M_THS_Y_LSB        0x57
 102#define FXOS8700_M_THS_Z_MSB        0x58
 103#define FXOS8700_M_THS_Z_LSB        0x59
 104#define FXOS8700_M_THS_COUNT        0x5a
 105#define FXOS8700_M_CTRL_REG1        0x5b
 106#define FXOS8700_M_CTRL_REG2        0x5c
 107#define FXOS8700_M_CTRL_REG3        0x5d
 108#define FXOS8700_M_INT_SRC          0x5e
 109#define FXOS8700_A_VECM_CFG         0x5f
 110#define FXOS8700_A_VECM_THS_MSB     0x60
 111#define FXOS8700_A_VECM_THS_LSB     0x61
 112#define FXOS8700_A_VECM_CNT         0x62
 113#define FXOS8700_A_VECM_INITX_MSB   0x63
 114#define FXOS8700_A_VECM_INITX_LSB   0x64
 115#define FXOS8700_A_VECM_INITY_MSB   0x65
 116#define FXOS8700_A_VECM_INITY_LSB   0x66
 117#define FXOS8700_A_VECM_INITZ_MSB   0x67
 118#define FXOS8700_A_VECM_INITZ_LSB   0x68
 119#define FXOS8700_M_VECM_CFG         0x69
 120#define FXOS8700_M_VECM_THS_MSB     0x6a
 121#define FXOS8700_M_VECM_THS_LSB     0x6b
 122#define FXOS8700_M_VECM_CNT         0x6c
 123#define FXOS8700_M_VECM_INITX_MSB   0x6d
 124#define FXOS8700_M_VECM_INITX_LSB   0x6e
 125#define FXOS8700_M_VECM_INITY_MSB   0x6f
 126#define FXOS8700_M_VECM_INITY_LSB   0x70
 127#define FXOS8700_M_VECM_INITZ_MSB   0x71
 128#define FXOS8700_M_VECM_INITZ_LSB   0x72
 129#define FXOS8700_A_FFMT_THS_X_MSB   0x73
 130#define FXOS8700_A_FFMT_THS_X_LSB   0x74
 131#define FXOS8700_A_FFMT_THS_Y_MSB   0x75
 132#define FXOS8700_A_FFMT_THS_Y_LSB   0x76
 133#define FXOS8700_A_FFMT_THS_Z_MSB   0x77
 134#define FXOS8700_A_FFMT_THS_Z_LSB   0x78
 135#define FXOS8700_A_TRAN_INIT_MSB    0x79
 136#define FXOS8700_A_TRAN_INIT_LSB_X  0x7a
 137#define FXOS8700_A_TRAN_INIT_LSB_Y  0x7b
 138#define FXOS8700_A_TRAN_INIT_LSB_Z  0x7d
 139#define FXOS8700_TM_NVM_LOCK        0x7e
 140#define FXOS8700_NVM_DATA0_35       0x80
 141#define FXOS8700_NVM_DATA_BNK3      0xa4
 142#define FXOS8700_NVM_DATA_BNK2      0xa5
 143#define FXOS8700_NVM_DATA_BNK1      0xa6
 144#define FXOS8700_NVM_DATA_BNK0      0xa7
 145
 146/* Bit definitions for FXOS8700_CTRL_REG1 */
 147#define FXOS8700_CTRL_ODR_MSK       0x38
 148#define FXOS8700_CTRL_ODR_MAX       0x00
 149#define FXOS8700_CTRL_ODR_MIN       GENMASK(4, 3)
 150
 151/* Bit definitions for FXOS8700_M_CTRL_REG1 */
 152#define FXOS8700_HMS_MASK           GENMASK(1, 0)
 153#define FXOS8700_OS_MASK            GENMASK(4, 2)
 154
 155/* Bit definitions for FXOS8700_M_CTRL_REG2 */
 156#define FXOS8700_MAXMIN_RST         BIT(2)
 157#define FXOS8700_MAXMIN_DIS_THS     BIT(3)
 158#define FXOS8700_MAXMIN_DIS         BIT(4)
 159
 160#define FXOS8700_ACTIVE             0x01
 161#define FXOS8700_ACTIVE_MIN_USLEEP  4000 /* from table 6 in datasheet */
 162
 163#define FXOS8700_DEVICE_ID          0xC7
 164#define FXOS8700_PRE_DEVICE_ID      0xC4
 165#define FXOS8700_DATA_BUF_SIZE      3
 166
 167struct fxos8700_data {
 168        struct regmap *regmap;
 169        struct iio_trigger *trig;
 170        __be16 buf[FXOS8700_DATA_BUF_SIZE] ____cacheline_aligned;
 171};
 172
 173/* Regmap info */
 174static const struct regmap_range read_range[] = {
 175        {
 176                .range_min = FXOS8700_STATUS,
 177                .range_max = FXOS8700_A_FFMT_COUNT,
 178        }, {
 179                .range_min = FXOS8700_TRANSIENT_CFG,
 180                .range_max = FXOS8700_A_FFMT_THS_Z_LSB,
 181        },
 182};
 183
 184static const struct regmap_range write_range[] = {
 185        {
 186                .range_min = FXOS8700_F_SETUP,
 187                .range_max = FXOS8700_TRIG_CFG,
 188        }, {
 189                .range_min = FXOS8700_XYZ_DATA_CFG,
 190                .range_max = FXOS8700_HP_FILTER_CUTOFF,
 191        }, {
 192                .range_min = FXOS8700_PL_CFG,
 193                .range_max = FXOS8700_A_FFMT_CFG,
 194        }, {
 195                .range_min = FXOS8700_A_FFMT_THS,
 196                .range_max = FXOS8700_TRANSIENT_CFG,
 197        }, {
 198                .range_min = FXOS8700_TRANSIENT_THS,
 199                .range_max = FXOS8700_PULSE_CFG,
 200        }, {
 201                .range_min = FXOS8700_PULSE_THSX,
 202                .range_max = FXOS8700_OFF_Z,
 203        }, {
 204                .range_min = FXOS8700_M_OFF_X_MSB,
 205                .range_max = FXOS8700_M_OFF_Z_LSB,
 206        }, {
 207                .range_min = FXOS8700_M_THS_CFG,
 208                .range_max = FXOS8700_M_THS_CFG,
 209        }, {
 210                .range_min = FXOS8700_M_THS_X_MSB,
 211                .range_max = FXOS8700_M_CTRL_REG3,
 212        }, {
 213                .range_min = FXOS8700_A_VECM_CFG,
 214                .range_max = FXOS8700_A_FFMT_THS_Z_LSB,
 215        },
 216};
 217
 218static const struct regmap_access_table driver_read_table = {
 219        .yes_ranges =   read_range,
 220        .n_yes_ranges = ARRAY_SIZE(read_range),
 221};
 222
 223static const struct regmap_access_table driver_write_table = {
 224        .yes_ranges =   write_range,
 225        .n_yes_ranges = ARRAY_SIZE(write_range),
 226};
 227
 228const struct regmap_config fxos8700_regmap_config = {
 229        .reg_bits = 8,
 230        .val_bits = 8,
 231        .max_register = FXOS8700_NVM_DATA_BNK0,
 232        .rd_table = &driver_read_table,
 233        .wr_table = &driver_write_table,
 234};
 235EXPORT_SYMBOL(fxos8700_regmap_config);
 236
 237#define FXOS8700_CHANNEL(_type, _axis) {                        \
 238        .type = _type,                                          \
 239        .modified = 1,                                          \
 240        .channel2 = IIO_MOD_##_axis,                            \
 241        .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),           \
 242        .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |  \
 243                BIT(IIO_CHAN_INFO_SAMP_FREQ),                   \
 244}
 245
 246enum fxos8700_accel_scale_bits {
 247        MODE_2G = 0,
 248        MODE_4G,
 249        MODE_8G,
 250};
 251
 252/* scan indexes follow DATA register order */
 253enum fxos8700_scan_axis {
 254        FXOS8700_SCAN_ACCEL_X = 0,
 255        FXOS8700_SCAN_ACCEL_Y,
 256        FXOS8700_SCAN_ACCEL_Z,
 257        FXOS8700_SCAN_MAGN_X,
 258        FXOS8700_SCAN_MAGN_Y,
 259        FXOS8700_SCAN_MAGN_Z,
 260        FXOS8700_SCAN_RHALL,
 261        FXOS8700_SCAN_TIMESTAMP,
 262};
 263
 264enum fxos8700_sensor {
 265        FXOS8700_ACCEL  = 0,
 266        FXOS8700_MAGN,
 267        FXOS8700_NUM_SENSORS /* must be last */
 268};
 269
 270enum fxos8700_int_pin {
 271        FXOS8700_PIN_INT1,
 272        FXOS8700_PIN_INT2
 273};
 274
 275struct fxos8700_scale {
 276        u8 bits;
 277        int uscale;
 278};
 279
 280struct fxos8700_odr {
 281        u8 bits;
 282        int odr;
 283        int uodr;
 284};
 285
 286static const struct fxos8700_scale fxos8700_accel_scale[] = {
 287        { MODE_2G, 244},
 288        { MODE_4G, 488},
 289        { MODE_8G, 976},
 290};
 291
 292/*
 293 * Accellerometer and magnetometer have the same ODR options, set in the
 294 * CTRL_REG1 register. ODR is halved when using both sensors at once in
 295 * hybrid mode.
 296 */
 297static const struct fxos8700_odr fxos8700_odr[] = {
 298        {0x00, 800, 0},
 299        {0x01, 400, 0},
 300        {0x02, 200, 0},
 301        {0x03, 100, 0},
 302        {0x04, 50, 0},
 303        {0x05, 12, 500000},
 304        {0x06, 6, 250000},
 305        {0x07, 1, 562500},
 306};
 307
 308static const struct iio_chan_spec fxos8700_channels[] = {
 309        FXOS8700_CHANNEL(IIO_ACCEL, X),
 310        FXOS8700_CHANNEL(IIO_ACCEL, Y),
 311        FXOS8700_CHANNEL(IIO_ACCEL, Z),
 312        FXOS8700_CHANNEL(IIO_MAGN, X),
 313        FXOS8700_CHANNEL(IIO_MAGN, Y),
 314        FXOS8700_CHANNEL(IIO_MAGN, Z),
 315        IIO_CHAN_SOFT_TIMESTAMP(FXOS8700_SCAN_TIMESTAMP),
 316};
 317
 318static enum fxos8700_sensor fxos8700_to_sensor(enum iio_chan_type iio_type)
 319{
 320        switch (iio_type) {
 321        case IIO_ACCEL:
 322                return FXOS8700_ACCEL;
 323        case IIO_ANGL_VEL:
 324                return FXOS8700_MAGN;
 325        default:
 326                return -EINVAL;
 327        }
 328}
 329
 330static int fxos8700_set_active_mode(struct fxos8700_data *data,
 331                                    enum fxos8700_sensor t, bool mode)
 332{
 333        int ret;
 334
 335        ret = regmap_write(data->regmap, FXOS8700_CTRL_REG1, mode);
 336        if (ret)
 337                return ret;
 338
 339        usleep_range(FXOS8700_ACTIVE_MIN_USLEEP,
 340                     FXOS8700_ACTIVE_MIN_USLEEP + 1000);
 341
 342        return 0;
 343}
 344
 345static int fxos8700_set_scale(struct fxos8700_data *data,
 346                              enum fxos8700_sensor t, int uscale)
 347{
 348        int i;
 349        static const int scale_num = ARRAY_SIZE(fxos8700_accel_scale);
 350        struct device *dev = regmap_get_device(data->regmap);
 351
 352        if (t == FXOS8700_MAGN) {
 353                dev_err(dev, "Magnetometer scale is locked at 1200uT\n");
 354                return -EINVAL;
 355        }
 356
 357        for (i = 0; i < scale_num; i++)
 358                if (fxos8700_accel_scale[i].uscale == uscale)
 359                        break;
 360
 361        if (i == scale_num)
 362                return -EINVAL;
 363
 364        return regmap_write(data->regmap, FXOS8700_XYZ_DATA_CFG,
 365                            fxos8700_accel_scale[i].bits);
 366}
 367
 368static int fxos8700_get_scale(struct fxos8700_data *data,
 369                              enum fxos8700_sensor t, int *uscale)
 370{
 371        int i, ret, val;
 372        static const int scale_num = ARRAY_SIZE(fxos8700_accel_scale);
 373
 374        if (t == FXOS8700_MAGN) {
 375                *uscale = 1200; /* Magnetometer is locked at 1200uT */
 376                return 0;
 377        }
 378
 379        ret = regmap_read(data->regmap, FXOS8700_XYZ_DATA_CFG, &val);
 380        if (ret)
 381                return ret;
 382
 383        for (i = 0; i < scale_num; i++) {
 384                if (fxos8700_accel_scale[i].bits == (val & 0x3)) {
 385                        *uscale = fxos8700_accel_scale[i].uscale;
 386                        return 0;
 387                }
 388        }
 389
 390        return -EINVAL;
 391}
 392
 393static int fxos8700_get_data(struct fxos8700_data *data, int chan_type,
 394                             int axis, int *val)
 395{
 396        u8 base, reg;
 397        int ret;
 398        enum fxos8700_sensor type = fxos8700_to_sensor(chan_type);
 399
 400        base = type ? FXOS8700_OUT_X_MSB : FXOS8700_M_OUT_X_MSB;
 401
 402        /* Block read 6 bytes of device output registers to avoid data loss */
 403        ret = regmap_bulk_read(data->regmap, base, data->buf,
 404                               FXOS8700_DATA_BUF_SIZE);
 405        if (ret)
 406                return ret;
 407
 408        /* Convert axis to buffer index */
 409        reg = axis - IIO_MOD_X;
 410
 411        /* Convert to native endianness */
 412        *val = sign_extend32(be16_to_cpu(data->buf[reg]), 15);
 413
 414        return 0;
 415}
 416
 417static int fxos8700_set_odr(struct fxos8700_data *data, enum fxos8700_sensor t,
 418                            int odr, int uodr)
 419{
 420        int i, ret, val;
 421        bool active_mode;
 422        static const int odr_num = ARRAY_SIZE(fxos8700_odr);
 423
 424        ret = regmap_read(data->regmap, FXOS8700_CTRL_REG1, &val);
 425        if (ret)
 426                return ret;
 427
 428        active_mode = val & FXOS8700_ACTIVE;
 429
 430        if (active_mode) {
 431                /*
 432                 * The device must be in standby mode to change any of the
 433                 * other fields within CTRL_REG1
 434                 */
 435                ret = regmap_write(data->regmap, FXOS8700_CTRL_REG1,
 436                                   val & ~FXOS8700_ACTIVE);
 437                if (ret)
 438                        return ret;
 439        }
 440
 441        for (i = 0; i < odr_num; i++)
 442                if (fxos8700_odr[i].odr == odr && fxos8700_odr[i].uodr == uodr)
 443                        break;
 444
 445        if (i >= odr_num)
 446                return -EINVAL;
 447
 448        return regmap_update_bits(data->regmap,
 449                                  FXOS8700_CTRL_REG1,
 450                                  FXOS8700_CTRL_ODR_MSK + FXOS8700_ACTIVE,
 451                                  fxos8700_odr[i].bits << 3 | active_mode);
 452}
 453
 454static int fxos8700_get_odr(struct fxos8700_data *data, enum fxos8700_sensor t,
 455                            int *odr, int *uodr)
 456{
 457        int i, val, ret;
 458        static const int odr_num = ARRAY_SIZE(fxos8700_odr);
 459
 460        ret = regmap_read(data->regmap, FXOS8700_CTRL_REG1, &val);
 461        if (ret)
 462                return ret;
 463
 464        val &= FXOS8700_CTRL_ODR_MSK;
 465
 466        for (i = 0; i < odr_num; i++)
 467                if (val == fxos8700_odr[i].bits)
 468                        break;
 469
 470        if (i >= odr_num)
 471                return -EINVAL;
 472
 473        *odr = fxos8700_odr[i].odr;
 474        *uodr = fxos8700_odr[i].uodr;
 475
 476        return 0;
 477}
 478
 479static int fxos8700_read_raw(struct iio_dev *indio_dev,
 480                             struct iio_chan_spec const *chan,
 481                             int *val, int *val2, long mask)
 482{
 483        int ret;
 484        struct fxos8700_data *data = iio_priv(indio_dev);
 485
 486        switch (mask) {
 487        case IIO_CHAN_INFO_RAW:
 488                ret = fxos8700_get_data(data, chan->type, chan->channel2, val);
 489                if (ret)
 490                        return ret;
 491                return IIO_VAL_INT;
 492        case IIO_CHAN_INFO_SCALE:
 493                *val = 0;
 494                ret = fxos8700_get_scale(data, fxos8700_to_sensor(chan->type),
 495                                         val2);
 496                return ret ? ret : IIO_VAL_INT_PLUS_MICRO;
 497        case IIO_CHAN_INFO_SAMP_FREQ:
 498                ret = fxos8700_get_odr(data, fxos8700_to_sensor(chan->type),
 499                                       val, val2);
 500                return ret ? ret : IIO_VAL_INT_PLUS_MICRO;
 501        default:
 502                return -EINVAL;
 503        }
 504}
 505
 506static int fxos8700_write_raw(struct iio_dev *indio_dev,
 507                              struct iio_chan_spec const *chan,
 508                              int val, int val2, long mask)
 509{
 510        struct fxos8700_data *data = iio_priv(indio_dev);
 511
 512        switch (mask) {
 513        case IIO_CHAN_INFO_SCALE:
 514                return fxos8700_set_scale(data, fxos8700_to_sensor(chan->type),
 515                                          val2);
 516        case IIO_CHAN_INFO_SAMP_FREQ:
 517                return fxos8700_set_odr(data, fxos8700_to_sensor(chan->type),
 518                                        val, val2);
 519        default:
 520                return -EINVAL;
 521        }
 522}
 523
 524static IIO_CONST_ATTR(in_accel_sampling_frequency_available,
 525                      "1.5625 6.25 12.5 50 100 200 400 800");
 526static IIO_CONST_ATTR(in_magn_sampling_frequency_available,
 527                      "1.5625 6.25 12.5 50 100 200 400 800");
 528static IIO_CONST_ATTR(in_accel_scale_available, "0.000244 0.000488 0.000976");
 529static IIO_CONST_ATTR(in_magn_scale_available, "0.000001200");
 530
 531static struct attribute *fxos8700_attrs[] = {
 532        &iio_const_attr_in_accel_sampling_frequency_available.dev_attr.attr,
 533        &iio_const_attr_in_magn_sampling_frequency_available.dev_attr.attr,
 534        &iio_const_attr_in_accel_scale_available.dev_attr.attr,
 535        &iio_const_attr_in_magn_scale_available.dev_attr.attr,
 536        NULL,
 537};
 538
 539static const struct attribute_group fxos8700_attrs_group = {
 540        .attrs = fxos8700_attrs,
 541};
 542
 543static const struct iio_info fxos8700_info = {
 544        .read_raw = fxos8700_read_raw,
 545        .write_raw = fxos8700_write_raw,
 546        .attrs = &fxos8700_attrs_group,
 547};
 548
 549static int fxos8700_chip_init(struct fxos8700_data *data, bool use_spi)
 550{
 551        int ret;
 552        unsigned int val;
 553        struct device *dev = regmap_get_device(data->regmap);
 554
 555        ret = regmap_read(data->regmap, FXOS8700_WHO_AM_I, &val);
 556        if (ret) {
 557                dev_err(dev, "Error reading chip id\n");
 558                return ret;
 559        }
 560        if (val != FXOS8700_DEVICE_ID && val != FXOS8700_PRE_DEVICE_ID) {
 561                dev_err(dev, "Wrong chip id, got %x expected %x or %x\n",
 562                        val, FXOS8700_DEVICE_ID, FXOS8700_PRE_DEVICE_ID);
 563                return -ENODEV;
 564        }
 565
 566        ret = fxos8700_set_active_mode(data, FXOS8700_ACCEL, true);
 567        if (ret)
 568                return ret;
 569
 570        ret = fxos8700_set_active_mode(data, FXOS8700_MAGN, true);
 571        if (ret)
 572                return ret;
 573
 574        /*
 575         * The device must be in standby mode to change any of the other fields
 576         * within CTRL_REG1
 577         */
 578        ret = regmap_write(data->regmap, FXOS8700_CTRL_REG1, 0x00);
 579        if (ret)
 580                return ret;
 581
 582        /* Set max oversample ratio (OSR) and both devices active */
 583        ret = regmap_write(data->regmap, FXOS8700_M_CTRL_REG1,
 584                           FXOS8700_HMS_MASK | FXOS8700_OS_MASK);
 585        if (ret)
 586                return ret;
 587
 588        /* Disable and rst min/max measurements & threshold */
 589        ret = regmap_write(data->regmap, FXOS8700_M_CTRL_REG2,
 590                           FXOS8700_MAXMIN_RST | FXOS8700_MAXMIN_DIS_THS |
 591                           FXOS8700_MAXMIN_DIS);
 592        if (ret)
 593                return ret;
 594
 595        /* Max ODR (800Hz individual or 400Hz hybrid), active mode */
 596        ret = regmap_write(data->regmap, FXOS8700_CTRL_REG1,
 597                           FXOS8700_CTRL_ODR_MAX | FXOS8700_ACTIVE);
 598        if (ret)
 599                return ret;
 600
 601        /* Set for max full-scale range (+/-8G) */
 602        return regmap_write(data->regmap, FXOS8700_XYZ_DATA_CFG, MODE_8G);
 603}
 604
 605static void fxos8700_chip_uninit(void *data)
 606{
 607        struct fxos8700_data *fxos8700_data = data;
 608
 609        fxos8700_set_active_mode(fxos8700_data, FXOS8700_ACCEL, false);
 610        fxos8700_set_active_mode(fxos8700_data, FXOS8700_MAGN, false);
 611}
 612
 613int fxos8700_core_probe(struct device *dev, struct regmap *regmap,
 614                        const char *name, bool use_spi)
 615{
 616        struct iio_dev *indio_dev;
 617        struct fxos8700_data *data;
 618        int ret;
 619
 620        indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
 621        if (!indio_dev)
 622                return -ENOMEM;
 623
 624        data = iio_priv(indio_dev);
 625        dev_set_drvdata(dev, indio_dev);
 626        data->regmap = regmap;
 627
 628        ret = fxos8700_chip_init(data, use_spi);
 629        if (ret)
 630                return ret;
 631
 632        ret = devm_add_action_or_reset(dev, fxos8700_chip_uninit, data);
 633        if (ret)
 634                return ret;
 635
 636        indio_dev->channels = fxos8700_channels;
 637        indio_dev->num_channels = ARRAY_SIZE(fxos8700_channels);
 638        indio_dev->name = name ? name : "fxos8700";
 639        indio_dev->modes = INDIO_DIRECT_MODE;
 640        indio_dev->info = &fxos8700_info;
 641
 642        return devm_iio_device_register(dev, indio_dev);
 643}
 644EXPORT_SYMBOL_GPL(fxos8700_core_probe);
 645
 646MODULE_AUTHOR("Robert Jones <rjones@gateworks.com>");
 647MODULE_DESCRIPTION("FXOS8700 6-Axis Acc and Mag Combo Sensor driver");
 648MODULE_LICENSE("GPL v2");
 649