Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * FXOS8700 - NXP IMU (accelerometer plus magnetometer)
0004  *
0005  * IIO core driver for FXOS8700, with support for I2C/SPI busses
0006  *
0007  * TODO: Buffer, trigger, and IRQ support
0008  */
0009 #include <linux/module.h>
0010 #include <linux/regmap.h>
0011 #include <linux/acpi.h>
0012 #include <linux/bitops.h>
0013 
0014 #include <linux/iio/iio.h>
0015 #include <linux/iio/sysfs.h>
0016 
0017 #include "fxos8700.h"
0018 
0019 /* Register Definitions */
0020 #define FXOS8700_STATUS             0x00
0021 #define FXOS8700_OUT_X_MSB          0x01
0022 #define FXOS8700_OUT_X_LSB          0x02
0023 #define FXOS8700_OUT_Y_MSB          0x03
0024 #define FXOS8700_OUT_Y_LSB          0x04
0025 #define FXOS8700_OUT_Z_MSB          0x05
0026 #define FXOS8700_OUT_Z_LSB          0x06
0027 #define FXOS8700_F_SETUP            0x09
0028 #define FXOS8700_TRIG_CFG           0x0a
0029 #define FXOS8700_SYSMOD             0x0b
0030 #define FXOS8700_INT_SOURCE         0x0c
0031 #define FXOS8700_WHO_AM_I           0x0d
0032 #define FXOS8700_XYZ_DATA_CFG       0x0e
0033 #define FXOS8700_HP_FILTER_CUTOFF   0x0f
0034 #define FXOS8700_PL_STATUS          0x10
0035 #define FXOS8700_PL_CFG             0x11
0036 #define FXOS8700_PL_COUNT           0x12
0037 #define FXOS8700_PL_BF_ZCOMP        0x13
0038 #define FXOS8700_PL_THS_REG         0x14
0039 #define FXOS8700_A_FFMT_CFG         0x15
0040 #define FXOS8700_A_FFMT_SRC         0x16
0041 #define FXOS8700_A_FFMT_THS         0x17
0042 #define FXOS8700_A_FFMT_COUNT       0x18
0043 #define FXOS8700_TRANSIENT_CFG      0x1d
0044 #define FXOS8700_TRANSIENT_SRC      0x1e
0045 #define FXOS8700_TRANSIENT_THS      0x1f
0046 #define FXOS8700_TRANSIENT_COUNT    0x20
0047 #define FXOS8700_PULSE_CFG          0x21
0048 #define FXOS8700_PULSE_SRC          0x22
0049 #define FXOS8700_PULSE_THSX         0x23
0050 #define FXOS8700_PULSE_THSY         0x24
0051 #define FXOS8700_PULSE_THSZ         0x25
0052 #define FXOS8700_PULSE_TMLT         0x26
0053 #define FXOS8700_PULSE_LTCY         0x27
0054 #define FXOS8700_PULSE_WIND         0x28
0055 #define FXOS8700_ASLP_COUNT         0x29
0056 #define FXOS8700_CTRL_REG1          0x2a
0057 #define FXOS8700_CTRL_REG2          0x2b
0058 #define FXOS8700_CTRL_REG3          0x2c
0059 #define FXOS8700_CTRL_REG4          0x2d
0060 #define FXOS8700_CTRL_REG5          0x2e
0061 #define FXOS8700_OFF_X              0x2f
0062 #define FXOS8700_OFF_Y              0x30
0063 #define FXOS8700_OFF_Z              0x31
0064 #define FXOS8700_M_DR_STATUS        0x32
0065 #define FXOS8700_M_OUT_X_MSB        0x33
0066 #define FXOS8700_M_OUT_X_LSB        0x34
0067 #define FXOS8700_M_OUT_Y_MSB        0x35
0068 #define FXOS8700_M_OUT_Y_LSB        0x36
0069 #define FXOS8700_M_OUT_Z_MSB        0x37
0070 #define FXOS8700_M_OUT_Z_LSB        0x38
0071 #define FXOS8700_CMP_X_MSB          0x39
0072 #define FXOS8700_CMP_X_LSB          0x3a
0073 #define FXOS8700_CMP_Y_MSB          0x3b
0074 #define FXOS8700_CMP_Y_LSB          0x3c
0075 #define FXOS8700_CMP_Z_MSB          0x3d
0076 #define FXOS8700_CMP_Z_LSB          0x3e
0077 #define FXOS8700_M_OFF_X_MSB        0x3f
0078 #define FXOS8700_M_OFF_X_LSB        0x40
0079 #define FXOS8700_M_OFF_Y_MSB        0x41
0080 #define FXOS8700_M_OFF_Y_LSB        0x42
0081 #define FXOS8700_M_OFF_Z_MSB        0x43
0082 #define FXOS8700_M_OFF_Z_LSB        0x44
0083 #define FXOS8700_MAX_X_MSB          0x45
0084 #define FXOS8700_MAX_X_LSB          0x46
0085 #define FXOS8700_MAX_Y_MSB          0x47
0086 #define FXOS8700_MAX_Y_LSB          0x48
0087 #define FXOS8700_MAX_Z_MSB          0x49
0088 #define FXOS8700_MAX_Z_LSB          0x4a
0089 #define FXOS8700_MIN_X_MSB          0x4b
0090 #define FXOS8700_MIN_X_LSB          0x4c
0091 #define FXOS8700_MIN_Y_MSB          0x4d
0092 #define FXOS8700_MIN_Y_LSB          0x4e
0093 #define FXOS8700_MIN_Z_MSB          0x4f
0094 #define FXOS8700_MIN_Z_LSB          0x50
0095 #define FXOS8700_TEMP               0x51
0096 #define FXOS8700_M_THS_CFG          0x52
0097 #define FXOS8700_M_THS_SRC          0x53
0098 #define FXOS8700_M_THS_X_MSB        0x54
0099 #define FXOS8700_M_THS_X_LSB        0x55
0100 #define FXOS8700_M_THS_Y_MSB        0x56
0101 #define FXOS8700_M_THS_Y_LSB        0x57
0102 #define FXOS8700_M_THS_Z_MSB        0x58
0103 #define FXOS8700_M_THS_Z_LSB        0x59
0104 #define FXOS8700_M_THS_COUNT        0x5a
0105 #define FXOS8700_M_CTRL_REG1        0x5b
0106 #define FXOS8700_M_CTRL_REG2        0x5c
0107 #define FXOS8700_M_CTRL_REG3        0x5d
0108 #define FXOS8700_M_INT_SRC          0x5e
0109 #define FXOS8700_A_VECM_CFG         0x5f
0110 #define FXOS8700_A_VECM_THS_MSB     0x60
0111 #define FXOS8700_A_VECM_THS_LSB     0x61
0112 #define FXOS8700_A_VECM_CNT         0x62
0113 #define FXOS8700_A_VECM_INITX_MSB   0x63
0114 #define FXOS8700_A_VECM_INITX_LSB   0x64
0115 #define FXOS8700_A_VECM_INITY_MSB   0x65
0116 #define FXOS8700_A_VECM_INITY_LSB   0x66
0117 #define FXOS8700_A_VECM_INITZ_MSB   0x67
0118 #define FXOS8700_A_VECM_INITZ_LSB   0x68
0119 #define FXOS8700_M_VECM_CFG         0x69
0120 #define FXOS8700_M_VECM_THS_MSB     0x6a
0121 #define FXOS8700_M_VECM_THS_LSB     0x6b
0122 #define FXOS8700_M_VECM_CNT         0x6c
0123 #define FXOS8700_M_VECM_INITX_MSB   0x6d
0124 #define FXOS8700_M_VECM_INITX_LSB   0x6e
0125 #define FXOS8700_M_VECM_INITY_MSB   0x6f
0126 #define FXOS8700_M_VECM_INITY_LSB   0x70
0127 #define FXOS8700_M_VECM_INITZ_MSB   0x71
0128 #define FXOS8700_M_VECM_INITZ_LSB   0x72
0129 #define FXOS8700_A_FFMT_THS_X_MSB   0x73
0130 #define FXOS8700_A_FFMT_THS_X_LSB   0x74
0131 #define FXOS8700_A_FFMT_THS_Y_MSB   0x75
0132 #define FXOS8700_A_FFMT_THS_Y_LSB   0x76
0133 #define FXOS8700_A_FFMT_THS_Z_MSB   0x77
0134 #define FXOS8700_A_FFMT_THS_Z_LSB   0x78
0135 #define FXOS8700_A_TRAN_INIT_MSB    0x79
0136 #define FXOS8700_A_TRAN_INIT_LSB_X  0x7a
0137 #define FXOS8700_A_TRAN_INIT_LSB_Y  0x7b
0138 #define FXOS8700_A_TRAN_INIT_LSB_Z  0x7d
0139 #define FXOS8700_TM_NVM_LOCK        0x7e
0140 #define FXOS8700_NVM_DATA0_35       0x80
0141 #define FXOS8700_NVM_DATA_BNK3      0xa4
0142 #define FXOS8700_NVM_DATA_BNK2      0xa5
0143 #define FXOS8700_NVM_DATA_BNK1      0xa6
0144 #define FXOS8700_NVM_DATA_BNK0      0xa7
0145 
0146 /* Bit definitions for FXOS8700_CTRL_REG1 */
0147 #define FXOS8700_CTRL_ODR_MSK       0x38
0148 #define FXOS8700_CTRL_ODR_MAX       0x00
0149 #define FXOS8700_CTRL_ODR_MIN       GENMASK(4, 3)
0150 
0151 /* Bit definitions for FXOS8700_M_CTRL_REG1 */
0152 #define FXOS8700_HMS_MASK           GENMASK(1, 0)
0153 #define FXOS8700_OS_MASK            GENMASK(4, 2)
0154 
0155 /* Bit definitions for FXOS8700_M_CTRL_REG2 */
0156 #define FXOS8700_MAXMIN_RST         BIT(2)
0157 #define FXOS8700_MAXMIN_DIS_THS     BIT(3)
0158 #define FXOS8700_MAXMIN_DIS         BIT(4)
0159 
0160 #define FXOS8700_ACTIVE             0x01
0161 #define FXOS8700_ACTIVE_MIN_USLEEP  4000 /* from table 6 in datasheet */
0162 
0163 #define FXOS8700_DEVICE_ID          0xC7
0164 #define FXOS8700_PRE_DEVICE_ID      0xC4
0165 #define FXOS8700_DATA_BUF_SIZE      3
0166 
0167 struct fxos8700_data {
0168     struct regmap *regmap;
0169     struct iio_trigger *trig;
0170     __be16 buf[FXOS8700_DATA_BUF_SIZE] __aligned(IIO_DMA_MINALIGN);
0171 };
0172 
0173 /* Regmap info */
0174 static const struct regmap_range read_range[] = {
0175     {
0176         .range_min = FXOS8700_STATUS,
0177         .range_max = FXOS8700_A_FFMT_COUNT,
0178     }, {
0179         .range_min = FXOS8700_TRANSIENT_CFG,
0180         .range_max = FXOS8700_A_FFMT_THS_Z_LSB,
0181     },
0182 };
0183 
0184 static const struct regmap_range write_range[] = {
0185     {
0186         .range_min = FXOS8700_F_SETUP,
0187         .range_max = FXOS8700_TRIG_CFG,
0188     }, {
0189         .range_min = FXOS8700_XYZ_DATA_CFG,
0190         .range_max = FXOS8700_HP_FILTER_CUTOFF,
0191     }, {
0192         .range_min = FXOS8700_PL_CFG,
0193         .range_max = FXOS8700_A_FFMT_CFG,
0194     }, {
0195         .range_min = FXOS8700_A_FFMT_THS,
0196         .range_max = FXOS8700_TRANSIENT_CFG,
0197     }, {
0198         .range_min = FXOS8700_TRANSIENT_THS,
0199         .range_max = FXOS8700_PULSE_CFG,
0200     }, {
0201         .range_min = FXOS8700_PULSE_THSX,
0202         .range_max = FXOS8700_OFF_Z,
0203     }, {
0204         .range_min = FXOS8700_M_OFF_X_MSB,
0205         .range_max = FXOS8700_M_OFF_Z_LSB,
0206     }, {
0207         .range_min = FXOS8700_M_THS_CFG,
0208         .range_max = FXOS8700_M_THS_CFG,
0209     }, {
0210         .range_min = FXOS8700_M_THS_X_MSB,
0211         .range_max = FXOS8700_M_CTRL_REG3,
0212     }, {
0213         .range_min = FXOS8700_A_VECM_CFG,
0214         .range_max = FXOS8700_A_FFMT_THS_Z_LSB,
0215     },
0216 };
0217 
0218 static const struct regmap_access_table driver_read_table = {
0219     .yes_ranges =   read_range,
0220     .n_yes_ranges = ARRAY_SIZE(read_range),
0221 };
0222 
0223 static const struct regmap_access_table driver_write_table = {
0224     .yes_ranges =   write_range,
0225     .n_yes_ranges = ARRAY_SIZE(write_range),
0226 };
0227 
0228 const struct regmap_config fxos8700_regmap_config = {
0229     .reg_bits = 8,
0230     .val_bits = 8,
0231     .max_register = FXOS8700_NVM_DATA_BNK0,
0232     .rd_table = &driver_read_table,
0233     .wr_table = &driver_write_table,
0234 };
0235 EXPORT_SYMBOL(fxos8700_regmap_config);
0236 
0237 #define FXOS8700_CHANNEL(_type, _axis) {            \
0238     .type = _type,                      \
0239     .modified = 1,                      \
0240     .channel2 = IIO_MOD_##_axis,                \
0241     .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),       \
0242     .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |  \
0243         BIT(IIO_CHAN_INFO_SAMP_FREQ),           \
0244 }
0245 
0246 enum fxos8700_accel_scale_bits {
0247     MODE_2G = 0,
0248     MODE_4G,
0249     MODE_8G,
0250 };
0251 
0252 /* scan indexes follow DATA register order */
0253 enum fxos8700_scan_axis {
0254     FXOS8700_SCAN_ACCEL_X = 0,
0255     FXOS8700_SCAN_ACCEL_Y,
0256     FXOS8700_SCAN_ACCEL_Z,
0257     FXOS8700_SCAN_MAGN_X,
0258     FXOS8700_SCAN_MAGN_Y,
0259     FXOS8700_SCAN_MAGN_Z,
0260     FXOS8700_SCAN_RHALL,
0261     FXOS8700_SCAN_TIMESTAMP,
0262 };
0263 
0264 enum fxos8700_sensor {
0265     FXOS8700_ACCEL  = 0,
0266     FXOS8700_MAGN,
0267     FXOS8700_NUM_SENSORS /* must be last */
0268 };
0269 
0270 enum fxos8700_int_pin {
0271     FXOS8700_PIN_INT1,
0272     FXOS8700_PIN_INT2
0273 };
0274 
0275 struct fxos8700_scale {
0276     u8 bits;
0277     int uscale;
0278 };
0279 
0280 struct fxos8700_odr {
0281     u8 bits;
0282     int odr;
0283     int uodr;
0284 };
0285 
0286 static const struct fxos8700_scale fxos8700_accel_scale[] = {
0287     { MODE_2G, 244},
0288     { MODE_4G, 488},
0289     { MODE_8G, 976},
0290 };
0291 
0292 /*
0293  * Accellerometer and magnetometer have the same ODR options, set in the
0294  * CTRL_REG1 register. ODR is halved when using both sensors at once in
0295  * hybrid mode.
0296  */
0297 static const struct fxos8700_odr fxos8700_odr[] = {
0298     {0x00, 800, 0},
0299     {0x01, 400, 0},
0300     {0x02, 200, 0},
0301     {0x03, 100, 0},
0302     {0x04, 50, 0},
0303     {0x05, 12, 500000},
0304     {0x06, 6, 250000},
0305     {0x07, 1, 562500},
0306 };
0307 
0308 static const struct iio_chan_spec fxos8700_channels[] = {
0309     FXOS8700_CHANNEL(IIO_ACCEL, X),
0310     FXOS8700_CHANNEL(IIO_ACCEL, Y),
0311     FXOS8700_CHANNEL(IIO_ACCEL, Z),
0312     FXOS8700_CHANNEL(IIO_MAGN, X),
0313     FXOS8700_CHANNEL(IIO_MAGN, Y),
0314     FXOS8700_CHANNEL(IIO_MAGN, Z),
0315     IIO_CHAN_SOFT_TIMESTAMP(FXOS8700_SCAN_TIMESTAMP),
0316 };
0317 
0318 static enum fxos8700_sensor fxos8700_to_sensor(enum iio_chan_type iio_type)
0319 {
0320     switch (iio_type) {
0321     case IIO_ACCEL:
0322         return FXOS8700_ACCEL;
0323     case IIO_ANGL_VEL:
0324         return FXOS8700_MAGN;
0325     default:
0326         return -EINVAL;
0327     }
0328 }
0329 
0330 static int fxos8700_set_active_mode(struct fxos8700_data *data,
0331                     enum fxos8700_sensor t, bool mode)
0332 {
0333     int ret;
0334 
0335     ret = regmap_write(data->regmap, FXOS8700_CTRL_REG1, mode);
0336     if (ret)
0337         return ret;
0338 
0339     usleep_range(FXOS8700_ACTIVE_MIN_USLEEP,
0340              FXOS8700_ACTIVE_MIN_USLEEP + 1000);
0341 
0342     return 0;
0343 }
0344 
0345 static int fxos8700_set_scale(struct fxos8700_data *data,
0346                   enum fxos8700_sensor t, int uscale)
0347 {
0348     int i;
0349     static const int scale_num = ARRAY_SIZE(fxos8700_accel_scale);
0350     struct device *dev = regmap_get_device(data->regmap);
0351 
0352     if (t == FXOS8700_MAGN) {
0353         dev_err(dev, "Magnetometer scale is locked at 1200uT\n");
0354         return -EINVAL;
0355     }
0356 
0357     for (i = 0; i < scale_num; i++)
0358         if (fxos8700_accel_scale[i].uscale == uscale)
0359             break;
0360 
0361     if (i == scale_num)
0362         return -EINVAL;
0363 
0364     return regmap_write(data->regmap, FXOS8700_XYZ_DATA_CFG,
0365                 fxos8700_accel_scale[i].bits);
0366 }
0367 
0368 static int fxos8700_get_scale(struct fxos8700_data *data,
0369                   enum fxos8700_sensor t, int *uscale)
0370 {
0371     int i, ret, val;
0372     static const int scale_num = ARRAY_SIZE(fxos8700_accel_scale);
0373 
0374     if (t == FXOS8700_MAGN) {
0375         *uscale = 1200; /* Magnetometer is locked at 1200uT */
0376         return 0;
0377     }
0378 
0379     ret = regmap_read(data->regmap, FXOS8700_XYZ_DATA_CFG, &val);
0380     if (ret)
0381         return ret;
0382 
0383     for (i = 0; i < scale_num; i++) {
0384         if (fxos8700_accel_scale[i].bits == (val & 0x3)) {
0385             *uscale = fxos8700_accel_scale[i].uscale;
0386             return 0;
0387         }
0388     }
0389 
0390     return -EINVAL;
0391 }
0392 
0393 static int fxos8700_get_data(struct fxos8700_data *data, int chan_type,
0394                  int axis, int *val)
0395 {
0396     u8 base, reg;
0397     int ret;
0398     enum fxos8700_sensor type = fxos8700_to_sensor(chan_type);
0399 
0400     base = type ? FXOS8700_OUT_X_MSB : FXOS8700_M_OUT_X_MSB;
0401 
0402     /* Block read 6 bytes of device output registers to avoid data loss */
0403     ret = regmap_bulk_read(data->regmap, base, data->buf,
0404                    FXOS8700_DATA_BUF_SIZE);
0405     if (ret)
0406         return ret;
0407 
0408     /* Convert axis to buffer index */
0409     reg = axis - IIO_MOD_X;
0410 
0411     /* Convert to native endianness */
0412     *val = sign_extend32(be16_to_cpu(data->buf[reg]), 15);
0413 
0414     return 0;
0415 }
0416 
0417 static int fxos8700_set_odr(struct fxos8700_data *data, enum fxos8700_sensor t,
0418                 int odr, int uodr)
0419 {
0420     int i, ret, val;
0421     bool active_mode;
0422     static const int odr_num = ARRAY_SIZE(fxos8700_odr);
0423 
0424     ret = regmap_read(data->regmap, FXOS8700_CTRL_REG1, &val);
0425     if (ret)
0426         return ret;
0427 
0428     active_mode = val & FXOS8700_ACTIVE;
0429 
0430     if (active_mode) {
0431         /*
0432          * The device must be in standby mode to change any of the
0433          * other fields within CTRL_REG1
0434          */
0435         ret = regmap_write(data->regmap, FXOS8700_CTRL_REG1,
0436                    val & ~FXOS8700_ACTIVE);
0437         if (ret)
0438             return ret;
0439     }
0440 
0441     for (i = 0; i < odr_num; i++)
0442         if (fxos8700_odr[i].odr == odr && fxos8700_odr[i].uodr == uodr)
0443             break;
0444 
0445     if (i >= odr_num)
0446         return -EINVAL;
0447 
0448     return regmap_update_bits(data->regmap,
0449                   FXOS8700_CTRL_REG1,
0450                   FXOS8700_CTRL_ODR_MSK + FXOS8700_ACTIVE,
0451                   fxos8700_odr[i].bits << 3 | active_mode);
0452 }
0453 
0454 static int fxos8700_get_odr(struct fxos8700_data *data, enum fxos8700_sensor t,
0455                 int *odr, int *uodr)
0456 {
0457     int i, val, ret;
0458     static const int odr_num = ARRAY_SIZE(fxos8700_odr);
0459 
0460     ret = regmap_read(data->regmap, FXOS8700_CTRL_REG1, &val);
0461     if (ret)
0462         return ret;
0463 
0464     val &= FXOS8700_CTRL_ODR_MSK;
0465 
0466     for (i = 0; i < odr_num; i++)
0467         if (val == fxos8700_odr[i].bits)
0468             break;
0469 
0470     if (i >= odr_num)
0471         return -EINVAL;
0472 
0473     *odr = fxos8700_odr[i].odr;
0474     *uodr = fxos8700_odr[i].uodr;
0475 
0476     return 0;
0477 }
0478 
0479 static int fxos8700_read_raw(struct iio_dev *indio_dev,
0480                  struct iio_chan_spec const *chan,
0481                  int *val, int *val2, long mask)
0482 {
0483     int ret;
0484     struct fxos8700_data *data = iio_priv(indio_dev);
0485 
0486     switch (mask) {
0487     case IIO_CHAN_INFO_RAW:
0488         ret = fxos8700_get_data(data, chan->type, chan->channel2, val);
0489         if (ret)
0490             return ret;
0491         return IIO_VAL_INT;
0492     case IIO_CHAN_INFO_SCALE:
0493         *val = 0;
0494         ret = fxos8700_get_scale(data, fxos8700_to_sensor(chan->type),
0495                      val2);
0496         return ret ? ret : IIO_VAL_INT_PLUS_MICRO;
0497     case IIO_CHAN_INFO_SAMP_FREQ:
0498         ret = fxos8700_get_odr(data, fxos8700_to_sensor(chan->type),
0499                        val, val2);
0500         return ret ? ret : IIO_VAL_INT_PLUS_MICRO;
0501     default:
0502         return -EINVAL;
0503     }
0504 }
0505 
0506 static int fxos8700_write_raw(struct iio_dev *indio_dev,
0507                   struct iio_chan_spec const *chan,
0508                   int val, int val2, long mask)
0509 {
0510     struct fxos8700_data *data = iio_priv(indio_dev);
0511 
0512     switch (mask) {
0513     case IIO_CHAN_INFO_SCALE:
0514         return fxos8700_set_scale(data, fxos8700_to_sensor(chan->type),
0515                       val2);
0516     case IIO_CHAN_INFO_SAMP_FREQ:
0517         return fxos8700_set_odr(data, fxos8700_to_sensor(chan->type),
0518                     val, val2);
0519     default:
0520         return -EINVAL;
0521     }
0522 }
0523 
0524 static IIO_CONST_ATTR(in_accel_sampling_frequency_available,
0525               "1.5625 6.25 12.5 50 100 200 400 800");
0526 static IIO_CONST_ATTR(in_magn_sampling_frequency_available,
0527               "1.5625 6.25 12.5 50 100 200 400 800");
0528 static IIO_CONST_ATTR(in_accel_scale_available, "0.000244 0.000488 0.000976");
0529 static IIO_CONST_ATTR(in_magn_scale_available, "0.000001200");
0530 
0531 static struct attribute *fxos8700_attrs[] = {
0532     &iio_const_attr_in_accel_sampling_frequency_available.dev_attr.attr,
0533     &iio_const_attr_in_magn_sampling_frequency_available.dev_attr.attr,
0534     &iio_const_attr_in_accel_scale_available.dev_attr.attr,
0535     &iio_const_attr_in_magn_scale_available.dev_attr.attr,
0536     NULL,
0537 };
0538 
0539 static const struct attribute_group fxos8700_attrs_group = {
0540     .attrs = fxos8700_attrs,
0541 };
0542 
0543 static const struct iio_info fxos8700_info = {
0544     .read_raw = fxos8700_read_raw,
0545     .write_raw = fxos8700_write_raw,
0546     .attrs = &fxos8700_attrs_group,
0547 };
0548 
0549 static int fxos8700_chip_init(struct fxos8700_data *data, bool use_spi)
0550 {
0551     int ret;
0552     unsigned int val;
0553     struct device *dev = regmap_get_device(data->regmap);
0554 
0555     ret = regmap_read(data->regmap, FXOS8700_WHO_AM_I, &val);
0556     if (ret) {
0557         dev_err(dev, "Error reading chip id\n");
0558         return ret;
0559     }
0560     if (val != FXOS8700_DEVICE_ID && val != FXOS8700_PRE_DEVICE_ID) {
0561         dev_err(dev, "Wrong chip id, got %x expected %x or %x\n",
0562             val, FXOS8700_DEVICE_ID, FXOS8700_PRE_DEVICE_ID);
0563         return -ENODEV;
0564     }
0565 
0566     ret = fxos8700_set_active_mode(data, FXOS8700_ACCEL, true);
0567     if (ret)
0568         return ret;
0569 
0570     ret = fxos8700_set_active_mode(data, FXOS8700_MAGN, true);
0571     if (ret)
0572         return ret;
0573 
0574     /*
0575      * The device must be in standby mode to change any of the other fields
0576      * within CTRL_REG1
0577      */
0578     ret = regmap_write(data->regmap, FXOS8700_CTRL_REG1, 0x00);
0579     if (ret)
0580         return ret;
0581 
0582     /* Set max oversample ratio (OSR) and both devices active */
0583     ret = regmap_write(data->regmap, FXOS8700_M_CTRL_REG1,
0584                FXOS8700_HMS_MASK | FXOS8700_OS_MASK);
0585     if (ret)
0586         return ret;
0587 
0588     /* Disable and rst min/max measurements & threshold */
0589     ret = regmap_write(data->regmap, FXOS8700_M_CTRL_REG2,
0590                FXOS8700_MAXMIN_RST | FXOS8700_MAXMIN_DIS_THS |
0591                FXOS8700_MAXMIN_DIS);
0592     if (ret)
0593         return ret;
0594 
0595     /* Max ODR (800Hz individual or 400Hz hybrid), active mode */
0596     ret = regmap_write(data->regmap, FXOS8700_CTRL_REG1,
0597                FXOS8700_CTRL_ODR_MAX | FXOS8700_ACTIVE);
0598     if (ret)
0599         return ret;
0600 
0601     /* Set for max full-scale range (+/-8G) */
0602     return regmap_write(data->regmap, FXOS8700_XYZ_DATA_CFG, MODE_8G);
0603 }
0604 
0605 static void fxos8700_chip_uninit(void *data)
0606 {
0607     struct fxos8700_data *fxos8700_data = data;
0608 
0609     fxos8700_set_active_mode(fxos8700_data, FXOS8700_ACCEL, false);
0610     fxos8700_set_active_mode(fxos8700_data, FXOS8700_MAGN, false);
0611 }
0612 
0613 int fxos8700_core_probe(struct device *dev, struct regmap *regmap,
0614             const char *name, bool use_spi)
0615 {
0616     struct iio_dev *indio_dev;
0617     struct fxos8700_data *data;
0618     int ret;
0619 
0620     indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
0621     if (!indio_dev)
0622         return -ENOMEM;
0623 
0624     data = iio_priv(indio_dev);
0625     dev_set_drvdata(dev, indio_dev);
0626     data->regmap = regmap;
0627 
0628     ret = fxos8700_chip_init(data, use_spi);
0629     if (ret)
0630         return ret;
0631 
0632     ret = devm_add_action_or_reset(dev, fxos8700_chip_uninit, data);
0633     if (ret)
0634         return ret;
0635 
0636     indio_dev->channels = fxos8700_channels;
0637     indio_dev->num_channels = ARRAY_SIZE(fxos8700_channels);
0638     indio_dev->name = name ? name : "fxos8700";
0639     indio_dev->modes = INDIO_DIRECT_MODE;
0640     indio_dev->info = &fxos8700_info;
0641 
0642     return devm_iio_device_register(dev, indio_dev);
0643 }
0644 EXPORT_SYMBOL_GPL(fxos8700_core_probe);
0645 
0646 MODULE_AUTHOR("Robert Jones <rjones@gateworks.com>");
0647 MODULE_DESCRIPTION("FXOS8700 6-Axis Acc and Mag Combo Sensor driver");
0648 MODULE_LICENSE("GPL v2");