iio: imu: fxos8700: fix ACCEL measurement range selection

When device is in active mode, it fails to set an ACCEL full-scale
range(2g/4g/8g) in FXOS8700_XYZ_DATA_CFG. This is not align with the
datasheet, but it is a fxos8700 chip behavior.

Keep the device in standby mode before setting ACCEL full-scale range
into FXOS8700_XYZ_DATA_CFG in chip initialization phase and setting
scale phase.

Fixes: 84e5ddd5c4 ("iio: imu: Add support for the FXOS8700 IMU")
Signed-off-by: Carlos Song <carlos.song@nxp.com>
Link: https://lore.kernel.org/r/20221208071911.2405922-6-carlos.song@nxp.com
Cc: <Stable@vger.kernel.org>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
This commit is contained in:
Carlos Song 2022-12-08 15:19:09 +08:00 коммит произвёл Jonathan Cameron
Родитель a53f945879
Коммит 9d61c18205
1 изменённых файлов: 34 добавлений и 7 удалений

Просмотреть файл

@ -345,7 +345,8 @@ static int fxos8700_set_active_mode(struct fxos8700_data *data,
static int fxos8700_set_scale(struct fxos8700_data *data,
enum fxos8700_sensor t, int uscale)
{
int i;
int i, ret, val;
bool active_mode;
static const int scale_num = ARRAY_SIZE(fxos8700_accel_scale);
struct device *dev = regmap_get_device(data->regmap);
@ -354,6 +355,25 @@ static int fxos8700_set_scale(struct fxos8700_data *data,
return -EINVAL;
}
/*
* When device is in active mode, it failed to set an ACCEL
* full-scale range(2g/4g/8g) in FXOS8700_XYZ_DATA_CFG.
* This is not align with the datasheet, but it is a fxos8700
* chip behavier. Set the device in standby mode before setting
* an ACCEL full-scale range.
*/
ret = regmap_read(data->regmap, FXOS8700_CTRL_REG1, &val);
if (ret)
return ret;
active_mode = val & FXOS8700_ACTIVE;
if (active_mode) {
ret = regmap_write(data->regmap, FXOS8700_CTRL_REG1,
val & ~FXOS8700_ACTIVE);
if (ret)
return ret;
}
for (i = 0; i < scale_num; i++)
if (fxos8700_accel_scale[i].uscale == uscale)
break;
@ -361,8 +381,12 @@ static int fxos8700_set_scale(struct fxos8700_data *data,
if (i == scale_num)
return -EINVAL;
return regmap_write(data->regmap, FXOS8700_XYZ_DATA_CFG,
ret = regmap_write(data->regmap, FXOS8700_XYZ_DATA_CFG,
fxos8700_accel_scale[i].bits);
if (ret)
return ret;
return regmap_write(data->regmap, FXOS8700_CTRL_REG1,
active_mode);
}
static int fxos8700_get_scale(struct fxos8700_data *data,
@ -631,14 +655,17 @@ static int fxos8700_chip_init(struct fxos8700_data *data, bool use_spi)
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);
/*
* Set max full-scale range (+/-8G) for ACCEL sensor in chip
* initialization then activate the device.
*/
ret = regmap_write(data->regmap, FXOS8700_XYZ_DATA_CFG, MODE_8G);
if (ret)
return ret;
/* Set for max full-scale range (+/-8G) */
return regmap_write(data->regmap, FXOS8700_XYZ_DATA_CFG, MODE_8G);
/* Max ODR (800Hz individual or 400Hz hybrid), active mode */
return regmap_write(data->regmap, FXOS8700_CTRL_REG1,
FXOS8700_CTRL_ODR_MAX | FXOS8700_ACTIVE);
}
static void fxos8700_chip_uninit(void *data)