716 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * FXOS8700 - NXP IMU (accelerometer plus magnetometer)4 *5 * IIO core driver for FXOS8700, with support for I2C/SPI busses6 *7 * TODO: Buffer, trigger, and IRQ support8 */9#include <linux/module.h>10#include <linux/regmap.h>11#include <linux/acpi.h>12#include <linux/bitops.h>13#include <linux/bitfield.h>14 15#include <linux/iio/iio.h>16#include <linux/iio/sysfs.h>17 18#include "fxos8700.h"19 20/* Register Definitions */21#define FXOS8700_STATUS 0x0022#define FXOS8700_OUT_X_MSB 0x0123#define FXOS8700_OUT_X_LSB 0x0224#define FXOS8700_OUT_Y_MSB 0x0325#define FXOS8700_OUT_Y_LSB 0x0426#define FXOS8700_OUT_Z_MSB 0x0527#define FXOS8700_OUT_Z_LSB 0x0628#define FXOS8700_F_SETUP 0x0929#define FXOS8700_TRIG_CFG 0x0a30#define FXOS8700_SYSMOD 0x0b31#define FXOS8700_INT_SOURCE 0x0c32#define FXOS8700_WHO_AM_I 0x0d33#define FXOS8700_XYZ_DATA_CFG 0x0e34#define FXOS8700_HP_FILTER_CUTOFF 0x0f35#define FXOS8700_PL_STATUS 0x1036#define FXOS8700_PL_CFG 0x1137#define FXOS8700_PL_COUNT 0x1238#define FXOS8700_PL_BF_ZCOMP 0x1339#define FXOS8700_PL_THS_REG 0x1440#define FXOS8700_A_FFMT_CFG 0x1541#define FXOS8700_A_FFMT_SRC 0x1642#define FXOS8700_A_FFMT_THS 0x1743#define FXOS8700_A_FFMT_COUNT 0x1844#define FXOS8700_TRANSIENT_CFG 0x1d45#define FXOS8700_TRANSIENT_SRC 0x1e46#define FXOS8700_TRANSIENT_THS 0x1f47#define FXOS8700_TRANSIENT_COUNT 0x2048#define FXOS8700_PULSE_CFG 0x2149#define FXOS8700_PULSE_SRC 0x2250#define FXOS8700_PULSE_THSX 0x2351#define FXOS8700_PULSE_THSY 0x2452#define FXOS8700_PULSE_THSZ 0x2553#define FXOS8700_PULSE_TMLT 0x2654#define FXOS8700_PULSE_LTCY 0x2755#define FXOS8700_PULSE_WIND 0x2856#define FXOS8700_ASLP_COUNT 0x2957#define FXOS8700_CTRL_REG1 0x2a58#define FXOS8700_CTRL_REG2 0x2b59#define FXOS8700_CTRL_REG3 0x2c60#define FXOS8700_CTRL_REG4 0x2d61#define FXOS8700_CTRL_REG5 0x2e62#define FXOS8700_OFF_X 0x2f63#define FXOS8700_OFF_Y 0x3064#define FXOS8700_OFF_Z 0x3165#define FXOS8700_M_DR_STATUS 0x3266#define FXOS8700_M_OUT_X_MSB 0x3367#define FXOS8700_M_OUT_X_LSB 0x3468#define FXOS8700_M_OUT_Y_MSB 0x3569#define FXOS8700_M_OUT_Y_LSB 0x3670#define FXOS8700_M_OUT_Z_MSB 0x3771#define FXOS8700_M_OUT_Z_LSB 0x3872#define FXOS8700_CMP_X_MSB 0x3973#define FXOS8700_CMP_X_LSB 0x3a74#define FXOS8700_CMP_Y_MSB 0x3b75#define FXOS8700_CMP_Y_LSB 0x3c76#define FXOS8700_CMP_Z_MSB 0x3d77#define FXOS8700_CMP_Z_LSB 0x3e78#define FXOS8700_M_OFF_X_MSB 0x3f79#define FXOS8700_M_OFF_X_LSB 0x4080#define FXOS8700_M_OFF_Y_MSB 0x4181#define FXOS8700_M_OFF_Y_LSB 0x4282#define FXOS8700_M_OFF_Z_MSB 0x4383#define FXOS8700_M_OFF_Z_LSB 0x4484#define FXOS8700_MAX_X_MSB 0x4585#define FXOS8700_MAX_X_LSB 0x4686#define FXOS8700_MAX_Y_MSB 0x4787#define FXOS8700_MAX_Y_LSB 0x4888#define FXOS8700_MAX_Z_MSB 0x4989#define FXOS8700_MAX_Z_LSB 0x4a90#define FXOS8700_MIN_X_MSB 0x4b91#define FXOS8700_MIN_X_LSB 0x4c92#define FXOS8700_MIN_Y_MSB 0x4d93#define FXOS8700_MIN_Y_LSB 0x4e94#define FXOS8700_MIN_Z_MSB 0x4f95#define FXOS8700_MIN_Z_LSB 0x5096#define FXOS8700_TEMP 0x5197#define FXOS8700_M_THS_CFG 0x5298#define FXOS8700_M_THS_SRC 0x5399#define FXOS8700_M_THS_X_MSB 0x54100#define FXOS8700_M_THS_X_LSB 0x55101#define FXOS8700_M_THS_Y_MSB 0x56102#define FXOS8700_M_THS_Y_LSB 0x57103#define FXOS8700_M_THS_Z_MSB 0x58104#define FXOS8700_M_THS_Z_LSB 0x59105#define FXOS8700_M_THS_COUNT 0x5a106#define FXOS8700_M_CTRL_REG1 0x5b107#define FXOS8700_M_CTRL_REG2 0x5c108#define FXOS8700_M_CTRL_REG3 0x5d109#define FXOS8700_M_INT_SRC 0x5e110#define FXOS8700_A_VECM_CFG 0x5f111#define FXOS8700_A_VECM_THS_MSB 0x60112#define FXOS8700_A_VECM_THS_LSB 0x61113#define FXOS8700_A_VECM_CNT 0x62114#define FXOS8700_A_VECM_INITX_MSB 0x63115#define FXOS8700_A_VECM_INITX_LSB 0x64116#define FXOS8700_A_VECM_INITY_MSB 0x65117#define FXOS8700_A_VECM_INITY_LSB 0x66118#define FXOS8700_A_VECM_INITZ_MSB 0x67119#define FXOS8700_A_VECM_INITZ_LSB 0x68120#define FXOS8700_M_VECM_CFG 0x69121#define FXOS8700_M_VECM_THS_MSB 0x6a122#define FXOS8700_M_VECM_THS_LSB 0x6b123#define FXOS8700_M_VECM_CNT 0x6c124#define FXOS8700_M_VECM_INITX_MSB 0x6d125#define FXOS8700_M_VECM_INITX_LSB 0x6e126#define FXOS8700_M_VECM_INITY_MSB 0x6f127#define FXOS8700_M_VECM_INITY_LSB 0x70128#define FXOS8700_M_VECM_INITZ_MSB 0x71129#define FXOS8700_M_VECM_INITZ_LSB 0x72130#define FXOS8700_A_FFMT_THS_X_MSB 0x73131#define FXOS8700_A_FFMT_THS_X_LSB 0x74132#define FXOS8700_A_FFMT_THS_Y_MSB 0x75133#define FXOS8700_A_FFMT_THS_Y_LSB 0x76134#define FXOS8700_A_FFMT_THS_Z_MSB 0x77135#define FXOS8700_A_FFMT_THS_Z_LSB 0x78136#define FXOS8700_A_TRAN_INIT_MSB 0x79137#define FXOS8700_A_TRAN_INIT_LSB_X 0x7a138#define FXOS8700_A_TRAN_INIT_LSB_Y 0x7b139#define FXOS8700_A_TRAN_INIT_LSB_Z 0x7d140#define FXOS8700_TM_NVM_LOCK 0x7e141#define FXOS8700_NVM_DATA0_35 0x80142#define FXOS8700_NVM_DATA_BNK3 0xa4143#define FXOS8700_NVM_DATA_BNK2 0xa5144#define FXOS8700_NVM_DATA_BNK1 0xa6145#define FXOS8700_NVM_DATA_BNK0 0xa7146 147/* Bit definitions for FXOS8700_CTRL_REG1 */148#define FXOS8700_CTRL_ODR_MAX 0x00149#define FXOS8700_CTRL_ODR_MSK GENMASK(5, 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 0x01161#define FXOS8700_ACTIVE_MIN_USLEEP 4000 /* from table 6 in datasheet */162 163#define FXOS8700_DEVICE_ID 0xC7164#define FXOS8700_PRE_DEVICE_ID 0xC4165#define FXOS8700_DATA_BUF_SIZE 3166 167struct fxos8700_data {168 struct regmap *regmap;169 struct iio_trigger *trig;170 __be16 buf[FXOS8700_DATA_BUF_SIZE] __aligned(IIO_DMA_MINALIGN);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_INT2273};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 the294 * CTRL_REG1 register. ODR is halved when using both sensors at once in295 * 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_MAGN: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, ret, val;349 bool active_mode;350 static const int scale_num = ARRAY_SIZE(fxos8700_accel_scale);351 struct device *dev = regmap_get_device(data->regmap);352 353 if (t == FXOS8700_MAGN) {354 dev_err(dev, "Magnetometer scale is locked at 0.001Gs\n");355 return -EINVAL;356 }357 358 /*359 * When device is in active mode, it failed to set an ACCEL360 * full-scale range(2g/4g/8g) in FXOS8700_XYZ_DATA_CFG.361 * This is not align with the datasheet, but it is a fxos8700362 * chip behavier. Set the device in standby mode before setting363 * an ACCEL full-scale range.364 */365 ret = regmap_read(data->regmap, FXOS8700_CTRL_REG1, &val);366 if (ret)367 return ret;368 369 active_mode = val & FXOS8700_ACTIVE;370 if (active_mode) {371 ret = regmap_write(data->regmap, FXOS8700_CTRL_REG1,372 val & ~FXOS8700_ACTIVE);373 if (ret)374 return ret;375 }376 377 for (i = 0; i < scale_num; i++)378 if (fxos8700_accel_scale[i].uscale == uscale)379 break;380 381 if (i == scale_num)382 return -EINVAL;383 384 ret = regmap_write(data->regmap, FXOS8700_XYZ_DATA_CFG,385 fxos8700_accel_scale[i].bits);386 if (ret)387 return ret;388 return regmap_write(data->regmap, FXOS8700_CTRL_REG1,389 active_mode);390}391 392static int fxos8700_get_scale(struct fxos8700_data *data,393 enum fxos8700_sensor t, int *uscale)394{395 int i, ret, val;396 static const int scale_num = ARRAY_SIZE(fxos8700_accel_scale);397 398 if (t == FXOS8700_MAGN) {399 *uscale = 1000; /* Magnetometer is locked at 0.001Gs */400 return 0;401 }402 403 ret = regmap_read(data->regmap, FXOS8700_XYZ_DATA_CFG, &val);404 if (ret)405 return ret;406 407 for (i = 0; i < scale_num; i++) {408 if (fxos8700_accel_scale[i].bits == (val & 0x3)) {409 *uscale = fxos8700_accel_scale[i].uscale;410 return 0;411 }412 }413 414 return -EINVAL;415}416 417static int fxos8700_get_data(struct fxos8700_data *data, int chan_type,418 int axis, int *val)419{420 u8 base, reg;421 s16 tmp;422 int ret;423 424 /*425 * Different register base addresses varies with channel types.426 * This bug hasn't been noticed before because using an enum is427 * really hard to read. Use an a switch statement to take over that.428 */429 switch (chan_type) {430 case IIO_ACCEL:431 base = FXOS8700_OUT_X_MSB;432 break;433 case IIO_MAGN:434 base = FXOS8700_M_OUT_X_MSB;435 break;436 default:437 return -EINVAL;438 }439 440 /* Block read 6 bytes of device output registers to avoid data loss */441 ret = regmap_bulk_read(data->regmap, base, data->buf,442 sizeof(data->buf));443 if (ret)444 return ret;445 446 /* Convert axis to buffer index */447 reg = axis - IIO_MOD_X;448 449 /*450 * Convert to native endianness. The accel data and magn data451 * are signed, so a forced type conversion is needed.452 */453 tmp = be16_to_cpu(data->buf[reg]);454 455 /*456 * ACCEL output data registers contain the X-axis, Y-axis, and Z-axis457 * 14-bit left-justified sample data and MAGN output data registers458 * contain the X-axis, Y-axis, and Z-axis 16-bit sample data. Apply459 * a signed 2 bits right shift to the readback raw data from ACCEL460 * output data register and keep that from MAGN sensor as the origin.461 * Value should be extended to 32 bit.462 */463 switch (chan_type) {464 case IIO_ACCEL:465 tmp = tmp >> 2;466 break;467 case IIO_MAGN:468 /* Nothing to do */469 break;470 default:471 return -EINVAL;472 }473 474 /* Convert to native endianness */475 *val = sign_extend32(tmp, 15);476 477 return 0;478}479 480static int fxos8700_set_odr(struct fxos8700_data *data, enum fxos8700_sensor t,481 int odr, int uodr)482{483 int i, ret, val;484 bool active_mode;485 static const int odr_num = ARRAY_SIZE(fxos8700_odr);486 487 ret = regmap_read(data->regmap, FXOS8700_CTRL_REG1, &val);488 if (ret)489 return ret;490 491 active_mode = val & FXOS8700_ACTIVE;492 493 if (active_mode) {494 /*495 * The device must be in standby mode to change any of the496 * other fields within CTRL_REG1497 */498 ret = regmap_write(data->regmap, FXOS8700_CTRL_REG1,499 val & ~FXOS8700_ACTIVE);500 if (ret)501 return ret;502 }503 504 for (i = 0; i < odr_num; i++)505 if (fxos8700_odr[i].odr == odr && fxos8700_odr[i].uodr == uodr)506 break;507 508 if (i >= odr_num)509 return -EINVAL;510 511 val &= ~FXOS8700_CTRL_ODR_MSK;512 val |= FIELD_PREP(FXOS8700_CTRL_ODR_MSK, fxos8700_odr[i].bits) | FXOS8700_ACTIVE;513 return regmap_write(data->regmap, FXOS8700_CTRL_REG1, val);514}515 516static int fxos8700_get_odr(struct fxos8700_data *data, enum fxos8700_sensor t,517 int *odr, int *uodr)518{519 int i, val, ret;520 static const int odr_num = ARRAY_SIZE(fxos8700_odr);521 522 ret = regmap_read(data->regmap, FXOS8700_CTRL_REG1, &val);523 if (ret)524 return ret;525 526 val = FIELD_GET(FXOS8700_CTRL_ODR_MSK, val);527 528 for (i = 0; i < odr_num; i++)529 if (val == fxos8700_odr[i].bits)530 break;531 532 if (i >= odr_num)533 return -EINVAL;534 535 *odr = fxos8700_odr[i].odr;536 *uodr = fxos8700_odr[i].uodr;537 538 return 0;539}540 541static int fxos8700_read_raw(struct iio_dev *indio_dev,542 struct iio_chan_spec const *chan,543 int *val, int *val2, long mask)544{545 int ret;546 struct fxos8700_data *data = iio_priv(indio_dev);547 548 switch (mask) {549 case IIO_CHAN_INFO_RAW:550 ret = fxos8700_get_data(data, chan->type, chan->channel2, val);551 if (ret)552 return ret;553 return IIO_VAL_INT;554 case IIO_CHAN_INFO_SCALE:555 *val = 0;556 ret = fxos8700_get_scale(data, fxos8700_to_sensor(chan->type),557 val2);558 return ret ? ret : IIO_VAL_INT_PLUS_MICRO;559 case IIO_CHAN_INFO_SAMP_FREQ:560 ret = fxos8700_get_odr(data, fxos8700_to_sensor(chan->type),561 val, val2);562 return ret ? ret : IIO_VAL_INT_PLUS_MICRO;563 default:564 return -EINVAL;565 }566}567 568static int fxos8700_write_raw(struct iio_dev *indio_dev,569 struct iio_chan_spec const *chan,570 int val, int val2, long mask)571{572 struct fxos8700_data *data = iio_priv(indio_dev);573 574 switch (mask) {575 case IIO_CHAN_INFO_SCALE:576 return fxos8700_set_scale(data, fxos8700_to_sensor(chan->type),577 val2);578 case IIO_CHAN_INFO_SAMP_FREQ:579 return fxos8700_set_odr(data, fxos8700_to_sensor(chan->type),580 val, val2);581 default:582 return -EINVAL;583 }584}585 586static IIO_CONST_ATTR(in_accel_sampling_frequency_available,587 "1.5625 6.25 12.5 50 100 200 400 800");588static IIO_CONST_ATTR(in_magn_sampling_frequency_available,589 "1.5625 6.25 12.5 50 100 200 400 800");590static IIO_CONST_ATTR(in_accel_scale_available, "0.000244 0.000488 0.000976");591static IIO_CONST_ATTR(in_magn_scale_available, "0.001000");592 593static struct attribute *fxos8700_attrs[] = {594 &iio_const_attr_in_accel_sampling_frequency_available.dev_attr.attr,595 &iio_const_attr_in_magn_sampling_frequency_available.dev_attr.attr,596 &iio_const_attr_in_accel_scale_available.dev_attr.attr,597 &iio_const_attr_in_magn_scale_available.dev_attr.attr,598 NULL,599};600 601static const struct attribute_group fxos8700_attrs_group = {602 .attrs = fxos8700_attrs,603};604 605static const struct iio_info fxos8700_info = {606 .read_raw = fxos8700_read_raw,607 .write_raw = fxos8700_write_raw,608 .attrs = &fxos8700_attrs_group,609};610 611static int fxos8700_chip_init(struct fxos8700_data *data, bool use_spi)612{613 int ret;614 unsigned int val;615 struct device *dev = regmap_get_device(data->regmap);616 617 ret = regmap_read(data->regmap, FXOS8700_WHO_AM_I, &val);618 if (ret) {619 dev_err(dev, "Error reading chip id\n");620 return ret;621 }622 if (val != FXOS8700_DEVICE_ID && val != FXOS8700_PRE_DEVICE_ID) {623 dev_err(dev, "Wrong chip id, got %x expected %x or %x\n",624 val, FXOS8700_DEVICE_ID, FXOS8700_PRE_DEVICE_ID);625 return -ENODEV;626 }627 628 ret = fxos8700_set_active_mode(data, FXOS8700_ACCEL, true);629 if (ret)630 return ret;631 632 ret = fxos8700_set_active_mode(data, FXOS8700_MAGN, true);633 if (ret)634 return ret;635 636 /*637 * The device must be in standby mode to change any of the other fields638 * within CTRL_REG1639 */640 ret = regmap_write(data->regmap, FXOS8700_CTRL_REG1, 0x00);641 if (ret)642 return ret;643 644 /* Set max oversample ratio (OSR) and both devices active */645 ret = regmap_write(data->regmap, FXOS8700_M_CTRL_REG1,646 FXOS8700_HMS_MASK | FXOS8700_OS_MASK);647 if (ret)648 return ret;649 650 /* Disable and rst min/max measurements & threshold */651 ret = regmap_write(data->regmap, FXOS8700_M_CTRL_REG2,652 FXOS8700_MAXMIN_RST | FXOS8700_MAXMIN_DIS_THS |653 FXOS8700_MAXMIN_DIS);654 if (ret)655 return ret;656 657 /*658 * Set max full-scale range (+/-8G) for ACCEL sensor in chip659 * initialization then activate the device.660 */661 ret = regmap_write(data->regmap, FXOS8700_XYZ_DATA_CFG, MODE_8G);662 if (ret)663 return ret;664 665 /* Max ODR (800Hz individual or 400Hz hybrid), active mode */666 return regmap_update_bits(data->regmap, FXOS8700_CTRL_REG1,667 FXOS8700_CTRL_ODR_MSK | FXOS8700_ACTIVE,668 FIELD_PREP(FXOS8700_CTRL_ODR_MSK, FXOS8700_CTRL_ODR_MAX) |669 FXOS8700_ACTIVE);670}671 672static void fxos8700_chip_uninit(void *data)673{674 struct fxos8700_data *fxos8700_data = data;675 676 fxos8700_set_active_mode(fxos8700_data, FXOS8700_ACCEL, false);677 fxos8700_set_active_mode(fxos8700_data, FXOS8700_MAGN, false);678}679 680int fxos8700_core_probe(struct device *dev, struct regmap *regmap,681 const char *name, bool use_spi)682{683 struct iio_dev *indio_dev;684 struct fxos8700_data *data;685 int ret;686 687 indio_dev = devm_iio_device_alloc(dev, sizeof(*data));688 if (!indio_dev)689 return -ENOMEM;690 691 data = iio_priv(indio_dev);692 dev_set_drvdata(dev, indio_dev);693 data->regmap = regmap;694 695 ret = fxos8700_chip_init(data, use_spi);696 if (ret)697 return ret;698 699 ret = devm_add_action_or_reset(dev, fxos8700_chip_uninit, data);700 if (ret)701 return ret;702 703 indio_dev->channels = fxos8700_channels;704 indio_dev->num_channels = ARRAY_SIZE(fxos8700_channels);705 indio_dev->name = name ? name : "fxos8700";706 indio_dev->modes = INDIO_DIRECT_MODE;707 indio_dev->info = &fxos8700_info;708 709 return devm_iio_device_register(dev, indio_dev);710}711EXPORT_SYMBOL_GPL(fxos8700_core_probe);712 713MODULE_AUTHOR("Robert Jones <rjones@gateworks.com>");714MODULE_DESCRIPTION("FXOS8700 6-Axis Acc and Mag Combo Sensor driver");715MODULE_LICENSE("GPL v2");716